您当前的位置:首页 > 电脑百科 > 软件技术 > 软件技术

串口接收不定长数据的几种方法

时间:2022-09-21 14:34:14  来源:今日头条  作者:嵌入式Linux

串口作为单片机开发的一个常用的外设,应用范围非常广。大部分时候,串口需要接收处理的数据长度是不定的。那么怎么才能判断一帧数据是否结束呢,今天就以STM32单片机为例,介绍几种接收不定长数据的方法。

首先,我们需要打开一个串口,使用STM32CubeMx来配置,如下:

 

然后打开串口中断、添加发送和接收的DMA,DMA参数设置为默认即可,如下图。(DMA可根据自身需求选择是否打开)

 

 

配置一下时钟等,点击生成代码,这样就可以使用串口了。首先我们定义一个串口接收的结构体,并定义一个结构体变量,如下:

#define  RX_MAXLEN  200  //最大接收数据长度


typedef struct{
      uint8_t  RxBuf[RX_MAXLEN];//接收缓存
      uint16_t RxCnt;    //接收数据计数
      uint16_t RxLen;    //接收数据长度
      uint8_t RxStart;    //开始接收标志
      uint8_t RxFlag;    //一帧数据接收完成标志
}Uart_Tpye_t;


Uart_Tpye_t Uart1;

下面介绍几种接收数据的方法:

1.空闲中断

空闲中断可以配合接收中断或DMA来使用。

当使用DMA+空闲中断时,需要在初始化完成后手动打开空闲中断和DMA接收。

__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//打开串口空闲中断 
HAL_UART_Receive_DMA(&huart1, Uart1.RxBuf, RX_MAXLEN); //串口DMA接收数据

编写空闲中断函数,如下:

//串口空闲中断
void UART_IDLECallBack(UART_HandleTypeDef *huart)
{
    uint32_t temp;  
  /*uart1 idle processing function*/
    if(huart == &huart1)
    {
      if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))  
      {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
        /*your own code*/
        HAL_UART_DMAStop(&huart1);//停止DMA
        Uart1.RxLen = RX_MAXLEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中传输的数据个数
        Uart1.RxFlag = 1;
        HAL_UART_Receive_DMA(&huart1,Uart1.RxBuf,RX_MAXLEN); //开启下次接收
      }
    }
}

在主程序中判断接收完成标志,并处理数据:

if(Uart1.RxFlag == 1)//接收完一帧数据
{
  printf("Rev %d Bytesrn",Uart1.RxLen);
  Uart1.RxFlag = 0;
}

最后,别忘了在串口中断函数中调用自己编写的空闲中断函数。

 

运行程序测试,结果如下:

 

使用接收中断+空闲中断与DMA类似,只不过需要打开接收中断:

__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//打开串口空闲中断  
HAL_UART_Receive_IT(&huart1, &RevByte, 1); //串口中断接收数据

编写接收中断回调函数,每次接收一个字节:

uint8_t RevByte;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{    
  if(huart->Instance==USART1)
  {
    Uart1.RxBuf[Uart1.RxCnt]=RevByte;
    Uart1.RxCnt++;
    if(Uart1.RxCnt==RX_MAXLEN)
    {
      Uart1.RxCnt = RX_MAXLEN-1;
    }
    HAL_UART_Receive_IT(&huart1, &RevByte, 1); //串口中断接收数据
  }
}

编写空闲中断回调函数,与DMA的方式类似,只是数据长度判断方式不一样:

//串口空闲中断
void UART_IDLECallBack(UART_HandleTypeDef *huart)
{
  uint32_t temp;  
  /*uart1 idle processing function*/
  if(huart == &huart1)
  {
    if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))  
    {
      __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
      Uart1.RxFlag = 1;
      Uart1.RxLen = Uart1.RxCnt;
      Uart1.RxCnt = 0;
    }
  }
}

同样,在主程序中判断一帧数据的接收完成并处理。

 

