郭天祥教程的练习题,三个独立键盘实现按下第一个时计时停止,按下第二个时计时开始,按下第三个是计数值清零从头开始。这是我自己编的程序,可以正常实现功能。但是我在自己调试程序排错的时候,想到了中断的概念。比如这里按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--);
}
此帖出自
小平头技术问答
- #include<reg52.h>
复制代码 [ 本帖最后由 qrswll 于 2012-4-20 10:10 编辑 ]sbit dula=P2^6; //数码管段选
sbit wela=P2^7; //数码位选选
sbit SDA=P2^0; //IIC数据线
sbit SCL=P2^1; //IIC时钟线
unsigned char aa,bb,shi,ge,flag,num1;
//-------数码管数字显示表----//
unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
//------uS级延时函数----//
void delay()
{;;}
//-----mS级延时函数----//
void delay1(unsigned char x)
{
unsigned char a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
//--------IIC总线函数----//
void start() //IIC总线起始
{
SDA=1;
delay();
SCL=1;
delay();
SDA=0;
delay();
}
void writebyte(unsigned char writedata) //IIC写字节
{
unsigned char temp,i;
temp=writedata;
for(i=0;i<8;i++)
{
SCL=0;
delay();
temp=temp<<1;
SDA=CY;
delay();
SCL=1;
delay();
}
SCL=0;
delay();
SDA=1;
delay();
}
unsigned char readbyte() //IIC读字节
{
unsigned char i,j;
for(i=0;i<8;i++)
{
SCL=0;
delay();
j=(j<<1)|SDA;
delay();
SCL=1;
delay();
}
return j;
}
void ACK() //IIC应答
{
unsigned char i;
SCL=0;
delay();
if(SDA==1&&i<250)
{
i++;
}
SCL=1;
delay();
SCL=0;
delay();
}
void stop() //IIC总线结束
{
SDA=0;
delay();
SCL=1;
delay();
SDA=1;
}
//-------数码管显示函数--------//
void display(unsigned char one,unsigned char two)
{
if(bb==1)
{
P0=0x00; //消隐
dula=1;
P0=table[one];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
wela=0;
}
if (bb==2)
{
dula=1;
P0=table[two];
dula=0;
P=0xff;
wela=1;
P0=0xfd;
wela=0;
bb=0;
}
}
//---------初始化函数----------//
void init()
{
TMOD=0x11; //开定时器0和1
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
EA=1;
ET0=1;
ET1=1;
TR0=1;
TR1=1;
start(); //读EEPROM的0x03地址空间,即标志位的值存放的空间
writebyte(0xa0);
ACK();
writebyte(0x03);
ACK();
start();
writebyte(0xa1);
ACK();
flag=readbyte();
stop();
if(flag!=0x99) //标志位flag,判断,如果是第一次上电,给0x08地址初始化值0x00;疑问发源地2。
{
start();
writebyte(0xa0);
ACK();
writebyte(0x08);
ACK();
writebyte(0x00);
ACK();
stop();
delay1(10);
start(); //同时给标志位flag赋值=判断的值,防止下次上电再初始化00.
writebyte(0xa0);
ACK();
writebyte(0x03);
ACK();
writebyte(0x99); //标志位的判断换成0x96,0x94之类的都会有BUG,重新上电后总是从23开始计数
ACK();
stop();
}
start(); //如果不是第一次上电,则读取0x08里面的值num1(0x08是真正数据存储地址,不是标志位地址)
writebyte(0xa0);
ACK();
writebyte(0x08);
ACK();
start();
writebyte(0xa1);
ACK();
num1=readbyte();
stop();
}
//-----主函数--------//
void main()
{
init();
while(1)
{
start(); //每执行一次while循环都把计数值num1写入0x08地址中,方便重新上电后读取,继续计数。
writebyte(0xa0);
ACK();
writebyte(0x08);
ACK();
writebyte(num1);
ACK();
stop();
shi=num1/10; //两位数码管十位个位值的计算
ge=num1%10;
display(shi,ge);
}
}
//-----定时器0中断,负责计数值加加以及清零-----//
void timer0 () interrupt 1
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
aa++;
if(aa==100)
{
aa=0;
num1++;
}
if(num1>=100) //疑问发源地1。。。
{
num1=0;
}
}
//-----定时器1中断,负责数码管现实中需要的延时,满足视觉暂留------//
void timer1 () interrupt 3
{
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
bb++;
}
一周热门 更多>