今天帮人调试了下AT24C02的程序,最终可以成功写入和读取,但是问题是读取的数值总是比关掉电源时的数值小2,而且在0~9这段期间不能成功写入,初始化都为9,例如在数值为3时断掉电源,假若成功保存,应该在重新开启电源时读取数值3,但结果显示的却是9。求大侠解释,谢谢~!个人怀疑是程序中的延时导致的。
以下是程序:
#include<reg51.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define PCF8591 0x90
#define AT24C02 0xa0
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
uchar code tablewe[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F};
uchar AD_CHANNEL;
sbit sda=P2^0;
sbit scl=P2^1;
bit ack; //应答检验位
bit flag;
int dis[8],D[5],k;
char temp[];
char *p;
int num=0;
sbit led=P2^7;
void delay() //延时 5us
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void delay_1ms(uchar i)
{
uchar j;
while(i--)
for(j=0;j<110;j++);
}
void start()
{
sda=1; //大于4.7us
delay();
scl=1;
delay();
sda=0; //大于4us
delay();
scl=0;
_nop_();
_nop_();
}
void stop()
{
scl=0;
_nop_();
_nop_();
sda=0;
_nop_();
_nop_();
scl=1;
delay(); // 大于4us
sda=1;
delay(); // 大于4.7us
}
void response(uchar a)
{
if(a==0) //在此发出应答或非应答信号 sda=0为应答 sda=1为非应答
sda=0;
else
sda=1;
delay();
scl=0;
_nop_();
_nop_();
scl=1; //延时大于4us
delay();
scl=0;
_nop_();
_nop_();
}
void write_byte(uchar sdadata)
{
uchar j;
for(j=0;j<8;j++)
{
sdadata=sdadata<<1;
scl=0;
delay(); // 允许数据线电平变化
sda=CY; //将PSW最高位MSB 送走
delay();
scl=1; //拉高时钟线 数据有效
delay();
}
scl=0;
_nop_();
_nop_();
sda=1;
delay();// 释放总线,接受应答信号
scl=1;
delay();
if(sda==1)
ack=0;
else
ack=1;
scl=0; //钳住I2C总线,允许应答时 。SDA发生电平变化
_nop_();
_nop_();
}
uchar read_byte()
{
uchar m,data_read;
data_read=0;
sda=1;
for(m=0;m<8;m++)
{
scl=0;
delay(); // 在这5us里,发送数据
scl=1;
delay();
data_read=(data_read<<1)|sda;
}
scl=0;
delay();
return data_read;
}
char send(uchar qijian_address,uchar suba,uchar *data1,uchar no) // 发函数 no为字节数
{
uchar i;
start();
write_byte(qijian_address);
if(ack==0)
return(0);
write_byte(suba); //suba为器件内部储存单元地址
if(ack==0)
return(0);
for(i=0;i<no;i++) //页方式输入
{
write_byte(*data1);
if(ack==0)
return(0);
data1++;
}
stop();
return(1);
}
uchar receive(uchar qijian_address,uchar address,uchar no) //
{
uchar *data2,i;
start();
write_byte(qijian_address); //指定器件接收
if(ack==0)
return(0);
write_byte(address); //指定器件储存单元地址
if(ack==0)
return(0);
start();
write_byte(qijian_address+1);
if(ack==0)
return(0);
for(i=0;i<no-1;i++) //页方式输入 每页8个字节 详情请百度页地址空间的“上卷”现象
{ //解决上卷现象的方法
*data2=read_byte();
response(0);
data2++;
}
*data2=read_byte(); //第8个字节后要用非应答而不能应答 所以上面的循环只循环7次
response(1); //发送非应答
stop(); //关闭总线
return data2;
}
void init() //初始化 释放总线
{
scl=1;
delay();
sda=1;
delay(); // init
}
/*bit DACconversion(unsigned char address,unsigned char c,unsigned char Val)
{
start(); //启动总线
write_byte(address); //发送器件地址
if(ack==0)
return(0);
write_byte(c); //发送控制字节
if(ack==0)
return(0);
write_byte(Val); //发送DAC的数值
if(ack==0)
return(0);
stop(); //结束总线
return(1);
}*/
void dispaly(int number)
{
int i;
dis[0]=table[number%10000/1000];
dis[1]=table[number%1000/100]|0x80;
dis[2]=table[number%100/10];
dis[3]=table[number%10];
dis[4]=table[number%10000/1000]; //千位
dis[5]=table[number%1000/100]|0x80; //百位带小数点
dis[6]=table[number%100/10]; //十位
dis[7]=table[number%10]; //个位
for(i=0;i<8;i++)
{
P0=dis;
P1=tablewe;
delay_1ms(1);
}
}
void main()
{
delay_1ms(1);
init();
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
num=receive(AT24C02,4,8);
while(1)
{
dispaly(num);
if(flag==1)
{
*p=num;
send(AT24C02,4,p,8);
flag=0;
}
}
}
void time()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
k++;
if(k==20)
{
k=0;
num++;
if(num==100)
num=0;
flag=1;
}
}
同样的问题也出现我项目中, 是用2402保存程序需要数据,客户说出现数据烧录不正确的情况,后来和芯片原厂进行沟通,他们提出修改烧写方法,结果问题得到解决,但是仿真时候会出错,实际测试OK,具体原因正在分析中!希望该答案对你有帮助,下面为具体解决办法,以后有问题多交流,我QQ260568227
1、目前每写一个数据是16Bit,改成每次只写8Bit有效数据,另一个8Bit用FFH替代;
如:待写数据是
2、每写一个16Bit数据后,需延时20ms。