zoukankan      html  css  js  c++  java
  • 基于mini2440的IIC读写(裸机)

    mini2440开发板提供的测试代码过于复杂,让人很难理解,而且有些错误,如GPE14-15不能设置上拉电阻,可是代码里却设置了,虽然无关紧要。为了方便学习,我在闲暇之时我研究了一下。IIC的原理是比较简单的,可是在实际编程中却遇到很多困难。不知道哪里出了错误,有些逻辑上认为正确的,但在硬件上却不能实现。如下两行代码:

    rGPECON &= ~(0x0f<<28);
    rGPECON |= (0xa0<<28);


    是为设置GPE14、GPE15位SCL和SDA的,在加上第一句代码后烧写程序就运行失败了。现在还不知道为什么加上第一行代码后就失败了,求高手解释。有些问题不实践真的不知道什么原因,所谓实践出真知嘛。希望对有兴趣的朋友有所帮助。

    我们来看程序编写过程:

    s3c2440的IIC七位地址时的数据接收和发送格式:



    灰色的是从设备发送的。


    IIC的具体时序:


    由此可知SCL为高位时SDA从高位跃迁到低位时表示开始、SCL为高位时SDA从低位跃迁到高位时表示结束。我们可以设置IICSTAT寄存器来发送开始或结束信号。在第九个时钟时主设备或从设备拉低SDA,表示应答ACK。应答后产出中断,此时可以将数据写入IICDS或读出,然后清除中断标志位IICCON[4]恢复操作。具体的操作参考芯片手册或源代码。


    mini2440的IIC接口连接一个EEPROM即AT24C08A,我选择页写和连续读来测试IIC接口。具体时序如下:



    其中页写的时许很明确。但是连读读的时序前面不太明确,在数据手册中我们可以得知连续读是当前地址读和随机读的一种,所以前面的时序我采取随机读时许,即组合起来。要是还不太清楚请看源代码。随机读时序如下:


    AT24C08A接法在硬件电路图中可知如下:


    查数据手册可以其地址为0xa0或0xa1。最低位为读写标志。在s3c2440中根据IIC模式自动选择,所以地址我们只需填写0xa0即可。

    值得注意的是EEPROM读写速度不是很快,所以每次读写一个字节都要加一定延时,这点十分关键。这往往是程序读写失败的原因。当然我们也需要设置好SCL的频率。在IICCON里设置这里不多说。

    在接收模式下最后一个字节数据不发送ACK这点也需要注意。

    测试代码中我们采用将数据写入EEPROM中然后读取出来输出到串口来检验,程序可以采用中断或轮询,代码如下:

    mian.c部分

    #define  GLOBAL_CLK 1
    
    #include "def.h"
    #include "option.h"
    #include "2440addr.h"
    #include "profile.h"
    #include "mmu.h"
    
    typedef unsigned char uchar;
    typedef unsigned int uint;
    
    extern void AT24C08_wirte(uchar waddr, uchar *dat,  int num);
    extern void AT24C08_read(uchar waddr, uchar *rev,  int num);
    extern void IIC_init(void);
    extern void delay(int time);
    
    uchar dat[]={"0123456789abcdef"};
    uchar rev[50]={0};
    
    void Main(void)
    {
    
    	rGPBCON=(1<<0);//关闭蜂鸣器
        rGPBDAT=0x00;
    	
    	IIC_init();
    
    	AT24C08_wirte(0x00, dat, 16);
    	Uart_Printf("
    
    ");
    	AT24C08_read(0x00, rev, 10);
    	
    	Uart_Printf("
    %s
    ",rev);
    }
    


    IIC.c部分

    #include "def.h"
    #include "option.h"
    #include "2440addr.h"
    #include "profile.h"
    #include "mmu.h"
    
    typedef unsigned char uchar;
    typedef unsigned int uint;
    void __irq IIC_INT(void);
    
    int flag=1;//中断标志
    
    void delay(int time)
    {
    	int i,j,k;
    	for(i=0;i<100;++i)
    		for(k=0;k<100;++k)
    			for(j=0;j<time;j++);
    }
    
    //IIC初始化
    void IIC_init(void)
    {
    	//设置GPE15、GPE14为SDA、SCL
    	rGPECON |= (0xa0<<28);
    	
    	//允许ACK、允许中断、发送频率Khz
    	rINTMSK &= ~(1<<27);
    	rIICCON |= (1<<7 | 0<<6 | 1<<5 | 0xf);
    	rIICSTAT |= 1<<4;//IICDS可写
    	
    	MMU_Init();//映射地址
    	pISR_IIC = (unsigned)IIC_INT;//中断入口
    }
    
    //AT24C08页写
    void AT24C08_wirte(uchar waddr, uchar *dat, int num)
    {
    	int i=0;
    
    	rIICDS = 0xa0;//AT24C08地址
    	rIICSTAT =0xf0;//发送模式、发送开始信号
    	while(flag == 1)
    		delay(100);//等待中断
    	flag = 1;
    	
    	rIICDS = waddr;//起始地址
    	rIICCON = 0xaf;//清除中断标志位
    	while(flag == 1)
    		delay(100);//等待中断
    	flag = 1;
    		
    	for(i=0;i<num;++i){
    		rIICDS = *(dat + i);
    		rIICCON = 0xaf;//清除中断标志位
    		while(flag == 1)
    			delay(100);//等待中断
    		flag = 1;
    	}
    	
    	rIICSTAT =0xd0;//发送停止位
    	rIICCON = 0xaf;//清除中断标志位
    	delay(100);
    }
    
    //AT24C08连续读		
    void AT24C08_read(uchar waddr, uchar *rev, int num)
    {
    	int i=0;
    	
    	rIICDS = 0xa0;
    	rIICSTAT =0xf0;//发送从机地址
    	while(flag == 1)
    		delay(100);//等待中断
    	flag = 1;
    	
    	rIICDS = waddr;//初始地址
    	rIICCON = 0xaf;//清除中断标志位
    	while(flag == 1)
    		delay(100);//等待中断
    	flag = 1;
    	
    	rIICDS = 0xa0;
    	rIICSTAT =0xb0;//接收模式
    	rIICCON = 0xaf;//清除中断标志位
    	while(flag == 1)
    		delay(100);//等待中断
    	flag = 1;
    	
    	for(i=0;i<num;++i){
    		if(i == (num-1)) rIICCON = 0x2f;
    		else rIICCON = 0xaf;
    		while(flag == 1)
    			delay(100);//等待中断
    		flag = 1;
    		*(rev + i) = rIICDS;
    		delay(100);
    	}
    	
    	rIICSTAT =0x90;//发送停止位
    	rIICCON = 0xaf;//清除中断标志位
    	delay(100);
    }
    
    //中断服务函数
    void __irq IIC_INT(void)
    {
    	flag = 0;
    	rSRCPND |= 1<<27;//先清除SRCPND
    	rINTPND |= 1<<27;
    }
    
    
    /*
    #include "2440addr.h"
    
    typedef unsigned char uchar;
    typedef unsigned int uint;
    
    void delay(int time)
    {
    	int i,j,k;
    	for(i=0;i<100;++i)
    		for(k=0;k<100;++k)
    			for(j=0;j<time;j++);
    }
    
    //IIC初始化
    void IIC_init(void)
    {
    	//设置GPE15、GPE14为SDA、SCL
    	rGPECON |=  (0xa0<<28);
    	//允许ACK、允许中断、发送频率Khz
    	rIICCON |= (1<<7 | 0<<6 | 1<<5 | 0xf);
    	rIICSTAT |= (1<<4);//IICDS可写
    }
    
    //AT24C08页写
    void AT24C08_wirte(uchar waddr, uchar *dat, int num)
    {
    	int i=0;
    
    	rIICDS = 0xa0;//AT24C08地址
    	rIICSTAT =0xf0;//发送模式、发送开始信号
    	while(!(rIICCON & 0x10))
    		delay(100);//等待中断
    
    	rIICDS = waddr;//起始地址
    	rIICCON &= ~(1<<4);//清除中断标志位
    	while(!(rIICCON & 0x10))
    		delay(100);//等待中断
    	
    	for(i=0;i<num;++i){
    		rIICDS = *(dat + i);
    		rIICCON &= ~(1<<4);//清除中断标志位
    		while(!(rIICCON & 0x10))
    			delay(100);//等待中断
    	}
    	
    	rIICSTAT =0xd0;//发送停止位
    	rIICCON &= ~(1<<4);//清除中断标志位
    	delay(100);
    }
    
    //AT24C08连续读		
    void AT24C08_read(uchar waddr, uchar *rev, int num)
    {
    	int i=0;
    
    	rIICDS = 0xa0;
    	rIICSTAT =0xf0;//发送EEPROM地址
    	while(!(rIICCON & 0x10))
    		delay(100);//等待中断
    	
    	rIICDS = waddr;//初始地址
    	rIICCON &= ~(1<<4);//清除中断标志位
    	while(!(rIICCON & 0x10))
    		delay(100);//等待中断
    		
    	rIICDS = 0xa0;
    	rIICSTAT =0xb0;//接收模式
    	rIICCON &= ~(1<<4);//清除中断标志位
    	while(!(rIICCON & 0x10))
    			delay(100);//等待中断
    	
    	for(i=0;i<num;++i){
    		if(i == (num-1)) rIICCON &= ~(1<<7 | 1<<4);//不发送ACK
    		else rIICCON &= ~(1<<4);//清除中断标志位
    		while(!(rIICCON & 0x10))
    			delay(100);//等待中断
    		*(rev+i) = rIICDS;
    		delay(100);
    	}
    
    	rIICSTAT =0x90;//发送停止位
    	rIICCON &= ~(1<<4);//清除中断标志位
    	delay(100);
    }
    */


    这里包含了中断和轮询方式,其中轮询方式被我注释了。

    我们通过代码在结合芯片手册可以直观的了解IIC接口的读写。代码中有很多注释方便大家阅读。

    程序运行结果:


    将0123456789abcdef写入EEPROM,然后读出0123456789。


    源代码地址:http://download.csdn.net/detail/a16839678/6010041

  • 相关阅读:
    关于技术的学习及批判 人工智能
    爱迪生如何看待手机程序员怎么用移动互联网 人工智能
    量子学习及思考4群体意识 人工智能
    程序员的出路 人工智能
    函数式编程学习之路(14) 人工智能
    量子学习及思考1开篇 人工智能
    函数式编程学习之路(16)图灵完备 人工智能
    开机启动
    动态连接库
    静态常量的问题
  • 原文地址:https://www.cnblogs.com/pangblog/p/3283345.html
Copyright © 2011-2022 走看看