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

在阅读本文前,你需要先做到串口成功接收一个数据(相信这一点是很简单的)
这几天简单总结了一下用串口怎么接收一帧数据的办法,个人使用的有三种,下面逐一介绍:

第一种:使用中断的方式;

这种在数据接收不频繁状态下使用。简单易实现。既然是使用中断,所以自然需要硬件的支持,比如stm32就可以这么做,具体操作见我之前的博客stm32串口中断接收一帧数据

8位单片机估计是没有的,嵌入式32位的处理器应该会有,可以依据自己使用的芯片查一下对应的寄存器手册,重点关注一下中断寄存器和uart寄存器的介绍部分。

第二种:使用自定义结束符;

这种也是很高效的,具体的做法是,在一帧数据尾部添加一个小尾巴 ~ ~
拿我的做法举例,因为我传输的内容里面不会出现特殊字符,所以我选择特殊字符 ‘#’标识一帧数据接收完成,然后立一个flag,交由通讯处理函数去处理。
这里结束符的选取,不可以是通讯中可能传输的字符,尽量使用一个字符,简化逻辑判断。
这种方式缺点也是很明显的,即只适用于自定义的通讯格式,或者尾部结束符唯一确定的情况。代码如下:

#define MAX_LEN 10  //单个数据包的最大长度
unsigned char rxDataBuff[MAX_LEN]; //串口数据接收区
unsigned char rxLen = 0//串口接收数据计数
unsigned char rxFlag = 0//*************************************************
// 串口中断服务程序
// 依据你具体使用的mcu对应修改,这里只给出一个逻辑
// params:none
// return: none
// note:修改了全局变量 rxFlag 、 rxDataBuff[MAX_LEN] 、reLen
//*************************************************
void serialHandle()
{
    unsigned char dataTmp;
    if(RI == INT->status)//判断是否为接收中断
    {
        dataTmp = INT->data; //将串口buff的数据读出
        if('#' != dataTmp)
        {
            //
            //非结束符,把数据放到接收区
            //
            rxDataBuff[reLen++] = dataTmp;
        }
        else
        {
            //
            //结束符
            //
            rxDataBuff[reLen] = '\0';
            rxFlag = 1;
        }

    }
}
//*************************************************
// 循环内处理函数
// 此函数应该放到你的主循环里面
// 
// note:检测到flag首先清除标志位和接收计数
//*************************************************
void serialLoop()
{
    if(rxFlag == 1)
    {
        rxFlag = 0; //清除标志位
        rxLen = 0//清除接收计数
        //
        //通讯处理
        //
    }
}

第三种:外加一个定时器

这种方式相对来说延时自己计算,具体做法是在串口接收数据时启动定时器,每接收一帧数据要复位定时值以保证定时器不会溢出。亲测在高频率接收不会乱码等。定时器的超时值设置为1.5倍接收一个数据的时间,这样一来,当定时器超时时候,就意味着串口接收数据停止了。此时同样立一个flag,然后交由通讯处理函数处理。
这里的定时器大可不必单独再用一个定时器,可以使用系统滴答定时器,让滴答一次计数加一。超时的值设置要根据波特率调整,例如9600的波特率下,接收数据速率为9600bit/s = 1200B/s 也就是 0.83ms/B 那么我们的超时值可以设置为0.84*1.5 = 1.26ms 取个整1.3ms。其他波特率以此类推……
如果数据过去频繁,这种方式可能会产生粘包的情况(没测,如果有这方面使用需求一定要自己测试一下)。关于粘包处理,如果每个包数据长度基本相等的话,可以简单做一个根据包长度判断是否发生粘包。

#define MAX_LEN 10  //单个数据包的最大长度
unsigned char rxDataBuff[MAX_LEN]; //串口数据接收区
unsigned char rxLen = 0; //串口接收数据计数
unsigned char rxFlag = 0;
volatile unsigned char usCnt = 0; // 滴答计数变量,必须用volatile修饰
volatile unsigned char rxStart = 0; //开始接收标识
//*************************************************
// 串口中断服务程序
// 依据你具体使用的mcu对应修改,这里只给出一个逻辑
// params:none
// return: none
// note:修改了全局变量 rxFlag 、 rxDataBuff[MAX_LEN] 、reLen
//*************************************************
void serialHandle()
{
    unsigned char dataTmp;
    if(RI == INT->status)//判断是否为接收中断
    {
        rxStart = 1;
        rxDataBuff[rxLen++] = INT->data;
        usCnt = 0;
    }
}
//*************************************************
// 循环内处理函数
// 此函数应该放到你的主循环里面
// 
// note:检测到flag首先清除标志位和接收计数
//*************************************************
void serialLoop()
{
    if(rxFlag == 1)
    {
        rxFlag = 0; //清除标志位
        rxLen = 0; //清除接收计数
        //
        //通讯处理…………
        //
    }
}
//*************************************************
// 串口超时检测函数
// 此函数应该放到你系统滴答定时器处理函数里面
// 我的滴答设置是500us中断一次
// note:
//*************************************************
void serialTimeOut()
{
    if(rxStart == 1)
    {
        if(++usCnt > 3)
        {
            rxStart = 0;
            rxFlag = 1;
        }
    }
}

