嵌入式-stm32-HAL库通过定时器中断翻转LED灯

2023-12-22 08:52:18

一:这是前面的通过GPIO点LED灯文章,现在是通过定时器控制LED灯

《嵌入式-stm32-hal库通过GPIO点LED灯》

二:知识前置

1.什么是定时器

答:使用精准的时基,通过硬件的方式,实现定时功能,
定时器的核心就是计数器CNT(counter)。
在这里插入图片描述

2.定时器分类及功能

①基本定时器(TIM6~TIM7):没有输入输出通道,常用作时基,也就是俗称定时功能。
②通用定时器(TIM2~TIM5):具有多路独立通道,可用于输入捕获/输出比较,也可用作时基,用于PWM生成(控制电机速度、LED亮度调节)。
③高级定时器(TIM1和TIM8):包括通用定时器所有功能外,还有具备带死区控制的互补信号输出、刹车输入等功能。

在这里插入图片描述在这里插入图片描述

3.通用定时器介绍

1) 16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。
2) 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。
3)4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
		A.输入捕获
		B.输出比较
		C.PWM 生成(边缘或中间对齐模式)
		D.单脉冲模式输出
4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
5)如下事件发生时产生中断/DMA:
		A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
		B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
		C.输入捕获
		D.输出比较
		E.支持针对定位的增量(正交)编码器和霍尔传感器电路
		F.触发输入作为外部时钟或者按周期的电流管理

4.定时器计数模式

两个关键寄存器:
CNT:counter Register,计数器
ARR:Auto-Reload Register,自动装载寄存器

ARR 是一个 16 位的寄存器,用于设置定时器的周期性计数值(相当于水缸口临界值)。当定时器计数达到 ARR 的值时,会产生定时器溢出中断,然后重新从 0 开始计数。
CNT 是另一个 16 位的寄存器,用于存储定时器的当前计数值(相当于水龙头放水中的监测水位)。在定时器开始计数后,CNT 会逐渐增加,直到达到 ARR 的值,然后重新从 0 开始计数。

在这里插入图片描述

在这里插入图片描述

5.看关键词,你能回答多少

(可以先跳过,结束实验再回来看这个知识点,八股文)
答1:APB1是Advanced Peripheral Bus 1的缩写,外围总线,它是ARM Cortex-M系列微控制器中的一个总线接口。APB1是一种低速总线,通常用于连接低速周边设备,例如定时器、看门狗定时器、串口接口等。在一些具有多个APB总线的器件中,APB1通常用于连接外围设备,而APB2则用于连接更高速的设备,例如高速ADC和高速DMA控制器。

答2:TCLK(Test Clock)是测试时钟的缩写,是一种用于测试和调试集成电路(IC)的时钟信号。在芯片设计中,TCLK通常用于控制和同步测试数据的传输速率。它可以帮助验证电路的功能性和可靠性,并检测任何潜在的故障或错误。TCLK的频率和相位可以根据具体的测试需求进行设置和调整。

答3:在单片机领域,****RCC通常是指Reset and Clock Control(复位和时钟控制)模块,它是一种用于控制系统时钟和复位信号的硬件模块。RCC模块通常包括多个寄存器,可以被配置为产生各种不同的时钟信号,以满足不同外设的时钟要求。此外,RCC模块还负责处理系统复位信号,并确保系统在复位后能够正常启动和运行。RCC模块通常是单片机系统中比较重要的模块之一,因为它直接影响到系统的稳定性和可靠性。

答4:在STM32CubeMX中,PLLCLKHCLK是与时钟系统相关的参数。

  1. PLLCLK(Phase-Locked Loop Clock)是指使用锁相环(PLL)产生的系统时钟频率。PLL是一种电路模块,可以通过将输入时钟频率乘以固定倍数来生成高频时钟信号。在STM32微控制器中,PLL通常用于提供高频时钟给系统,以满足处理器和外设的时序要求。
  2. HCLK(Host Clock)是指处理器核心时钟频率,也称为系统主时钟。HCLK是从PLLCLK或其他源时钟分频得到的,它为整个系统提供基准时钟信号。所有的处理器内部模块和外设都以HCLK作为参考时钟。
    在STM32CubeMX中,你可以配置PLLCLK的参数,例如输入时钟源、倍频因子等,以及HCLK的分频系数。这样可以根据具体的应用需求来调整系统时钟频率,以满足性能和功耗的平衡。

