本帖最后由 正点原子运营 于 2024-4-1 17:46 编辑
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板
2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版
6)正点原子STM32技术交流QQ群:725095144
STM32F103内部有多种多个定时器(TIM),本章介绍STM32F103基本定时器的使用,基本定时器是一类只能实现定时功能、没有外部接口的定时器。通过本章的学习,读者将学习到基本定时器的使用。 本章分为如下几个小节: 16.1 硬件设计 16.2 程序设计 16.3 下载验证
16.1 硬件设计 16.1.1 例程功能 1. LED1以1Hz的频率闪烁 2. LED0闪烁,提示程序正在运行
16.1.2 硬件资源 1. LED LED0 - PB5 LED1 - PE5 2. TIM6
16.1.3 原理图 本章实验使用的TIM6为STM32F103的片上资源,因此并没有相应的连接原理图。
16.2 程序设计 16.2.1 HAL库的TIM驱动 本章实验将配置TIM6每间隔500毫秒产生一次中断,并在其中断服务函数中改变一次LED1的状态,具体的步骤如下: ①:初始化TIM6 ②:开启TIM6中断模式计数 在HAL库中对应的驱动函数如下: ①:初始化TIM 该函数用于初始化TIM的各项参数,其函数原型如下所示: - HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
复制代码该函数的形参描述,如下表所示: 表16.2.1.1 函数HAL_TIM_Base_Init()形参描述 该函数的返回值描述,如下表所示: 表16.2.1.2 函数HAL_TIM_Base_Init()返回值描述 该函数需要传入TIM的句柄指针,该句柄中就包含了TIM的初始化配置参数结构体,该结构体的定义如下所示: - typedef struct
- {
- uint32_t Prescaler; /* 分频系数 */
- uint32_t CounterMode; /* 计数模式 */
- uint32_t Period; /* 重装载值 */
- uint32_t ClockDivision; /* 计数分频 */
- uint32_t RepetitionCounter; /* 重复计数器 */
- uint32_t AutoReloadPreload; /* 自动重装载 */
- }TIM_Base_InitTypeDef;
复制代码该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- TIM_HandleTypeDef tim_handle = {0};
-
- /* 初始化TIM6 */
- tim_handle.Instance = TIM6;
- tim_handle.Init.Prescaler = 72 - 1;
- tim_handle.Init.Period = 1000 - 1;
- HAL_TIM_Base_Init(&tim_handle);
- }
复制代码②:开启TIM中断模式计数 该函数用于开启TIM中断模式计数,其函数原型如下所示: - HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
复制代码该函数的形参描述,如下表所示: 表16.2.1.3 函数HAL_TIM_Base_Start_IT()形参描述 该函数的返回值描述,如下表所示: 表16.2.1.4 函数HAL_TIM_Base_Start_IT()返回值描述 该函数的使用示例,如下所示: - #include "stm32f1xx_hal.h"
- void example_fun(void)
- {
- /* 开启TIM6中断模式计数 */
- HAL_TIM_Base_Start_IT(&tim_handle);
- }
复制代码16.2.2 基本定时器驱动 本章实验的基本定时器驱动主要负责向应用层提供基本定时器的初始化函数,并实现基本定时器的中断回调函数。本章实验中,基本定时器的驱动代码包括btmr.c和btmr.h两个文件。 基本定时器驱动中,对TIM的相关宏定义,如下所示: - #define BTIM_TIMX_INT TIM6
- #define BTIM_TIMX_INT_IRQn TIM6_DAC_IRQn
- #define BTIM_TIMX_INT_IRQHandler TIM6_DAC_IRQHandler
- #define BTIM_TIMX_INT_CLK_ENABLE() \
- do { \
- __HAL_RCC_TIM6_CLK_ENABLE(); \
- } while (0)
复制代码基本定时器驱动中TIM6的初始化函数,如下所示: - /**
- *@brief 初始化基本定时器
- *@param arr: 自动重装载值
- *@param psc: 预分频系数
- *@retval 无
- */
- voidbtim_timx_int_init(uint16_t arr, uint16_t psc)
- {
- g_timx_handle.Instance =BTIM_TIMX_INT;
- g_timx_handle.Init.Prescaler = psc;
- g_timx_handle.Init.Period = arr;
- HAL_TIM_Base_Init(&g_timx_handle);
- HAL_TIM_Base_Start_IT(&g_timx_handle);
- }
复制代码从TIM6的初始化代码中可以看到,该函数调用了函数HAL_TIM_Base_Init()和函数HAL_TIM_Base_Start_IT()分别用来初始化TIM6和开启了TIM6的中断模式计数。 基本定时器驱动中TIM6的计数溢出回调函数,如下所示: - /**
- *@brief HAL库基本定时器超时中断回调函数
- *@param 无
- *@retval 无
- */
- voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if (htim->Instance == BTIM_TIMX_INT)
- {
- LED1_TOGGLE();
- }
- }
复制代码从上面的代码中可以看出,在TIM6每次计数溢出后都会翻转一次LED1的状态。
16.2.3 实验应用代码 本章实验的应用代码,如下所示: - int main(void)
- {
- HAL_Init(); /* 初始化HAL库 */
- sys_stm32_clock_init(RCC_PLL_MUL9); /* 配置时钟,72MHz */
- delay_init(72); /* 初始化延时 */
- usart_init(115200); /* 初始化串口 */
- led_init(); /* 初始化LED */
- btim_timx_int_init(5000 - 1, 7200 - 1); /* 初始化基本定时器,溢出频率为2Hz */
-
- while (1)
- {
- LED0_TOGGLE();
- delay_ms(200);
- }
- }
复制代码从上面的代码中可以看到,TIM6的自动重装载配置为(5000-1),TIM6的预分频器数值配置为(7200-1),并且TIM6的时钟频率为72MHz,因此TIM6的计数频率为10KHz,且TIM6计数5000次溢出一次,因此溢出频率为2Hz,又因为TIM6每溢出一次都会改变一次LED1的状态,因此LED1的闪烁频率为1Hz。
16.3 下载验证 在完成编译和烧录操作后,可以看到板子上的LED0和LED1都在闪烁,但闪烁频率不同,LED0每间隔200毫秒改变一次状态,LED1在TIM6的中断回调函数中被改变状态,其闪烁的频率约为1Hz。 |