温馨提示:
本文不会重复之前提到的内容,如需查看,请参考附录
目录
内容提炼:
PWM输出很简单,只需要记住CubeMX中3个具体量的设置,以及使用三个函数就可以玩转PWM输出。
配置:
- 通过设置 Prescaler 来设置定时器频率
- 通过设置 Counter Period 来设置周期
- 通过设置 Pulse 来设置占空比
- 通过设置 CH Polarity 来设置极性
PWM波的频率设置计算公式:
周期 = 定时器频率/PWM波的频率
预分频系数 = (APB1 Timer/定时器频率 )-1;
一般直接另周期为1,这样,令 定时器频率 = PWM波的频率 即可,只需要设置预分频系数。
如:设置PWM的频率为8KHz:
由于APB1 Timer=50MHz,
所以 预分频系数 = (50MHz/8KHz)-1 = 6249
函数:
在进入主循环之前以中断方式启动TIM16。
使用函数:
HAL_TIM_Base_Start_IT(设备句柄地址);
然后以中断方式启动生成PWM。
使用函数:
HAL_TIM_PWM_Start_IT(设备句柄地址,通道号);
我们可以动态改变脉宽值的方式来改变占空比
使用函数:
__HAL_TIM_SET_COMPARE(设备句柄地址,通道号,脉宽值);
理论知识:
由于本文章针对蓝桥杯比赛,所以原理性的部分不再赘述。当然,了解原理会更好,不过不了解原理也可以操作,只要按照套路来就行。原理可参考以下文章:
STM32—PWM原理及配置(入门详解)_stm32pwm配置详解-CSDN博客
要生成一个确定的PWM波,需要三个元素,周期、占空比、极性。只要会设置和改变这三个量,就可以玩转PWM波输出。
我们可以动态改变脉宽值的方式来改变占空比
使用函数:
__HAL_TIM_SET_COMPARE(设备句柄地址,通道号,脉宽值);
下面要求编写一个警示灯例程,由于板载的LED是由外部芯片控制的,所以这里用PA6引脚来控制外加的LED(如果你会玩蜂鸣器的话,可以它用来代替LED)
一、需求分析
1、需要的外设资源分析:
- 选择TIM16作为PWM输出定时器,TIM16只有一个通道——PA6。
- 外加材料:面包板一块、双向公头杜邦线两根、LED一颗、300~500R的电阻一个。
LED负极连接PA6,正极接3.3V电源,连线如下图所示:
2、外设具体分析:
查看原理图,和手册
由手册可知:
- 通过设置 Counter Period 来设置周期
- 通过设置 Pulse 来设置占空比
- 通过设置 CH Polarity 来设置极性
3、软件分析:
要求分析:使LED灯产生呼吸灯的效果。
功能分析:需要不断改变PWM的占空比让占空比进入先增大再减小然后再增大的循环,这一操作可以在PWM的中断回调函数里实现。
二、软件配置
参考附录的内容,新建名为“PWM_Out_Demo”的项目。
时钟配置:将APB1 timer clocks设置为50MHz
按照分析配置TIM16:
先启用TIM16的通道1,设置为PWM输出模式:
然后配置 Parameter Settings :
- 设置 Prescaler 为49999
- 设置 Counter Period 为199
- 设置 Pulse 为5
- 设置 CH Polarity 为High
结果如图:
然后打开TIM16全局中断,设置优先级为1。
生成项目文件后,打开MDK。
三、代码编写
分析:
在进入主循环之前以中断方式启动TIM16。
使用函数:
HAL_TIM_Base_Start_IT(设备句柄地址);
然后以中断方式启动生成PWM。
使用函数:
HAL_TIM_PWM_Start_IT(设备句柄地址,通道号);
代码如下:
main.c
/* USER CODE BEGIN WHILE */
HAL_TIM_Base_Start_IT(&htim16);
HAL_TIM_PWM_Start_IT(&htim16,TIM_CHANNEL_1);
while (1)
{
/* USER CODE END WHILE */
然后找到中断回调函数,在stm32g4xx_it.c文件用Find中搜索:TIM16
找到TIM16的中断服务函数:
void TIM1_UP_TIM16_IRQHandler(void)
全局定义一个表示脉宽的变量,初始化为50。定义一个标志位。
在中断服务函数中实现:利用连续中断的特性(相当于循化),让脉宽递增到195然后递减到5,之后再递增到195,每次都改变PWM波脉宽的值从而改变占空比。
代码如下:
stm32g4xx_it.c
/**
* @brief This function handles TIM1 update interrupt and TIM16 global interrupt.
*/
void TIM1_UP_TIM16_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_UP_TIM16_IRQn 0 */
/* USER CODE END TIM1_UP_TIM16_IRQn 0 */
HAL_TIM_IRQHandler(&htim16);
/* USER CODE BEGIN TIM1_UP_TIM16_IRQn 1 */
if(flag)
{
pulseWidth++;
if(pulseWidth >= 195)
flag=0;
}
else
{
pulseWidth--;
if(pulseWidth <= 5)
flag=1;
}
__HAL_TIM_SET_COMPARE(&htim16,TIM_CHANNEL_1,pulseWidth);
/* USER CODE END TIM1_UP_TIM16_IRQn 1 */
}
四、运行测试
编译、下载。
运行结果:
PWM呼吸灯实验现象