【STM32定时器】实验3:定时器输出比较PWM:呼吸灯(CuBeMX版)+PWM相关函数解析
本实验基于STM32F407ZGT6,利用定时器14的输出比较功能生成PWM波控制LED实现呼吸灯效果。通过CubeMX配置定时器14的时钟源、时基单元和PWM模式,设置PF9引脚为TIM14_CH1输出,并启用串口输出CCR值。实验分析了PWM生成步骤,包括时钟使能、定时器初始化、PWM模式配置等,重点解读了HAL_TIM_PWM_Start()函数的工作原理,该函数通过操作捕获/比较使能寄存器
Timer实验3:定时器输出比较PWM:呼吸灯(CuBeMX版)+PWM相关函数解析
文章目录
1、实验目的
结合定时器的输出比较功能,使其产生PWM波,控制两个小灯呈现为呼吸状态
有关定时器理论部分,详见【STM32学习笔记】Timer总结:从模式控制器、时基单元、输入捕获、输出比较
2、配置CuBeMX
1)选择MCU
使用STM32F407ZGT6

2)配置时钟和调试接口



3)配置定时器
通过查看该单片机的电路原理图,其两个LED灯连接方式如下:

LED0对应PF9管脚
LED1对应PF10管脚
查看数据手册可得,PF9可对应TIM14_CH1,所以该实验选择定时器14,定时周期还设置为1ms,同时定时器14挂载在APB1上

4)配置串口
配置串口,输出捕获/比较寄存器(CCR)的值

串口的详细配置,详见:
【STM32学习笔记】串口总结:串口轮询模式、串口中断模式、串口DMA模式以及串口接收不定长数据
5)配置路径生成代码


3、PWM步骤
1)开启 TIM14 和 GPIO 时钟,配置 PF9 选择复用功能 AF9(TIM14)输出。
2)初始化 TIM14,设置 TIM14 的 ARR 和 PSC 等参数。
3)设置 TIM14_CH1 的 PWM 模式,使能 TIM14 的 CH1 输出。
HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
TIM_OC_InitTypeDef *sConfig,
uint32_t Channel)
4)使能 TIM14。
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
5)修改 TIM14_CCR1 来控制占空比。
4、相关语句分析
1)开启PWM
/**
* @brief Starts the PWM signal generation.
* @param htim TIM handle
* @param Channel TIM Channels to be enabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
该函数输入参数上面已作解释
在该函数里主要包括了使能捕获/比较通道、使能定时器,如下图所示:

展开使能捕获/比较通道函数TIM_CCxChannelCmd为:
/**
* @brief Enables or disables the TIM Capture Compare Channel x.
* @param TIMx to select the TIM peripheral
* @param Channel specifies the TIM Channel
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1
* @arg TIM_CHANNEL_2: TIM Channel 2
* @arg TIM_CHANNEL_3: TIM Channel 3
* @arg TIM_CHANNEL_4: TIM Channel 4
* @param ChannelState specifies the TIM Channel CCxE bit new state.
* This parameter can be: TIM_CCx_ENABLE or TIM_CCx_DISABLE.
* @retval None
*/
void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
{
uint32_t tmp;
/* Check the parameters */
assert_param(IS_TIM_CC1_INSTANCE(TIMx));
assert_param(IS_TIM_CHANNELS(Channel));
tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
/* Reset the CCxE Bit */
TIMx->CCER &= ~tmp;
/* Set or reset the CCxE Bit */
TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
}
该函数的主要功能为使能或者关闭定时器的捕获/比较通道,是对 捕获/比较使能寄存器 (TIMx_CCER) 的操作,高级定时器的捕获/比较使能寄存器 (TIMx_CCER) 如下图,16位的寄存器每四位控制一个捕获/比较通道,其中CCxE控制OCx信号是否输出,该函数主要对此位进行操作。


