定时器中断实验代码2
131.5.3定时器中断实验代码(2)
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Inc/main.h
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define LED2_Pin GPIO_PIN_5
#define LED2_GPIO_Port GPIOE
#define LED1_Pin GPIO_PIN_5
#define LED1_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Inc/gpio.h
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.h
* @brief This file contains all the function prototypes for
* the gpio.c file
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_GPIO_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Inc/tim.h
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.h
* @brief This file contains all the function prototypes for
* the tim.c file
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM1_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __TIM_H__ */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Inc/usart.h
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
extern uint8_t u_buf[256];//printf?
#define printf(...) HAL_UART_Transmit(&huart1, (uint8_t *)u_buf, sprintf((char*)u_buf, __VA_ARGS__), 0xffff)
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Inc/stm32f1xx_it.h
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F1xx_IT_H
#define __STM32F1xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void TIM1_UP_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F1xx_IT_H */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Src/main.c
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 "usart.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 */
uint8_t UART_Buf[200];
uint32_t G_TIM_Count = 0;
uint8_t G_UART_Flag = 0;
/* 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 */
/* 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_TIM1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(1 == G_UART_Flag)
{
printf("MCU stm32 run time is %lus \n",G_TIM_Count);
G_UART_Flag = 0;
}
/* 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 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim1)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
G_TIM_Count++;
if(1 == G_TIM_Count%5)
{
G_UART_Flag = 1;
}
if(0 == G_TIM_Count%2)
{
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
}
}
}
/* 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 */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Src/gpio.c
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.c
* @brief This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Src/tim.c
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim1;
/* TIM1 init function */
void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 7199;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 9999;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM1 interrupt Init */
HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* TIM1 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM1_UP_IRQn);
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Src/usart.c
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 "usart.h"
/* USER CODE BEGIN 0 */
uint8_t u_buf[256];
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* ========================================================================
* Project: CubeIDE/06TIM
* File: Core/Src/stm32f1xx_it.c
* ======================================================================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2024 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 "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* 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 -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern TIM_HandleTypeDef htim1;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M3 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f1xx.s). */
/******************************************************************************/
/**
* @brief This function handles TIM1 update interrupt.
*/
void TIM1_UP_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_UP_IRQn 0 */
/* USER CODE END TIM1_UP_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_UP_IRQn 1 */
/* USER CODE END TIM1_UP_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
一、定时器中断实验
1.1 统计单片机上电时间
TIM1 已配置为每秒产生一次更新中断,因此可在周期回调中把 32 位全局变量加一:
volatile uint32_t G_TIM_Count = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1)
{
G_TIM_Count++;
}
}
变量单位是“秒”,前提是定时器实际更新周期确实为 1 秒。uint8_t 只能表示 0~255,约 255 秒就会回绕;uint32_t 会在 2^32 秒后回绕,约为 136 年。整数回绕通常不会让单片机“死机”,但会让累计时间从 0 重新开始,所以长时间运行的系统仍应设计溢出处理。
G_TIM_Count 同时被中断和主循环访问,应使用 volatile,避免编译器把主循环看到的值长期缓存在寄存器中。volatile 只保证每次都实际读写内存,不等同于线程安全;本例 Cortex-M3 对对齐的 32 位读写可作为单次访问完成,复杂共享结构仍需要临界区。
1.2 打印单片机上电时间
先用缓冲区格式化,再调用阻塞式串口发送:
uint8_t UART_Buf[200];
int len = snprintf((char *)UART_Buf,
sizeof(UART_Buf),
"MCU stm32 run time is %lus\r\n",
(unsigned long)G_TIM_Count);
if (len > 0)
{
uint16_t send_len = (len < (int)sizeof(UART_Buf))
? (uint16_t)len
: (uint16_t)(sizeof(UART_Buf) - 1U);
HAL_UART_Transmit(&huart1, UART_Buf, send_len, 1000);
}
snprintf 比 sprintf 多一个缓冲区上限,可避免输出超过 200 字节。若已经正确生成以 '\0' 结尾的字符串,也可用 strlen((char *)UART_Buf) 取得实际长度。不能使用 sizeof(UART_Buf) 作为有效字符串长度,否则会把数组中未使用的尾部字节也发送出去。
HAL_UART_Transmit 是阻塞调用,发送期间 CPU 会等待,因此它应位于主循环,不应放在定时器中断回调中。
1.3 编译并观察效果
若把格式化与发送直接写在 while (1) 中,主循环会以 CPU 和串口允许的最高速度反复打印,并不是每秒打印一次。即使主循环判断:
if ((G_TIM_Count % 5U) == 0U)
{
printf(...);
}
也仍有逻辑问题:G_TIM_Count 在一整秒内都保持 5、10、15 等值,而主循环在这一秒内会运行成千上万次,于是相同时间会被重复打印。
取余运算只说明“当前秒数能被 5 整除”,不能自动把代码限制为只执行一次。需要检测一次性事件,或使用由中断置位、主循环清零的标志。
1.4 观察效果
重复输出的真实时序如下:
中断时刻: 4s 5s 6s
G_TIM_Count: 4 ───────── 5 ─────────────────────── 6
主循环判断: 真 真 真 真 真 ... 假
串口输出: 连续输出许多次“5s”
定时器仍然只是一秒中断一次;重复打印来自这一秒内主循环多次满足相同条件,不是定时器一秒触发了很多次。解决办法是让 ISR 在目标时刻只产生一个通知。
1.5 更换思路
第一步可以先把“五秒到了”的判断移到定时器回调中:
G_TIM_Count++;
if ((G_TIM_Count % 5U) == 0U)
{
/* 五秒事件只在这次中断里出现一次 */
}
因为回调每秒只进入一次,所以 5、10、15 秒各命中一次。但不要因此直接在回调里发送串口;判断可以留在 ISR,耗时工作仍交给主循环。
1.6 注释主函数
调试时可以暂时注释主循环里的打印代码,先确认计数和中断判断能正常编译运行。更可靠的验证方式是:
- 在调试器 Watch 窗口观察
G_TIM_Count。 - 在回调入口设置断点,但不要长时间停住,以免改变系统时序。
- 临时翻转一个 GPIO,用示波器或逻辑分析仪测量周期。
注释代码只是一种定位手段,最终实现仍应保留“ISR 通知、主循环处理”的完整通路。
1.7 观察效果
如果把打印直接放进回调,确实能得到 5、10、15 秒各一次的表面效果,但阻塞式 UART 会延长 ISR:
TIM1更新中断
├─ 秒计数与条件判断 很短
└─ 格式化 + UART阻塞发送 较慢,不适合ISR
ISR 执行期间,同级或更低优先级中断可能无法及时响应;如果 HAL 超时依赖 SysTick,而当前中断优先级又阻止 SysTick 运行,还可能出现超时计数不前进的问题。因此回调只保留计数、GPIO 和标志操作。
1.8 问题优化
增加一个全局事件标志:
volatile uint8_t G_UART_Flag = 0;
职责划分为:
sequenceDiagram
participant T as TIM1中断回调
participant F as G_UART_Flag
participant M as 主循环
T->>T: G_TIM_Count++
T->>F: 到指定秒数时置1
M->>F: 轮询标志
F-->>M: 标志为1
M->>M: printf/HAL_UART_Transmit
M->>F: 清0
这与操作系统里“快速中断处理 + 延后处理”的思想相似,不过本例没有真正创建两个 Linux 式上下半部,只是用标志把耗时工作移出硬件中断上下文。
1.9 增加变量
全局变量放在用户代码区域,并标明其含义:
volatile uint32_t G_TIM_Count = 0U; /* 上电秒数 */
volatile uint8_t G_UART_Flag = 0U; /* 串口打印事件 */
uint8_t 足够保存 0/1 标志。变量名应表达用途,避免使用 j、y1 等离开课堂上下文后难以理解的名称。
单一标志只能表示“至少发生过一次事件”。如果主循环可能阻塞十几秒,期间多个五秒事件会合并成一次。对不能丢失的事件,应改用递增的待处理计数器、环形队列或 RTOS 消息机制。
1.10 初始化变量
静态存储期的全局变量即使不显式赋值也会被初始化为 0,但写出 = 0U 能让意图更清楚。每次复位后:
G_TIM_Count = 0
G_UART_Flag = 0
TIM1启动后,每次更新中断令 G_TIM_Count 加1
在中断回调中,到达打印时刻只置位:
if ((G_TIM_Count % 5U) == 0U)
{
G_UART_Flag = 1U;
}
不要在主循环每次迭代开头把标志清零,否则中断刚产生的事件可能在检查前就被覆盖。
1.11 注释之前判断
主循环不再直接根据 G_TIM_Count % 5 判断,而是消费标志:
if (G_UART_Flag == 1U)
{
G_UART_Flag = 0U;
printf("MCU stm32 run time is %lus\r\n",
(unsigned long)G_TIM_Count);
}
先清标志再执行慢速打印,可缩短“旧事件尚未清除”的窗口。如果必须让打印值严格对应产生事件时的 5、10、15,而不是主循环稍后读到的时间,可在 ISR 中把当时的计数值复制到另一个共享变量,再置位标志。
1.12 观察效果
中断与主循环的最终分工如下:
| 位置 | 适合执行 | 不适合执行 |
|---|---|---|
| TIM1 回调 | 加计数、置标志、短 GPIO 操作 | printf、阻塞串口、HAL_Delay、复杂计算 |
| 主循环 | 格式化、串口发送、业务处理 | 长时间关中断或无界阻塞 |
这样既能保证每五秒只产生一次打印事件,也能让中断尽快返回。主循环每消费一次标志就将其清零,为下一次事件做准备。
1.13 观察窗口
调试器 Watch/Expressions 窗口可以同时观察:
G_TIM_Count:每秒递增
G_UART_Flag:目标时刻由0变1,主循环处理后恢复0
TIM1->CNT:在0到9999之间循环
TIM1->SR 的 UIF:更新时置位,HAL中断处理后清除
复位后计数回到 0;启动 TIM1 后约一秒变为 1。调试器暂停 CPU 时,定时器是否继续计数取决于调试冻结配置,所以断点期间的观察结果可能与脱机运行不同。
1.14 加小人化更改
配套最终代码把条件写成:
if ((G_TIM_Count % 5U) == 1U)
{
G_UART_Flag = 1U;
}
这样输出时刻是 1、6、11、16……秒,而不是 1 秒后再等到 5 秒输出。它提供了更快的首次反馈,但相邻两次输出仍相隔 5 秒。若业务定义要求严格在 5、10、15……秒输出,就应使用 % 5U == 0U,而不是把两种时间序列混称为同一行为。
1.15 让第二个灯每隔两秒翻转一次
在同一个每秒回调中增加:
if ((G_TIM_Count % 2U) == 0U)
{
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
}
LED2 在第 2、4、6……秒翻转。由于一次翻转只改变一个状态,灯保持亮 2 秒、再保持灭 2 秒,完整亮灭周期为 4 秒。
LED 板载电路为低电平有效:
3.3 V ── LED ── 1 kΩ ── PE5
│
GPIO输出级
PE5=0:GPIO灌电流,LED2亮
PE5=1:没有足够压差,LED2灭
这不影响 TogglePin 的时间规律,只会影响哪个逻辑电平对应“亮”。
1.16 问题优化
多个定时器共用 HAL_TIM_PeriodElapsedCallback 时必须区分句柄:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1)
{
/* TIM1任务 */
}
else if (htim->Instance == TIM2)
{
/* TIM2任务 */
}
}
不能只因为当前工程只有 TIM1 就永久忽略参数,否则以后增加定时器会让所有分支重复执行。
串口输出可从“snprintf + HAL_UART_Transmit”简化为 printf,但 printf 并不会天然知道要使用哪个 UART,必须实现底层字符输出重定向。
1.17 粘贴内容并更改
常见的 GCC/newlib 重定向方式是在 usart.c 或独立文件中实现 _write:
#include <stdio.h>
int _write(int file, char *ptr, int len)
{
(void)file;
if (HAL_UART_Transmit(&huart1,
(uint8_t *)ptr,
(uint16_t)len,
1000) == HAL_OK)
{
return len;
}
return -1;
}
若使用 Keil/Arm Compiler,重定向入口可能是 fputc;应根据当前工具链选择一种实现,不要同时复制多套互相冲突的桩函数。还要确认:
huart1在当前源文件中可见,必要时使用extern UART_HandleTypeDef huart1;。- 头文件声明、函数签名和工具链匹配。
- 重定向函数不在 ISR 中被调用。
- 量产代码按需要处理超时与返回错误。
1.18 回到主函数里更改
完成重定向后,主循环可直接写:
if (G_UART_Flag == 1U)
{
G_UART_Flag = 0U;
printf("MCU stm32 run time is %lus\r\n",
(unsigned long)G_TIM_Count);
}
配套 06TIM 工程的完整逻辑可以概括为:
volatile uint32_t G_TIM_Count = 0U;
volatile uint8_t G_UART_Flag = 0U;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
G_TIM_Count++;
if ((G_TIM_Count % 5U) == 1U)
G_UART_Flag = 1U;
if ((G_TIM_Count % 2U) == 0U)
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
}
}
/* 初始化完成后 */
HAL_TIM_Base_Start_IT(&htim1);
while (1)
{
if (G_UART_Flag == 1U)
{
G_UART_Flag = 0U;
printf("MCU stm32 run time is %lus\r\n",
(unsigned long)G_TIM_Count);
}
}
编译、烧录并打开串口后,应看到 1、6、11……秒的运行时间;LED1 每秒翻转,LED2 每两秒翻转。若希望输出 5、10、15……秒,只需把打印条件改为 G_TIM_Count % 5U == 0U。整个设计的重点不是某个具体余数,而是“硬件定时器产生稳定节拍,中断快速记录事件,主循环处理耗时任务”。