址的地址寄存器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个字节。
下面是用FL2440开发板的程序分析:
#include
#include "2440addr.h"
#include "def.h"
#include "IIC.h"
static U8 _iicData[IICBUFSIZE];
static volatile int _iicDataCount;//发送计数标志
static volatile int _iicStatus;//IIC状态标志
static volatile int _iicMode;//IIC模式标志
static int _iicPt;
extern void Uart_Printf(char *fmt,...);
extern void Uart_Init(int baud);
void Delay(int x);
//===================================================================
//SMDK2440 IIC configuration
//GPE15=IICSDA, GPE14=IICSCL
//"Interrupt mode" for IIC block
//===================================================================
//******************[ Test_Iic ]**************************************
void Test_Iic(void)
{
unsigned int i,j,save_E,save_PE;
static U8 data[512];//256
//Uart_Init(115200);
Uart_Printf("nIIC Test(Interrupt) using AT24C02n");
save_E= rGPECON;
save_PE= rGPEUP;
rGPEUP|= 0xc000;//Pull-up disable
rGPECON &=0xfffffff;
rGPECON |= 0xa0000000;//GPE15:IICSDA , GPE14:IICSCL