输入的第二个参数为捕获/比较通道标识符,具体定义如下:
/** @defgroup TIM_Channel TIM Channel
* @{
*/
#define TIM_CHANNEL_1 0x00000000U /*!< Capture/compare channel 1 identifier */
#define TIM_CHANNEL_2 0x00000004U /*!< Capture/compare channel 2 identifier */
#define TIM_CHANNEL_3 0x00000008U /*!< Capture/compare channel 3 identifier */
#define TIM_CHANNEL_4 0x0000000CU /*!< Capture/compare channel 4 identifier */
#define TIM_CHANNEL_ALL 0x0000003CU /*!< Global Capture/compare channel identifier */
输入的第三个参数为通道使能状态:
/** @defgroup Channel_CC_State TIM Capture/Compare Channel State
* @{
*/
#define TIM_CCx_ENABLE 0x00000001U /*!< Input or output channel is enabled */
#define TIM_CCx_DISABLE 0x00000000U /*!< Input or output channel is disabled */
#define TIM_CCxN_ENABLE 0x00000004U /*!< Complementary output channel is enabled */
#define TIM_CCxN_DISABLE 0x00000000U /*!< Complementary output channel is enabled */
/**
有以上定义后,我们对TIM_CCxChannelCmd函数进行详细介绍:
tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
TIM_CCER_CC1E是通道1的使能位掩码(通常为0x0001)。- 结合上面TIM_CHANNEL_x的定义值,可计算目标通道的使能位位置:
TIM_CHANNEL_1→ 移位0位 →tmp = 0x0001TIM_CHANNEL_2→ 移位4位 →tmp = 0x0010TIM_CHANNEL_3→ 移位8位 →tmp = 0x0100TIM_CHANNEL_4→ 移位12位 →tmp = 0x1000- 关键:STM32的
CCER寄存器中,每个通道的使能位(CCxE)间隔4位(详见上面捕获/比较使能寄存器 (TIMx_CCER) 的图)。
/* Reset the CCxE Bit */
TIMx->CCER &= ~tmp;
- 先清除当前通道的使能状态,为后续设置做准备。
/* Set or reset the CCxE Bit */
TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
- 若
ChannelState = TIM_CCx_ENABLE(通常为1):
- 将
1左移相同位数后写入CCER,使能目标通道。- 若
ChannelState = TIM_CCx_DISABLE(通常为0):
- 左移结果为0,
|=操作不改变寄存器值(保持第二步的清零状态)。
使能定时器函数已在前面实验介绍过,不展开了,详见:【STM32定时器】实验1:定时器基本用法(CuBeMX版)+启动函数解析中相关部分
2)设置通道的 PWM 模式函数—— HAL_TIM_PWM_ConfigChannel
/**
* @brief Initializes the TIM PWM channels according to the specified
* parameters in the TIM_OC_InitTypeDef.
* @param htim TIM PWM handle
* @param sConfig TIM PWM configuration structure
* @param Channel TIM Channels to be configured
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
TIM_OC_InitTypeDef *sConfig,
uint32_t Channel)
第一个参数 htim 是定时器初始化句柄,也就是 TIM_HandleTypeDef 结构体指针类型,这 和 HAL_TIM_PWM_Init 函数调用时候参数保存一致即可。
第二个参数 sConfig 是 TIM_OC_InitTypeDef 结构体指针类型,这也是该函数最重要的参数。 该参数用来设置 PWM 输出模式,极性,比较值等重要参数。首先我们来看看结构体定义:
/**
* @brief TIM Output Compare Configuration Structure definition
*/
typedef struct
{
uint32_t OCMode; /*!< Specifies the TIM mode.
This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
uint32_t OCPolarity; /*!< Specifies the output polarity.
This parameter can be a value of @ref TIM_Output_Compare_Polarity */
uint32_t OCNPolarity; /*!< Specifies the complementary output polarity.
This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
@note This parameter is valid only for timer instances supporting break feature. */
uint32_t OCFastMode; /*!< Specifies the Fast mode state.
This parameter can be a value of @ref TIM_Output_Fast_State
@note This parameter is valid only in PWM1 and PWM2 mode. */
uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_Idle_State
@note This parameter is valid only for timer instances supporting break feature. */
uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
@note This parameter is valid only for timer instances supporting break feature. */
} TIM_OC_InitTypeDef;
该结构体成员我们重点关注前三个。成员变量 OCMode 用来设置模式,也就是我们前面讲解的 7 种模式,这里我们设置为 PWM 模式 1。
成员变量 Pulse 用来设置捕获比较值。
成员变量 OCPolarity 用 来 设 置 输 出 极 性 是 高 还 是 低 。
第 三 个 参 数 Channel 用 来 选 择 定 时 器 的 通 道 , 取 值 范 围 为 TIM_CHANNEL_1~ TIM_CHANNEL_4。
5、整体代码
参数定义
/* USER CODE BEGIN PV */
char message[20];
/* USER CODE END PV */
main函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM14_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim14, TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
for(int i = 0; i<1000; i++){
uint32_t cc_value = __HAL_TIM_GET_COMPARE(&htim14, TIM_CHANNEL_1); //»ñÈ¡µ±Ç°¼Ä´æÆ÷Öµ
sprintf(message, "%d\r\n", cc_value);
HAL_UART_Transmit(&huart1, (uint8_t*)message, strlen(message), HAL_MAX_DELAY); //´®¿Ú·¢ËÍ
__HAL_TIM_SET_COMPARE(&htim14, TIM_CHANNEL_1, i); //ÉèÖüĴæÆ÷Öµ
HAL_Delay(9); //ÑÓʱ10ms
}
for(int i = 999; i>=0; i--){
uint32_t cc_value = __HAL_TIM_GET_COMPARE(&htim14, TIM_CHANNEL_1);
sprintf(message, "%d\r\n", cc_value);
HAL_UART_Transmit(&huart1, (uint8_t*)message, strlen(message), HAL_MAX_DELAY);
__HAL_TIM_SET_COMPARE(&htim14, TIM_CHANNEL_1, i);
HAL_Delay(9);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
6、实验结果
呼吸灯就不上传了
7、结语
学习记录,欢迎批评指正
更多推荐



所有评论(0)