s3c2440的IIC应用——读写AT24C02A

发布者:心境恬淡最新更新时间:2016-05-30 来源: eefocus关键字:s3c2440  IIC应用  读写AT24C02A 手机看文章 扫描二维码
随时随地手机看文章
IIC(Inter-Integrated Circuit,I2C)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微处理器及其外围设备,它的最主要优点是简单和有效。它只需要数据线SDA和时钟线SCL,就能够实现CPU与被控IC之间、IC与IC之间进行双向传送。
 
       s3c2440内部有一个IIC总线接口,因此为我们连接带有IIC通信模块的外围设备提供了便利。它具有四种操作模式:主设备发送模式、主设备接收模式、从设备发送模式和从设备接收模式。在这里我们只把s3c2440当做IIC总线的主设备来使用,因此只介绍前两种操作模式。在主设备发送模式下,它的工作流程为:首先配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xF0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要继续发送数据,那么在接收到应答信号后,再把待发送的数据写入寄存器IICDS中,清除中断标志后,再次等待应答信号;如果不想再发送数据了,那么把0x90写入寄存器IICSTAT中,清除中断标志并等待停止条件后,即完成了一次主设备的发送。在主设备接收模式下,它的工作流程为:首先配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xB0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要接收数据,那么在应答信号后,读取寄存器IICDS,清除中断标志;如果不想接收数据了,那么就向寄存器IICSTAT写入0x90,清除中断标志并等待停止条件后,即完成了一次主设备的接收。在完成上述两个模式时,主要用到了控制寄存器IICCON、控制状态寄存器IICSTAT和发送接收数据移位寄存器IICDS。由于我们只把s3c2440当做主设备来用,并且系统的IIC总线上只有这么一个主设备,因此用来设置从设备地址的地址寄存器IICADD,和用于仲裁总线的多主设备线路控制寄存器IICLC都无需配置。寄存器IICCON的第6位和低4位用于设置IIC的时钟频率,因为IIC的时钟线SCL都是由主设备提供的。s3c2440的IIC时钟源为PCLK,当系统的PCLK为50MHz,而从设备最高需要100kHz时,可以将IICCON的第6位置1,IICCON的低4位全为0即可。寄存器IICCON的第7位用于设置是否发出应答信号,第5位用于是否使能发送和接收中断,第4位用于中断的标志,当接收或发送数据后一定要对该位进行清零,以清除中断标志。寄存器IICSTAT的高2位用于设置是哪种操作模式,当向第5位写0或写1时,则表示结束IIC或开始IIC通讯,第4位用于是否使能接收/发送数据。
 
       由于通讯是双方的事情,在了解了主设备的操作模式后,还要清楚从设备的运行机制,两者要达到完美地结合,才能实现彼此的通讯。在这里,从设备是EEPROM——AT24C02A,要想让s3c2440能够正确地对AT24C02A读写,就必须让s3c2440的时序完全按照AT24C02A的时序。AT24C02A的写操作有两种模式:字节写和页写。字节写是先接收带有写命令的设备地址信息,如果符合就应答,再接收设备内存地址信息,发出应答后,再接收要写入的数据,这样就完成了字节写过程。页写与字节写的区别就是,页写可以一次写多个数据,而字节写只能一次写一个数据。但由于AT24C02A的一页才8个字节,所以页写也最多写8个数据,而且只能在该页内写,不会发生一次页写同时写两页的情况。AT24C02A的读操作有三种模式:当前地址读、随机读和序列读。当前地址读是只能读取当前地址内的数据,它的时序是先接收带有读命令的设备地址信息,如果符合就应答,然后发送当前地址内的数据,在没有接收从主设备发来的应答信号的情况下终止该次操作。随机读的时序是,连续接收带有写命令的设备地址信息和设备内存地址信息,然后主设备重新开启IIC通信,AT24C02A再次接收到带有读命令的设备地址信息,在发出应答信号以后,发送该内存地址的数据,在没有接收到任何应答信号的情况下结束该次通信。当前地址读和随机读一次都只能读取一个数据,而序列读一次可以读取若干个数据,它的时序就是在当前地址读或随机读发出数据后,接收到了应答信号,那么AT24C02A会把下一个内存地址中的数据送出,除非AT24C02A接收不到任何应答信号,否则它会一直把下一个内存地址中的数据送出。序列读没有一页8个字节的限制。
 
       在介绍完了s3c2440和AT24C02A的IIC通讯方式后,我们就可以写程序了。在这里,我们用UART来实现PC机对AT24C02A的读写。UART的通讯协议是,PC机先发送命令字节:0xC0表示要向AT24C02A写数据,0xC1表示要读取AT24C02A的数据,在命令字节后,紧跟着的是设备内存地址和写入或读取的字节数。如果是要写EEPROM数据,则在这三个字节后是要写入的数据内容。在UART通讯完毕后,s3c2440会根据命令的不同,写入或读取AT24C02A,如果是读取EEPROM,则s3c2440还会利用UART把读取到的数据上传到PC机。在这个程序中,我们只开启了UART的接收中断,而没有开启发送中断,即让s3c2440主动去完成发送任务。并且在与AT24C02A操作中,我们使用的是页写和序列读的模式,这样可以最大程度的完成一次读或写操作,而且我们所编写的页写和序列读子程度也同样可以实现字节写和随机读的模式。在这里我们限制一次读或写的数据量最多为8个字节。
 
