单片机测量PWM占空比的三种方法

PWM(Pulse Width Modulation),一般指脉冲宽度调节,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中,比如LED亮度调节、电机转速控制等。
而在某些特殊应用中,我们也需要通过测量输入PWM的占空比,来实现不同的输出控制,这就需要使用到PWM占空比的测量方法。这里介绍三种不同的测量方法:阻塞方式、中断方式以及定时器捕获功能。

1. 阻塞方式

MCU阻塞方式测量PWM占空比的原理比较简单,也只需要使用到一个普通的IO端口(设置为输入模式,对于51而言那就是一个普通的双向口)。具体实现流程为:

  • 等待上升沿到来,然后开启定时器,开始计时;
  • 等待下降沿到来,记录下定时器的计数值,即得到PWM的高电平时间H
  • 同时,清零定时器,重新开始计数;
  • 等待上升沿到来,记录下定时器的计数值,即得到PWM的低电平时间L
  • 计算得出占空比:duty = H / (H + L);

阻塞方式原理简单,而且只需要MCU有一个定时器的资源即可实现;但采集时阻塞CPU运行,阻塞的时间和输入PWM的周期相关,只适用于实时性较低的系统。

另外,上述流程中存在着一个严重的BUG,即当输入的PWM占空比为0%或者100%时,程序会被一直阻塞,等待上升沿/下降沿的到来。所以解决方法是,在等待上升沿/下降沿的过程中,实时提取定时器的值,一旦定时时间超过1个周期的限定(一般可定义为2-3个周期时间),即退出等待,并根据端口电平判断此时占空比为0%(低电平)或100%(高电平)

示例代码,仅供参考:

//获取PWM输入脚的电平
#define PWM_IN()   xxxxxx
//定义超时时间(如2-3倍PWM周期)
#define T1_TIMEOUT  xxxxxxuint8_t PWM_Analyse(void)
{uint8_t duty = 0xFF;uint16_t pwm_H = 0;uint16_t pwm_L = 0;if (PWM_IN())   //初始为高电平,则开始等待低电平{TH1 = 0;while (PWM_IN()) //等待下降沿{if (TH1 >= T1_TIMEOUT)  //下降沿没有到来,判定为100%占空比{duty = 100;return duty;}}TH1 = 0;TL1 = 0;while (!PWM_IN()) //等待上升沿{if (TH1 >= T1_TIMEOUT)  //上升沿没有到来,判定为0%占空比{duty = 0;return duty;}}pwm_L = (TH1 << 8) | TL1;TH1 = 0;TL1 = 0;while (PWM_IN()) //等待下降沿{if (TH1 >= T1_TIMEOUT)  //下降沿没有到来,判定为100%占空比{duty = 100;return duty;}}pwm_H = (TH1 << 8) | TL1;duty = pwm_H * 100 / (pwm_H + pwm_L);return duty;}else    //当前为低电平,则开始等待高电平{TH1 = 0;while (!PWM_IN()) //等待上升沿{if (TH1 >= T1_TIMEOUT)  //上升沿没有到来,判定为0%占空比{duty = 0;return duty;}}TH1 = 0;TL1 = 0;while (PWM_IN()) //等待下降沿{if (TH1 >= T1_TIMEOUT)  //下降沿没有到来,判定为100%占空比{duty = 100;return duty;}}pwm_H = (TH1 << 8) | TL1;TH1 = 0;TL1 = 0;while (!PWM_IN()) //等待上升沿{if (TH1 >= T1_TIMEOUT)  //上升沿没有到来,判定为0%占空比{duty = 0;return duty;}}pwm_L = (TH1 << 8) | TL1;duty = pwm_H * 100 / (pwm_H + pwm_L);return duty;}return 0xFF;
}

2. 中断方式

中断方式的PWM采集原理与阻塞方式相同,只是将判定移动至外部中断中。开启MCU端口的外部中断(上升沿和下降沿中断);如果MCU外部中断触发不支持上升和下降沿中断,则先开启上升沿中断,在中断处理中切换中断触发条件。

处理方法:在中断处理函数中,根据当前电平状态,记录下定时器的值,并清零定时器的值,重新开始下一轮计时。

