HAL库实验中断开关点灯及串口通信

中断介绍

1、什么是中断

中断是计算机独有的一种工作方式;在主程序执行的过程中,中断主程序的执行;在执行子程序的过程中,中断子程序的执行。中断程序主要是为某些特定控制功能而设定。与子程序不同,中断是随机发生且必须立即响应的。需要执行中断程序必须要有中断源(引发中断的信号)每个中断信号都有一个编号加以识别,也就是我们说的中断事件号。
通信中断:CPU 的串行通信端口可通过程序进行控制。通信端口的这种操作模式称为自由端口模式。在自由端口模式下,程序定义波特率、每个字符的位数、奇偶校验和协议。接收和发送中断可简化程序控制的通信。
时基中断:基于时间的中断包括定时中断和定时器 T32/T96 中断。可使用定时中断指定循环执行的操作。循环时间位于 1 ms 到 255 ms 之间,按增量为 1 ms 进行设置。必须在定时中断 0 的 SMB34 和定时中断 1 的 SMB35 中写入循环时间。
当多个中断同时发生请求时,CPU对中断响应有优先顺序,从高到低的中断顺序分别是通信中断、I/O中断及最低的时基中断。
需要注意的是,当比如在执行I/O中断时,通信中断又产生了,此时不会马上去执行通信中断,而是执行完正在执行的I/O中断后再执行通信中断。而如果同时产生的话就是按优先顺序执行了

2、中断的作用

跟据中断的定义,我们可以通过中断使处理器转而去优先运行正常控制流之外的代码。当中断信号达到肘, CPU 必须停止它当前正在做的事情,并且切换到一个另一个活动。为了做到这就要在内核态堆钱保存程序计数器的当前值 (寄存器的内容) ,并把与中断类型相关的地址放进程序计数量。
在这里插入图片描述
中断处理是指CPU响应中断,转入中断处理程序,系统开始处理中断。
中断响应是指CPU收到中断请求后转向相应的事件处理程序。
开中断后,系统就可以响应其他的中断了,关中断后,系统不响应其他的中断除非优先级高的中断。
中断屏蔽是指在中断请求产生后,系统用软件方式有选择地封锁部分中断而允许其余部分中断仍能得到响应。

3、中断的类型及优先级

分类:
硬件中断(Hardware Interrupt) :
可屏蔽中断(maskable interrupt)。硬件中断的一类,可通过在中断屏蔽寄存器中设定位掩码来关闭。
非可屏蔽中断(non-maskable interrupt,NMI)。硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。典型例子是时钟中断(一个硬件时钟以恒定频率—如50Hz—发出的中断)。
处理器间中断(interprocessor interrupt)。一种特殊的硬件中断。由处理器发出,被其它处理器接收。仅见于多处理器系统,以便于处理器间通信或同步。
伪中断(spurious interrupt)。一类不希望被产生的硬件中断。发生的原因有很多种,如中断线路上电气信号异常,或是中断请求设备本身有问题。
软件中断(Software Interrupt) :
软件中断。是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态(Kernel Mode/Ring 0)的子例程,它常被用作实现系统调用(System call)。
优先级:
在某一时刻有几个中断源同时发出中断请求时,处理器只响应其中优先权最高的中断源。当处理机正在运行某个中断服务程序期间出现另一个中断源的请求时,如果后者的优先权低于前者,处理机不予理睬,反之,处理机立即响应后者,进入所谓的“嵌套中断”。中断优先权的排序按其性质、重要性以及处理的方便性决定,由硬件的优先权仲裁逻辑或软件的顺序询问程序来实现。
在这里插入图片描述

CubeMX中断方式点灯

1、题目分析

用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。
这里选用的核心板为STM32F103C8T6最小核心板
设置PA1端接开关,PB5接LED
对于按键电路,设置上拉式按键

按键按下,引脚PA1读到低电平 按键释放,引脚PA1读到高电平

LED灯的触发方式

按键按下瞬间,形成下降沿 按键释放瞬间,形成上升沿

因此这里设置上升沿触发,即松开按键时灯亮,因为题目要求为开关接高高电平亮灯。