unsigned char iic_buffer[8];         //IIC数据通讯缓存数组
unsigned char address,length;        //EEPROM内存地址和数据通信的长度
unsigned char flag;                      //应答标志
unsigned char comm;                   //命令
unsigned char devAddr=0xa0;      //从设备AT24C02A的地址
……              ……
 
//IIC通信中断
void __irq IicISR(void)
{
       rSRCPND |= 0x1<<27;
       rINTPND |= 0x1<<27;
       flag = 0;                //清标志
}
 
//UART通信中断,只开启了接收中断,因此无需判断是接收还是发送
void __irq uartISR(void)
{
       char ch;
       static char command;
       static char count;
       rSUBSRCPND |= 0x1;
       rSRCPND |= 0x1<<28;
       rINTPND |= 0x1<<28;
 
       ch = rURXH0;             //接收字节数据
       if(command==0)           //判断命令
       {
              switch(ch)
              {
              case 0xc0:              //写EEPROM
                     command = 0xc0;
                     count=0;
                     comm = 0;
              break;
              case 0xc1:              //读EEPROM
                     command = 0xc1;  
                     count=0;
                     comm = 0;
              break;
              default:
                     command = 0;
                     count =0;
                     rUTXH0=ch;
              break;
              }
       }
       else
       {
              if(command == 0xc0)           //写命令
              {
                    
                     count++;
                     if (count == 1)
                     {
                            address = ch;          //接收设备内存地址信息
                     }
                     else if(count == 2)
                     {
                            length = ch;           //接收写入数据个数信息
                     }
                     else               //接收具体要写入EEPROM的数据
                     {
                            iic_buffer[count-3] = ch;
                            if(count==length+2)             //接收完本次所有数据
                            {
                                   rUTXH0=0xc0;
                                   count=0;
                                   command=0;
                                   comm=1;                      //标志写命令,用于主程序
                            }                                
                     }
              }
              else if(command ==0xc1)             //读命令
              {                  
                     count++;
                     if(count==1)
                     {
                            address = ch;                 //接收设备内存地址信息
                     }
                     else
                     {
                            length = ch;                  //接收读取数据个数信息
                            rUTXH0=0xc1;
                            count=0;
                            command=0;
                            comm = 2;                    //标志读命令,用于主程序
                     }
              }
       }           
}
 