0%和100%的处理:设定一个定时递增的变量,同时在外部中断中执行清零操作。若该变量超过一定值(说明外部中断有较长时间没有触发),则判定为0%或100%。

uint16_t pwm_H = 0;
uint16_t pwm_L = 0;
uint16_t pwm_time_out = 0;
void EXT1_ISR(void) interrupt EXTI1_VECTOR
{if (PWM_IN()){pwm_L = (TH1 << 8) | TL1;    //记录低电平时间TH1 = 0;TL1 = 0;}else{pwm_H = (TH1 << 8) | TL1;    //记录高电平时间TH1 = 0;TL1 = 0;}//该变量定时递增(如1ms递增1),在外部中断中清零//在主程序中判断,超过一定值时认为PWM占空比为0%或100%pwm_time_out = 0;return;
}

注:使用中断方式,则占空比计算不建议放在中断中处理;同时,为了保证占空比的准确性,可以连续2-3次计算结果一致时,再确定当前占空比的结果。

3. MCU捕获方式

采用捕获方式的前提是MCU支持捕获功能。当前部分厂家推出的51内核单片机,会包含一个定时器2,其拥有捕获功能;或者采用32位单片机,一般都带有捕获功能。捕获的原理很简单,当上升沿或下降沿来临时,MCU硬件将定时器/计数器的值保存在一个影子寄存器中,并产生捕获中断。
通过固定每次上升/下降沿的计数器值,相减即可分别得出高电平值和低电平值,从而计算出占空比。

下面以某颗51内核的MCU为例,提供示例代码:

unsigned int pwm_fall = 0, pwm_rise = 0;volatile unsigned int pwm_H;
volatile unsigned int pwm_L;volatile unsigned char pwm_time_out;
//------------------------------------------------------------
void T2_interrupt(void) interrupt 5          //定时器2中断;
{if (CCCON & 0x02) //CC1中断标志位{CCCON  &= 0xFD; //清除中断标志if (PWM_IN())   //上升沿触发{pwm_rise = CC1;     //获取捕获寄存器中的值pwm_L = pwm_rise - pwm_fall;}else{pwm_fall = CC1;     //获取捕获寄存器中的值pwm_H = pwm_fall - pwm_rise;}//该变量定时递增(如1ms递增1),在外部中断中清零//在主程序中判断,超过一定值时认为PWM占空比为0%或100%pwm_time_out = 0;}
}

注: pwm_rise/pwm_fall/pwm_L/pwm_H都必须使用无符号数,否则相减时可能得到错误的值。

总结

方式一任何单片机都可以实现,但是阻塞方式会使系统的实时性变差;
方式二在使用时,需要保证外部中断的最高优先级,不可以被其他中断打断,以保证其准确性;
方式三的稳定性和准确性都较高,但是需要MCU硬件支持。

单片机测量PWM占空比的三种方法相关推荐

  1. 单片机跑马灯程序c语言,MCS-51单片机控制跑马灯的三种方法

    描述 在MCS一51单片机的控制系统中,它的四个并行8位输入输出端口P0一P3是我们经常使用的.在并行端口的编程学习中,"跑马灯"是单片机并行端口输出控制的典型实例.所谓跑马灯,是 ...

  2. 简单51单片机c语言编程流水灯,51单片机如何实现流水灯?51单片机实现流水灯的三种方法详细分析...

    描述 首先,介绍下原理.下图为主控芯片和流水灯模块的原理图.流水灯模块接在单片机的P1口,由原理图可以知道,在P1口给一个低电平即可点亮LED灯.相反,如果要LED灯熄灭,就要把P1口的电平变为高电平 ...

  3. stcisp一直检测单片机_三种方法对比:STC51单片机实现免冷启动

    具体实现方法实践可用的无外乎三种: 1)使用CH340的DTR和RTS控制单片机断电再上电.点上位机下载按钮的时候,DTR和RTS引脚电平变化. 2)再使用一个单片机,检测串口下载命令流. 3)在程序 ...

  4. 单片机长时间程序跑飞_单片机程序跑飞的三种现象、原因及解决方法

    今天在编写单片机程序的时候,由于中断服务程序写的不好,导致单片机程序总是跑飞,最后费了好长时间,花了很大功夫才找到问题原因,由此总结了单片机程序跑飞的三种现象.原因及解决方法. 一.数组越界(数组溢出 ...

  5. 调节e18-d80nk的测量距离_线缆太长负载太远,负载端电压难测量?三种方法帮你搞定...

    关键词:电缆, 线缆阻抗, 负载电流, 开尔文检测 在产品设计,研发过程中,我们常会碰到稳压器与负载分离的情况.此时,如果电缆线太长,线缆阻抗无法忽略.负载电流太大,这些都会使得配电线上的压降增大,从 ...

  6. 测量频率和占空比的几种方法

    转:https://blog.csdn.net/yyx112358/article/details/78414594 想当年天天水论坛好为人师,现在已经全面转向计算机视觉方向了,颇为感慨.不过,自己的 ...

  7. 使用 STM32 测量频率和占空比的几种方法

    以前在本科时写的教程文章,主要是把自己当时参赛的方法拿出来做了个总结. 想当年天天水论坛好为人师,现在已经全面转向计算机视觉方向了,颇为感慨.不过,自己的理性选择,个中得失早就意料之中.塞翁失马,焉知 ...

  8. 独家 | 将时间信息编码用于机器学习模型的三种编码时间信息作为特征的三种方法...

    作者:Eryk Lewinson 翻译:汪桉旭 校对:zrx本文约4400字,建议阅读5分钟 本文研究了三种使用日期相关的信息如何创造有意义特征的方法. 标签:时间帧,机器学习,Python,技术演示 ...

  9. Altium Designer画元器件封装三种方法

    下面跟大家分享Altium Designer画元器件封装的三种方法. 如有错误,望大家指正. 一.手工画法. (1)新建个PCB库. 下面以STM8L151C8T6为例画封装,这是它的封装信息 设置好 ...

  10. python控制示波器获取波形_三种方法教你用示波器快速捕获异常

    万事开头难!当你想用示波器来分析问题时,你一定有想过,我要如何才能把问题抓下来?当然,只有抓下来之后,才能进行后面种种的分析,否则一切都是空谈.本文将带你用三种最好用的方法将异常抓下来. 一.滚动模式 ...

最新文章

  1. python基础知识面试题-python基础知识的重点面试题
  2. 在C#中使用代理的方式触发事件 的简单习作
  3. HashMap两种遍历数据的方式
  4. mysql 抓包乱码_mysql知识资源收集
  5. SpringMVC接收Post的实体/JSon数据
  6. 【Linux入门学习之】数据流重定向
  7. python是什么意思中文、好学吗-爬虫Python入门好学吗?学什么?
  8. 安卓暗黑模式软件_Android App Dark Theme(暗黑模式)适配指南
  9. sqlmap安装及问题汇总
  10. Hilbert变换及谱分析
  11. Vue + Element-UI —— 项目实战(一)
  12. 如何在两台电脑之间共享文件
  13. 阿里字体库的运用(网站上面的购物车或者一些小图标 箭头)
  14. 今夏流行的十大避暑胜地
  15. YBT高效进阶3.4.2 洛谷P2341 POJ2186受欢迎的牛Popular Cows
  16. 2021 第十二届 蓝桥杯 国赛决赛 Java B组 真题 详细解析
  17. Zuul动态路由及动态Filter实现
  18. 号外!号外!仅需5000元,即可配置Apollo计算平台!
  19. 全球及中国电化学研磨设备行业盈利模式与竞争态势分析报告2022-2028年
  20. 【欣赏】logo设计原则 + 一组设计独特的logo欣赏

热门文章

  1. 关于VBV-------Video Buffering Verifier
  2. R中安装rgl时“configure: error: missing required library GL”错误的解决方法
  3. 阿里云E-HPC+i4p大内存实例,加速寻因生物单细胞数据分析效率
  4. 手机php文件怎么改后辍,手机百度云盘修改文件后缀名的方法
  5. 文件打不开只读或服务器未响应,Mac的Word经常未响应怎么办
  6. Echarts 实现 设备运行状态图 工业大数据展示
  7. idea出现的怪异现象
  8. 从零开始学习html(十)CSS格式化排版——下
  9. AndroidStudio安装之后虚拟机启动失败解决方法
  10. CAD2014安装一整套流程