打印

51单片机模拟PWM遇到一个奇怪的问题

[复制链接]
1895|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xiaomuhong26|  楼主 | 2010-10-29 12:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序如下:
//原意是让P10口的LED从暗渐变到亮,然后又从最亮渐变到暗。
//问题:这个程序,在测试时发现,当其从暗渐变到最亮时,没有问题,但是从亮变到暗时,在渐变过程中有时会闪烁一下;如果改变延时时间,他会不闪烁,但分析不出是什么原因造成的?希望高手指点一下。谢谢!

#include<reg52.h>     
sbit LED = P1^0;      //接有一组LED,当LED=0时,LED灭
unsigned char  PWM_ON ; //高电平脉冲所占用的时间
#define T0_time 200  //定时器初值
#define TO_delay 2000  //延时
#define CYCLE 100   //PWM周期

void delay(unsigned int cnt)
{
while(--cnt);
}


main()
{
   bit Flag; //累加累减标志
 TMOD |=0x01;      
 TH0=(65536-T0_time)/256;
   TL0=(65536-T0_time)%256;     
 IE= 0x82;                 
 TR0=1;
 while(!Flag)
  {
    delay(TO_delay);         
    PWM_ON++;            
   if(PWM_ON == CYCLE)
      {                  
       Flag=1;
      }
  }
while(Flag)              
  {
    delay(TO_delay);
    PWM_ON--;
    if(PWM_ON == 0)
     {
      Flag=0;
    }
  }
}

void tim(void) interrupt 1 using 1
{
static unsigned char count;
TH0=(65536-T0_time)/256;
TL0=(65536-T0_time)%256;     
count++;

if(!PWM_ON)
{
   LED=0;
}
if (count==PWM_ON)
{
  LED = 0;            
}

if(count == CYCLE)
{
  count=0;
  LED = 1;         
}



}

相关帖子

沙发
airwill| | 2010-10-29 13:58 | 只看该作者
这时程序的缺陷 (bug) 导致的,

看从亮变暗的过程. 主程序执行 PWM_ON--;
定时中断周期性地检测 (count==PWM_ON) 的条件.
如果 上一次中断时, 正好 count = PWM_ON-1, 下一次中断时, count 加了一, 但如果在两次中断之间, 执行了一次  PWM_ON--; 那么就漏掉了一次 (count==PWM_ON) 的条件, 于是  LED = 0;   漏掉一次的执行机会, 结果就闪了一下.
可见这个判断方式是有缺陷的, 另外这里还漏掉了 count =0 时的判断机会, 导致 PWM_ON =0 时会常亮!
楼主写程序, 可要好好注意这些细节哪!

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
xiaomuhong26 + 1 我很赞同
板凳
xiaomuhong26|  楼主 | 2010-11-1 19:31 | 只看该作者
谢谢指点,我现在己经解决问题了

使用特权

评论回复
地板
xiaomuhong26|  楼主 | 2010-11-1 19:59 | 只看该作者
#include<reg52.h>   
sbit LED = P1^0;     
unsigned char PWM_ON ;  //高电平所占时间
#define CYCLE 100  //100级

void delay(unsigned int cnt)
{
while(--cnt);
}

main()
{
bit Flag;
TMOD |=0x01;            
TH0=(65536-100)/256;
TL0=(65536-100)%256;     
IE= 0x82;                 
TR0=1;
PWM_ON=0;
while(!Flag)
  {
   delay(5000);         
   PWM_ON++;            
   if(PWM_ON == CYCLE)
     {                    
      Flag=1;
   }
}   
while(Flag)              
  {
   delay(5000);
   PWM_ON--;
   if(PWM_ON == 0)
     {
      Flag=0;
    }
}         
}

void tim(void) interrupt 1 using 1
{
static unsigned char count;
TH0=(65536-100)/256;
TL0=(65536-100)%256;     
count++;
if(!PWM_ON||!count)
  LED=1;   //LED=1时,LED灭
if (count <= PWM_ON)
{
  LED = 0;            //LED亮
}
else if(count <= CYCLE)
{
  LED = 1;          //LED灭
}
else
  count=0;
}


这是我重新改过的程序,现在己经没有了闪烁,不知里面还有没有漏洞,麻烦各位大侠指点一下,不胜感激!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

85

帖子

1

粉丝