STM32学习笔记——串口中断

文章介绍了如何在STM32项目中使用HAL库设置串口接收中断,以解决程序因等待数据而卡死或数据丢包的问题。通过开启中断,在中断函数内部进行数据解算和指令发送,确保实时性。同时提到,可以使用DMA降低CPU负载,但针对小型项目,满足需求更为重要。文中提供了CubeMX配置步骤以及Keil软件的代码示例,包括数据溢出处理和数据包结束位判断。
摘要由CSDN通过智能技术生成

前言

我在HC05的文章里面已经做了串口收发的实验。但是如果在实际项目中使用的话,会出现一些问题。

比如,程序会一直停留在检测串口的函数中,如果HC05不发送数据,那么程序会因为一直没有接收到数据,导致程序卡死。

当数据发送过来,而单片机在进行其他的操作时,会来不及更新接收到的数据,导致数据丢包。

所以在实际操作中,会对串口接收开启中断,并在中断函数内,做数据的解算并对单片机发送指令。

当然你还可以开启DMA来降低CPU的功耗,让你的单片机可以做更多的事情,但是对于一个小车来说,没有那个必要。
完成项目需求比炫技重要。后续更新了DMA我会在这里转载

准备及硬件调试

这里我就不多作解释了,不清楚的可以跳转到我之前的文章观看
stm32__hc05链接

CubeMX配置

按照之前文章的方式配置,注意你的晶振频率。完成前面的配置之后只需要再开启接收中断即可

在这里插入图片描述

keil软件编写

/* USER CODE BEGIN 0 */
#include "stdio.h"
#include "string.h"

#define RXBUFFERSIZE  256     //最大接收字节数

char RxBuffer[RXBUFFERSIZE];  //接收数据
uint8_t aRxBuffer;                  //接收中断缓冲
uint8_t Uart2_Rx_Cnt = 0;     //接收缓冲计数
/* USER CODE END 0 */

/* USER CODE BEGIN 1 */
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(RxBuffer,0x00,sizeof(RxBuffer));
		HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	
	}
	else
	{
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //
	
		if(RxBuffer[0] == 'c'&&RxBuffer[1] == 'm')//当发送1时,cm
		{
			unit_change = 0;
		}
		else if(RxBuffer[0] == '+'&&RxBuffer[1] == 'm')//当发送2时,m
		{
			unit_change = 1;
		}
		
		
		if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
      	    while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1_Rx_Cnt = 0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //因为接收中断使用了一次即关闭,所以在最后加入这行代码即可实现无限使用
}
/* USER CODE END 1 */

在usart.c中添加上面两段代码
HAL_UART_RxCpltCallback()函数是一个弱函数,所以我们直接重新写一个HAL_UART_RxCpltCallback()函数来写中断回调

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

在main函数中开启中断

注解

在这个回调函数里面,首先是if语句来检测是否数据溢出
然后将寄存器aRxBuffer的值传给RxBuffer[]

if(RxBuffer[0] == 'c'&&RxBuffer[1] == 'm')//当发送1时,cm
		{
			unit_change = 0;
		}
		else if(RxBuffer[0] == '+'&&RxBuffer[1] == 'm')//当发送2时,m
		{
			unit_change = 1;
		}

这一部分是我对接收到的数据作的解析判断,写在中断回调函数里的好处就是,每一次接收到数据,都能作一次解析判断,不会因为串口发送的频率过快导致指令更新不及时

if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
      	    while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1_Rx_Cnt = 0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
		}

判断结束位,数据接收完毕之后,将接收到的数据在发送回去,我这里串口连接的是电脑XCOM,所以XCOM发送什么数据过来,它会再显示一遍接收到的数据。
当然你也可以用蓝牙模块来代替XCOM这样就是手机端发送数据,然后手机端再接收一遍。
原理都是一样的,不过是发送和接收的平台变了而已

这里可以用来检测我们的数据有没有发错,可以把这儿的发送删掉,只保留memset()函数来清空数组
当然你也可以不清空或者不在这个地方清空,代码是死的,人是活的,一切看你自己的想法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

注意沈题!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值