定时器作为单片机不可或缺的外设,当然也是学习单片机时重要的知识点,但是STM32单片机的定时器非常多而且结构复杂。*其中在STM32F4中,共有14个定时器,定时器分为通用定时器,基本定时器和高级定时器。*我将通过三章分别进行讲解。本章我将先简单介绍一下基本定时器的特性及其HAL库函数,然后通过工程配置向大家展示其基本功能的实现。
基本定时器
在STM32F4中,TIM6和TIM7为基本定时器,主要特性如下:
- 16 位自动重载递增计数器
- 16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数 介于 1 和 65536 之间
- 用于触发 DAC 的同步电路
- 发生计数器上溢更新事件时会生成中断/DMA 请求
材料
- 正点原子探索者开发板,芯片为STM32F407ZGT6
- 开发板的原理图
- STM32F4系列HAL库开发手册
- STM32CubeMX
- keil5
定时器主要HAL库函数
打开HAL库函数手册定时器的章节,可以发现里面定时器相关的函数是非常多的,与之前GPIO的函数有着天壤之别,那么我们该怎么使用这些函数呢?不要着急,我们慢慢分析。
定时器HAL库函数主要分为类,分别为:通用基本功能、从机功能、输出比较功能、PWM功能、输入捕获功能、单脉冲功能和时间编码功能。十分繁杂,我这里没办法每一个都进行细说,但从名字也知道个大概,具体函数功能也可以在HAL库函数参考手册上面找到说明。我在这里主要介绍一下通用基本功能相关函数。
- HAL_TIM_Base_Init() 初始化定时器时基单元
- HAL_TIM_Base_DeInit() 禁用定时器,与初始化相反
- HAL_TIM_Base_MspInit() MSP初始化函数,定时器初始化时会自动调用
- HAL_TIM_Base_MspDeInit() 与上一个相反
- HAL_TIM_Base_Start() 开启定时器
- HAL_TIM_Base_Stop() 停止定时器
- HAL_TIM_Base_Start_IT() 以中断模式开启定时器
- HAL_TIM_Base_Stop_IT() 关闭中断模式的定时器
- HAL_TIM_Base_Start_DMA() 以DMA模式开启定时器
- HAL_TIM_Base_Stop_DMA() 关闭DMA模式的定时器
工程配置
本次我就以TIM6为例配置STM32CubeMX工程,进入工程后先配置时钟,在RCC中高低速时钟均选择外部晶振
然后进入时钟树的配置,这里我们为了能够准确地知道定时器的频率,就要了解该定时器的频率是由哪个时钟源输出的,在STM32F4中,TIM2-7和TIM12-14是挂载在APB1时钟线上的,而TIM1和TIM8-11则是挂载在APB2时钟线上,我们这里用到了TIM6,所以应该是APB1,经过分频后我得到了一个84MHz的时钟源。
那么定时器的时钟周期怎么计算呢,不用着急,先给大家看看我的定时器配置
TIM6
- 预分频系数为8400-1
- 向上计数模式(从0开始向上计数至初值并发生上溢事件)
- 自动重装载值为5000-1
- 开启自动重装载模式(即定时器溢出时会自动重装初值)
定时器的时钟源为84MHz,分频系数为8400-1,也就是8400分频,分频后为84M/8400=10K,装载值为5000-1,则每周期计数5000次,就是500ms一个周期
接下来需要在NVIC中使能中断,对STM32CubeMX的NVIC不理解的可以参考《STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)》
最后配置一下LED灯的IO口就可以生成代码了,具体IO配置过程参照《STM32CubeMX实战教程(二)——按键点个灯》
进入代码
生成代码并编译过后,首先来到定时器初始化的地方
/* TIM6 init function */
void MX_TIM6_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim6.Instance = TIM6;
htim6.Init.Prescaler = 8400-1;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 5000-1;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
基本都是我们之前所配置的样子,但这里我想让大家留意一下 ** htim6.Instance = TIM6 ** 这一句,TIM6是定时器6的时基地址,之后的中断我们需要它用来进行参数判断,另外 htim6 是一个全局变量是STM32CubeMX给用户生成的结构体,里面包含了定时器初始化的所有信息,我们可以直接使用该结构体进行传参,正如下面这个函数
现在进入main函数并在while循环前加入开启定时器函数,这里所传入的 htim6就是刚刚定时器初始化后的结构体。
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);
/* USER CODE END 2 */
并在main函数之后添加回调函数代码,如果对回调函数的概念不清晰,欢迎阅读《STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)》。
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM6)
{
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
}
/* USER CODE END 4 */
下载验证
重新编译就可以下载验证了,最后我的工程已上传,欢迎下载,在《基于STM32CubeMX的基本定时器》。
非常抱歉由于CSDN官网上传的资源必须要设定积分,否则几乎无法通过审核,这里就没有办法免费开发给大家,不过源码在教程里已经非常详细了。
结语
非常感谢大家的阅读,如有不当或者错误的地方,欢迎指正,谢谢支持。如果感一个字一个字敲出来不容易,如果觉对你有帮助的,别忘了点个赞~
祝大家事业蒸蒸日上!
奥里给~