目录
stm32中断原理
在STM32微控制器中,中断是一种重要的事件驱动机制,用于处理实时事件而无需持续轮询。中断在处理外部事件(如按键输入、定时器溢出等)时非常有用。以下是关于STM32中断的基本原理:
中断控制器:STM32微控制器内部有一个中断控制器,负责管理和分配中断请求。中断控制器会根据中断优先级来确定哪个中断应该被处理。
中断优先级:每个中断源都有一个优先级,优先级较高的中断会在优先级较低的中断之前得到处理。在STM32中,中断优先级通常通过NVIC(Nested Vectored Interrupt Controller)进行配置。
中断向量表:中断向量表是一个存储中断处理函数地址的表格。当发生中断时,处理器会根据中断号在中断向量表中查找对应的中断处理函数的地址并跳转执行。
中断处理流程:当发生中断时,处理器会立即暂停当前任务,保存当前上下文(如寄存器状态)并跳转到中断处理函数。中断处理函数执行完毕后,会恢复之前保存的上下文并返回到中断发生的地方继续执行。
配置中断:要在STM32中启用中断,通常需要配置相应的中断优先级、中断触发条件以及中断处理函数。这通常涉及设置相关的寄存器和中断控制器。
标准库
在STM32微控制器开发中,标准库通常指的是STMicroelectronics提供的STM32标准外设库(Standard Peripheral Library)或者Cube库(Cube库是HAL库的前身,提供了更高级的抽象层)。这些库提供了一系列函数和驱动程序,用于简化对STM32外设(如GPIO、UART、SPI等)的控制和配置。
以下是关于STM32标准库的一些重要信息:
功能:STM32标准库提供了一组函数,用于配置和控制微控制器的外设。这些函数可以帮助开发者快速编写代码,而无需深入了解底层寄存器的操作。
使用:开发者可以通过包含相应的头文件并调用库中的函数来使用STM32标准库。例如,要配置一个GPIO引脚,可以调用库中提供的函数来设置引脚的模式、速度、上拉/下拉等属性。
优点:使用STM32标准库可以简化开发流程,减少对寄存器级编程的需求,提高代码的可移植性和可维护性。
替代品:随着时间的推移,STMicroelectronics逐渐推出了Cube库(Cube库包含了HAL库和LL库),提供了更高级的抽象层和更丰富的功能。Cube库通常被认为是标准库的更先进版本。
高低电平使LED亮灭灯
连接硬件:
将一个LED连接到STM32F103核心板的GPIOA端口的一个引脚(比如PA5)。
将一个开关(用杜邦线模拟)连接到GPIOB端口的一个引脚(比如PB0)。
编写中断处理程序:
首先,需要初始化GPIOA和GPIOB端口为输入和输出模式,并启用相应的中断功能。
然后,编写中断处理程序,当检测到GPIOB端口引脚的状态改变时,执行相应的操作来控制GPIOA端口引脚的状态。
编程实现:
在你的STM32F103项目中,你需要设置GPIOA引脚为输出模式,用于控制LED。设置GPIOB引脚为输入模式,用于读取开关状态。
配置GPIOB引脚的中断触发条件,例如上升沿或下降沿触发中断。
在中断服务程序中,读取GPIOB引脚的状态,如果检测到状态变化,根据开关状态控制GPIOA引脚来点亮或熄灭LED。
调试和测试:
烧录程序到STM32F103核心板上,确保硬件连接正确。
测试开关的功能,检查LED是否根据开关状态正确亮灭。
采用串口中断方式做串口通信
分别实现:
(1)当stm32接收到1个字符"s"时,停止持续发送"hello windows!"; 当接收到1个字符"t"时,持续发送"hello windows!"
(2)当stm32接收到字符"stop stm32!"时,停止持续发送"hello windows!"; 当接收到字符"go stm32!"时,持续发送"hello windows!"
代码:
c
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include <string.h>
void SystemClock_Config(void);
char c;//指令 0:停止 1:开始
char message[]="hello Windows\n";//输出信息
char tips[]="CommandError\n";//提示1
char tips1[]="Start.....\n";//提示2
char tips2[]="Stop......\n";//提示3
int flag=0;//标志 0:停止发送 1.开始发送
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
//设置接受中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
//当flag为1时,每秒发送一次信息
//当flag为0时,停止
while (1)
{
if(flag==1){
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为0时,发送提示并改变flag
if(c=='s'){
flag=0;
}
//当输入的指令为1时,发送提示并改变flag
else if(c=='t'){
flag=1;
}
//当输入不存在指令时,发送提示并改变flag
else {
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF);
}
//重新设置中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
}
/* USER CODE END 4 */
/**
* @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_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != 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 */
}
编译没有错误后,进行烧录就完了。