前言
本篇博客使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。
一、PWM
1.PWM定义
PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。
脉宽调制(PWM,Pulse Width Modulation)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
2.PWM参数
- pwm的频率:是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期);也就是说一秒钟PWM有多少个周期
单位: Hz
表示方式: 50Hz 100Hz - pwm的周期:T=1/f(周期=1/频率),例如50Hz = 20ms 一个周期
如果频率为50Hz ,也就是说一个周期是20ms 那么一秒钟就有 50次PWM周期 - 占空比:是一个脉冲周期内,高电平的时间与整个周期时间的比例
单位: % (0%-100%)
表示方式:20%
脉宽时间占总周期时间的比例,就是占空比
3.基本原理
- PWM就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。
- 也可以这样理解,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。
- PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压;PWM频率越大,相应越快。
在下图的通用定时器框图中,主要涉及到最顶上的一部分(计数时钟的选择)、中间部分(时基单元)、右下部分(PWM输出)这三个部分。这里主要讲解一下右下部分(PWM输出):
在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值);
当CNT小于CCRx时,TIMx_CHx通道输出低电平;
当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平;
这个时候就可以对其下一个准确的定义了:所谓脉冲宽度调制模式(PWM模式),就是可以产生一个由TIMx_ARR寄存器确定频率,由TIMx_CCRx寄存器确定占空比的信号。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术
4.PWM输出模式的区别
PWM模式1:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)
PWM模式2:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平
注意:PWM的模式只是区别什么时候是有效电平,但并没有确定是高电平有效还是低电平有效。这需要结合CCER寄存器的CCxP位的值来确定。例如:若PWM模式1,且CCER寄存器的CCxP位为0,则当TIMx_CNT<TIMx_CCR1时,输出高电平;同样的,若PWM模式1,且CCER寄存器的CCxP位为2,则当TIMx_CNT<TIMx_CCR1时,输出低电平。
5.PWM产生
- 通过STM32控制板,有两种方式能产生PWM,第一是利用普通IO口输出PWM,第二种是利用定时器的PWM的IO口或复用IO口。
- STM32的定时器除了TIM6和7,其他的定时器都可以用来产生PWM输出。
- 其中高级定时器TIM1和TIM8可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出。
- 一般能够输出PWM的端口都会在主要功能那一栏出现CHx的标志,而普通定时器没有出现这种标志。
两者区别:
- 一般而言,尽量选用PWM口进行PWM输出,因为普通IO口模拟PWM的输出频率越高,进入定时器中断的次数就越快,中断间隔的时间越短,如果再有其他类型的中断也要处理时,会因为中断的优先级嵌套等待响应,影响控制精度,PWM输出误差增大,也会影响其他如ADC等中断处理,甚至会较出现单片机逻辑出错,死机或者跑飞的情况。
- 普通IO也可以输出PWM,只是产生PWM一般用转用芯片(开关电源上用的较多)或者单片机的PWM内置模块如定时器,很小直接用MCU的IO口线直接输出因为那样太耗MCU资源了。
7.PWM的计数模式
- 向上计数模式:当TIMx_CR1 寄存器中的DIR位为低的时候执行向上计数
下面是一个PWM模式1的例子。当TIMx_CNT<TIMx_CCRx时PWM信号参考OCxREF为高,否则为低。如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。如果比较值为0,则OCxREF保持为’0:
- 向下计数模式:当TIMx_CR1 寄存器的DIR位为高时执行向下计数。
在 PWM 模式 1,当 TIMx_CNT>TIMx_CCRx 时 OCxREF 为低,否则为高。如果
TIMx_CCRx 中的比较值大于 TIMx_ARR 中的自动重装载值,则 OCxREF 保持为
“1"。该模式下不能产生 0%的 PWM 波形。 - 中央对齐模式:当TIMx_CR1 寄存器中的CMS位不为 00 时为中央对齐模式(所有其他的配置对
OCxREF/OCx信号都有相同的作用)。
根据不同的CMS位的设置,比较标志可能在计数器向上计数时被置 1、在计数器向下计数时被置 1、或在计数器向上和向下计数时被置 1。。TIMx_CR1 寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。
图中给出了一些中央对齐的PWM波形的例子
TIMx_ARR=8
PWM 模式 1
TIMx_CR1 寄存器中的 CMS=01,在中央对齐模式 1 时,当计数器向下计
数时标志被设置
8.PWM相关配置寄存器
8.1 捕获/比较模式寄存器(TIMx_CCMR1)
作用
:在PWM输出模式下,确定PWM的模式、使能相应的预装载寄存器等操作
8.2 捕获/比较使能寄存器(TIMx_CCER)
作用
:在PWM输出模式下,确定PWM的输出极性和输出使能
8.3 捕获/比较寄存器(TIMx_CCR1)
作用
:在PWM输出模式下,确定比较的值
二、工程代码
1.用STM32CubeMx创建工程
1.1 创建新项目
点击ACCESS TO MCU SELECTOR,在Part Number里选择我们的核心板(STM32F103C8)
1.2 配置RCC和SYS
在目录System Core下选择RCC,将HSE改成Crystal/Ceramic Reasonator.
紧接着点击SYS,然后将Debug改成Serial Wire
1.3 配置定时器TIM3
- 勾选Internal Clock(内部时钟)
- 通道1选择:PWM Generation CH1(PWM输出通道1)
- Prtscaler (定时器分频系数) :
71
- Counter Mode(计数模式):
Up
(向上计数模式) - Counter Period(自动重装载值) :
500
- CKD(时钟分频因子) :
No Division
(不分频 )
1.4 配置定时器TIM4
TIM4配置与TIM3相同
1.5 配置时钟
点击CLOCK CONFIGURATION,然后将HCLK改为72Mhz,点击回车
1.6 生成项目
点击Project Manager,填写项目名称,并将IDE改为MDK-ARM,版本改为V5
点击Code Generator,进行如下勾选,然后点击GENERATE CODE
2.用Keil编写代码
2.1 定义变量
在main.c中定义一个全局变量
代码如下
uint16_t pwm=0; //占空比
2.2 打开PWM通道
在主函数中添加两行代码
代码如下
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
2.3 在while循环中写入调用代码
代码如下
while (pwm< 500)
{
pwm++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwm);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, pwm);
HAL_Delay(1);
}
while (pwm)
{
pwm--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, pwm);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, pwm);
HAL_Delay(1);
}
HAL_Delay(200);
三、运行结果
1.硬件连线
- USB转TTL
3V3 —> 3V3
GND —> GND
RXD —> A9
TXD —> A10
- LED灯连接
LED灯短脚 —> A6
LED灯长脚 —> 3V3
PB6 —> PC13
2.软件烧录
打开Flymcu:
3.结果展示
breathing lamp
总结
本篇博客主要是关于PWM的部分知识的初步了解,并用使用定时器的TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动的外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。
希望大家给博主多多支持,欢迎交流问题!
参考:https://blog.csdn.net/qq_45237293/article/details/111997424
https://blog.csdn.net/as480133937/article/details/103439546
https://blog.csdn.net/dgut13432976621/article/details/120062700