//AT24C02A页写,当sizeofdate为1时,是字节写
//输入参数依次为设备内存地址、IIC数据缓存数组和要写入的数据个数
void wr24c02a(unsigned char wordAddr,unsigned char *buffer,int sizeofdate )
{
       int i;
       flag =1;                               //应答标志
       rIICDS = devAddr;
       rIICCON &= ~0x10;            //清中断标志
       rIICSTAT = 0xf0;                 //主设备发送模式
       while(flag == 1)                   //等待从设备应答,
              delay(100);                   //一旦进入IIC中断,即可跳出该死循环
             
       flag = 1;
       rIICDS = wordAddr;            //写入从设备内存地址
       rIICCON &= ~0x10;
       while(flag)
              delay(100);
             
//连续写入数据
       for(i=0;i        {
              flag = 1;
              rIICDS = *(buffer+i);
              rIICCON &= ~0x10;
              while(flag)
                     delay(100);
       }
      
       rIICSTAT = 0xd0;         //发出stop命令,结束该次通讯
       rIICCON = 0xe0;          //为下次IIC通讯做准备
      
       delay(100);                   //等待
}
 
//AT24C02A的序列读,当sizeofdate为1时,是随机读
//输入参数依次为设备内存地址、IIC数据缓存数组和要读取的数据个数
void rd24c02a(unsigned char wordAddr,unsigned char *buffer,int sizeofdate )
{
       int i;
       unsigned char temp;
       flag =1;
       rIICDS = devAddr;                     //
       rIICCON &= ~0x10;            //清中断标志
       rIICSTAT = 0xf0;                 //主设备发送模式
       while(flag)
              delay(100);
      
       flag = 1;
       rIICDS = wordAddr;
       rIICCON &= ~0x10;
       while(flag)
              delay(100);
             
       flag = 1;
       rIICDS =  devAddr;            //
       rIICCON &= ~0x10;           
       rIICSTAT = 0xb0;                //主设备接收模式
       while (flag)
              delay(100);
             
       flag = 1;
       temp = rIICDS;                    //读取从设备地址
       rIICCON &= ~0x10;
       while(flag)
              delay(100);
 
//连续读
       for(i=0;i        {
              flag = 1;
              if(i==sizeofdate-1)                             //如果是最后一个数据
                     rIICCON &= ~0x80;                   //不再响应
              *(buffer+i) = rIICDS;
              rIICCON &= ~0x10;
              while(flag)
                     delay(100);
       }
      
       rIICSTAT = 0x90;         //结束该次通讯
       rIICCON = 0xe0;          //
      
       delay(100);                         
}
 
void Main(void)
{
       ……        ……
//初始化IIC
rIICCON = 0xe0;                        //设置IIC时钟频率,使能应答信号,并开启中断
rIICSTAT = 0x10;
 
pISR_UART0 = (U32)uartISR;
       pISR_IIC = (U32)IicISR;
  
       flag=1;
       comm=0;
 
       while(1)
       {
              switch(comm)               //判断命令
              {
                     case 1:                   //写EEPROM命令
                            wr24c02a(address,iic_buffer,length);
                            comm=0;
                            flag=1;
                            address=0;
                            length=0;
                     break;
                     case 2:                          //读EEPROM命令
                            rd24c02a(address,iic_buffer,length);
                            comm=0;
                            flag=1;
                            address=0;
                            for(i=0;i                             {
                                   delay(500);
                                   rUTXH0 = iic_buffer[i];                                  
                            }    
                            length=0;                     
                     break;
              }
}
}
 
 
       虽然这段程序不是很难,但也花费了我不少的时间,总是出现这样或那样的问题。现在我就把编写上述程序时需要注意的事项总结几点,避免大家少走弯路:
⑴清IIC中断标志语句rIICCON &= ~0x10;一定要在读写寄存器IICDS的后面,不能放到它的前面;
⑵在等待应答的死循环while内,一定要加上延时的程序;
⑶在读取AT24C02A数据时,当读到最后一个数据时,一定不能让s3c2440发送应答信号,否则以后会无法再读取AT24C02A数据,除非关电重启;
⑷在真正对AT24C02A进行读取数据时,在发送带有读命令的从设备地址后,AT24C02A会再返回一个从设备地址信息或从设备内存地址信息作为应答,所以一定要把该字节读取后抛弃,因为它不是我们所要读取的信息;
⑸按照AT24C02A的时序,在发送从设备地址字节时,它的最低位是0表示写,1表示读。但对于s3c2440来说,不用人为设置这一位,即是0是1都无所谓,因为这一位是由s3c2440根据是主设备发送模式还是主设备接收模式来自动设置。
关键字:s3c2440  IIC应用  读写AT24C02A 引用地址:s3c2440的IIC应用——读写AT24C02A

上一篇:s3c2440的A/D转换应用
下一篇:s3c2440实时时钟中断

推荐阅读最新更新时间:2024-03-16 14:55

S3C2440裸机实验(7)----LCD驱动
lcd只要搞清楚了时序其实还是比较简单的,现在LINUX下的LCD驱动如果是像三星的处理器都有很好的支持,只需要修改一些参数就OK了,如果是芯片级的驱动那是比较复杂的,主要是涉及到Framebuffer会让人很抓狂,等完成了裸机的驱动我将会开始写linux的驱动程序编写的文章,请各位网友关注并提出宝贵意见!!! 先来看一下s3c2440中LCD控制器的结构: 从上面结构图可以看出:整个lcd控制器大致可以由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器几个部分组成。 1。REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的 2。LCDCDM
[单片机]
<font color='red'>S3C2440</font>裸机实验(7)----LCD驱动
嵌入式驱动编写之简单驱动Hello_word
开发环境 BootLoader:u-boot-1.1.6 kernel:linux-2.6.30.4 cpu:S3C2440 步骤 1、编写驱动代码 这应该是最简单的一个驱动了,只在内核打印一下信息,代码如下: #include linux/module.h #include linux/kernel.h MODULE_LICENSE( GPL ); static int __init le2440_hello_init(void) { printk( 1 n Hello,changle_2440!n ); printk( 1 nThis is first driver progr
[单片机]
嵌入式驱动编写之简单驱动Hello_word
基于 S3C2440 的嵌入式多媒体控制器设计
根据当今移动终端设备多功能、低功耗、易于移植的要求,分别从硬件和软件系统 2 方面提出了一种基于三星μS3C2440 芯片的嵌入式多媒体娱乐控制器的解决方案,同时介绍了利用 CLinux 构造嵌入式系统的方法,并提出了基于MiniGUI开发多媒体娱乐软件的基本方案。通过测试,系统能够满足用户在文字、音视频处理以及常用有线、无线数据交换等多方面的要求。 由于移动通信技术的高速发展,移动电话早已超出原有的进行语音通信的领域,正逐步成为手持娱乐终端的中心。手机用户希望自己的手机在完成通信基本功能的同时还能作为 PDA、MP3 播放器、数码相机、摄像机、视频播放机等。因此,设计出多功能、低功耗的多媒体终端至关重要。ARM+Linux系统
[单片机]
基于 <font color='red'>S3C2440</font> 的嵌入式多媒体控制器设计
基于IIC1.0的时钟芯片应用程序设计
摘要:在对串行实时时钟芯片X1203内部结构和工作特性作基本介绍的基础上,设计出用单片机的通用I/O口线虚拟I2C总线来实现与时钟芯片的串行接口电路以及利用虚拟I2C总线软件包VIIC设计时钟芯片1203的应用程序。 关键词:单片机 实时时钟 虚拟I2C总线 实时时钟是微机测控系统中的一个重要组成部分。美国Xicor公司推出的串行接口实时时钟芯片X1203提供备用电源输入引脚,使器件能用非可重新充电电池任务用电源。该芯片以其体积小、功耗低、使用简单、接口容易、与单片机连线少为主要特点,同时具有较高的精度,能很好满足微机测控系统的求。下面具体介绍该芯片的内部结构、工作特性、与51系列单片机接口设计实例以及如何利用虚拟I2C总线软件包
[单片机]
S3C2440时钟体系分析
FCLK 时钟用于CPU HCLK时钟用于AHB bus 外设 PCLK 时钟用于 APB bus 外设 S3C2440 有两个锁相环(PLLs), 一个用于FCLK,HCLK,PCLK 另一个专门用于USB 模块 时钟控制逻辑可以在没有PLL的情况下制作慢速时钟,并通过软件将时钟连接/断开与每个外围模块的连接,从而降低了功耗。 通过在片内集成的2个锁相环:MPLL和UPLL,可对输入的Fin=12MHz的晶振频率进行倍频。S3C2440使用了三个倍频因子MDIV、PDIV和SDIV来设置倍频,通过寄存器MPLLCON和UPLLCON可设置倍频因子。其中MPLLCON寄存器用于设置处理器内核时钟主频FCLK,其输入输
[单片机]
<font color='red'>S3C2440</font>时钟体系分析
S3C2440-DMA
[单片机]
STM32的IIC应用详解3
这两天将STM32的IIC按照原子哥的程序,大致走了一遍,多少对IIC不是那么地陌生了,也多少有了自己的一些感悟,在这里,将这两天的学习的一个大致步骤总结下,一来可以让自己形成一个清晰地思路,二来,希望能给一些新手一点启发。 首先IIC是一种通信协议,通信方式相对比较简单,主要有两条线,SDA,SCL。SDA是串行数据线,上面走命令和数据,而SCL只是一条时钟线,其保证数据是按照时钟节拍来进行传输。IIC上面可以外挂很多的IIC芯片,每一个芯片对应着不同的地址,通过地址来将不同的芯片进行分开,保证不同芯片之间的数据传输,由于每一个芯片都是可以独立地收发,故,每一个芯片都是主机/从机。接下来,就是数据的传输过程了, 大致的一个数
[单片机]
STM32的<font color='red'>IIC</font><font color='red'>应用</font>详解3
S3C2440开发板裸机程序系列09—PWM控制舵机
1. Timer1的PWM控制舵机 S3C2440的Timer0、Timer1、Timer2和Timer3具有PWM功能,以前的blog已经叙述过,详见: S3C2440开发板裸机程序系列05—定时器PWM TQ2440开发板的Timer0的TOUT0输出连接了Beep,所以,这次利用Timer1的TOUT1输出来连接舵机的控制信号。 舵机的内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。通过调整控制信号的高电平宽度,即可实现舵机不同转角的控制。 舵机控制原理详见:舵机的原理和控制 程序思路很简单: 设置GPB1为TOUT1的输出格
[单片机]
<font color='red'>S3C2440</font>开发板裸机程序系列09—PWM控制舵机
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多每日新闻
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved