51单片机定时器控制led亮2s灭0.5s


#include<reg51.h>
#define uchar unsigned char
uchar cnt=0;
void main()
{
 TMOD=0x01;
 TH0=(65536-50000)/256;
 TL0=(65536-50000)%256;
 TR0=1;
 EA=1;
 ET0=1;
    P1=0x00;
    while(1);
}
void timer0() interrupt 1
{
    TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
    cnt++;
    if(cnt>=40)
    {
        cnt=0;
        P1=~P1;
    }
}

这是我自己敲的。但无法实现效果

  1. 在定时器中断服务函数timer0()中,没有清除中断标志TF0,导致中断服务函数无法正常执行。需要在timer0()函数中添加清除TF0中断标志的代码,例如:TF0=0;
  2. 在定时器中断服务函数timer0()中,计数器cnt的初始化和累加没有进行数据类型强制转换,可能会出现程序逻辑错误,需要在timer0()函数中修改计数器cnt的类型为unsigned int并进行数据类型强制转换,例如:(uchar)(cnt++)。
  3. 在定时器中断服务函数timer0()中,每隔一定时间取反P1口的值的方式不够安全,因为中断服务函数可能在P1端口取反操作尚未完成时再次执行,导致P1端口取反出错。更好的方式应该是使用软件中断方式,保证P1端口取反操作完成后再执行下一次中断服务函数。

改进版代码如下:

#define uchar unsigned charuchar cnt=0;

void main()
{
    TMOD=0x01;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    TR0=1;
    EA=1;
    ET0=1;
    P1=0x00;
    while(1);
}

void timer0() interrupt 1{
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    TF0=0;
    cnt++;
    if(cnt>=40)
    {
        cnt=0;
        P1=~P1;
    }
    while(!P1_0);   //等待P1.0端口取反操作完成}