答5:PSC?
预分频器(Prescaler)是一种用于降低输入信号频率的电子元件或模块。它通常用于时钟系统中,用于将高频的输入信号分频成较低频的信号,以满足特定需求。
预分频器的工作原理是通过将输入信号按照预设的分频比进行划分,从而降低输出信号的频率。例如,如果预分频比为1:10,则每个输入脉冲产生的输出脉冲数为输入脉冲数的十分之一。这样可以将高频信号转换为较低频的信号,方便后续电路对信号进行处理和控制。
预分频器在数字电子系统中广泛使用,特别是在计数器、定时器、频率合成器等应用中。它可以帮助调整时钟频率,实现精确的时间控制、频率测量、频率变换等功能。通过设置不同的预分频比,可以得到不同的输出频率,以适应不同的应用需求。

6.定时器溢出时间计算公式(全文重点)

在这里插入图片描述
例如,要定时500ms,则:PSC=7199,ARR=4999,Tclk=72M。

三:定时器中断实验逻辑(hal库)

1.需求:使用定时器中断方法,每500ms翻转一次LED1灯状态。

	1. RCC配置
	2. LED1灯配置
	3. 时钟数配置
	4. TIM2配置

四:stm32CubeMX实现步骤以及细节

1.打开Stm32CubeMX,界面如图

在这里插入图片描述

2.选芯片:stm32f103c8t6

在这里插入图片描述

4.读芯片引脚原理图

找LED灯是哪个引脚控制,如图右侧PB8
在这里插入图片描述
在这里插入图片描述

5.先把LED灯设置为高电平模式

这样子上电之后,灯默认就是关的,这时候代码控制外设翻转高低电平,就可以点灯了
在这里插入图片描述

6.定时器TIM2的手动配置

在这里插入图片描述

7.配置时钟频率

在这里插入图片描述

8.RCC配置

在这里插入图片描述

9.代码自动设置生成的文件

在这里插入图片描述

10.图形化最后一步

在这里插入图片描述

五:keil5代码

1.keil5界面

在这里插入图片描述2.全文只增加的代码有①②
①在main.c里增加的代码
在这里插入图片描述

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}//回调函数,当定时器时间到了,中断之后,下一步代码要前往的方向
尝试解释一下:
这段代码是一个回调函数,用于处理定时器中断事件。

在STM32的HAL库中,定时器的中断服务程序(IRQ)会调用该回调函数,以执行特定的操作。在这个例子中,回调函数是"HAL_TIM_PeriodElapsedCallback",它会在定时器中断周期结束时被调用。
代码中的逻辑是判断触发中断的定时器实例是否为TIM2。如果是TIM2,那么会执行"HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8)"语句。这条语句的作用是将GPIOB引脚8的状态进行翻转(即从高电平变为低电平,或从低电平变为高电平)。
因此,当TIM2的定时器中断周期结束时,GPIOB引脚8的状态将会翻转一次,也就是在每次定时器中断时,GPIOB引脚8的电平状态将会交替变化。这种操作可以用于控制外部设备或指示灯的状态变化,例如在定时器中断时,让一个LED灯闪烁。

②在main.c里增加的代码在这里插入图片描述HAL_TIM_Base_Start_IT(&htim2);//在main主函数里面添加,启动定时器
③这是手动添加业务代码之后总的main.c代码,其余.c和.h都没有改变

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}//这是①
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);//这是②
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

六:实验结果就是LED灯每500ms秒亮一次,快速闪烁

以上,完

文章来源:https://blog.csdn.net/weixin_50833257/article/details/135126488
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。