[51单片机] 定时器的应用

[复制链接]
1706|18
 楼主| 夏盼 发表于 2014-11-5 22:46 | 显示全部楼层 |阅读模式
我的程序想实现让8个二极管依次以200ms的间隔连续闪烁5次,但是实际运行时发现有问题,请指教
  1. #include"reg51.h"
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit led1=P1^0;
  5. sbit led2=P1^1;
  6. sbit led3=P1^2;
  7. sbit led4=P1^3;
  8. sbit led5=P1^4;
  9. sbit led6=P1^5;
  10. sbit led7=P1^6;
  11. sbit led8=P1^7;
  12. uchar num1;
  13. void main()
  14. {
  15.         TMOD=0x01;
  16.         TH0=(65536-45872)/256;
  17.         TL0=(65536-45872)%256;
  18.         EA=1;
  19.         ET0=1;
  20.         TR0=1;
  21.         led1=1;
  22.         led2=1;
  23.         led3=1;
  24.         led4=1;
  25.         led5=1;
  26.         led6=1;
  27.         led7=1;
  28.         led8=1;
  29.         while(1)
  30.         {
  31.                 if((num1==4)||(num1==8)||(num1==12)||(num1==16)||(num1==20))
  32.                 {
  33.                         led1=~led1;
  34.                 }
  35.                 if((num1==24)||(num1==28)||(num1==32)||(num1==36)||(num1==40))
  36.                 {        led1=1;
  37.                         led2=~led2;
  38.                 }
  39.                 if((num1==44)||(num1==48)||(num1==52)||(num1==56)||(num1==60))
  40.                 {        led2=1;
  41.                         led3=~led3;
  42.                 }
  43.                 if((num1==64)||(num1==68)||(num1==72)||(num1==76)||(num1==80))
  44.                 {        led3=1;
  45.                         led4=~led4;
  46.                 }
  47.                 if((num1==84)||(num1==88)||(num1==92)||(num1==96)||(num1==100))
  48.                 {        led4=1;
  49.                         led5=~led5;
  50.                 }
  51.                 if((num1==104)||(num1==108)||(num1==112)||(num1==116)||(num1==120))
  52.                 {        led5=1;
  53.                         led6=~led6;
  54.                 }
  55.                 if((num1==124)||(num1==128)||(num1==132)||(num1==136)||(num1==140))
  56.                 {        led6=1;
  57.                         led7=~led7;
  58.                 }
  59.                 if((num1==144)||(num1==148)||(num1==152)||(num1==156))
  60.                 {        led7=1;
  61.                         led8=~led8;
  62.                 }                 
  63.                 if(num1==160)
  64.                 {       
  65.                         led8=~led8;
  66.                         led8=1;
  67.                         num1=0;
  68.                 }       
  69.         }       
  70.         }
  71. void T0_time()interrupt 1
  72.         {
  73.                 TH0=(65536-45872)/256;
  74.                 TL0=(65536-45872)%256;
  75.                 num1++;       
  76.         }


wangch_sh 发表于 2014-11-6 08:16 | 显示全部楼层
有什么问题?
ayb_ice 发表于 2014-11-6 08:25 | 显示全部楼层
本帖最后由 ayb_ice 于 2014-11-6 08:27 编辑

你这个错误关键在num1的处理上,这个变量在不停的被中断累加,在主循环的一次循环处理中可能值会发生变化,导致错误,
你这个程序还有明显不合理的地方,加个else合理些,会大大提高效率
if((num1==4)||(num1==8)||(num1==12)||(num1==16)||(num1==20))
{
     led1=~led1;
}else
但仍然会有问题


typedef unsigned char U8;

#define BIT0        (1<<0)
#define BIT1        (1<<1)

#define LED0_7        P1

sbit LED0 = P1^0;

bit flag_200ms;

#define ms        /50

void main(void)
{
        U8 stage = 0;

        init()

        while(1)
        {
                if(flag_200ms){
                        flag_200ms = 0;
                        stage++;
                        if(stage >= 8){
                                stage = 0;
                        }

                        switch(stage){
                        default:
                        case 0:
                                LED0 = (LED0_7 & BIT0) ^ BIT0;
                                break;

                        case 1:
                                LED1 = (LED0_7 & BIT1) ^ BIT1;
                                break;

                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                                ......
                                break
                        }
                }
        }

}


