找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2799|回复: 7
收起左侧

51单片机理通定时器输出PWM例程

  [复制链接]
ID:396245 发表于 2020-1-1 15:50 | 显示全部楼层 |阅读模式
新年好!

去zuo年tian,有个网友问我51单片机怎么输出PWM波,跟他说了半天,他没转过弯来。后来我觉得索性写一个出来把。今年把它分享出来,算是给大家的新年礼物。

开门第一话,授人以鱼不如授人以渔。简单介绍一下原理及程序过程。
通过定时中断翻转IO口电平。PWM波一个周期需要两次电平翻转,因为高电平时间与低电平时间可能不相对,所以定时器需要根据该电平状态的持续时间来负初值,也就是说,不能用常量。赋初值后启动定时器,中断时翻转IO口电平,实现PWM波的输出。

开门第二话,直接上代码。
IO口及变量定义
//定义IO口以及高低电平持续时间对应定时器初值的暂存变量

sbit PWM=P2^6;
uint PWM_H=0;        //高电平定时器初值
uint PWM_L=0;        //低电平定时器初值

初始化部分,提供“周期+脉宽”和“频率+占空比”两种方式的初始化函数
  1. ////////////////////////////////////////////////////////////////////////
  2. //        名称 : PWM_Init_Cycle(uint cycle,uint width)
  3. //        功能 : 通过周期和脉宽调制PWM波
  4. //        参数 :
  5. //                        uint cycle                周期                单位:微秒                范围:20-65535
  6. //                        uint width                脉宽                单位:微秒                范围:20-65535
  7. //        返回 : 无
  8. ////////////////////////////////////////////////////////////////////////
  9. void PWM_Init_Cycle(uint cycle,uint width)
  10. {
  11.         TMOD=0x01;//定时器0工作方式1
  12.         EA=1;                        //开总中断
  13.         ET0=1;                //开定时器0中断
  14. TH0=TL0=0;
  15.         PWM_H=0xFFFF-width;
  16.         PWM_L=0xFFFF-(cycle-width);
  17. TR0=1;                //启动定时器0
  18. }
  19. ////////////////////////////////////////////////////////////////////////
  20. //        名称 : PWM_Init_Fre(uint fre,uchr duty)
  21. //        功能 : 通过频率和占空比调制PWM波
  22. //        参数 :
  23. //                        uint fre                        频率                        单位:赫兹                        范围:20-50000
  24. //                        uchr duty                        占空比                单位:百分比                范围:1-100
  25. //        返回 : 无
  26. ////////////////////////////////////////////////////////////////////////
  27. void PWM_Init_Fre(uint fre,uchr duty)
  28. {
  29.         int cycle=1000000/fre;
  30.         TR0=0;                //停止定时器0
  31.         TMOD=0x01;//定时器0工作方式1
  32.         TH0=TL0=0;
  33.         EA=1;                        //开总中断
  34.         ET0=1;                //开定时器0中断
  35. PWM_H=cycle/100*duty;  //算出持续时间
  36.         PWM_L=cycle-PWM_H;
  37.         PWM_H=0xFFFF - PWM_H;</font><span style="font-size: small;">/持续时间转换为初值</span><font size="2">
  38.         PWM_L=0xFFFF - PWM_L;
  39. TR0=1;                //启动定时器0
  40. }</font>
复制代码
PWM调制定时器中断处理
  1. ////////////////////////////////////////////////////////////////////////
  2. //        名称 : interrupt_timer0(void)
  3. //        功能 : 定时器0溢出终端处理函数
  4. //        参数 : 无
  5. //        返回 : 无
  6. ////////////////////////////////////////////////////////////////////////
  7. void interrupt_timer0(void) interrupt 1
  8. {
  9.         PWM=!PWM;                //翻转IO电平
  10.         if(PWM)                        //高电平,把高电平对应的初值搬入定时器
  11.         {
  12.                 TH0=(uchr)(PWM_H>>8);
  13.                 TL0=(uchr)(PWM_H>>0);
  14.         }
  15.         else                        //低电平,把低电平对应的初值搬入定时器
  16.         {
  17.                 TH0=(uchr)(PWM_L>>8);
  18.                 TL0=(uchr)(PWM_L>>0);
  19.         }
  20. }
复制代码
是不是觉得特别简单。放心,我没有偷懒代码都在。


总结一下,由于是通过定时器中断调制的脉宽,所以,高低电平持续时间都不能大于65535个机器周期。同事,由于中断处理函数也需要时间,高低电平持续时间也都不能太短,最好在10个机器周期以上,如果太短,CPU就没时间干其他事了。这算是一个缺点把,但这个范围应该也够用了。


最后,需要源码与仿真的朋友可以下载附件。
PWM for AT89C52(源码+仿真).zip (57.95 KB, 下载次数: 54)

评分

参与人数 2黑币 +130 收起 理由
星星x + 30 很给力!
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:85480 发表于 2020-1-2 15:53 | 显示全部楼层
新年第一帖,好人。
回复

使用道具 举报

ID:581198 发表于 2020-1-21 06:12 来自手机 | 显示全部楼层
写得很好,谢谢楼主
回复

使用道具 举报

ID:36831 发表于 2020-1-21 15:16 | 显示全部楼层
学习楼主思路  每天学习一点点
回复

使用道具 举报

ID:661513 发表于 2020-1-21 15:33 来自手机 | 显示全部楼层
收下了,谢谢楼主
回复

使用道具 举报

ID:635120 发表于 2020-1-23 22:16 | 显示全部楼层
感谢楼主
回复

使用道具 举报

ID:88606 发表于 2020-1-25 13:37 | 显示全部楼层
新年快乐!
回复

使用道具 举报

ID:635120 发表于 2020-1-28 10:54 | 显示全部楼层
慢慢学习  谢谢楼主
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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