STM32CUBEMX配置教程(四)定时器中断配置
基于STM32H743VI 使用STM32CUBEMX两年了,始终觉得这个工具非常的方便,但因为不是经常使用,导致有些要点总是会有些遗忘,因此写下这一系列教程以供记忆,顺便让我这个大萌新给广大小萌新提供一些学习帮助。
本次配置的工程链接在最下方,有需要自取。 0基础可以从第一个教程开始阅读STM32CUBEMX配置教程(一)基础配置STM32CUBEMX配置教程(二)时钟等内部参数配置STM32CUBEMX配置教程(三)通用GPIO配置
此次教程的具体效果为定时器控制IO口点灯闪烁。
1 新建工程
参考STM32CUBEMX配置教程(一)基础配置
2 修改时钟树
参考STM32CUBEMX配置教程(二)时钟等内部参数配置
3 GPIO输出配置
配置PA0为输出模式,低速,推挽输出。 参考STM32CUBEMX配置教程(三)通用GPIO配置
4 定时器原理与分类
部分原理参考【STM32】HAL库 STM32CubeMX教程六----定时器中断
STM32定时器分为基本定时器、通用定时器和高级定时器,部分型号还具有低功耗定时器等等。
STM32基本定时器具有以下功能:
16位向上、向下、向上/下自动装载计数器
16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
定时触发ADC或者DAC以达到固定频率采用或者还原的目的(部分基本定时器具有此功能)
STM32通用定时器具有以下功能:
16位向上、向下、向上/下自动装载计数器
16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
4 个独立通道(TIMx_CH1~4)可以用作: 测量输入信号的脉冲长度( 输入捕获) 输出比较 单脉冲模式输出 PWM输出(边缘或中间对齐模式)
支持针对定位的增量(正交)编码器和霍尔传感器电路
如下事件发生时产生中断/DMA: 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内 部/外部触发) 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) 输入捕获 输出比较
STM32高级定时器具有以下功能: 高级定时器具有基本、通用定时器的所有的功能,
还具有控制交直流电动机所有的功能,
输出6路互补带死区的信号,刹车功能等等
5 定时器配置实战
在此使用基础定时器的中断来控制灯的翻转,以TIM6为例。先在cubemx中的左侧找到Timers选项并选中TIM6:
在左侧方框中的Activated前的方框中打勾以激活该定时器,此时下方方框就会显示定时器的相关配置参数。
其中参数含义分别为:
Prescaler 分频系数
Counter Mode 计数模式(分为向上和向下)
Count Period 计数周期
auto-reload preload 自动重装载
TRGO Event Selection 触发事件其中分频系数和计数周期较为常用,可用于设置定时器溢出时间,一般来说溢出也代表定时器中断的产生(如果配置了中断)。溢出时间计算公式如下:
上面那个公式中arr为Count Period的设置数值,psc为Prescaler的设置数值。
Tclk为定时器挂载的时钟线的频率。对于STM32H743而言最高为240Mhz(根据自己的设置有关),不记得可以看看自己配置的时钟树。
下图中的TO APB1 Timer clocksClocks和TO APB2 Timer clocksClocks都是240Mhz。(虽然TIM6挂在哪个总线上忘记了,但是这里只有240M,有知道的小伙伴可以评论留言)。
如果我想要让灯每隔500ms切换一次状态,也就是每隔500ms进入一次中断,也就是Tout(上上一个图公式)为500ms。则需要设置psc为2399,arr为49999。那么溢出时间为:
2400*50000/240(us)=500ms
除了分频系数和计数周期这两个参数,计数模式(Counter Mode )使用默认的UP即可,auto-reload preload配置为Enable使能以使不停产生500ms的定时器中断,TRGO Event Selection 触发事件在配置定时器中断时无需修改,这个参数功能往往被用来控制ADC、DAC的固定频率采样
最终配置图如下:
还有一个非常重要的配置,打开定时器中断,找到并打开NVIC Settings一栏,在Enabled的方框下打勾以使能TIM6 global interrupt。,到此配置结束,点击生成代码。
6 启动定时器与修改中断函数
配置完成,需要在程序中手动启动定时器,系统才能进入定时器中断。 此函数为:
HAL_TIM_Base_Start_IT(&htim6);
注意,如果使用HAL_TIM_Base_Start(&htim6);函数打开定时器,则定时器会启动,但不会进入定时器中断。
主函数代码:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM6_Init();
HAL_TIM_Base_Start_IT(&htim6);
while (1)
{
}
}
那么如何在中断到来时控制灯翻转呢?在keil工程中的main文件的目录下找到stm32h7xxit.c这个文件,我们配置的所有中断函数都能在此找到。
打开这个c文件,找到TIM6的中断,在其中添加翻转PA0的代码即可:
有同学可能疑问为什么还有DAC等字样,TIM6可以做DAC触发源,我们在此没用到不用管即可。
/**
* @brief This function handles TIM6 global interrupt, DAC1_CH1 and DAC1_CH2 underrun error interrupts.
*/
void TIM6_DAC_IRQHandler(void)
{
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_0);//翻转gpio
/* USER CODE END TIM6_DAC_IRQn 0 */
HAL_TIM_IRQHandler(&htim6);
/* USER CODE BEGIN TIM6_DAC_IRQn 1 */
/* USER CODE END TIM6_DAC_IRQn 1 */
}
在此看看效果,实际我的PA0上没有灯,给大家看看波形,可以看到输出了1HZ的方波,也就是每隔500ms翻转一次,如果有灯的话就能看到一闪一闪亮晶晶了!