void T0_time()interrupt 1
{
        TH0=(65536-45872)/256;
        TL0=(65536-45872)%256;
        num1++;

        {
                static U8 c = 0;

                if(++c >= 200ms){
                        c = 0;
                        flag_200ms = 1;
                }
        }
}




 楼主| 夏盼 发表于 2014-11-6 13:03 | 显示全部楼层
wangch_sh 发表于 2014-11-6 08:16
有什么问题?

所有的灯都会闪
 楼主| 夏盼 发表于 2014-11-6 13:17 | 显示全部楼层
ayb_ice 发表于 2014-11-6 08:25
你这个错误关键在num1的处理上,这个变量在不停的被中断累加,在主循环的一次循环处理中可能值会发生变化, ...

虽然现在我还没有发现问题出在什么地方,但是我认为应该不是出在num1上,下面我这程序也是用的num++,运行就很正确
  1. #include"reg51.h"
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit led1=P1^0;
  5. sbit led2=P1^1;
  6. sbit led3=P1^2;
  7. sbit led4=P1^3;
  8. sbit led5=P1^4;
  9. sbit led6=P1^5;
  10. sbit led7=P1^6;
  11. sbit led8=P1^7;
  12. uchar num1,num2;
  13. void main()
  14. {
  15.         TMOD=0x01;
  16.         TH0=(65536-45872)/256;
  17.         TL0=(65536-45872)%256;
  18.         EA=1;
  19.         ET0=1;
  20.         TR0=1;
  21.         while(1)
  22.         {
  23.         switch(num1)
  24.         {
  25.                 case 0:
  26.                 while(num1<=20)
  27.                 {
  28.                         if(num2==4)
  29.                         {
  30.                                 num2=0;
  31.                                 led1=~led1;
  32.                         }       
  33.                 }
  34.                 case 20:
  35.                         while(num1<=40)
  36.                 {
  37.                         if(num2==4)
  38.                         {        led1=1;
  39.                                 num2=0;
  40.                                 led2=~led2;
  41.                         }       
  42.                 }
  43.                 case 40:
  44.                         while(num1<=60)
  45.                 {
  46.                         if(num2==4)
  47.                         {        led2=1;
  48.                                 num2=0;
  49.                                 led3=~led3;
  50.                         }       
  51.                 }
  52.                 case 60:
  53.                         while(num1<=80)
  54.                 {
  55.                         if(num2==4)
  56.                         {        led3=1;
  57.                                 num2=0;
  58.                                 led4=~led4;
  59.                         }       
  60.                 }
  61.                 case 80:
  62.                         while(num1<=100)
  63.                 {
  64.                         if(num2==4)
  65.                         {        led4=1;
  66.                                 num2=0;
  67.                                 led5=~led5;
  68.                         }       
  69.                 }
  70.                 case 100:
  71.                         while(num1<=120)
  72.                 {
  73.                         if(num2==4)
  74.                         {        led5=1;
  75.                                 num2=0;
  76.                                 led6=~led6;
  77.                         }       
  78.                 }
  79.                 case 120:
  80.                         while(num1<=140)
  81.                 {
  82.                         if(num2==4)
  83.                         {        led6=1;
  84.                                 num2=0;
  85.                                 led7=~led7;
  86.                         }       
  87.                 }
  88.                 case 160:
  89.                         while(num1<=180)
  90.                 {
  91.                         if(num2==4)
  92.                         {        led7=1;
  93.                                 num2=0;
  94.                                 led8=~led8;
  95.                         }       
  96.                 }led8=1;num1=0;break;
  97.         }
  98.   }
  99. }
  100. void T0_time()interrupt 1
  101. {
  102.                 TH0=(65536-45872)/256;
  103.                 TL0=(65536-45872)%256;
  104.                 num1++;
  105.                 num2++;       
  106. }
ayb_ice 发表于 2014-11-6 13:35 | 显示全部楼层
既然这么认为,我也就不说什么了,

此没有问题只能说明这个没有问题,也只能说明没有看到问题。。。
 楼主| 夏盼 发表于 2014-11-6 14:03 | 显示全部楼层
ayb_ice 发表于 2014-11-6 13:35
既然这么认为,我也就不说什么了,

此没有问题只能说明这个没有问题,也只能说明没有看到问题。。。 ...

恩,我是不会放弃治疗的
ayb_ice 发表于 2014-11-6 14:28 | 显示全部楼层
if(num2==4)
{
    num2=0;
    led1=~led1;
  delay(50ms); // 加延时函数就能看出问题
}     
ayb_ice 发表于 2014-11-6 14:48 | 显示全部楼层
简单的修改最先的代码

        while(1)
        {
                        uchar t;
                        t = num1;
                        while(t == num1);
                       
                if((num1==4)||(num1==8)||(num1==12)||(num1==16)||(num1==20))
                {
                        led1=~led1;
                }
wangch_sh 发表于 2014-11-6 15:14 | 显示全部楼层
定时200ms准不准?
还是先把程序简化。
if((num1==4)||(num1==8)||(num1==12)||(num1==16)||(num1==20))
                {
                        led1=~led1;
                }
先试第一个灯,看对不对。对了,再加第二个灯。。。
yangfan19641964 发表于 2014-11-6 15:25 | 显示全部楼层
~是字节按位取反.  准确的应该是: led1=!led1;
yangfan19641964 发表于 2014-11-6 15:48 | 显示全部楼层
有些编译器不会出问题.  但不能保证所有的编译都正确
ayb_ice 发表于 2014-11-6 16:03 | 显示全部楼层
本帖最后由 ayb_ice 于 2014-11-6 16:08 编辑

基本逻辑有问题
我前面的说法有些不正确的

本应每中断一次才进行一次主循环处理,这样就逻辑合理了,但LZ的程序是在不停的处理,而CPU相对很快,所以不停的符合条件,不停的闪烁


LZ对num1这个变量的访问还是有些问题,这个变量类似计数器的飞读概念,

建议先赋值给局部变量,再使用局部变量进行判断,这样要可靠多了

评分

参与人数 1威望 +1 收起 理由
夏盼 + 1 很给力!

查看全部评分

yangfan19641964 发表于 2014-11-6 16:29 | 显示全部楼层
楼上说到本质了。 应该在中断里再加一个标志,主程序每处理一次中断溢出、就将改标志清掉。

另外,应该在主程序中加一个变量,移位控制。主循环没理由那么大、那么繁琐。
joyme 发表于 2014-11-6 16:31 | 显示全部楼层
问题在于num1 == 4 之类的条件成立可持续50ms,而主程序循环跑得很快,在50ms里灯的状态会不停的快速变换
uchar  last_num;
if(last_num == num1)
    continue;
else
    last_num = num1;
后面的处理怎么方便怎么做就好了
yangfan19641964 发表于 2014-11-6 16:38 | 显示全部楼层
void  T0_timer()   interrupt 1
{
       num1++;
       if  (num1==4)
       {
                num1=0;
                Bflash=1;
       }
}


uchar  sta=0x01, counter=0;

while(1)
{
          if  (Bflash)
          {
                 Bflash=0;
                 sta=~sta;
                 counter++;

                  if (counter==6)
                  {
                          counter=0;
                          sta=sta<<1;         if (!sta)   sta=0x01;
                  }
                 
                  P1=sta;
          }
yangfan19641964 发表于 2014-11-6 16:42 | 显示全部楼层
错了。要修改
yangfan19641964 发表于 2014-11-6 16:45 | 显示全部楼层
                Bflash=0;
                 P1 = P1 ^ sta;
                 counter++;

                  if (counter==6)
                  {
                          counter=0;
                          sta=sta<<1;         if (!sta)   sta=0x01;
                          P1=sta;
                  }
                 
   
yangfan19641964 发表于 2014-11-6 23:47 | 显示全部楼层
最后的 P1 = sta  疑似不要.

我写的程序可能初学者不习惯, 但好处在于:
1  程序代码空间小
2   便于修改时间间隔     将定时时间修改,  只需改 if  (num1==4)
3  便于修改闪烁次数      只需改   if  (counter==6)
4  便于修改闪烁的管脚数   比如,  只有6个灯闪烁   if  (sta==0x40)   sta=0x01;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

15

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部