STM32F103中断控制灯与串口通信

一、文章内容提示

学习stm32中断、DMA通信原理和编程方法。使用stm32tubemx和HAL库分别完成以下编程练习:

  1. 用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。
  2. 采用串口中断方式重做上次的串口通信:一个STM32的USART串口通信程序(汇编)
  3. STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。

二、STM32中断

2.1 中断概念

  • 中断:

CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行,这一过程称为中断。引发中断的称为中断源。
比如:看电视时突然门铃响,那么门铃响就相当于中断源。有些中断还能够被其他高优先级的中断所中断,那么这种情况又叫做中断的嵌套。
STM32F10x芯片有84个中断通道,包括 16 个内核中断和 68 个可屏蔽中断,这些中断通道已按照不同优先级顺序固定分配给相应的外部设备。

  • 抢占优先级:高抢占式优先级的中断事件会打断当前的主程序/中断程序的运行。中断嵌套。
  • 响应优先级:在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。不能嵌套,只能等待低响应优先级中断执行完成才能得到响应。
  • 规则:先抢占优先级,后响应优先级;抢占式优先级决定是否会有中断嵌套。

2.2 NVIC介绍

NVIC英文全称是Nested Vectored Interrupt Controller:中文意思就是嵌套向量中断控制器,它属于M3内核的一个外设,控制着芯片的 中断相关功能。由于ARM给NVIC预留了非常多的功能,但对于使用M3内核设计芯片的公司可能就不需要这么多功能,于是就需要在NVIC上裁剪。ST公司的STM32F103芯片内部中断数量就是NVIC裁剪后的结果。 中断控制相关寄存器在固件库core_cm3.h文件NVIC结构体内。可打开任意库函数工程即可查看到。

2.3 中断优先级

  • STM32F103芯片支持60个可屏蔽中断通道,每个中断通道都具备自己的中断优先级控制字节(8位,但是STM32F103中只使用4位,高4位有效),用于表达优先级的高4位又被为组成抢占式优先级和响应
  • 优先级:通常也把响应优先级称为“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。 高抢占式优先级的中断事件会打断当前的主程序或者中断程序运行,俗称中断嵌套。在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理那一个。

三、高低电平控制控制LED灯亮和灭

3.1 步骤

  • 新建项目

请添加图片描述

  • 选择STM32F103C8,后续按图示即可

请添加图片描述

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
到这一部分,操作到和图示一致。

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

3.2 加入代码

在Keil打开的项目里找到 main.c打开,加入以下代码:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    
    
	GPIO_PinState b0_pin = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);  // 读取b0的状态
	b0_pin=1-b0_pin;
	switch (GPIO_Pin){
    
    //判断引脚
		case GPIO_PIN_0:
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,1-b0_pin);  // 将a1写入与b0相同的电位
			break;
	}
	
}

注意代码加在main函数外面。

3.3 烧录

  • 用串口调试助手烧录即可。

3.4 实验结果

因视频太大,所以剪辑了一下,实际显示可能稍有出入;
中断是:GPIOB端口一引脚接一个开关(用杜邦线模拟代替),即用杜邦线连接断开,此处未拍出。

请添加图片描述

四、串口通信

4.1 步骤

步骤和前面的一致,但有不一样的地方参考下面图示。

  • 在设置完SYS和RCC后,设置下图所示:

请添加图片描述

  • 设置完后面想应的后,重新命名项目,及保存路径,将CodeGenerator设置后,GENERATE CODE,然后open project在Keil里打开。

请添加图片描述

4.2 加入代码

  • 在keil5里打开项目,进入main.c文件,在里面定义如下数据,注意不是在main函数里,而是在头文件后:
uint8_t aRxBuffer;//接收缓冲中断
uint8_t Uart1_RxBuff[256];//接收缓冲
uint8_t Uart1_Rx_Cnt=0;//接收缓冲计数
uint8_t cAlmStr[]="数据溢出(大于256)";
  • 在main.c里添加,注意不是加在main函数里
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    
    
  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);   //再开启接收中断

}
  • 在main函数里,最后面添加:
//接收中断函数
	HAL_UART_Receive_IT(&huart1,(uint8_t*)&aRxBuffer,1);

4.3 实验结果

  • 连接串口,烧录

请添加图片描述

  • 通过串口助手发送消息,显示:

请添加图片描述

注意:
烧录时Boot0要置1;
调试时串口置0。

小小的总结

  • 设置了中断之后,在回调函数里写入我们想要实现功能,当我们触发中断的时候,就会实现功能。
  • 用STM32CubeMX来代替写代码特别方便,只需要写入一些我们想要的函数即可。
  • 烧录时还是要注意器件的连接问题,接触不良就会烧录不成功,其次一定要注意Boot0置1和置0,不然就不能完成实验。

参考文献

  1. stm32之串口通信DMA传输完成中断
  2. STM32F103中断系统
  3. 通过中断来控制LED灯(STMF103C8+HAL库)

猜你喜欢

转载自blog.csdn.net/YouthBlood9/article/details/121173798