STM32CubeMX实战教程(四)——基本定时器(还是点灯)

基本定时器

    • 前言
    • 基本定时器
    • 材料
    • 定时器主要HAL库函数
    • 工程配置
    • 进入代码
    • 下载验证
    • 结语

前言

定时器作为单片机不可或缺的外设,当然也是学习单片机时重要的知识点,但是STM32单片机的定时器非常多而且结构复杂。*其中在STM32F4中,共有14个定时器,定时器分为通用定时器,基本定时器和高级定时器。*我将通过三章分别进行讲解。本章我将先简单介绍一下基本定时器的特性及其HAL库函数,然后通过工程配置向大家展示其基本功能的实现。

基本定时器

在STM32F4中,TIM6和TIM7为基本定时器,主要特性如下:

  • 16 位自动重载递增计数器
  • 16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数 介于 1 和 65536 之间
  • 用于触发 DAC 的同步电路
  • 发生计数器上溢更新事件时会生成中断/DMA 请求

材料

  1. 正点原子探索者开发板,芯片为STM32F407ZGT6
  2. 开发板的原理图
  3. STM32F4系列HAL库开发手册
  4. STM32CubeMX
  5. keil5

定时器主要HAL库函数

打开HAL库函数手册定时器的章节,可以发现里面定时器相关的函数是非常多的,与之前GPIO的函数有着天壤之别,那么我们该怎么使用这些函数呢?不要着急,我们慢慢分析。
定时器HAL库函数主要分为类,分别为:通用基本功能、从机功能、输出比较功能、PWM功能、输入捕获功能、单脉冲功能和时间编码功能。十分繁杂,我这里没办法每一个都进行细说,但从名字也知道个大概,具体函数功能也可以在HAL库函数参考手册上面找到说明。我在这里主要介绍一下通用基本功能相关函数
STM32CubeMX实战教程(四)——基本定时器(还是点灯)_第1张图片

  • HAL_TIM_Base_Init() 初始化定时器时基单元
  • HAL_TIM_Base_DeInit() 禁用定时器,与初始化相反
  • HAL_TIM_Base_MspIni() 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中高低速时钟均选择外部晶振
STM32CubeMX实战教程(四)——基本定时器(还是点灯)_第2张图片
然后进入时钟树的配置,这里我们为了能够准确地知道定时器的频率,就要了解该定时器的频率是由哪个时钟源输出的,在STM32F4中,TIM2-7和TIM12-14是挂载在APB1时钟线上的,而TIM1和TIM8-11则是挂载在APB2时钟线上,我们这里用到了TIM6,所以应该是APB1,经过分频后我得到了一个84MHz的时钟源。
时钟配置
那么定时器的时钟周期怎么计算呢,不用着急,先给大家看看我的定时器配置
STM32CubeMX实战教程(四)——基本定时器(还是点灯)_第3张图片
TIM6

  • 预分频系数为8400-1
  • 向上计数模式(从0开始向上计数至初值并发生上溢事件)
  • 自动重装载值为5000-1
  • 开启自动重装载模式(即定时器溢出时会自动重装初值)

定时器的时钟源为84MHz,分频系数为8400-1,也就是8400分频,分频后为84M/8400=10K,装载值为5000-1,则每周期计数5000次,就是500ms一个周期

接下来需要在NVIC中使能中断,对STM32CubeMX的NVIC不理解的可以参考《STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)》
STM32CubeMX实战教程(四)——基本定时器(还是点灯)_第4张图片
最后配置一下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 */

进入回调函数后对定时器的时基地址进行判断从而确定定时器号,也就是我刚刚说到的Instance确认之后进行LED灯的翻转操作。

本次实验中,对基本定时器6进行了初始化配置,周期为500ms,也就是每500ms发生溢出并产生一个上溢事件,并在回调函数中对LED灯进行翻转操作,所以实验现象是每500msLED灯翻转一次

下载验证

重新编译就可以下载验证了,最后我的工程已上传,欢迎下载。

非常抱歉由于CSDN官网上传的资源必须要设定积分,否则几乎无法通过审核,这里就没有办法免费开发给大家,不过源码在教程里已经非常详细了。

结语

非常感谢大家的阅读,如有不当或者错误的地方,欢迎指正,谢谢支持。如果感一个字一个字敲出来不容易,如果觉对你有帮助的,别忘了点个赞~
祝大家事业蒸蒸日上!

奥里给~

你可能感兴趣的:(stm32,单片机,嵌入式)