2.特点协议判断帧头帧尾及长度

有时候我们需要自己定义协议传输数据,这时候就可以在通讯协议里添加特点的帧头帧尾以及数据长度字节,通过判断这些字节来判断数据的开始和结束。假设定义一个简单的传输协议如下:

帧头

数据长度,1字节

数据,N字节

0x5A,0xA5

数据部分的字节数

有效数据

可以使用中断方式接收数据:

HAL_UART_Receive_IT(&huart1, &RevByte, 1); //串口中断接收数据

接收中断函数如下:

//串口接收中断回调函数
uint8_t RevByte;
uint16_t RevTick = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  static uint16_t Rx_len;


  if(huart->Instance==USART1)
  {
    Uart1.RxBuf[Uart1.RxCnt]=RevByte;
    switch(Uart1.RxCnt)
    {
      case 0:
        if(Uart1.RxBuf[Uart1.RxCnt] == 0x5A)//帧头1正确
          Uart1.RxCnt++;
        else
          Uart1.RxCnt = 0;
        break;
      case 1:
        if(Uart1.RxBuf[Uart1.RxCnt] == 0xA5)//帧头2正确
          Uart1.RxCnt++;
        else
          Uart1.RxCnt = 0;
        break;
      case 2:
        Rx_len = Uart1.RxBuf[Uart1.RxCnt];
        Uart1.RxCnt++;
        break;
      default:
        Uart1.RxCnt++;
        if((Rx_len+3) == Uart1.RxCnt)//数据接收完成
        {
          Uart1.RxFlag = 1;
          Uart1.RxLen = Uart1.RxCnt;
          Uart1.RxCnt = 0;
        }
        break;
    }
    HAL_UART_Receive_IT(&huart1, &RevByte, 1); //串口中断接收数据
  }
}

同样,在主程序中判断一帧数据的接收完成并处理,运行测试结果如下:

 

3.超时判断

超时判断其实与空闲中断的原理类似,只不过是通过定时器来取代空闲中断来判断一帧数据的结束,一般采样接收中断+超时判断的方式。之前的文章Freemodbus移植就是采样这种方式。

超时判断的时间跟波特率有关,假设串口起始位和结束位各1位,那么接收一个字节就需要8+2=10位,在9600波特率下,一秒钟就能接收9600/10=960字节。也就是一个字节需要1.04ms,那么超时时间最小可以设置为1.5倍的单字节接收时间,或者更长。

超时判断可以使用硬件定时器或软件定时器来实现。硬件定时器的方式可以参考之前的Freemodbus移植部分的程序。软件定时器定义一个计时变量,该变量在systick中断中+1实现计时,可以节省硬件资源,但计时最小分辨率跟systick中断有关。

编写中断接收函数:

//串口接收中断回调函数
uint8_t RevByte;
uint16_t RevTick = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance==USART1)
  {
    Uart1.RxBuf[Uart1.RxCnt]=RevByte;
    Uart1.RxCnt++;
    Uart1.RxStart = 1;//开始接收标志
    RevTick = 0;//计时清零
    if(Uart1.RxCnt==RX_MAXLEN)
    {
      Uart1.RxCnt = RX_MAXLEN-1;
    }
    HAL_UART_Receive_IT(&huart1, &RevByte, 1); //串口中断接收数据
  }
}

编写超时判断函数,在Systick中断中调用:

//串口接收超时判断,该函数在Systick中断(1ms中断一次)中调用
void UartTimeOut()
{
  if(Uart1.RxStart == 1)
  {
    RevTick++;
    if(RevTick > 2)
    {
      Uart1.RxLen = Uart1.RxCnt;
      Uart1.RxCnt = 0;
      Uart1.RxStart = 0;
      Uart1.RxFlag = 1;
    }
  }
}

使用时只要打开接收中断即可,不再需要空闲中断。

HAL_UART_Receive_IT(&huart1, &RevByte, 1); //串口中断接收数据

