基于HEL库中断开关点灯以及USART串口中断通信

一、中断的介绍

1.中断的定义

中断通常被定义为一个事件,该事件能够改变处理器执行指令的顺序。这样的事件与 CPU 芯片内外部硬件电路产生的电信号相对应。
  中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。
在这里插入图片描述

中断分为同步中断和异步中断:

同步中断:同步中断是当指令执行时由控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后 CPU 才会发出中断。

异步中断:异步中断是由其他硬件设备依照 CPU时钟信号随机产生的。

通常所说的中断指的是异步中断,我们将同步中断称为异常。(异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的)

2.中断的执行过程

中断处理:指CPU响应中断,转入中断处理程序,系统开始处理中断。
中断响应:指CPU收到中断请求后转向相应的事件处理程序。
中断屏蔽:指在中断请求产生后,系统用软件方式有选择地封锁部分中断而允许其余部分中断仍能得到响应。

3.中断的优先级

中断的优先级:
1.多个中断同时出现时,处理器先响应高优先级的中断
2.低优先级中断的ISR执行时,可以被高优先级中断再次打断
3.ISR比App Code拥有更高的执行优先级在这里插入图片描述

4.中断方式使用按键

操作过程中利用杜邦线分别接高低电平代替按键开关。在这里插入图片描述

二、中断方式点灯

1.引脚的分配

PA5引脚作为led灯的输出口,PA5设置为GPIO_Output
PB15为开关的输出口,将PB15设置为GPIO_EXTI15
在这里插入图片描述

2.外设的配置

将引脚命名LD2,初始电平设置为低电平low
在这里插入图片描述
将PB15口的触发方式选择为下降沿触发,引脚名称命名为B1_EXTI
在这里插入图片描述
使引脚对应的外部中断线EXTI Line[15:10]
选择GPIO—NVIC—勾选EXTI Line[15:10]
在这里插入图片描述选择SYS,将debug选为Serial Wire
在这里插入图片描述
选择RCC将HSE改为Crystal/Ceramic Resonator
在这里插入图片描述

3.配置中断的优先级

将Priority Group设置为4bit在这里插入图片描述
EXTI Line[15:10]中的Preemption Priority设置为15
在这里插入图片描述

4.工程文件的配置

选择project manager,工程命名为diandeng
设置保存路径,将IDE改为MDK-ARM在这里插入图片描述

5.代码编写

/* 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)没有错误在这里插入图片描述

6.文件的烧录

利用烧录软件FlyMcu对hex文件进行烧录在这里插入图片描述

7.程序运行结果

当开关接高电平时,LED亮灯;接低电平时,LED灭灯
在这里插入图片描述

三、中断方式串口通信

1.HEL库实现串口通信

(1)HEL库的配置

选择RCC,HSE选择外部时钟源
在这里插入图片描述
设置串口,选择USART1,MODE–异步通信,波特率为115200 Bits/s,传输数据长度为8 Bit,GPIO引脚设置 USART1_RX/USART_TX,NVIC Settings 一栏使能接收中断
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建文件,选择MDK-ARM格式并打开在这里插入图片描述

(2)代码的编译

当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”的代码如下:

#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;
		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 */
}

编译结果,没有错误在这里插入图片描述

(3)串口通信的实现

串口每隔0.5s输出Hello windows
当下方发送s,串口会进入中断,发送t,之后回到原循环,继续发送hello Windows。在这里插入图片描述

2.USART串口中断通信

(1)代码分析

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);
 }

(2)程序的编译

0 Error(s)可知,编译错误
在这里插入图片描述

(3)串口通信的实现(字符串)

当stm32接收到字符“stop stm32!”时,停止持续发送“hello Windows”; 当接收到字符“go stm32!”时,持续发送“hello Windows”
在这里插入图片描述

四、总结

通过对中断的学习可知,在正常运行程序时,中断方式不必等待数据的传输过程,由于程序的预先安排或内外部事件,引起中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源。HEL库是一种十分方便的实现中断的方式,只需要修改部分代码实现串口中断完成 STM32 与上位机的通讯,代码主要实现是在发送数据函数中。通过对代码的实现,更好的传输数据提升了效率,希望能帮到各位读者。

参考文献

串口通信的相关知识
中断系统的相关知识
stm32 与主机通讯
STM32串口通信USART学习笔记
HAL库实验中断开关点灯及串口通信

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值