这就是我目前所能想到和已经实践过的三种串口接收一帧数据的方式了,如果觉得有用就顶一下吧

       ,___          .-;'
        "-.`\_...._/.`
    ,      \        /
 .-' ',    / ()   ()\
`'._   \  /()    .  (|
    > .' ;,     -'-  /
   / <   |;,     __.;
   '-.'-.|  , \    , \
      `>.|;, \_)    \_)
       `-;     ,    /
          \    /   <
           '. <`'-,_)
            '._)
  • 22
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: CubeMX是一种用于STM32微控制器的可视化配置工具,可以用来生成代码和配置硬件外设。当我们需要在STM32上使用串口进行不定接收时,可以使用CubeMX来配置相关参数。 首先,在CubeMX中选择对应的STM32系列微控制器型号,然后进入串口配置页面。在该页面中,我们可以选择需要使用的串口(如USART1、USART2等)以及相关的引脚配置。 接下来,在串口配置页面中,我们需要选择接收模式为无中断(Polling)模式或中断(Interrupt)模式。一般情况下,使用中断模式可以更好地处理不定数据的接收。 在中断模式下,我们需要配置接收缓冲区的大小。这个缓冲区的大小决定了我们能够一次接收的最大数据度。在CubeMX的串口配置页面中,我们可以设置接收缓冲区的大小,一般建议设置一个合适的大小以适应实际需求。 在代码生成完成后,我们需要编写相应的中断服务程序来处理串口接收中断。当接收到数据时,中断服务程序会将数据存放在接收缓冲区中,并根据数据的具体度进行相应的处理。 总结起来,使用CubeMX进行串口的不定接收,需要选择合适的串口和引脚配置,并在中断模式下设置接收缓冲区的大小。然后,通过编写中断服务程序来处理接收到的数据。这样,我们可以实现在STM32上进行不定数据串口接收。 ### 回答2: CubeMX 是 STMicroelectronics 公司开发的一款嵌入式软件工具,用于生成和配置 STM32 微控制器的初始化代码。在 CubeMX 中配置串口模块时,可以选择接收不定数据。 串口通信是一种常用的通信方式,通过串口可以将数据在设备之间进行传输。在接收数据时,不定意味着数据度是不确定的,可能会接收到任意度的数据。 在 CubeMX 中配置串口接收不定数据,首先需要选择串口模块,并设置合适的波特率和数据位数等参数。然后,在接收数据的功能代码中,可以使用中断或轮询的方式来接收数据。 使用中断方式,在 CubeMX 中使能串口接收中断,并实现相应的中断处理函数。中断函数可以在接收到数据后,根据需要进行处理,比如将数据存储到缓冲区中,或者进行其他操作。 使用轮询方式,在主循环中不断检测串口接收寄存器的状态,如果寄存器中有数据可读,则读取数据并进行处理。这种方式需要注意的是,如果没有数据可读,则可能会导致主循环一直占用 CPU 资源,因此需要设置合适的延时来避免过度占用资源。 总之,通过 CubeMX 配置串口模块接收不定数据,可以选择中断或轮询方式,根据实际需求来实现数据的接收和处理。这样可以简化开发过程,提高效率。 ### 回答3: CubeMX是一款强大的嵌入式开发工具,它能够帮助开发者快速配置和生成嵌入式系统的代码框架。在使用CubeMX配置串口时,可以设置串口为不定接收。 不定接收意味着串口可以接收不确定度的数据。具体操作如下: 首先,打开CubeMX并创建一个新的项目。然后选择所需的单片机型号和连接引脚配置。 接下来,在"Configuration"选项卡中,找到"USART"(UART)功能,并将其启用。然后选择所需的串口,例如USART1,并设置波特率等参数。 在"Configuration"选项卡的底部,有一个名为"Advanced Settings"的部分。在这里,可以找到一个名为"DMA Settings"的选项。打开该选项,并将"Rx Transfer Length"配置为不定(即设置为0)。 现在,点击工具栏上的"Project"按钮,并选择"Save"来保存配置。 生成代码后,将在生成的代码中找到相应的ISR(Interrupt Service Routine)函数,例如"USART1_IRQHandler"。这是串口接收中断服务程序的函数名。 在ISR函数中,使用相应的接收函数,例如"HAL_UART_Receive_DMA"函数,来设置接收缓冲区和缓冲区大小。由于我们将接收度设置为不定,因此可以用较大的缓冲区来接收数据。 最后,在主程序中,通过判断接收缓冲区是否有数据到达或是否已接收到完整的数据帧来处理接收的数据。 以上是使用CubeMX配置串口接收不定数据的基本步骤。根据具体的开发需求和单片机型号,可能需要进行进一步的设置和配置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值