同样,在主程序中判断一帧数据的接收完成并处理。测试结果就不贴了。

4.总结

上面几种方式都可以实现串口接收不定长数据,各有优缺点,可根据实际需求选择用哪种。需要注意的是,上面的例程只是简单地接收数据,实际应用中,还需要考虑连续接收多帧数据的情况,是缓存之后处理,还是舍弃后面的数据,都需要自己写程序实现。

文章链接:
https://mp.weixin.qq.com/s/N9_37bwnquM5rMbNMf_Sjg

转载自:Mr张工 嵌入式技术开发

文章来源:串口接收不定长数据的几种方法

版权申明:本文来源于网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。



Tags:串口   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
串口作为单片机开发的一个常用的外设,应用范围非常广。大部分时候,串口需要接收处理的数据长度是不定的。那么怎么才能判断一帧数据是否结束呢,今天就以STM32单片机为例,介绍几...【详细内容】
2022-09-21  Tags: 串口  点击:(0)  评论:(0)  加入收藏
GD32 虚拟串口通讯速度测试硬件说明: MCU: GD32C103 120M,128K,32k RAM. 输入:USB 5V. OBD功能口定义:OBD(2,10)VPWM、OBD 7(K线)、OBD 6(CAN H)、OBD 14(CAN L)、OBD 15(L...【详细内容】
2022-09-14  Tags: 串口  点击:(21)  评论:(0)  加入收藏
一、FIFO是First Input First Output的缩写,先入先出队列。使用的场景:一般是在不同的时钟域之间的数据传输(简单理解即:一个(读\写)快,另外的一个(读\写)慢的场景中。)本质操作:就是将...【详细内容】
2022-09-14  Tags: 串口  点击:(32)  评论:(0)  加入收藏
in10串口单片机烧录开启失败的问题今天和大家一起来分享下。不少的用户在安装了这个软件之后,首次开启使用的时候都有遇到这样的问题。原因可能是相关的程序串口被占用了,我们...【详细内容】
2022-09-01  Tags: 串口  点击:(0)  评论:(0)  加入收藏
在物联网中,串口服务器大家想必都是耳熟能详的一个词,但是网上对这个产品的概念讲的比较明白的,没多少,碰巧在网上看到一篇对于串口服务器概念讲解比较明了的文章,如下:串口服务器...【详细内容】
2022-08-26  Tags: 串口  点击:(55)  评论:(0)  加入收藏
一、串口服务器作用①串口服务器就是能够连接计算机端口和其他嵌入式的计算机设备,并记录端口设备的具体型号数据信息。②串口服务器所需连接的使用指定的服务器端口,在此型号...【详细内容】
2022-04-22  Tags: 串口  点击:(87)  评论:(0)  加入收藏
在目前工业4.0的背景下,企业需要一套可以远程调试设备的系统,利用物联网技术,通过结合PLC设备将设备的信息进行采集、收集,控制。利用PLC设备将设备的数据进行远程采集显示到云...【详细内容】
2021-07-14  Tags: 串口  点击:(208)  评论:(0)  加入收藏
Serial Studio是一个多平台,多用途的串行数据可视化程序。该项目的目标是使嵌入式开发人员和制造商可以轻松地可视化,呈现和分析其项目和设备生成的数据,而无需为每个项目编写...【详细内容】
2021-04-14  Tags: 串口  点击:(1178)  评论:(0)  加入收藏
目前较为常用的串口有9针串口(DB9)和25针串口(DB25),通信距离较近时(<12m),可以用电缆线直接连接标准RS232端口(RS422,RS485较远),若距离较远,需附加调制解调器(MODEM)。最为简单且常...【详细内容】
2020-10-28  Tags: 串口  点击:(543)  评论:(0)  加入收藏
串 口串行通讯端口,简称串口,也称COM口。串口的接口标准规范和总线标准规范是RS-232,有时候也叫做RS-232口。微机上的串口通常是9针,也有25针的接口,最大速率115200bps。串行接口...【详细内容】
2020-09-11  Tags: 串口  点击:(406)  评论:(0)  加入收藏
▌简易百科推荐
串口作为单片机开发的一个常用的外设,应用范围非常广。大部分时候,串口需要接收处理的数据长度是不定的。那么怎么才能判断一帧数据是否结束呢,今天就以STM32单片机为例,介绍几...【详细内容】
2022-09-21  嵌入式Linux  今日头条  Tags:串口   点击:(0)  评论:(0)  加入收藏
在网络犯罪日益猖獗的世界中,知道有许多方法可以维护网络安全令人欣慰。详细了解如何加密。在短短 20 年的时间里,互联网已经从一种理论工具转变为我们日常活动各个方面的中心...【详细内容】
2022-09-19  qaseven  今日头条  Tags:加密   点击:(12)  评论:(0)  加入收藏
我们在使用AutoCAD工作的时候,经常会遇到这样的情况,就是对已经制作好的一批DWG文件,想大批量的统一添加修改图层或者删除图层。我们使用批处理文件+脚本文件,就可以很简单地实...【详细内容】
2022-09-19  糖苦小屋  今日头条  Tags:AutoCAD   点击:(14)  评论:(0)  加入收藏
很多朋友都不知道如何把WTG系统安装到U盘中使用,今天小编就来教大家把WTG系统安装在U盘中的方法。在安装系统之前,首先我们需要了解一下什么样的U盘适合安装WTG系统。众所周知...【详细内容】
2022-09-17  小布在未来生活    Tags:U盘   点击:(12)  评论:(0)  加入收藏
用win10系统的用户都知道系统更新的时候再用户关闭电脑时会自动更新,这样总是需要等待很长的时间,今天就和大家分享win10系统取消关机自动更新系统方法。1、按win+r打开运行窗...【详细内容】
2022-09-15  电脑达人小锦     Tags:自动更新   点击:(18)  评论:(0)  加入收藏
在用户们使用win10系统的过程中,当系统突然无法上网,并且提示网络发现已关闭这种问题时该怎么办呢?今天就为大家分享win10网络发现已关闭的解决方法。1、可以看到“网络发现先...【详细内容】
2022-09-14  电脑达人小锦     Tags:网络发现   点击:(384)  评论:(0)  加入收藏
用户发现每次复制同名文件时,系统没有出现任何提示框就直接覆盖了,导致文件还没来得及备份就丢失了,接下来一起来看看win10复制同名文件没有提示直接覆盖的解决方法。1、打开此...【详细内容】
2022-09-14   电脑达人小锦     Tags:复制   点击:(17)  评论:(0)  加入收藏
windows11虽然发布已经有一段时间了,小弟虽然不才但也是方圆几千米第一个用上win11的靓仔。但是,一定还有很多小伙伴一直在坚守Win10,就像当初坚守win7一样&hellip;&hellip;额,...【详细内容】
2022-09-14  王书  今日头条  Tags:LTSC   点击:(16)  评论:(0)  加入收藏
一、FIFO是First Input First Output的缩写,先入先出队列。使用的场景:一般是在不同的时钟域之间的数据传输(简单理解即:一个(读\写)快,另外的一个(读\写)慢的场景中。)本质操作:就是将...【详细内容】
2022-09-14  嵌入式Linux  今日头条  Tags:FIFO   点击:(32)  评论:(0)  加入收藏
windows 安卓 苹果预览图MAUI介绍随着MAUI正式版的发布,一直想用MAUI来写点东西或者实现一个小的项目来学习这个微软发布的心再次躁动起来。前面预览版也有过搭建测试过,但都...【详细内容】
2022-09-14  元宇宙meta  今日头条  Tags:MAUI   点击:(28)  评论:(0)  加入收藏
站内最新
站内热门
站内头条