首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

24C04问题

24C04问题

在使用Atmel公司24C04写程序的时候,首次把程序下载到单片机实验板上,出现乱码,重新下载后,程序显示的结果正常。请问高手如何解决这个问题
请把您的电路图和要实现的功能简单介绍一下  谢谢
电信第一才子

/******根据时间长短显示位数,显示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里面不管怎么自加,都不能满足中断函数里面的判断条件。

至于第二次烧写就能正确显示,我还没想太明白。

欢迎其他网友参与讨论

电信第一才子
版主说的比较好  我在分析一下   关注中
睡觉睡到自然醒,数钱数到手抽筋!
  ▲╭╩═╮╔════╗╔════╗╔════╗╔════╗╔════╗
    ╭╯G O ╠╣支持楼主╠╣正真牛人 ╠╣雁过留声╠╣人过留帖╠╣拿分走人╣
    ╰⊙═⊙╯╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝
相信是个潜力贴  难道没人能解答吗  等待
睡觉睡到自然醒,数钱数到手抽筋!
  ▲╭╩═╮╔════╗╔════╗╔════╗╔════╗╔════╗
    ╭╯G O ╠╣支持楼主╠╣正真牛人 ╠╣雁过留声╠╣人过留帖╠╣拿分走人╣
    ╰⊙═⊙╯╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝

你的那些读存储器的语句应该放到while循环里。

不然你的存储器只是在程序开始的时候被访问,

其他的显示结果都是CPU处理出来的。

理论上你用原来的程序

第一次烧写后不断电,复位一下程序也能显示正确结果

电信第一才子
,IIC存取的初值是0XFF,我想是因为开始的时候下载的是0XFF,所以在数码管上显示会乱的,重新下载的时候,IIC里面已经存取了掉电前的数据,所以就不乱了
看来楼主是自己明白了  呵呵  人才啊
睡觉睡到自然醒,数钱数到手抽筋!
  ▲╭╩═╮╔════╗╔════╗╔════╗╔════╗╔════╗
    ╭╯G O ╠╣支持楼主╠╣正真牛人 ╠╣雁过留声╠╣人过留帖╠╣拿分走人╣
    ╰⊙═⊙╯╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝
[em01][em01]不错 楼主回去试验一下 如果成功 一定要发一篇总结帖
电信第一才子
版主很热情啊  谢谢;
版主的提议很好的,单片机已经不是一个人战斗的时代了,我晚上实验完毕,就把结论告诉大家。
我也期待楼上的结果
睡觉睡到自然醒,数钱数到手抽筋!
  ▲╭╩═╮╔════╗╔════╗╔════╗╔════╗╔════╗
    ╭╯G O ╠╣支持楼主╠╣正真牛人 ╠╣雁过留声╠╣人过留帖╠╣拿分走人╣
    ╰⊙═⊙╯╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝╚◎══◎╝
QUOTE:
以下是引用才子klk在2009-6-23 10:56:00的发言:

您的程序我简单看了一下,是您的读写顺序的问题。

在程序的开始,您就读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里面不管怎么自加,都不能满足中断函数里面的判断条件。

至于第二次烧写就能正确显示,我还没想太明白。

欢迎其他网友参与讨论

QUOTE:
根据斑竹的思路,我 把程序该了下,出了很大的问题:当秒显示到59的时候,分钟会一直的自动加一,秒表保持显示59,况且首次乱码的问题还是存在的。再此也非常感谢斑竹的热心帮助。希望使用过24C04的同仁,分享下解决方案。以下是Keil C Build的结果
QUOTE:
Build target 'Target 1'
compiling 1小时.c...
linking...
*** WARNING L15: MULTIPLE CALL TO SEGMENT
SEGMENT: ?PR?RESPONS?1小时
CALLER1: ?PR?TIME0?1小时
CALLER2: ?C_C51STARTUP
Program Size: data=26.0 xdata=0 code=941
creating hex file from "1小时"...
"1小时" - 0 Error(s), 1 Warning(s).
奇怪的是不管你15行前面加几行注释,警告总是提示在15行,但是这时候的程序已经不是以前的了
QUOTE:

[此贴子已经被作者于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;
}

}
}
}

修改后的程序 如上所示,请参考一下

电信第一才子
返回列表