2、CubeMX工程设置

先新建工程,然后外设设置指示灯LED引脚PB5,设置引脚模式为输出模式GPIO_Output、设置按键引脚PA1,设置引脚为外部中断功能,PA1与外部中断线EXIT1连接GPIO_EXIT1。
在这里插入图片描述

对于LED对应的PB5管脚,默认设置即可,名字设为LED
请添加图片描述

对于开关对应管脚PA1,设置其触发方式为上升沿触发

External Interrupt Mode with Rising edge trigger detection

上升沿

External Interrupt Mode with Falling edge trigger detection

下降沿

External Interrupt Mode with Rising/Falling edge trigger detection

上升沿和下降沿

User Label处设置名字为 A1_EXTI
请添加图片描述
使能对应的外部中断线,点击Enabled
请添加图片描述
配置中断优先级
直接使用中断编号设置的默认中断优先级请添加图片描述
时钟设置,这里设置了36M

请添加图片描述
之后生成工程文件即可

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)

当捕获到上升沿,触发中断,就会进入到这个函数里面

然后就会执行HAL_GPIO_EXTI_Callback(GPIO_Pin)函数,此函数为回调函数,我们打开可以发现前面有个weak。
前面的 __weak 表示此函数为虚函数,需要用户重写的。

3、代码撰写

在Keil文件中的gpio.c文件可以找到中断服务函数
在这里插入图片描述
那么我们在main.c文件中找个地方重新写一下。位置在main函数下方。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if( GPIO_Pin == A1_EXTI_Pin)//判断外部中断源
	{
		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);//翻转LED状态
	}
}

在这里插入图片描述
编译
在这里插入图片描述
将代码烧录到C8T6核心板中

在这里插入图片描述

中断方式串口通信

1、题目要求

完成一个STM32的USART串口通讯程序(查询方式即可,暂不要求采用中断方式),要求:
1)设置波特率为115200,1位停止位,无校验位;
2)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。

根据题目,我设置,串口自动发送Hello windows!,如果接收到其他数据,则返回其他数据,之后继续发送Hello windows

2、工程设置

设置RCC
设置高速外部时钟HSE,选择外部时钟源
在这里插入图片描述
设置串口
1)点击USART1
2)设置MODE为异步通信
3)基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1,接收和发送都使能
4)GPIO引脚设置 USART1_RX/USART_TX(这里一般自动设置好了)
5) NVIC Settings 一栏使能接收中断
在这里插入图片描述
在这里插入图片描述
时钟设置:
在这里插入图片描述
之后导出Keil文件并打开。

3、代码撰写

printf函数设置
在main.c和usart.c中添加头文件#include "stdio.h"之后,在usart.c文件中,添加如下代码,进行重定义
/* USER CODE BEGIN 1 */

//加入以下代码,支持printf函数,而不需要选择use MicroLIB

//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)	
#if 1
//#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	 HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0x0001);  
	return ch;
}
#endif 

/* USER CODE END 1 */

在main.c主函数中,添加发送数据

/* USER CODE END WHILE */
  	printf("Hello windows!\r\n");
	HAL_Delay(500);
/* USER CODE BEGIN 3 */

在main.c中添加如下定义,用来接收串口数据

uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_RxBuff[256];		//接收缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数
uint8_t	cAlmStr[] = "数据溢出(大于256)\r\n";

添加开启接收中断的语句

/* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */

在main.c下部添加中断回调函数

/* USER CODE BEGIN 4 */
/**
  * @brief  Rx Transfer completed callbacks.
  * @param  huart pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
		Uart1_Rx_Cnt = 0;
		memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
		HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);	
	}
	else
	{
		Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
	
		if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
			Uart1_Rx_Cnt = 0;
			memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

编译后,不报错,烧录即可

4、串口助手通信

进行通信,boot0接0利用XCOM进行通信

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

参考:
[1]https://blog.csdn.net/qq_20233867/article/details/72236576
[2] https://blog.csdn.net/qq_44918248/article/details/114579472
[3] https://blog.csdn.net/qq_44918248/article/details/114579472

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值