STM32CubeMX教程5 TIM 定时器概述及基本定时器

目录

1、准备材料

2、实验目标

3、定时器概述

​4、实验流程

4.0、前提知识

4.1、CubeMX相关配置

4.1.0、工程基本配置

4.1.1、时钟树配置

4.1.2、外设参数配置

4.1.3、外设中断配置

4.2、生成代码

4.2.0、配置Project Manager页面

4.2.1、外设初始化调用流程

4.2.2、外设中断调用流程

4.2.3、添加其他必要代码

5、常用函数

6、烧录验证

7、注释详解


读者可访问 GitHub - lc-guo/STM32CubeMX-Series-Tutorial 获取原始工程代码


1、准备材料

开发板(STM32F407G-DISC1

STM32CubeMX软件(Version 6.10.0

ST-LINK/V2 驱动

keil µVision5 IDE(MDK-Arm

逻辑分析仪nanoDLA

2、实验目标

使用STM32CubeMX软件配置STM32F407开发板使用基本定时器TIM6实现每500ms控制绿灯状态变化一次,基本定时器TIM7实现每1s控制红灯状态变化一次

3、定时器概述

STM32F407拥有2个基础定时器、10个通用定时器和2个高级定时器,14个定时器全部挂载在APB1和APB2时钟总线上,APB2时钟总线时钟频率最高可达84MHz,APB1时钟总线时钟频率最高可达42MHz,除TIM2和TIM5为32位外,其余定时器全部为16位,其结构框图如下图所示(注释1)

​不同的定时器具有不同的特性,有些定时器的计数器长度为16位,有些则为32位;有些定时器可以递增、递减或递增/递减计数,但有些定时器只能递增计数;有些定时器可以产生DMA请求,有些则不可以;另外定时器捕获/比较通道数量也不一样;具体特性区别请看下表(注释2)

​4、实验流程

4.0、前提知识

基本定时器由TIM6和TIM7组成,计数器为16位,内部结构较为简单,只有定时器的基本功能,可以做定时或驱动DAC,本实验暂不讨论DAC,只用定时功能,如下图所示为基本定时器框架(注释3)

基本定时器的时钟来源为APB1 Timer clocks,当通过控制器启动基本定时器TIM6/7时,时钟信号经过PSC预分频器将时钟分频,然后以分频后的时钟频率增加计数器的值,当计数器达到自动重载寄存器设置的值之后,产生溢出

4.1、CubeMX相关配置

4.1.0、工程基本配置

打开STM32CubeMX软件,单击ACCESS TO MCU SELECTOR选择开发板MCU(选择你使用开发板的主控MCU型号)选中MCU型号后单击页面右上角Start Project开始工程,具体如下图所示

​开始工程之后在配置主页面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具体如下图所示

​详细工程建立内容读者可以阅读“STM32CubeMX教程1 工程建立

4.1.1、时钟树配置

基本定时器涉及到定时时间的问题,而TIM6/7的时钟来源自APB1 Timer clocks,因此需要先知道APB1 Timer clocks的频率,才可以计算基本定时器的溢出时间

如下图所示,时钟树上所有总线频率均设置为了STM32F4能达到的最高频率,此时APB1 Timer clocks=84MHz

4.1.2、外设参数配置

在Pinout & Configuration页面左侧功能分类栏目中点开Timers栏目,单击栏目下的TIM6和TIM7

在页面中间TIM6/7 Mode and Configuration 中勾选Activated激活基本定时器,One Pulse Mode为单次定时模式,勾选该模式则定时器只触发一次,默认定时器为连续触发,触发完一次后自动重载ARR中设置的值重新计数

在页面中间Configuration栏中可设置基本定时器参数,包括 Prescaler (预分频系数)、 Counter Mode (计数模式)和 Counter Period (ARR寄存器的值)通过这些参数的设置可以决定基本定时器的溢出时间

APB1 Timer clocks=84MHz,PSC=8399,ARR=4999,此时可计算溢出时间为(PSC+1)(ARR+1)/APB1 Timer clocks=0.5秒=500毫秒,则每500ms定时器产生一次溢出,ARR设置为9999则定时器1s溢出一次

 auto-reload preload :可以选择使能或不使能,如果不使能该参数,则在使用__HAL_TIM_SET_AUTORELOAD()函数动态修改基本定时器ARR参数值时,修改的值会立马生效;而如果使能该参数,则修改的值会在当前计数溢出之后下次得到修改

 Trigger Output (TRGO) Parameters :一般是用来设置用作其他外设的触发源的,比如将Trigger Event Selection选择为Update Event,然后在其他外设比如ADC中配置外部触发源时选择该定时器的触发事件(如果可以的话),这样在定时器产生Update Event时就可以启动外设,实现用定时器来控制外设启动的功能

上述配置如下图所示

4.1.3、外设中断配置

基本定时器的触发有三种模式 ① 轮询方式、② 中断方式和③ DMA方式,这里只介绍前两种方式

① 对于轮询方式,当前设置已经足够,只需要在生成的程序中使用HAL_TIM_Base_Start(&htim6)启动基本定时器,然后不断轮询计数值或UEV事件标志来判断是否发生了计数溢出

② 中断方式是基本定时器最常用的方式,在Pinout & Configuration页面左侧功能分类栏目中点开NVIC栏目,然后选择合适的中断优先级并勾选基本定时器6和7的中断使能

4.2、生成代码

4.2.0、配置Project Manager页面

单击进入Project Manager页面,在左边Project分栏中修改工程名称、工程目录和工具链,然后在Code Generator中勾选“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后单击页面右上角GENERATE CODE生成工程,具体如下图所示

详细Project Manager配置内容读者可以阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节

4.2.1、外设初始化调用流程

在工程代码主函数main()中调用MX_TIM6_Init()函数对基本定时器TIM6参数进行了配置

在该MX_TIM6_Init()函数中调用了HAL_TIM_Base_Init()对定时器进行了初始化

然后在HAL_TIM_Base_Init()函数中调用了HAL_TIM_Base_MspInit()函数对TIM6时钟和中断设置/使能

TIM7初始化流程类似,具体定时器TIM6初始化流程如下图所示

4.2.2、外设中断调用流程

激活了基本定时器并启动TIM6/7全局中断之后,会在stm32f4xx_it.c中新增TIM6/7的中断服务函数TIM6_DAC_IRQHandler()和TIM7_IRQHandler()

该函数均调用HAL库的定时器中断统一处理函数HAL_TIM_IRQHandler(),该函数通过一系列的判断最终得出基本定时器目的为周期回调(注释4),因此最终调用周期回调函数HAL_TIM_PeriodElapsedCallback(),该函数为虚函数

TIM7中断调用流程类似,具体定时器TIM6中断调用流程如下图所示

4.2.3、添加其他必要代码

重新在tim.c中实现周期回调函数HAL_TIM_PeriodElapsedCallback(),当定时器TIM6溢出则翻转GREEN_LED引脚状态,当定时器TIM7溢出则翻转RED_LED引脚状态,具体代码如下图所示

​源代码如下

/*基本定时器周期回调函数*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htim6)
    {
        HAL_GPIO_TogglePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin) ;
    }

    if(htim == &htim7)
    {
        HAL_GPIO_TogglePin(RED_LED_GPIO_Port, RED_LED_Pin) ;
    }
}

在主函数中以中断方式启动基本定时器TIM6/7,具体代码如下图所示

5、常用函数

/*以轮询工作方式启动定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)

/*停止轮询工作方式的定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)

/*以中断工作方式启动定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)

/*停止中断工作方式的定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim)

/*定时器周期回调子函数*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

6、烧录验证

烧录程序,开发板上电后观察现象为绿灯每隔500ms状态改变一次,红灯每隔1s状态改变一次

使用逻辑分析仪监测PD12/14引脚状态,可以看出TIM6每500ms翻转一次PD12引脚状态,TIM7每1000ms翻转一次PD14引脚状态

7、注释详解

注释1:图片来源STM32F407VGT6 Datasheet DS8626

注释2:图片来源STM32 CubeMX 学习:003-定时器(其原表有错误)

注释3:图片来源STM32F4xx中文参考手册

注释4:具体过程请参看 HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) 函数详解

  • 36
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用HAL库的嵌入式系统中,获取定时器的计数值可以通过以下步骤进行: 1. 配置定时器:使用HAL库的定时器配置函数(例如`HAL_TIM_Base_Init()`)来初始化定时器,并设置定时器的时钟源、分频系数和自动重载寄存器的值等参数。 2. 启动定时器:使用HAL库的定时器启动函数(例如`HAL_TIM_Base_Start()`)来启动定时器开始计数。 3. 获取计数值:使用HAL库的定时器获取计数值函数(例如`__HAL_TIM_GET_COUNTER()`)来获取定时器的当前计数值。该函数会返回一个无符号整型数,表示定时器当前的计数值。 下面是一个示例代码片段,演示了如何使用HAL库获取定时器计数值的过程: ```c #include "stm32f4xx_hal.h" TIM_HandleTypeDef htim; // 定时器句柄 int main(void) { // 初始化 HAL 库 HAL_Init(); // 配置定时器 htim.Instance = TIM2; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 1000; HAL_TIM_Base_Init(&htim); // 启动定时器 HAL_TIM_Base_Start(&htim); while (1) { // 获取计数值 uint32_t count = __HAL_TIM_GET_COUNTER(&htim); // 在这里使用计数值进行相应的操作 // 延时一段时间 HAL_Delay(100); } } ``` 在上面的示例中,我们使用了STM32F4系列的定时器TIM2,通过`__HAL_TIM_GET_COUNTER()`函数获取定时器的计数值,并在主循环中进行相应的操作。注意根据使用的具体芯片和定时器类型进行相应的修改。 希望以上信息对你有帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值