/******根据时间长短显示位数,显示1小时**
************带有小数点标识符*************
**********首次上电会乱码*****************
**********注释2009-06-16 17:42**********/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit sda=P3^3; // 定义sda
sbit scl=P3^2; // 定义scl
sbit dula=P2^4; // 数码管段选
sbit wela=P2^3; // 数码管位选
uchar num,sec,min,hour;// num为250ms的次数,sec为秒, min为分钟, hour为小时
uint ms;//毫秒数值大于256
uint secsum;// 总秒数
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e,0xff}; //0到F编码,共阳,0xff数码管不显示任何数
uchar code tabledot[]={
0x40,0x79,0x24,0x30,
0x19,0x12,0x02,0x78,0x00,
0x10,0xff}; //0到9带小数点,0xff数码管不显示任何数
void delay()//延时大概几个机器周期
{ ;; }
void delay1ms(uint z)//延时毫秒级
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void start() //开始信号
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop() //停止
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void respons() //应答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<255))i++;
scl=0;
delay();
}
void init()//I2C初始化
{
sda=1;
delay();
scl=1;
delay();
}
void write_byte(uchar date)//写一个字节
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay();
sda=CY;
delay();
scl=1;
delay();
}
scl=0;
delay();
sda=1;
delay();
}
uchar read_byte()//读一个字节
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
return k;
}
void write_add(uchar address,uchar date)//指定地址写一个字节
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar address) //指定地址读一个字节
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;
}
void display(uchar mins,uchar ming,uchar secs,uchar secg)//数码管显示时间
{
wela=1;//开数码管位选
P0=0x08; //送位选
delay1ms(5);
wela=0; //锁存
dula=1;
P1=table[mins]; //送段码
delay1ms(5);
dula=0; //锁存
wela=1;
P0=0x04;
delay1ms(5);
wela=0;
dula=1;
P1=tabledot[ming]; //送带小数点段码
delay1ms(5);
dula=0; //锁存
wela=1;//开数码管位选
P0=0x02; //送位选
delay1ms(5);
wela=0; //锁存
dula=1;
P1=table[secs]; //送段码
delay1ms(5);
dula=0; //锁存
wela=1;//开数码管位选
P0=0x01; //送位选
delay1ms(5);
wela=0; //锁存
dula=1;
P1=table[secs]; //送段码
delay1ms(5);
dula=0; //锁存
}
void main()
{ init();//I2C初始化
min=read_add(130); //读分钟数据
if(min>60) min=0;
sec=read_add(131);//读秒数据
if(sec>60) sec=0;
TMOD=0x02;//定时器0方式2
TH0=6; //赋初值,自动重装
TL0=6;
TCON=0x10; //开TR0
IE=0x82; //开EA,ET0
delay1ms(1000);
while(1)
{
secsum=sec+min*60;//计算总时间,单位是秒
if(secsum<10) //几秒,只显示最后一位
display(16,10,16,sec);
else
{ if(secsum<60)//几十秒,只显示最后两位
display(16,10,sec/10,sec%10);
else
{ if(secsum<600)//几分钟,只显示最后三位
display(16,min,sec/10,sec%10);
else
{ //if(secsum<3600)//十几分钟,前两位不显示
display(min/10,min%10,sec/10,sec%10);
}
}
}
}
}
void time0() interrupt 1
{ num++;//自动重装
if(num==4)//1ms
{ num=0;
ms++;
if(ms==1000)//1s
{ ms=0;
sec++;
if(sec==60)//1分钟
{ sec=0;
min++;
if(min==60)//1小时
{ min=0;
}
write_add(130,min);//在地址130写分钟数据
}
write_add(131,sec);//在地址131写秒表地址
}
}
}
[此贴子已经被作者于2009-6-22 21:21:03编辑过]
您的程序我简单看了一下,是您的读写顺序的问题。
在程序的开始,您就读IIC里面的数据。但这时IIC器件里面还没有数据。所以开始显示的是乱码。
还有一个地方有问题就是中断处理函数里面
void time0() interrupt 1
{ num++;//自动重装
if(num==4)//1ms
{ num=0;
ms++;
if(ms==1000)//1s
{ ms=0;
sec++;
if(sec==60)//1分钟
{ sec=0;
min++;
if(min==60)//1小时
{ min=0;
}
write_add(130,min);//在地址130写分钟数据
}
write_add(131,sec);//在地址131写秒表地址
}
}
}
这个函数里面的if语句最好都改成">="
因为24C02存储器最初的状态是随机的,很大的几率比你所判断的数值大 所以在while里面不管怎么自加,都不能满足中断函数里面的判断条件。
至于第二次烧写就能正确显示,我还没想太明白。
欢迎其他网友参与讨论
你的那些读存储器的语句应该放到while循环里。
不然你的存储器只是在程序开始的时候被访问,
其他的显示结果都是CPU处理出来的。
理论上你用原来的程序
第一次烧写后不断电,复位一下程序也能显示正确结果
您的程序我简单看了一下,是您的读写顺序的问题。
在程序的开始,您就读IIC里面的数据。但这时IIC器件里面还没有数据。所以开始显示的是乱码。
还有一个地方有问题就是中断处理函数里面
void time0() interrupt 1
{ num++;//自动重装
if(num==4)//1ms
{ num=0;
ms++;
if(ms==1000)//1s
{ ms=0;
sec++;
if(sec==60)//1分钟
{ sec=0;
min++;
if(min==60)//1小时
{ min=0;
}
write_add(130,min);//在地址130写分钟数据
}
write_add(131,sec);//在地址131写秒表地址
}
}
}
这个函数里面的if语句最好都改成">="
因为24C02存储器最初的状态是随机的,很大的几率比你所判断的数值大 所以在while里面不管怎么自加,都不能满足中断函数里面的判断条件。
至于第二次烧写就能正确显示,我还没想太明白。
欢迎其他网友参与讨论
[此贴子已经被作者于2009-6-23 21:05:47编辑过]
/******根据时间长短显示位数,显示1小时**
************带有小数点标识符*************
**********首次上电会乱码*****************
**********注释2009-06-16 17:42**********/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit sda=P3^3; // 定义sda
sbit scl=P3^2; // 定义scl
sbit dula=P2^4; // 数码管段选
sbit wela=P2^3; // 数码管位选
uchar num = 0,sec = 0,min = 0,hour = 0;// num为250ms的次数,sec为秒, min为分钟, hour为小时
uint ms;//毫秒数值大于256
uchar sec_temp,min_temp;
uint secsum;// 总秒数
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e,0xff}; //0到F编码,共阳,0xff数码管不显示任何数
uchar code tabledot[]={
0x40,0x79,0x24,0x30,
0x19,0x12,0x02,0x78,0x00,
0x10,0xff}; //0到9带小数点,0xff数码管不显示任何数
void delay()//延时大概几个机器周期
{
;
;
}
void delay1ms(uint z)//延时毫秒级
{
uint x,y;
for(x=z;x>0;x--)
{
for(y=110;y>0;y--);
}
}
void start() //开始信号
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop() //停止
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void respons() //应答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<255))
{
i++;
}
scl=0;
delay();
}
void init()//I2C初始化
{
sda=1;
delay();
scl=1;
delay();
}
void write_byte(uchar date)//写一个字节
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay();
sda=CY;
delay();
scl=1;
delay();
}
scl=0;
delay();
sda=1;
delay();
}
uchar read_byte()//读一个字节
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
return k;
}
void write_add(uchar address,uchar date)//指定地址写一个字节
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar address) //指定地址读一个字节
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;
}
void display(uchar mins,uchar ming,uchar secs,uchar secg)//数码管显示时间
{
wela=1;
dula=1;
P0=0x08; //送位选
P1=table[mins]; //送段码
dula=0; //锁存
wela=0;
delay1ms(5);
wela=1;
dula=1;
P0=0x04;
P1=tabledot[ming]; //送带小数点段码
dula=0; //锁存
wela=0;
delay1ms(5);
wela=1;
dula=1;
P0=0x02; //送位选
P1=table[secs]; //送段码
dula=0; //锁存
wela=0;
delay1ms(5);
wela=1;
dula=1;
P0=0x01; //送位选
P1=table[secg]; //送段码 *******此处修改为secg
dula=0; //锁存
wela=0;
delay1ms(5);
}
void main()
{
init();//I2C初始化
TMOD=0x02;//定时器0方式2
TH0=6; //赋初值,自动重装
TL0=6;
TCON=0x10; //开TR0
IE=0x82; //开EA,ET0
min=read_add(130); //读分钟数据
sec=read_add(131);//读秒数据
if(min >= 60)
{
min = 0;
}
if(sec >= 60)
{
sec = 0;
}
while(1)
{
secsum=sec+min*60;//计算总时间,单位是秒
if(secsum<10) //几秒,只显示最后一位
{
display(16,10,16,sec);
}
else
{
if(secsum<60)//几十秒,只显示最后两位
{
display(16,10,sec/10,sec%10);
}
else
{
if(secsum<600)//几分钟,只显示最后三位
{
display(16,min,sec/10,sec%10);
}
else
{ //if(secsum<3600)//十几分钟,前两位不显示
display(min/10,min%10,sec/10,sec%10);
}
}
}
}
}
void time0() interrupt 1
{
num++;//自动重装
if(num >= 4)//1ms
{
num=0;
ms++;
if(ms >= 1000)//1s
{
ms=0;
sec++;
if(sec >= 60)
{
sec = 0;
min++;
}
write_add(131,sec);//在地址131写秒表地址
write_add(130,min);//在地址130写分钟数据
if(min >= 60)//1小时
{
min=0;
}
}
}
}
修改后的程序 如上所示,请参考一下
SIcz2yQQ.rar (54.87 KB)
这是修改后的keil工程 和 proteus文件
2404又不是ram掉电不会丢失数据的
分析下来是你系统设计的思路问题
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |