打印
[51单片机]

定时器的应用

[复制链接]
1250|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
夏盼|  楼主 | 2014-11-5 22:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我的程序想实现让8个二极管依次以200ms的间隔连续闪烁5次,但是实际运行时发现有问题,请指教
#include"reg51.h"
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit led4=P1^3;
sbit led5=P1^4;
sbit led6=P1^5;
sbit led7=P1^6;
sbit led8=P1^7;
uchar num1;
void main()
{
        TMOD=0x01;
        TH0=(65536-45872)/256;
        TL0=(65536-45872)%256;
        EA=1;
        ET0=1;
        TR0=1;
        led1=1;
        led2=1;
        led3=1;
        led4=1;
        led5=1;
        led6=1;
        led7=1;
        led8=1;
        while(1)
        {
                if((num1==4)||(num1==8)||(num1==12)||(num1==16)||(num1==20))
                {
                        led1=~led1;
                }
                if((num1==24)||(num1==28)||(num1==32)||(num1==36)||(num1==40))
                {        led1=1;
                        led2=~led2;
                }
                if((num1==44)||(num1==48)||(num1==52)||(num1==56)||(num1==60))
                {        led2=1;
                        led3=~led3;
                }
                if((num1==64)||(num1==68)||(num1==72)||(num1==76)||(num1==80))
                {        led3=1;
                        led4=~led4;
                }
                if((num1==84)||(num1==88)||(num1==92)||(num1==96)||(num1==100))
                {        led4=1;
                        led5=~led5;
                }
                if((num1==104)||(num1==108)||(num1==112)||(num1==116)||(num1==120))
                {        led5=1;
                        led6=~led6;
                }
                if((num1==124)||(num1==128)||(num1==132)||(num1==136)||(num1==140))
                {        led6=1;
                        led7=~led7;
                }
                if((num1==144)||(num1==148)||(num1==152)||(num1==156))
                {        led7=1;
                        led8=~led8;
                }                 
                if(num1==160)
                {       
                        led8=~led8;
                        led8=1;
                        num1=0;
                }       
        }       
        }
void T0_time()interrupt 1
        {
                TH0=(65536-45872)/256;
                TL0=(65536-45872)%256;
                num1++;       
        }


相关帖子

沙发
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
有什么问题?

所有的灯都会闪

使用特权

评论回复
5
夏盼|  楼主 | 2014-11-6 13:17 | 只看该作者
ayb_ice 发表于 2014-11-6 08:25
你这个错误关键在num1的处理上,这个变量在不停的被中断累加,在主循环的一次循环处理中可能值会发生变化, ...

虽然现在我还没有发现问题出在什么地方,但是我认为应该不是出在num1上,下面我这程序也是用的num++,运行就很正确
#include"reg51.h"
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit led4=P1^3;
sbit led5=P1^4;
sbit led6=P1^5;
sbit led7=P1^6;
sbit led8=P1^7;
uchar num1,num2;
void main()
{
        TMOD=0x01;
        TH0=(65536-45872)/256;
        TL0=(65536-45872)%256;
        EA=1;
        ET0=1;
        TR0=1;
        while(1)
        {
        switch(num1)
        {
                case 0:
                while(num1<=20)
                {
                        if(num2==4)
                        {
                                num2=0;
                                led1=~led1;
                        }       
                }
                case 20:
                        while(num1<=40)
                {
                        if(num2==4)
                        {        led1=1;
                                num2=0;
                                led2=~led2;
                        }       
                }
                case 40:
                        while(num1<=60)
                {
                        if(num2==4)
                        {        led2=1;
                                num2=0;
                                led3=~led3;
                        }       
                }
                case 60:
                        while(num1<=80)
                {
                        if(num2==4)
                        {        led3=1;
                                num2=0;
                                led4=~led4;
                        }       
                }
                case 80:
                        while(num1<=100)
                {
                        if(num2==4)
                        {        led4=1;
                                num2=0;
                                led5=~led5;
                        }       
                }
                case 100:
                        while(num1<=120)
                {
                        if(num2==4)
                        {        led5=1;
                                num2=0;
                                led6=~led6;
                        }       
                }
                case 120:
                        while(num1<=140)
                {
                        if(num2==4)
                        {        led6=1;
                                num2=0;
                                led7=~led7;
                        }       
                }
                case 160:
                        while(num1<=180)
                {
                        if(num2==4)
                        {        led7=1;
                                num2=0;
                                led8=~led8;
                        }       
                }led8=1;num1=0;break;
        }
  }
}
void T0_time()interrupt 1
{
                TH0=(65536-45872)/256;
                TL0=(65536-45872)%256;
                num1++;
                num2++;       
}

使用特权

评论回复
6
ayb_ice| | 2014-11-6 13:35 | 只看该作者
既然这么认为,我也就不说什么了,

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

使用特权

评论回复
7
夏盼|  楼主 | 2014-11-6 14:03 | 只看该作者
ayb_ice 发表于 2014-11-6 13:35
既然这么认为,我也就不说什么了,

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

恩,我是不会放弃治疗的

使用特权

评论回复
8
ayb_ice| | 2014-11-6 14:28 | 只看该作者
if(num2==4)
{
    num2=0;
    led1=~led1;
  delay(50ms); // 加延时函数就能看出问题
}     

使用特权

评论回复
9
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;
                }

使用特权

评论回复
10
wangch_sh| | 2014-11-6 15:14 | 只看该作者
定时200ms准不准?
还是先把程序简化。
if((num1==4)||(num1==8)||(num1==12)||(num1==16)||(num1==20))
                {
                        led1=~led1;
                }
先试第一个灯,看对不对。对了,再加第二个灯。。。

使用特权

评论回复
11
yangfan19641964| | 2014-11-6 15:25 | 只看该作者
~是字节按位取反.  准确的应该是: led1=!led1;

使用特权

评论回复
12
yangfan19641964| | 2014-11-6 15:48 | 只看该作者
有些编译器不会出问题.  但不能保证所有的编译都正确

使用特权

评论回复
13
ayb_ice| | 2014-11-6 16:03 | 只看该作者
本帖最后由 ayb_ice 于 2014-11-6 16:08 编辑

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

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


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

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

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
夏盼 + 1 很给力!
14
yangfan19641964| | 2014-11-6 16:29 | 只看该作者
楼上说到本质了。 应该在中断里再加一个标志,主程序每处理一次中断溢出、就将改标志清掉。

另外,应该在主程序中加一个变量,移位控制。主循环没理由那么大、那么繁琐。

使用特权

评论回复
15
joyme| | 2014-11-6 16:31 | 只看该作者
问题在于num1 == 4 之类的条件成立可持续50ms,而主程序循环跑得很快,在50ms里灯的状态会不停的快速变换
uchar  last_num;
if(last_num == num1)
    continue;
else
    last_num = num1;
后面的处理怎么方便怎么做就好了

使用特权

评论回复
16
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;
          }

使用特权

评论回复
17
yangfan19641964| | 2014-11-6 16:42 | 只看该作者
错了。要修改

使用特权

评论回复
18
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;
                  }
                 
   

使用特权

评论回复
19
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

粉丝