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

文章目录

  • 一、中断的介绍
    • 1.中断的定义
    • 2.中断的执行过程
    • 3.中断的优先级
    • 4.中断方式使用按键
  • 二、中断方式点灯
    • 1.引脚的分配
    • 2.外设的配置
    • 3.配置中断的优先级
    • 4.工程文件的配置
    • 5.代码编写
    • 6.文件的烧录
    • 7.程序运行结果
  • 三、中断方式串口通信
    • 1.HEL库实现串口通信
      • (1)HEL库的配置
      • (2)代码的编译
      • (3)串口通信的实现
    • 2.USART串口中断通信
      • (1)代码分析
      • (2)程序的编译
      • (3)串口通信的实现(字符串)
  • 四、总结
  • 参考文献

一、中断的介绍

1.中断的定义

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

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

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

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

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

2.中断的执行过程

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

3.中断的优先级

中断的优先级:
1.多个中断同时出现时,处理器先响应高优先级的中断
2.低优先级中断的ISR执行时,可以被高优先级中断再次打断
3.ISR比App Code拥有更高的执行优先级基于HEL库中断开关点灯以及USART串口中断通信_第2张图片

4.中断方式使用按键

操作过程中利用杜邦线分别接高低电平代替按键开关。基于HEL库中断开关点灯以及USART串口中断通信_第3张图片

二、中断方式点灯

1.引脚的分配

PA5引脚作为led灯的输出口,PA5设置为GPIO_Output
PB15为开关的输出口,将PB15设置为GPIO_EXTI15
基于HEL库中断开关点灯以及USART串口中断通信_第4张图片

2.外设的配置

将引脚命名LD2,初始电平设置为低电平low
基于HEL库中断开关点灯以及USART串口中断通信_第5张图片
将PB15口的触发方式选择为下降沿触发,引脚名称命名为B1_EXTI
基于HEL库中断开关点灯以及USART串口中断通信_第6张图片
使引脚对应的外部中断线EXTI Line[15:10]
选择GPIO—NVIC—勾选EXTI Line[15:10]
基于HEL库中断开关点灯以及USART串口中断通信_第7张图片选择SYS,将debug选为Serial Wire
基于HEL库中断开关点灯以及USART串口中断通信_第8张图片
选择RCC将HSE改为Crystal/Ceramic Resonator
基于HEL库中断开关点灯以及USART串口中断通信_第9张图片

3.配置中断的优先级

将Priority Group设置为4bit基于HEL库中断开关点灯以及USART串口中断通信_第10张图片
EXTI Line[15:10]中的Preemption Priority设置为15
基于HEL库中断开关点灯以及USART串口中断通信_第11张图片

4.工程文件的配置

选择project manager,工程命名为diandeng
设置保存路径,将IDE改为MDK-ARM基于HEL库中断开关点灯以及USART串口中断通信_第12张图片

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的文件中基于HEL库中断开关点灯以及USART串口中断通信_第13张图片
编译可知,0 Error(s)没有错误基于HEL库中断开关点灯以及USART串口中断通信_第14张图片

6.文件的烧录

利用烧录软件FlyMcu对hex文件进行烧录基于HEL库中断开关点灯以及USART串口中断通信_第15张图片

7.程序运行结果

当开关接高电平时,LED亮灯;接低电平时,LED灭灯

三、中断方式串口通信

1.HEL库实现串口通信

(1)HEL库的配置

选择RCC,HSE选择外部时钟源
基于HEL库中断开关点灯以及USART串口中断通信_第16张图片
设置串口,选择USART1,MODE–异步通信,波特率为115200 Bits/s,传输数据长度为8 Bit,GPIO引脚设置 USART1_RX/USART_TX,NVIC Settings 一栏使能接收中断
基于HEL库中断开关点灯以及USART串口中断通信_第17张图片
基于HEL库中断开关点灯以及USART串口中断通信_第18张图片
基于HEL库中断开关点灯以及USART串口中断通信_第19张图片
创建文件,选择MDK-ARM格式并打开基于HEL库中断开关点灯以及USART串口中断通信_第20张图片

(2)代码的编译

当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 */
}

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

(3)串口通信的实现

串口每隔0.5s输出Hello windows
当下方发送s,串口会进入中断,发送t,之后回到原循环,继续发送hello Windows。基于HEL库中断开关点灯以及USART串口中断通信_第21张图片

2.USART串口中断通信

(1)代码分析

main函数调用连续发送数据函数基于HEL库中断开关点灯以及USART串口中断通信_第22张图片
添加字符串库基于HEL库中断开关点灯以及USART串口中断通信_第23张图片
中断控制器 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库中断开关点灯以及USART串口中断通信_第24张图片

四、总结

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

参考文献

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

你可能感兴趣的:(单片机,嵌入式硬件,stm32)