STM32串口详解

实验一:简单的利用串口接收中断回调函数实现数据的返回

 

关于串口调试助手,还应知道:

  • 发送英文字符需要用一个字符即8位,发送汉字需要两个字符即16位,如上图,发送汉字“姜”实际是发送“BD AA”而发送英文字符X实际是发送“58”,本质上没有太大区别;
  • 勾选了下方“发送新行”后,XCOM就会再你输入的需要发送的数据后自动加上一个回车(0X0D+0X0A),如果不勾选则我们在手动输入完“宋S”后还需敲一个回车键只有这样点击发送后,调试助手上方窗体才能将其显示,这是因为我们在程序的串口中断中自定义了一个数据接收协议,即只有当接受的数据以回车结尾(0X0D+0X0A),串口才认可数据接受完毕

这里可以看出下列代码中的 0D回车,0A换行 是用来判断结束位的

if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D))

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>//meset()函数调用
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数
/* USER CODE END PV */
  /* USER CODE BEGIN 2 */
    HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);   //中断接收一个字符
  /* USER CODE END 2 */
/*
串口接收中断回调函数
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
	{
		if (Uart1_Rx_Cnt >= 255)
		{
			memset(RxBuffer,0x00,sizeof(RxBuffer));//对数组进行清零操作
			HAL_UART_Transmit(&huart1,(uint8_t *)"数据溢出",4,0xffff);//
		}
		else
		{
			RxBuffer[Uart1_Rx_Cnt++]=aRxBuffer;   //接收数据转存
			if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位 0D回车,0A换行 
					{
						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,&aRxBuffer,1);	//使得程序可以重新触发接收中断	+

} 

上述代码实现的是 发送数据被返回

实验二:

1、串口发送/接收函数

  • HAL_UART_Transmit();串口发送数据,使用超时管理机制 
  • HAL_UART_Receive();串口接收数据,使用超时管理机制
  • HAL_UART_Transmit_IT();串口中断模式发送  
  • HAL_UART_Receive_IT();串口中断模式接收
  • HAL_UART_Transmit_DMA();串口DMA模式发送
  • HAL_UART_Transmit_DMA();串口DMA模式接收

2、串口中断函数

  • HAL_UART_IRQHandler(UART_HandleTypeDef *huart);  //串口中断处理函数
  • HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
  • HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
  • HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
  • HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
  • HAL_UART_ErrorCallback();串口接收错误函数

3串口查询函数

  HAL_UART_GetState();  判断UART的接收是否结束,或者发送数据是否忙碌

UART几个标志位

TXE、TC、RXNE、ORE。

TXE:发送数据寄存器为空 (Transmit data register empty)

  • 0:数据未传输到移位寄存器
  • 1:数据传输到移位寄存器

TC:发送完成 (Transmission complete)

  • 0:传送未完成
  • 1:传送已完成

RXNE:读取数据寄存器不为空 (Read data register not empty)

  • 0:未接收到数据
  • 1:已准备好读取接收到的数据

ORE:上溢错误 (Overrun error)

  • 0:无上溢错误
  • 1:检测到上溢错误

UART接收丢失数据

UART接收丢失数据与软件和硬件都有可能有关系,下面说几个常见丢失数据的原因及解决办法。

1.接收溢出丢失数据

指未及时取走数据导致溢出错误而丢失数据,通常是发生在大量数据、以查询方式接收数据的情况下。在MCU启动过程中、接收数据过多处理不及时、复杂系统响应不及时等情况都会出现数据丢失的情况。

解决办法:

  • 及时清除溢出错误标志
  • 利用通信协议过滤因数据丢失导致的问题

2.接收中断丢失数据

使用UART中断接收数据相比查询接收数据的方式更常见,中断方式比查询方式响应更及时,但不合理处理同样也会存在数据丢失的情况。

在数据量大时,UART接收中断函数耗时、优先级低等情况下容易丢失数据。

解决办法:

  • 中断函数里减少不必要的耗时
  • 合理分配中断优先级
  • 使能中断前清除标志位

3.时钟误差导致丢失数据

在通信波特率较高的情况下,如果时钟误差加大,很可能导致数据丢失。

解决办法:

  • 使用更高精度晶振
  • 降低通信波特率

UART发送丢失数据

UART发送丢失数据很多工程师都遇到过,通常情况下是传输未完成的原因。

HAL库已经有几年了,但还是有很多工程师都使用标准外设库,这时如果自己封装接口不当,就会存在发送最后一字节数据丢失的问题。

1.UART传输未完成导致数据丢失

如下代码,只考虑非空,但实际传输并未完成。

//往USART1,发送 length长度的数据data
void SendData(u8 *data,u8 length)
{
    u8 i;
    for(i=0;i<length;i++)
    {
        USART_SendData(USART2, data[i]);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)//等得发送完成
        {
        }  
    }
}

但发送非空不代表发送完成,虽然在某些场合更高效,但某些场合就会导致数据丢失。

比如:使用此函数发送之后进入休眠、关闭接收端设备电源等情况下。

解决办法:使用HAL封装的接口,代码包含判断传输完成

/*******************************************************************************
  * @函数名称	SendData1
  * @函数说明   向串口1发送数组信息
  * @输入参数 
			data:要发送的信息的首地址
			len: 发送的长度
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void SendData1(u8 *data,u8 length)
{
    u8 i;
    for(i=0;i<length;i++)
    {
			HAL_UART_Transmit(&huart1,&data[i],length,0xFFFF); //将收到的信息发送出去,HAL封装的接口,代码包含判断传输完成
    }
}

  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

姜浩鑫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值