如上一贴
http://bbs.mydigit.cn/read.php?tid=327041,我以确定时序基本无问题,现在又遇到新问题,代码如下:
// 发送一个字节子程序unsigned char I2C_write_byte(unsigned char indata)
{ unsigned char i, ack=200;
for (i=0; i<8; i++) // I2C 发送8 位数据 {
if (indata & 0x80) // 高在前低在后 SDA = 1;
else SDA = 0;
indata <<= 1; // 发送左移一位 _nop_();_nop_();_nop_();
SCL = 1; _nop_();_nop_();_nop_();
SCL = 0; }
SDA =1; // 设置SDA为输入 _nop_();_nop_();_nop_();
SCL = 1; // 读取从机应答状态 _nop_();_nop_();_nop_();
// if(SDA)// ack = I2C_NACK;// else// ack = I2C_ACK;do{ ack--; SDA =1; // 设置SDA为输入 if((SDA==0)||(ack==0)) break;}while(1); SCL = 0; return ack;
}
多字节读程序:void IIC_ser_read(uchar chip_add,uchar firstadd ,uchar length ,uchar getadd,uchar *aim)
{
I2C_start(); //启动总线
I2C_write_byte(chip_add & 0xfe); //发送器件地址
I2C_write_byte(firstadd); //发送器件子地址
I2C_start(); //启动总线
I2C_write_byte(chip_add | 0x01); //发送器件读地址
length -= 1;
while(length)
{
aim[getadd] = I2C_read_byte(I2C_ACK);
getadd += 1;
length -= 1;
}
aim[getadd] = I2C_read_byte(I2C_NACK);
I2C_stop();
}
//多字节写程序 void IIC_ser_write(uchar chip_add,uchar firstadd,uchar length,uchar sendadd,uchar *aim)
{
I2C_start(); //启动总线
I2C_write_byte(chip_add & 0xfe); //发送器件地址
I2C_write_byte(firstadd); //发送器件子地址
while( length )
{
I2C_write_byte(aim[sendadd]);
sendadd += 1;
length -= 1;
}
I2C_stop();
Delay(10000); //每次写入Eeprom之间至少有5ms延时间隔,否则出现数据紊乱
}
上述多字节读程序无误,已经经过昨天一晚上的检查与验证,但是如下程序段,读能正常读,就是想24c04的110~115单元写数据时候只能写到110、111单元,其他单元写不进去,而按此法连续些112~117单元以及后续的连续单元又能正常读写。后来用如下weeprom()函数往112~115单元连续写入0x55后用多字节读取函数读出来又的确是0x55.实在是头大,因为rda5802的iic接口将会和at24c02公用,而rda又只支持连续读写寄存器不能iic单个读取寄存器,所以,卡在这个问题上了。
void weeprom(uchar chip_add,uchar add, uchar dat)
{
I2C_start(); //启动总线
I2C_write_byte(chip_add & 0xfe); //发送器件地址
I2C_write_byte(add); //发送器件子地址
I2C_write_byte(dat);
I2C_stop();
Delay(8000); //每次写入Eeprom之间至少有5ms延时间隔,否则出现数据紊乱
}
下面是多字节读写函数在整个程序段中出现的情况,关于上一次问题上热心的坛友建议咨询研读iic协议问题,我也检查过了,甚至对从机的应答监测我都用了延时等待与时间溢出的搞法,结果都不理想。
还有一种情况是我程序本来就把at24c04中的存储单元搞混了,但是经过测试,此问题基本不存在。
case 8: //设定指定年、月、日闹钟 20YY-MM-DD HH-MM N
{
if( direct == 0 && i == 0x07 ) // 存储 农历每年一次闹钟
{
……
}
else
{
if(once == 1)
{
if(rom_once == 1)
{
i = get_store_add(4,6);
IIC_ser_read(0xa0,i,6,0,time_1302); rom_once = 0;
}
send(0xf4); // 清屏
disp_chn_string(0x02,0,tips7);
display_alarm();
once = 0;
}
edge = 0x0b;
i = 0x08;
……
if((back_anniversary_arlarm[x_value]==0x06) && (once==1))
rom_once = 1;
}
break;
}
case 9: //系统设置
{
if( direct == 0 && i == 0x08 ) // 存储 指定年月日闹钟
{
i = get_store_add(4,6);
IIC_ser_write(0xa0,i,6,0,time_1302); j = 20 + week % 5;
if((sec & 0x0f)==0)
i = 0;
weeprom(0xa0,j,i);
menu_times = 255;
//BCD_to_12864(0x0a,50,i);
//BCD_to_12864(0x0c,50,time_1302[4]);
//i=reeprom(0xa0,114);
//BCD_to_12864(0x0e,50,i);
//
//weeprom(0xa0,112,0x55);
//BCD_to_12864(0x10,50,time_1302[2]);
//i=reeprom(0xa0,112);
//BCD_to_12864(0x12,50,i);
}
[ 此帖被younges在2011-10-31 22:36重新编辑 ]