使用TIM3和TIM4,分别输出一个PWM波形,驱动一个外接的LED灯以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果
文章目录
前言
- STM32的通用定时器分为TIM2、TIM3、TIM4、TIM5,而每个定时器都有独立的4个通道可以用来作为:
输入捕获、输出比较、PWM输出、单脉冲模式输出
等 - STM32的定时器除了TIM6和TIM7(基本定时器)之外,其他的定时器都可以产生PWM输出。其中,高级定时器TIM1、TIM8可以同时产生7路
PWM输出
,而通用定时器可以同时产生4路PWM输出,这样STM32最多可以同时产生30路PWM输出!
一、PWM简介
1. 定义
脉冲宽度调制(PWM)
是一种数字信号,最常用于控制电路。该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。
2. 主要参数
PWM占空比
:
PWM信号保持高电平的时间百分比称为占空比。如果信号始终为高电平,则它处于100%占空比,如果它始终处于低电平,则占空比为0%。如图1所示,T1为占空比,T为一个PWM周期PWM的频率
:
PWM信号的频率决定PWM完成一个周期的速度。STM32的MDK编译器可以选择5MHZ,10MHZ,20MHZ和50MHZ
3. PWM产生方式
- 通过STM32控制板,有两种方式能产生PWM,第一是利用
普通IO口输出PWM
,第二种是利用定时器的PWM的IO口或复用IO口
。
3.1 普通IO口与PWM口
3.1 PWM端口
- STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出
3.2 普通IO口
- 一般能够输出PWM的端口都会在主要功能那一栏出现CHx的标志,而普通定时器没有出现这种标志。如图所示,上面的红框就是普通的定时器,不是专用的PWM端口
3.3 两者区别
- 一般而言,
尽量选用PWM口进行PWM输出
,因为普通IO口模拟PWM的输出频率越高,进入定时器中断的次数就越快,中断间隔的时间越短,如果再有其他类型的中断也要处理时,会因为中断的优先级嵌套等待响应,影响控制精度,PWM输出误差增大,也会影响其他如ADC等中断处理,甚至会较出现单片机逻辑出错,死机或者跑飞的情况 - 普通IO也可以输出PWM,只是产生PWM一般用转用芯片(开关电源上用的较多)或者单片机的PWM内置模块如定时器,很小直接用MCU的IO口线直接输出因为那样太耗MCU资源了
3.4 STM32f103c8t6的PWM口
- 因为自己在用stm32最小系统,因此在此贴出其PWM口配置
不是所有的芯片都有重映像功能的
,STM32f103c8t6这四个定时器就不需要重映像- 后续匹配相关引脚可查看下图对应查找:
详细配置如下:
TIM1_CH1->PA8;
TIM1_CH2->PA9;
TIM1_CH3->PA10;
TIM1_CH4->PA11;
TIM2_CH1->PA0;
TIM2_CH2->PA1;
TIM2_CH3->PA2;
TIM2_CH4->PA3;
TIM3_CH1->PA6;
TIM3_CH2->PA7;
TIM3_CH3->PB0;
TIM3_CH4->PB1;
TIM4_CH1->PB6;
TIM4_CH1->PB7;
TIM4_CH1->PB8;
TIM4_CH1->PB9;
4. PWM的工作原理
- 在下图的通用定时器框图中,主要涉及到最顶上的一部分(计数时钟的选择)、中间部分(时基单元)、右下部分(
PWM输出
)这三个部分。这里主要讲解一下右下部分(PWM输出):
- 下面以向上计数为例,简单地讲述一下PWM的工作原理:
- 在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值);
- 当CNT小于CCRx时,TIMx_CHx通道输出低电平;
- 当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平;
- 这个时候就可以对其下一个准确的定义了:所谓脉冲宽度调制模式(PWM模式),就是可以产生一个
由TIMx_ARR寄存器确定频率
,由TIMx_CCRx寄存器确定占空比的信号。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术
5. PWM的通道概览
- 每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器),包括捕获的输入部分(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)
- 捕获/比较模块由一个预装载寄存器和一个影子寄存器组成。读写过程仅操作预装载寄存器
- 在捕获模式下,捕获发生在影子寄存器上,然后再复制到预装载寄存器中。
在比较模式下,预装载寄存器的内容被复制到影子寄存器中,然后影子寄存器的内容和计数器进行比较
6. 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时,输出低电平
7. PWM的计数模式
向上计数模式:
下面是一个PWM模式1的例子。当TIMx_CNT<TIMx_CCRx时PWM信号参考OCxREF为高,否则为低。如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。如果比较值为0,则OCxREF保持为’0’:
向下计数模式:
在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)由硬件更新,不要用软件修改它。
8. PWM相关配置寄存器
- 捕获/比较模式寄存器总共2个,
TIMx_CCMR1和TIMx_CCMR2
- TIMx_CCMR1控制CH1和CH2,TIMx_CCMR2控制CH3和CH4。该寄存器的某些位在不同模式下功能不一样,上面一层对应输出而下面一层对应输入
- 其中模式设置位OCxM位,此位由3位组成,一共可以配置成7种模式,我们使用的是PWM模式,所以这三位必须为110/111
8.1 捕获/比较模式寄存器(TIMx_CCMR1)
作用:
在PWM输出模式下,确定PWM的模式、使能相应的预装载寄存器等操作:
8.2 捕获/比较使能寄存器(TIMx_CCER)
作用:
在PWM输出模式下,确定PWM的输出极性和输出使能:
8.3 捕获/比较寄存器(TIMx_CCR1)
作用:
在PWM输出模式下,确定比较的值:
9. PWM的一般步骤
- 使能定时器和相关IO口时钟。调用函数:RCC_APB1PeriphClockCmd()
- RCC_APB2PeriphClockCmd();
- 初始化IO口为复用功能输出。调用函数:GPIO_Init();
- 这里是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,所以需要开启AFIO时钟,同时设置重映射;调用函数:RCC_APB2PeriphClockCmd();GPIO_PinRemapConfig();
- 初始化定时器。调用函数:ARR,PSC等:TIM_TimeBaseInit();
- 初始化输出比较参数。调用函数:TIM_OC2Init();
- 使能预装载寄存器。调用函数:TIM_OC2PreloadConfig();
- 使能定时器。调用函数:TIM_Cmd();
- 不断改变比较值CCRx,达到不同的占空比效果;调用函TIM_SetCompare2()
二、工程文件创建
1. 创建新项目
- 在STMCubeMX主界面,点击
ACCEE TO MCU SELECTOR
:
- 在
Part Number
里选择STM32F103C8T6
,选中芯片,点击start project
:
2. 项目环境配置
2.1 配置RCC与SYS
-
点System Cor,选择
RCC
,在右侧弹出的菜单栏中选Crystal/Ceramic Resonator
:
-
选择调试接口,点System Cor,选择
SYS
。,在右侧弹出的菜单栏中选Serial Wire:
2.2 配置TIM3
- 选
Internal Clock
(内部时钟) - 通道1选择:
PWM Generation CH1
(PWM输出通道1) - Prtscaler (定时器分频系数) :
71
- Counter Mode(计数模式):
Up
(向上计数模式) - Counter Period(自动重装载值) :
500
- CKD(时钟分频因子) :
No Division
(不分频 )
2.3 配置TIM4
- 这里的配置与配置TIM3相似:
2.4 配置时钟树
- 如下图设置即可:
3. 工程文件配置
- 配置项目名称与位置:
- 项目生成:
4. Keil代码编写
4.1 在main.c文件添加变量
- 代码如下:
uint16_t pwm=0; //占空比
4.2 开启TIM3和TIM4的PWM的通道1
- 代码如下:
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
4.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. 线路连接
-
3V3 —> 3V3
-
GND —> GND
-
RXD —> A9
-
TXD —> A10
-
LED灯短脚 —> A6
-
LED灯长脚 —> 3V3
-
PB6 —> PC13
2. 代码烧录
- 打开FlyMcu:
3. 效果展示
- 效果视频如下:
呼吸灯
总结
通过这次实例演训,学习到了PWM的相关理论知识,以及在STM32F103C8T6核心开发板下,通过TIM3和TIM4输出PWM波形实现2个 LED呼吸灯效果的操作步骤;
在实操过程中,由于对于STM32引脚的不熟悉,导致多次PWM引脚匹配失败,但通过网上查阅相关资料,最终完成了本次实验作业!
同时也期待大家能够积极留言,指出我存在的问题,谢谢!
参考文献:
https://blog.csdn.net/Qxiaofei_/article/details/119059623
https://blog.csdn.net/dgut13432976621/article/details/120062700