请选择 进入手机版 | 继续访问电脑版
搜索
查看: 1274|回复: 0

[分享] 51单片机如何输出PWM,如何动态改变占空比?

[复制链接]
发表于 2018-1-22 09:59:16 | 显示全部楼层 |阅读模式
51单片机是可以输出PWM的,比较的麻烦。此时需要用到内部定时器来实现,可用两个定时器实现,也可以用一个定时器实现。

用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比。

下面重点介绍用一个定时器的实现PWM的方法。以周期为1ms(1kHZ)为例,要产生其它频率的PWM波,程序中只需作简单修改即可。用一个定时器时(如定时器T0),首先要确定PWM的周期T和占空比D,确定了这些以后,就可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则D*T=n*t,类似的可以求出PWM低电平时间需要多少个时间基准n。

因为这里我们是产生周期为1ms(1kHZ)的PWM,所以可设置中断的时间基准为0.01ms,,然后中断100次即为1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:

1、当time>=100时,time清零(此语句保证频率为1kHZ);

2、当time>n时(n应该在0-100之间变化开),让单片相应的I/O口输出低电平;

3、当time<=n时,让单片相应的I/O口输出高电平,此时占空比就为%n。

下面程序产生30%占空比的pwm:

  1. #include<reg51.h>  
  2.     #define uint unsigned int  
  3.     #define uchar unsigned char  
  4.       
  5.     sbit PWM=P2^0;//  P2.0输出pwm  
  6.     uchar time;  // 定义占空比的变量  
  7.       
  8.     void main()  
  9.     {  
  10.         TMOD=0x01;//定时器0工作方式1  
  11.         TH0=0xff;//(65536-10)/256;//赋初值定时  
  12.         TL0=0xf7;//(65536-10)%256;//0.01ms  
  13.         EA=1;//开总中断  
  14.         ET0=1;//开定时器0中断  
  15.         TR0=1;//启动定时器0   
  16.         while(1)  
  17.         {            
  18.         }            
  19.     }  
  20.       
  21.     void tim0() interrupt 1  
  22.     {  
  23.         TR0=0;//赋初值时,关闭定时器  
  24.         TH0=0xff;//(65536-10)/256;//赋初值定时  
  25.         TL0=0xf7;//(65536-10)%256;//0.01ms  
  26.         TR0=1;//打开定时器  
  27.       
  28.         time++;  
  29.         if(time>=100)  <span style="font-family: KaiTi_GB2312;">//1khz</span>  
  30.           time=0;     
  31.         if(time<=30)   <span style="font-family: KaiTi_GB2312;">//占空比%30,可改</span>  
  32.           PWM=1;   
  33.         else PWM=0;  
  34.     }
复制代码
最后的到波形,在示波器上显示如下图所示:

如果想修改占空比,直接在程序里面修改下面这句即可。

if(time<=30)//占空比%30,可改占空比

当然我们可以加入其它的手段来动态改变占空比,比如按键,上位机等。

51单片机按键控制输出pwm的占空比

