HAL库-定时器
所用工具
- 芯片 stm32f103c8t6
- 软件 stm32CudeMx Clion
- STM32F1XX HAL库
定时器概括
STM32F103共有8个定时器:
高级定时器(TIM1、TIM8);通用定时器(TIM2、TIM3、TIM4、TIM5);基本定时器(TIM6、TIM7)
基本定时器功能(TIM6、TIM7):
-
16位向上、向下、向上/下自动装载计数器
-
16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
-
触发DAC的同步电路 TIM6/7独有功能
-
位于APB1总线上
通用定时器(TIM2~TIM5)的主要功能:
-
16位向上、向下、向上/下自动装载计数器
-
16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
-
4个独立通道(TIMx_CH1~4)可以用作:
- 测量输入信号的脉冲长度(输入捕获)
- 输出比较
- 单脉冲模式输出
- PWM输出(边缘或者中间对齐模式)
-
支持针对定位的增量(正交)编码器和霍尔传感器电路
-
如下事件发生时产生中断/DMA:
- 更新:计数器向上溢出/向下溢出,计数器初始化()
- 触发事件(计数器启动、停止、初始化、或者由内部/外部触发计数)
- 输入捕获
- 输出比较
-
位于APB1总线上
高级定时器(TIM1,TIM8的主要功能):
- 高级定时器具有基本,定时器的所有功能
- 还具有控制交直流电动机所有功能
- 输出6路互补带死区的信号,刹车功能等等
- 位于APB2总线上
总括:基本定时器就是单纯的定时计数器,通用定时器多了四个通道,相对应的增加了功能,高级定时器具有基本,通用定时器的所有的功能,并且添加了其他功能
定时器模式
通用定时器可以向上计数、向下计数、向上向下双向计数模式
- 向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后从0开始计数并且产生一个计数器溢出事件。
- 向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0;然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
- 中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
计数时钟的选择
计数器时钟可由下列时钟源提供:
- 内部时钟(TIMx_CLK)
- 外部时钟模式1:外部捕获比较引脚(TIx)
- 外部时钟模式2:外部引脚输入(TIMx_ETR) 适用于TIM,3,4
- 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
工程创建
Clion新建一个项目
选择芯片
设置RCC
设置高速外部时钟HSE 选择外部时钟源
设置时钟
外部晶振为8MHz
- 选择外部时钟HSE 8MHz
- PLL锁相环倍频72倍
- 系统时钟来源选择为PLL
- 设置APB1分频器为 /2
- 这时候定时器的时钟频率为72Mhz
32的时钟树框图 可以参考
配置调试模式
非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
SYS 设置,选择 Debug 为 Serial Wire
GPIO设置
因为我们这里用LED来证明定时器起作用,所以还要配置GPIO引脚
- 起一个别名,宏定义
定时器设置
选择TIM2
定时器时钟选择内部时钟
Clock Source(时钟来源)
- 选项1 :Internal Clock 内部时钟
- 选项2 : ETR2 外部触发输入(ETR)(仅适用TIM2,3,4)
Prtscaler (定时器分频系数) : 7199
Counter Mode(计数模式) Up(向上计数模式)
Counter Period(自动重装载值) : 4999
CKD(时钟分频因子) : No Division 不分频
选项: 可以选择二分频和四分频
auto-reload-preload(自动重装载) : Enable 使能
TRGO Parameters 触发输出 (TRGO) 不使能 与本节无关,之后做详细介绍
TRGO: 定时器的触发信号输出 在定时器的定时时间到达的时候输出一个信号(如:定时器更新产生TRGO信号来触发ADC的同步转换,)
这两个为定时器主从模式配置,很少用到,我们用不到,所以全部关闭
使能定时器中断:
定时器溢出时间:
这里我们 arr=4999 psc=7199 Tclk=72Mhz Tout = (5000*7200)/72 us = 500ms
工程管理
- 设置项目名称
- 设置存储路径
- 选择所用IDE(这里用的是Clion,所以用STM32CubeIDE或者SW4STM32都可以)
然后点击上方GENERATE CODE 创建工程
回到Clion软件–编写代码
函数讲解:
HAL_TIM_IRQHandler(&htim2);
定时器中断处理函数 在stm32f1xx_it.c的 TIM2_IRQHandler()定时器中断服务函数中
这个函数的具体作用是判断中断是否正常,然后判断产生的是哪一类定时器中断(溢出中断/PWM中断…),然后进入相应的中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
在HAL库中,每进行完一个中断,不会离可退出,而会进入到中断回调函数中,
这里 我们使用的是定时器溢出中断回调函数
- void TIM2_IRQHandler(void) 首先进入中断函数
- HAL_TIM_IRQHandler(&htim2);之后进入中断处理函数
- 经过判断产生的是哪一类定时器中断(溢出中断/PWM中断…) 和定时器通道
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);进入相对应的中断回调函数
- 在中断回调函数中添加用户需要代码
你也可以在在stm32f1xx_it.c中找到中断回调函数
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 若定义类型的中断回调函数
我们这里使用定时器让LED延时点亮
定时器溢出时间为500ms,LED点亮延时500ms闪烁
- 在main.c主函数中使能定时器中断(HAL需要手动使能中断)
/************** 使能TIm2中断****************/
HAL_TIM_Base_Start_IT(&htim2);
- 在main.c主函数下方添加中断回调函数
/* USER CODE BEGIN 4 */
/********************************************************************************
* @author: Wang PengHuan
* @date: 2022-06-29 17:46
* @brief: 回调函数定时器溢出时间为500ms,LED点亮延时500ms闪烁
* @param: 哪一个TIM中断
* @return: None
********************************************************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
static unsigned char ledState = 0;
if (htim == (&htim2)) {
if (ledState == 0)
//这里的LED_GPIO_Port和LED_Pin都是我们先前初始化过的
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
ledState = !ledState;
}
}
/* USER CODE END 4 */