郭天祥教程的练习题,三个独立键盘实现按下第一个时计时停止,按下第二个时计时开始,按下第三个是计数值清零从头开始。这是我自己编的程序,可以正常实现功能。但是我在自己调试程序排错的时候,想到了中断的概念。比如这里按key3键是计数值从0开始显示,我在想如果定时器中断时间到,刚好在bb=0;bai=bb/100;shi=bb%100/10;ge=bb%10;这几句话后面进入中断程序(程序中用红 {MOD}标出了),进入中断后,bb被加到1,中断程序执行完回到主程序,此时个,十,百位分别是1,0,0,这样不是和我们程序的要求不一致了么(程序要求复位从0开始计时)。但是我把程序下载到板子上面没有出现按key3是1的情况,都是符合题目要求的0。请前辈指点,我的概念哪里出错了?
#include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
sbit key2=P3^5;
sbit key3=P3^6;
sbit key4=P3^7;
unsigned char aa,ge,shi,bai;
unsigned int bb;
void init();
void display(unsigned char,unsigned char,unsigned char);
void delay(unsigned int);
unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void main()
{
init();
while(1)
{
if(key1==0)
{
delay(5);
if(key1==0)
{
TR0=0;
}
}
if(key2==0)
{
if(key2==0)
{
TR0=1;
}
}
if(key3==0)
{
bb=0;
bai=bb/100;
shi=bb%100/10;
ge=bb%10;
//如果在这句话后,定时器中断定的时间到,进入定时器中断,那么bb被加1,个位被刷新为1,此时这个复位键复位到的是1??那么数码管也显示1?和要求不符,但实际下载程序到板子上的结果却是每次按这个键下去都是复位到0. if(key1==1){TR0=1;}
}
display(bai,shi,ge);
}
}
void init() //初始化函数
{ wela=1;
P0=0xff;
wela=0;
dula=1;
P0=0x00;
dula=0;
aa=0;
bb=0;
P3=0xff;
TMOD=0x01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
}
void timer0() interrupt 1 //定时器0中断
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
aa++;
if(aa==1)
{
aa=0;
bb++;
}
bai=bb/100;
shi=bb%100/10;
ge=bb%10;
if(bb==999)
{
bb=0;
}
}
void display(unsigned char one,unsigned char two,unsigned char three) //显示函数
{
dula=1;
P0=table[one];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
wela=0;
delay(1);
dula=1;
P0=table[two];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay(1);
dula=1;
P0=table[three];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;
wela=0;
delay(1);
}
void delay(unsigned int z) //延时程序
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
此帖出自
小平头技术问答
概述:一个掉电计数数据保存的程序,第一次上电初值为00,(计数值++,加至99归0),以后每次断电再次上电后,能接着断电前的计数值继续计数。
学长,这两天我学习了IIC总线存储器EEPROM的读写方法,视频教程老师说了一道题,要求实现掉电计数保持功能,即用定时器计数,每次数字改变都将变化的数字存入EEPROM,这样即使掉电了,再次上电立即读取EEPROM里面的值,可以在上次计数值的基础上继续往上加。
我编的程序是在主函数里面写了一个利用IIC总线读写EEPROM的程序,这样可以完成掉电保持,但是如果是这样,当我第一次启动程序时(此时从未对EEPROM相应的存储地址里写过值),应该是一个随机值,或者是根据说明书全1或者全0,我想把第一次程序启动时的值固定为00,但是想不出有什么办法。考虑了两种情况:
1.如果在主函数里面初始化令计数初值为0的话,掉电后上电,就不能读出上次的值了,不能完成功能。
2.如果计数初值赋0后,再读EEPROM里存的值,那么赋值的0被覆盖,毫无意义。。。
想了好久现在还没有想出有什么办法可以解决,求学长指点=。=
[ 本帖最后由 qrswll 于 2012-4-17 16:06 编辑 ]第一次我没办法,但第二次我有办法。
上电之初,不要直接在程序里把该单元清零。
在程序运行时,做一个子函数,当某个按键或者遇到什么条件时,就把该单元清零,从此,它就是零了。
这样以后,它就是0了,以后重上电既不会变成随机数,而是保持在上一次的数值里。
那个清零的操作,可以作为一个系统人工初始设置动作来完成。
这是我最近项目里的操作手法,不知道是否符合你的意图。
换句话来说,你想通过程序来实现的话,我突然想到的一个方法是:
在最开始写一段代码。
开辟多一个EEPROM里的单元,在你第一次初始化这个值为零以后,同时把这个值设置为一个很特别很特别的数值,就是说,非0非0xff,非任何可能的随机数——说是随机,一般来说,都是有一定规律的吧?
写一个特别点的数的话,就很难碰到巧合了——这里说的特别,说的是 二进制上0和1的排列,诸如什么0x55,0xaa之类的。
然后,以后你就判断,如果这个单元是这个你设置的值,那你就不会再去进行这个清零。否则就会清零。
我写个代码简单示意一下,关于eeprom的读写操作我不知道具体如何操作,我只写个示意的
U8 ClearFlag; //我说的那个标志
U8 Counter; //你想要的那个计数器
if(ClearFlag != 0x55)
{
Counter = 0;
ClearFlag = 0x55;
/*
Operation on write Counter & ClearFlag into EEPROM
*/
}
[ 本帖最后由 辛昕 于 2012-4-19 02:05 编辑 ]
几次都不对劲,我再发一次
[ 本帖最后由 辛昕 于 2012-4-19 02:07 编辑 ]
U8 Counter; //你想要的那个计数器
/* Operation on read out ClearFlag from EEPROM */
if(ClearFlag != 0x55)
{
Counter = 0;
ClearFlag = 0x55;
/* Operation on write Counter & ClearFlag into EEPROM */
}
else
/* Operation on read out Counter from EEPROM */
在实际应用中,可以设一个按键,按下时将计数值清零,是很不错的选择。如果需要在第一次上电就为0,再按一下清零键就好了。
学长后面想到的方法是一种低概率出错的方法,这里是8位存储数据,那么出错的概率就是1/256,在调试程序的时候,我每次都要把判断的标志位的值改一下,因为是存在EEPROM中的,所以上一次写入的值被保存在了同一个存储空间,想在下一次中调试就跳过了00初值的赋值了=。=(实际上觉得换个地址存也可以~)。刚开始的时候遇到好多问题,一开始是IIC总线读和写的时候,总是得不到想要的效果,我估计是程序执行得太快了,造成时序冲突,于是在两次写之间加了一个delay(10),想要的效果出来了,上电第一次会有初值,后面断电后,在原基础累加。
但是还是有些瑕疵,就是第一次上电的时候先是显示一个乱码,然后才跳成00。这我就不太懂了,调试了好多次,误打误撞把这个错误解决了,就是在解决之后我到现在都没明白是为什么。。。我在程序中用定时器中断进行计时,定时器中装入10ms,取变量aa==100的时候,得到1S的定时,完成两位数的数码管时间显示。其中有一句话是
if(num==100){num=0;}我把判断条件变成if(num>=100){num=0;},一开始的乱码就没有了。我估计是一开始还是读了EEPROM存储器里面的值。。。num设定的是unsigned char类型的。num通过num/10和num%10分别得到个位和十位显示的值。这是我的第一个疑问=。=
第二个疑问是这样发现的:在我基本实现了功能要求后,多次尝试修改标志位的值,但是发现了一个BUG.......在我设标志位为0x96和0x94的时候,断电再上电后计数的值并没有按照递增的顺序,而是从23开始往上加,无论当前计数值是多少,断电再上电都是23........不知道是什么原因
求学长指点 估计三言两语也说不清=。=代码贴在楼下~
[ 本帖最后由 qrswll 于 2012-4-20 08:33 编辑 ]一周热门 更多>