答:使用精准的时基,通过硬件的方式,实现定时功能,
定时器的核心就是计数器CNT(counter)。
①基本定时器(TIM6~TIM7):没有输入输出通道,常用作时基,也就是俗称定时功能。
②通用定时器(TIM2~TIM5):具有多路独立通道,可用于输入捕获/输出比较,也可用作时基,用于PWM生成(控制电机速度、LED亮度调节)。
③高级定时器(TIM1和TIM8):包括通用定时器所有功能外,还有具备带死区控制的互补信号输出、刹车输入等功能。
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.触发输入作为外部时钟或者按周期的电流管理
两个关键寄存器:
CNT:counter Register,计数器
ARR:Auto-Reload Register,自动装载寄存器
ARR 是一个 16 位的寄存器,用于设置定时器的周期性计数值(相当于水缸口临界值)。当定时器计数达到 ARR 的值时,会产生定时器溢出中断,然后重新从 0 开始计数。
CNT 是另一个 16 位的寄存器,用于存储定时器的当前计数值(相当于水龙头放水中的监测水位)。在定时器开始计数后,CNT 会逐渐增加,直到达到 ARR 的值,然后重新从 0 开始计数。
(可以先跳过,结束实验再回来看这个知识点,八股文)
答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中,PLLCLK和HCLK是与时钟系统相关的参数。
答5:PSC?
预分频器(Prescaler)是一种用于降低输入信号频率的电子元件或模块。它通常用于时钟系统中,用于将高频的输入信号分频成较低频的信号,以满足特定需求。
预分频器的工作原理是通过将输入信号按照预设的分频比进行划分,从而降低输出信号的频率。例如,如果预分频比为1:10,则每个输入脉冲产生的输出脉冲数为输入脉冲数的十分之一。这样可以将高频信号转换为较低频的信号,方便后续电路对信号进行处理和控制。
预分频器在数字电子系统中广泛使用,特别是在计数器、定时器、频率合成器等应用中。它可以帮助调整时钟频率,实现精确的时间控制、频率测量、频率变换等功能。通过设置不同的预分频比,可以得到不同的输出频率,以适应不同的应用需求。
例如,要定时500ms,则:PSC=7199,ARR=4999,Tclk=72M。
1. RCC配置
2. LED1灯配置
3. 时钟数配置
4. TIM2配置
找LED灯是哪个引脚控制,如图右侧PB8
这样子上电之后,灯默认就是关的,这时候代码控制外设翻转高低电平,就可以点灯了
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 */
以上,完