中断通常被定义为一个事件,该事件能够改变处理器执行指令的顺序。这样的事件与 CPU 芯片内外部硬件电路产生的电信号相对应。
中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。
中断分为同步中断和异步中断:
同步中断:同步中断是当指令执行时由
控制单元
产生的,之所以称为同步,是因为只有在一条指令终止执行后 CPU 才会发出中断。异步中断:异步中断是由其他硬件设备依照
CPU时钟信号随机
产生的。通常所说的中断指的是
异步中断
,我们将同步中断称为异常
。(异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的)
中断处理
:指CPU响应中断,转入中断处理程序,系统开始处理中断。
中断响应
:指CPU收到中断请求后转向相应的事件处理程序。
中断屏蔽
:指在中断请求产生后,系统用软件方式有选择地封锁部分中断而允许其余部分中断仍能得到响应。
中断的优先级:
1.多个中断同时出现时,处理器先响应高优先级的中断
2.低优先级中断的ISR执行时,可以被高优先级中断再次打断
3.ISR比App Code拥有更高的执行优先级
PA5引脚作为led灯的输出口,PA5设置为GPIO_Output
PB15为开关的输出口,将PB15设置为GPIO_EXTI15
将引脚命名LD2,初始电平设置为低电平low
将PB15口的触发方式选择为下降沿触发,引脚名称命名为B1_EXTI
使引脚对应的外部中断线EXTI Line[15:10]
选择GPIO—NVIC—勾选EXTI Line[15:10]
选择SYS,将debug选为Serial Wire
选择RCC将HSE改为Crystal/Ceramic Resonator
将Priority Group设置为4bit
EXTI Line[15:10]中的Preemption Priority设置为15
选择project manager,工程命名为diandeng
设置保存路径,将IDE改为MDK-ARM
/* USER CODE BEGIN 4 */
/*
* @brief EXTI line detection callbacks.
* @param GPIO_Pin: Specifies the pins connected EXTI line,
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if( GPIO_Pin == B1_EXTI_Pin ) // 判断外部中断源
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); // 翻转LD2状态
}
}
/* USER CODE END 4 */
将代码段放入main.c的文件中
编译可知,0 Error(s)没有错误
当开关接高电平时,LED亮灯;接低电平时,LED灭灯
选择RCC,HSE选择外部时钟源
设置串口,选择USART1,MODE–异步通信,波特率为115200 Bits/s,传输数据长度为8 Bit,GPIO引脚设置 USART1_RX/USART_TX,NVIC Settings 一栏使能接收中断
创建文件,选择MDK-ARM格式并打开
当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”的代码如下:
#include "gpio.h"
#include
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;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为1时,发送提示并改变flag
else if(c=='t'){
flag=1;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF);
}
//当输入不存在指令时,发送提示并改变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 */
}
串口每隔0.5s输出Hello windows
当下方发送s,串口会进入中断,发送t,之后回到原循环,继续发送hello Windows。
main函数调用连续发送数据函数
添加字符串库
中断控制器 NVIC 的配置
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置 USART 为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 抢断优先级为 1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级为 1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置 NVIC */
NVIC_Init(&NVIC_InitStructure);
}
字符串连续发送的函数
/***************** 发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到 USART */
USART_SendData(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do {
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while (*(str + k)!='\0');
/* 等待发送完成 */
while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {
}
}
USART 初始化配置以及串口中断优先级配置
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口 GPIO 的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
// 将 USART Tx 的 GPIO 配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将 USART Rx 的 GPIO 配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx, &USART_InitStructure);
// 串口中断优先级配置
NVIC_Configuration();
// 使能串口接收中断
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(DEBUG_USARTx, ENABLE);
}
当stm32接收到字符“stop stm32!”时,停止持续发送“hello Windows”; 当接收到字符“go stm32!”时,持续发送“hello Windows”
通过对中断的学习可知,在正常运行程序时,中断方式不必等待数据的传输过程,由于程序的预先安排或内外部事件,引起中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源。HEL库是一种十分方便的实现中断的方式,只需要修改部分代码实现串口中断完成 STM32 与上位机的通讯,代码主要实现是在发送数据函数中。通过对代码的实现,更好的传输数据提升了效率,希望能帮到各位读者。
串口通信的相关知识
中断系统的相关知识
stm32 与主机通讯
STM32串口通信USART学习笔记
HAL库实验中断开关点灯及串口通信