之前说到利用51单片机输出pwm,但是输出的pwm是固定占空比的,如果想要改变占空比,还得回过头来修改程序并重新烧写进单片机。这样做的话不但麻烦、效率低,还又把芯片的可烧写次数减少了一次,虽然51的芯片现在很便宜,但能省点就省点,能不浪费就不浪费,哈哈,开玩笑啦!最主要的还是为了灵活性,为此特地通过加入按键的功能来实现动态修改输出的pwm的占空比。这样在用pwm控制电机的时候就能使用按键来控制电机转速了。废话不多说,见下:

  1. #include<reg51.h>  
  2.       
  3.     #define uint unsigned int   
  4.     #define uchar unsigned char                           
  5.       
  6.     uchar time;   
  7.     double count=26;    //定义占空比,并初始占空比为26%  
  8.     sbit PWM=P2^0;      //P2^0口输出PWM   
  9.     sbit key_add=P3^4;   //电机加速的按键 的I/O口  
  10.     sbit key_dec=P3^5;   //电机减速的按键 的I/O口  
  11.       
  12.       
  13.     /************函数声明**************/  
  14.     void delayxms(uint z); //延时  
  15.     void Motor_add();     //电机加速,即增加占空比  
  16.     void Motor_dec();      //电机减速,即减少占空比  
  17.     void timer0_init();     //定时器0初始化  
  18.       
  19.     /*********主函数********************/  
  20.     void main()  
  21.     {      
  22.         timer0_init();  
  23.         delayxms(5);  
  24.         while(1)  
  25.         {  
  26.          Motor_add();  
  27.          Motor_dec();  
  28.         }  
  29.     }  
  30.       
  31.     /****************延时处理**********************/  
  32.     void delayxms(uint z) //延时xms程序  
  33.     {  
  34.         uint x,y;  
  35.         for(y=z;x>0;x--)  
  36.             for(y=110;y>0;y--);  
  37.     }  
  38.       
  39.       
  40.     void Motor_add()  //电机加速  
  41.     {  
  42.       if(key_add==0)  
  43.       {  
  44.           delayxms(2); //此处时间不能太长,否者会的中断产生冲突  
  45.       if(key_add==0)  
  46.       {  
  47.           count+=0.5;   //每按一次加速按键占空比加0.5  
  48.        if(count>=32)     //限定占空比上限  
  49.         {  
  50.          count=32;  
  51.         }  
  52.       }  
  53.         while(!key_add);  
  54.       }  
  55.     }  
  56.       
  57.     void Motor_dec()//电机减速  
  58.     {  
  59.      if(key_dec==0)  
  60.      {  
  61.       delayxms(2);//此处时间不能太长,否者会的中断产生冲突  
  62.       if(key_dec==0)  
  63.       {  
  64.         count-=0.5;     //每按一次减速按键占空比减0.5  
  65.        if(count<=25)    //限定占空比下限  
  66.        {  
  67.         count=25;  
  68.        }  
  69.       }  
  70.         while(!key_dec);  
  71.        }  
  72.     }  
  73.       
  74.     /***********定时器0初始化***********/  
  75.     void timer0_init()  
  76.     {  
  77.       TMOD=0x01; //定时器0工作于方式1  
  78.       TH0=(65536-10)/256;  
  79.       TL0=(65536-10)%256;  
  80.       TR0=1;  
  81.       ET0=1;  
  82.       EA=1;  
  83.     }  
  84.       
  85.     /**************定时0中断处理******************/  
  86.     void timer0_int() interrupt 1   
  87.     {  
  88.          
  89.       TR0=0;    //设置定时器初值期间,关闭定时器  
  90.       TH0=(65536-10)/256;  
  91.       TL0=(65536-10)%256;  
  92.       TR0=1;  
  93.            
  94.       time++;  
  95.       if(time<count)   //count为占空比  
  96.       {  
  97.         PWM=1;     //输出高电平  
  98.       }  
  99.       else   
  100.         PWM=0;   
  101.       if(time>=100)  
  102.       {  
  103.         time=0;  
  104.       }  
  105.      }
复制代码
特地标注了重要部分程序的注释。另外,可以在程序中修改按键每次增加或者减少的占空比,但有的时候发现在按键调节占空比时,不想占空比一直增加或者减少下去,还可以在程序里面修改限定占空比的上下限,当达到上限或下限时,相应的增加或减少占空比的按钮这时就不再增加或者减少占空比了。这样在电机控制时就可以防止不小心让电机速度增加到规定速度以上或以下了。这些在程序注释里面课看见在哪里改。除此之外,还可以加进来很多功能。这里就不举相应的子了。

来源:大漠飞鹰lb的csdn blog

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /5 下一条

facebook google plus twitter linkedin youku weibo rss
©2019 Microchip Corporation

小黑屋|手机版|Archiver|Microchip技术社区

GMT+8, 2019-7-17 21:30 , Processed in 0.044301 second(s), 6 queries , MemCache On.

快速回复 返回顶部 返回列表