请各位指点下下面这个程序哪里出问题了?是个关于在51单片机上IIC总线AT24C02芯片应用的程序
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SDA=P0^5; //定义数据线
sbit SCL=P0^6; //定义时钟线
code unsigned char duanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0xff}; //共阳数码管段码
uchar const wei_ma[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
uint timec=0;
uchar second;
void delay();//微妙级的延时
void ICC_init();//总线初始化
void start();//开始
void stop();//停止
void test_respons();//检测应答
void write_byte(uchar dat);//写一个字节
uchar read_byte();//读一个字节
void write_onebyte(uchar waddr,uchar wsubaddr,uchar dat);//主机向24C02中写入一字节数据
uchar read_onebyte(uchar raddr,uchar rsubaddr);//主机向24C02中读取一字节数据
void timer_init();//定时器初始化
void display(uchar temp,uchar begin);//数码管显示
void delay()
{
;;
}
void ICC_init()//总线初始化
{
SDA=1;
delay();
SCL=1;
delay();
}
void start()//在时钟信号(SCL)为高电平期间,数据信号(SDA)出现下降沿则为启动信号
{
SDA=1;
delay();
SCL=1;
delay();
SDA=0;
delay();
SCL=0;
}
void stop()//在时钟信号(SCL)为高电平期间,数据信号(SDA)出现上升沿则为启动信号
{
SDA=0;
delay();
SCL=1;
delay();
SDA=1;
delay();
}
/*******************************************
应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉为低电平,表示数据传输正确,产生应答。
*******************************************/
void test_respons()//检测应答
{
uchar i;
SCL=1;
delay();
while((SDA==1)&&(i<250))i++;//应答信号由接收设备产生,不是由单片机设置的,所以(SDA==1)是在SCL为高电平期间判断接收设备是否将SDA拉为低电平
//和(i<250)表示在一段时间内没有收到从期间的应答则主器件默认从器件已经收到数据而不再等待应答信号。
SCL=0;
delay();
}
void write_byte(uchar dat)//写一个字节
{
uchar i,dt;
dt=dat;
for(i=8;i>0;i--)
{
dt=dt<<1;
SCL=0;
delay();
SDA=CY;
delay();
SCL=1;//IIC总线进行数据传输时,时钟信号为高电平期间数据线上的数据必须保持稳定,
//只有当时钟信号为低电平时数据信号(SDA)的高低电平状态才允许变化
delay();
}
SCL=0;//不知为什么要用这句?
delay();
SDA=1;//不知为什么要用这句?
delay();
}
uchar read_byte()//读一个字节
{
uchar i,rdata;
SCL=0;//不知为什么要用这句???
delay();
SDA=1;//不知为什么要用这句???
delay();
for(i=8;i>0;i--)
{
SCL=1;//IIC总线进行数据传输时,时钟信号为高电平期间数据线上的数据必须保持稳定,
//只有当时钟信号为低电平时数据信号(SDA)的高低电平状态才允许变化
delay();
rdata=(rdata<<1)|SDA;
SCL=0;
delay();
}
return (rdata);
}
void write_onebyte(uchar waddr,uchar wsubaddr,uchar dat)//主机向24C02中写入一字节数据
{
start();
write_byte(waddr);
test_respons();
write_byte(wsubaddr);
test_respons();
write_byte(dat);
test_respons();
stop();
}
uchar read_onebyte(uchar raddr,uchar rsubaddr)//主机向24C02中读取一字节数据
{
uchar onedata;
start();
write_byte(raddr);
test_respons();
write_byte(rsubaddr);
test_respons();
start();
write_byte(raddr+1);
test_respons();
onedata=read_byte();
stop();
return (onedata);
}
void timer_init()
{
TMOD=0x02;
TH0=0X47;//定时0.2ms
TL0=0X47;
EA=1;
ET0=1;
TR0=1;
}
void display(uchar temp,uchar begin)
{
P0=0xff;
P1=0x00;
P0=duanma[temp];
P1=wei_ma[begin];
}
void time0() interrupt 1
{
timec++;
}
void main()
{
uchar m,x,begin=0;
ICC_init();
read_onebyte(0xa0,2);
timer_init();
m=second;
while(1)
{
x=m%10;
display(x,begin);
m=m/10;
begin++;
if(m==0)
{
m=second;
begin=0;
}
if(timec==5000)
{
second++;
write_onebyte(0xa0,2,second);
timec=0;
}
}
}
程序是将每隔一秒记一次数的数值写入AT24C02,断电再上电后单片机从AT24C02中将原来写入的数读出来,接着此数继续显示
在开发板上调试数码管能正常显示,但是断电后再次上电后不接着断电前的数据显示,各位大侠帮我看看哪儿出问题了?谢谢!
[解决办法]
main函数进来的时候第一次read_onebyte(0xa0,2);你又没给全局变量赋值
改成
second = read_onebyte(0xa0,2);
[解决办法]
掉电时数据存的是否正确,特别是需要显示哪一个数据。
[解决办法]
会不会是断电后,从新执行main函数时候出问题了。
你试着先判断下24C02,判断是否是前面已经执行过的
a=read_onebyte(0xa0,2);
if(a!=0)
{
}
可以从这方面考虑下
[解决办法]
你试试在main前面多read几次,我以前用一个铁电存储器的时候发现每次第一次read总会出错,后来程序里就连续read两次,取后一次的就可以了
[解决办法]
SCL=0; //不知为什么要用这句???
delay();
SDA=1; //不知为什么要用这句???
-------------------------------------
1)解释一下以上两句的含义:
51系列单片机,当使用SDA线作为输入时,需要先置1; 又因为仅当SCL线为低时,才可以改变SDA,所以先要将SCL置低。
2)在读出数据时,每读1字节数据,CPU给E2PROM一字节应答,读完最后一字节,给个非应答。你的程序不够规范;
3)C语言下,操作CY是不合理的。
[解决办法]
发送数据时候,数据要在时钟信号改变前准备好,数据线要设好数据信号后,再改变时钟信号线,
[解决办法]