本帖最后由 正点原子运营 于 2024-4-7 16:56 编辑
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板
2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版
6)正点原子STM32技术交流QQ群:725095144
本章将介绍使用STM32F103通用定时器的输入捕获功能。通过本章的学习,读者将学习到通用定时器输入捕获的使用。 本章分为如下几个小节: 19.1 硬件设计 19.2 程序设计 19.3 下载验证
19.1 硬件设计 19.1.1 例程功能 1. 按下并松开WKUP按键,串口输出WKUP被按下的时长 2. LED0闪烁,提示程序正在运行
19.1.2 硬件资源 1. LED LED0 - PB5 2. 按键 WKUP - PA0 3. TIM5 CH1 - PA0 4. USART1 USART1_TX - PA9 USART1_RX - PA10
19.1.3 原理图 本章实验使用的TIM5为STM32F103的片上资源,因此没有对应的连接原理图。
19.2 程序设计 19.2.1 HAL库的TIM驱动 本章实验将使用TIM5的通道1捕获WKUP按键被按下的高电平脉冲宽度,具体的步骤如下: ①:初始化定时器输入捕获 ②:配置定时器输入捕获通道 ③:开始定时器输入捕获 在HAL库中对应的驱动函数如下: ①:初始化定时器输入捕获 该函数用于初始化定时器输入捕获,其函数原型如下所示: - HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim);
复制代码该函数的形参描述,如下表所示: 表19.2.1.1 函数HAL_TIM_IC_Init()形参描述 该函数的返回值描述,如下表所示: 表19.2.1.2 函数HAL_TIM_IC_Init()返回值描述 该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- TIM_HandleTypeDef tim_handle = {0};
-
- /* 初始化TIM5输入捕获 */
- tim_handle.Instance = TIM5;
- tim_handle.Init.Prescaler = 72 - 1;
- tim_handle.Init.Period = 0xFFFF;
- HAL_TIM_IC_Init(&tim_handle);
- }
复制代码②:配置定时器输入捕获通道 该函数用于配置定时器的输入捕获通道,其函数原型如下所示: - HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel( TIM_HandleTypeDef *htim,TIM_IC_InitTypeDef*sConfig, uint32_t Channel);
复制代码该函数的形参描述,如下表所示: 表19.2.1.3 函数HAL_TIM_IC_ConfigChannel()形参描述 该函数的返回值描述,如下表所示: 表19.2.1.4 函数HAL_TIM_IC_ConfigChannel()返回值描述 该函数使用TIM_IC_InitTypeDef类型结构体指针传入了定时器输入捕获通道的配置参数,该结构体的定义如下所示: - typedef struct
- {
- uint32_t ICPolarity; /* 输入捕获极性 */
- uint32_t ICSelection; /* 输入 */
- uint32_t ICPrescaler; /* 输入分频系数 */
- uint32_t ICFilter; /* 输入滤波 */
- } TIM_IC_InitTypeDef;
复制代码该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- TIM_IC_InitTypeDeftim_ic_init_struct = {0};
-
- /* 配置定时器通道1输入捕获 */
- tim_ic_init_struct.ICPolarity =TIM_ICPOLARITY_RISING;
- tim_ic_init_struct.ICSelection =TIM_ICSELECTION_DIRECTTI;
- tim_ic_init_struct.ICPrescaler = TIM_ICPSC_DIV1;
- tim_ic_init_struct.ICFilter = 0;
- HAL_TIM_IC_ConfigChannel(&tim_handle, &tim_ic_init_struct, TIM_CHANNEL_1);
- }
复制代码③:开始定时器中断模式输入捕获 该函数用于开始定时器中断模式输入捕获,其函数原型如下所示: - HAL_StatusTypeDef HAL_TIM_IC_Start_IT( TIM_HandleTypeDef *htim,uint32_t Channel);
复制代码该函数的形参描述,如下表所示: 表19.2.1.5 函数HAL_TIM_IC_Start_IT()形参描述 该函数的返回值描述,如下表所示: 表19.2.1.6 函数HAL_TIM_IC_Start_IT()返回值描述 该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- /* 开启定时器通道1中断模式输入捕获 */
- HAL_TIM_IC_Start_IT(&tim_handle, TIM_CHANNEL_1);
- }
复制代码19.2.2通用定时器驱动 本章实验的通用定时器驱动主要负责向应用层提供通用定时器的初始化函数,并实现通用定时器的中断回调函数。本章实验中,通用定时器的驱动代码包括gtim.c和gtim.h两个文件。 通用定时器驱动中,对TIM、GPIO的相关宏定义,如下所示: - #define GTIM_TIMX_CAP TIM5
- #define GTIM_TIMX_CAP_IRQn TIM5_IRQn
- #define GTIM_TIMX_CAP_IRQHandler TIM5_IRQHandler
- #define GTIM_TIMX_CAP_CLK_ENABLE() \
- do { \
- __HAL_RCC_TIM5_CLK_ENABLE(); \
- }while (0)
- #define GTIM_TIMX_CAP_CHY TIM_CHANNEL_1
- #define GTIM_TIMX_CAP_CHY_GPIO_PORT GPIOA
- #define GTIM_TIMX_CAP_CHY_GPIO_PIN GPIO_PIN_0
- #define GTIM_TIMX_CAP_CHY_GPIO_CLK_ENABLE() \
- do { \
- __HAL_RCC_GPIOA_CLK_ENABLE(); \
- }while (0)
复制代码通用定时器驱动中TIM5的初始化函数,如下所示: - /**
- *@brief 初始化通用定时器输入捕获
- *@param arr: 自动重装载值
- *@param psc: 预分频系数
- *@retval 无
- */
- voidgtim_timx_cap_chy_init(uint16_t arr, uint16_t psc)
- {
- TIM_IC_InitTypeDef timx_ic_cap_struct = {0};
-
- /* 初始化定时器输入捕获 */
- g_timx_cap_handle.Instance = GTIM_TIMX_CAP;
- g_timx_cap_handle.Init.Prescaler = psc;
- g_timx_cap_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
- g_timx_cap_handle.Init.Period = arr;
- HAL_TIM_IC_Init(&g_timx_cap_handle);
- /* 配置定时器输入捕获通道 */
- timx_ic_cap_struct.ICPolarity = TIM_ICPOLARITY_RISING;
- timx_ic_cap_struct.ICSelection = TIM_ICSELECTION_DIRECTTI;
- timx_ic_cap_struct.ICPrescaler = TIM_ICPSC_DIV1;
- timx_ic_cap_struct.ICFilter = 0;
- HAL_TIM_IC_ConfigChannel( &g_timx_cap_handle,
- &timx_ic_cap_struct,
- GTIM_TIMX_CAP_CHY);
- /* 开始定时器中断模式输入捕获 */
- __HAL_TIM_ENABLE_IT(&g_timx_cap_handle, TIM_IT_UPDATE);
- HAL_TIM_IC_Start_IT(&g_timx_cap_handle, GTIM_TIMX_CAP_CHY);
- }
复制代码从TIM5的初始化代码中可以看到,初始化函数中初始化了TIM5的输入捕获并配置了TIM5的输入捕获通道1,最后开始TIM5的中断模式输入捕获。
19.2.3 实验应用代码 本章实验的应用代码,如下所示: - int main(void)
- {
- uint32_t total = 0;
- uint8_t t = 0;
-
- HAL_Init(); /* 初始化HAL库 */
- sys_stm32_clock_init(RCC_PLL_MUL9); /* 配置时钟,72MHz */
- delay_init(72); /* 初始化延时 */
- usart_init(115200); /* 初始化串口 */
- led_init(); /* 初始化LED */
- gtim_timx_cap_chy_init(0xFFFF, 72 - 1); /* 初始化通用定时器输入捕获 */
-
- while (1)
- {
- /* 捕获完成 */
- if ((g_timx_chy_cap_sta & 0x80) != 0)
- {
- /* 计算总捕获到的计数值 */
- total = g_timx_chy_cap_sta & 0x3F;
- total *= 0xFFFF;
- total += g_timx_chy_cap_val;
- printf("High: %dus\r\n", total);
-
- /* 开启下一次输入捕获 */
- g_timx_chy_cap_sta = 0;
- }
- if (++t == 20)
- {
- t = 0;
- LED0_TOGGLE();
- }
-
- delay_ms(10);
- }
- }
复制代码从上面的代码中可以看到,TIM5的预分频系数被配置为(72-1),同时因为TIM5的时钟频率为72MHz,因此TIM5的计数频率为1MHz,因此在TIM5成功捕获到外部输入信号的高电平后,可以直接计算出捕获到高电平的脉宽时间。
19.3 下载验证 在完成编译和烧录操作后,短暂按下并抬起WKUP按键,可以通过串口调试助手观察到捕获到的WKUP按键被按下的时间。 |