s3c2440的IIC应用——读写AT24C02A
时间:11-19
来源:互联网
点击:
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根据是主设备发送模式还是主设备接收模式来自动设置。
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根据是主设备发送模式还是主设备接收模式来自动设置。
s3c2440IIC应用读写AT24C02 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)