单片机输出PWM的常见方法

pwm的应用可以说非常广泛,控制电机速度、灯光亮度、通信调制等众多领域。
pwm的问题小伙伴问的比较多,最近也在用pwm,这里就分享一下关于pwm的一些内容。
什么是pwm?
pwm: pulse width modulation,脉冲宽度调制。
网上的解释很多,通过下图,你就能直观的理解pwm,其实就是高低电平组成的脉冲信号。
通过改变其中频率(脉冲周期)、占空比,就能应用在很多场合。
pwm常见输出方式
通过上面描述,pwm就是一个io口以不同的时间周期输出高、低电平。
1.新手 (菜鸟) 级别
while循环中,阻塞延时,控制io口高低输出:
while(1){ io口高电平 delay阻塞延时 io口低电平 delay阻塞延时}阻塞延时可以是:软件模拟延时,定时器阻塞延时等。
2.入门 (初级) 级别
while循环中,非阻赛延时,控制io口高低输出:
while(1){ io口高电平 delay非阻塞延时 io口低电平 delay非阻塞延时}非阻赛延时可以是:定时器标识检测、rtos(系统)延时等。
3.熟悉 (中级) 级别
定时器中断控制io高低电平输出:
定时器中断配置 ——> 启动定时器 ——> 响应中断,控制io高低电平···
4.熟练 (中级+) 级别
定时器pwm硬件控制输出:
配置pwm对应的io,以及定时器pwm输出 ——> 启动pwm自动输出···
void apptask(void *p_arg){ pwm_tim_configuration(); pwm_output(频率, 占空比); while(1) { //自己的应用代码 }}比较:
上面几种pwm输出方式,前面三种都会cpu干预pwm的输出,也就是会占用cpu资源,特别是前面两种方式,不仅占用cpu,误差还比较大。
使用第三种中断方式,如果频率比较高,cpu消耗的也比较严重。这种情况适合于没有硬件pwm输出的单片机。
第四种就是单片机自带硬件pwm输出功能,只需要简单配置就可以自动输出pwm波形,无需cpu干预。
硬件输出pwm例子
这里以大家熟悉的stm32f1为例:为大家简单分享一下硬件定时器输出pwm波形。
pwm定时器相关宏定义:
//定时器计数时钟(1m次/秒)#define pwm_counter_clock 1000000//预分频值(与系统时钟、计数值有关)#define pwm_prescaler_value (systemcoreclock/pwm_counter_clock - 1)**pwm配置:
**
/** * @brief 定时器pwm输出配置 * @param 无 * @retval 无 */void pwm_tim_configuration(void){ gpio_inittypedef gpio_initstructure; tim_timebaseinittypedef tim_timebasestructure; tim_ocinittypedef tim_ocinitstructure; /* 时钟配置 */ rcc_apb2periphclockcmd(rcc_apb2periph_gpioa, enable); rcc_apb1periphclockcmd(rcc_apb1periph_tim2, enable); /* 引脚配置 */ gpio_initstructure.gpio_pin = gpio_pin_0; gpio_initstructure.gpio_speed = gpio_speed_50mhz; gpio_initstructure.gpio_mode = gpio_mode_af_pp; gpio_init(gpioa, &gpio_initstructure); /* 时基配置 */ tim_timebasestructure.tim_prescaler = pwm_prescaler_value; //预分频值 tim_timebasestructure.tim_countermode = tim_countermode_up; //向上计数 tim_timebasestructure.tim_period = 0xffff; //定时周期(暂定值) tim_timebasestructure.tim_clockdivision = tim_ckd_div1; //分频因子 tim_timebaseinit(tim2, &tim_timebasestructure); /* pwm模式配置 */ tim_ocinitstructure.tim_ocmode = tim_ocmode_pwm1; //输出pwm1模式 tim_ocinitstructure.tim_outputstate = tim_outputstate_enable; //使能输出 tim_ocinitstructure.tim_pulse = 0; //脉宽值(暂定值) tim_ocinitstructure.tim_ocpolarity = tim_ocpolarity_high; //输出极性(tim_oc1对应通道1) tim_oc1init(tim2, &tim_ocinitstructure);}pwm输出函数接口:
/** * @brief 输出pwm * @param frequency:频率 dutycycle:占空比 * @retval 无 */void pwm_output(uint32_t frequency, uint32_t dutycycle){ uint32_t tim_period; uint32_t tim_pulse; tim_period = pwm_counter_clock/frequency - 1; //计算出计数周期(决定输出的频率) tim_pulse = (tim_period + 1)*dutycycle / 100; //计算出脉宽值(决定pwm占空比) tim_cmd(tim2, disable); //失能tim tim_setcounter(tim2, 0); //计数清零 tim_setautoreload(tim2, tim_period); //更改频率 tim_setcompare1(tim2, tim_pulse); //更改占空比(tim_setcompare1对应通道1) tim_cmd(tim2, enable); //使能tim}初始化配置,调用函数接口,直接就输出pwm波形了:
void apptask(void *p_arg){ pwm_tim_configuration(); pwm_output(1000, 20); while(1) { //自己的应用代码 }}输出pwm波形:
说明:
本例使用的是stm32标准外设库,如果要深入理解其中原理,还是建议使用标准外设库。
当然,如果想要快速使用pwm这个功能,不想理解其原理,可以直接使用stm32cubemx配置生成代码:
配置注意事项
想要更加精确控制,并更加满足应用层的需求,就需要自己一步一步深入了解原理。
下面说几点常见的问题吧。
1.引脚映射
如果你使用的引脚需要映射,就需要配置对应的参数。
比如:stm32f1使用pb11(需要查看数据手册):
需要增加对应的“映射”代码:
//复用功能rcc_apb2periphclockcmd(rcc_apb2periph_afio, enable);//定时器(pwm)引脚映射gpio_pinremapconfig(gpio_fullremap_tim2, enable);2.频率和占空比精度
如果使用32位定时器的话,频率范围更宽、精度也可以达到更高。比如:频率:0.01hz、 占空比0.01%等。
如果是16位的话,其中的参数都不能超过16位(65535):
#define pwm_counter_clock 1000000#define pwm_prescaler_value (systemcoreclock/pwm_counter_clock - 1)tim_period = pwm_counter_clock/frequency - 1; //计算出计数周期(决定输出的频率)tim_pulse = (tim_period + 1)*dutycycle / 100; //计算出脉宽值(决定pwm占空比)具体可根据自己情况进行配置,比如pwm(定时器)计数时钟、分频值等。
实际应用代码,建议增加各个参数的判断,以防越界(这里为了方便理解,就写的比较简单)。
3.更多
stm32都有硬件pwm输出功能,但不同的系列,其配置可能略有一些差异,简单参考官方例程以及手册。
现在大部分单片机都自带有硬件pwm输出功能,硬件的好处就是不用cpu干预。如果没有,可以尝试上面说的定时器中断的方式。

航空高光谱遥感区域成矿背景研究—以甘肃柳园-方山口地区为例2.0
wifi智能插座开发烧录程序视频教学
【世说设计】烧脑长文!近乎完美的DDS正弦波信号音生成器!
断路器工作原理
图解中南地区各省市新材料产业发展重点及目标
单片机输出PWM的常见方法
冒烟损坏的电脑硬盘维修
宽带电压控制放大器VCA610
新型红色荧光粉的发光效率提高16%
PLC系统如何与上位机通讯?
GPT-4 驱动的新Copilot编码助手
一氧化碳报警器帮助警告一氧化碳中毒
上海特斯拉超级工厂即将向欧洲出口Model 3
无线充电系统电屏蔽对空间磁场的影响
选择HDMI和DP哪个好
食品重金属检测仪的产品用途说明
2019年华为预计实现销售收入8500亿 智能手机出货量全球第二
讲讲单相全桥逆变器的原理及其建模
骁龙835和华为麒麟 两个档次,高通在CES2017直言说
安防市场整体智能化升级 智慧安防是建设智慧城市的基础