当前位置:首页>Linux>001-Linux系统中最好的C/C++串口接收驱动

001-Linux系统中最好的C/C++串口接收驱动

  • 2026-09-09 00:16:39
001-Linux系统中最好的C/C++串口接收驱动

1.发现问题

      在嵌入式Linux设备中,用C/C++语言开发串口通信软件,发现嵌入式设备通过串口接收外部设备传入的报文时,经常接收不全,具体表现为:

  1. 只接收了报文前面几十个字节。
  2. 接收一个长报文时,断断续续接收了好多个短报文。

      这种串口接收“断帧”问题对于通信功能是严重问题。

2.分析问题

      根据问题现象,分析可能的原因有以下两项:

  1. 串口硬件原因,导致本身接收不全。
  2. 串口软件驱动原因,能接收全,但需要自行缓冲及组帧。

      根据可能的原因,制定排查方案如下:

  1. 首先通过大量测试,检查是否能接收完整,以便排除硬件原因。
  2. 如果能接收完整,再试验如何能在一帧内完整接收长报文。

3.解决问题

      经排查,硬件没问题,断断续续能收到长报文的所有内容。所以考虑自行缓冲及组帧。      

      根据以上分析结论,制定解决方案,在串口普通接收的基础上,增加缓冲层,再增加完整帧判断机制,原理如下:

  1. 用while循环+select机制,持续监听串口接收,将接收到的报文拼接并缓存。
  2. 如果持续一段时间无接收,则认为此次报文接收完毕。

      核心源代码如下:

/* * FD:串口设备文件描述符 * data:输出缓冲区 * datalength:最多读取多少字节数 * gap_time_ms:指定的帧间隔,以ms为单位 * 返回值:返回实际读取的字节数 */intReadComPort_longdata(int FD,void *data, int datalength, int gap_time_ms){    int loopi = 0;    int  nread1 = 0;    unsigned char u8_buf[1500+1];	//一次最多接收1500字节,对于普通应用足够了    int cur_pos = 0;    fd_set inputs, testfds;    struct timeval timeout;    int result, nread;    if(data == NULL)    {        return 0;    }    if(datalength > 1500)	//一次最多接收1500字节,对于普通应用足够了    {        datalength = 1500;	//一次最多接收1500字节,对于普通应用足够了    }    FD_ZERO(&inputs);    FD_SET(FD, &inputs);    cur_pos = 0;    loopi=0;    do    {        testfds = inputs;        timeout.tv_sec = 0;        timeout.tv_usec = gap_time_ms * 1000;//ms级 断帧足够用了        result = select(FD + 1, &testfds, (fd_set *)NULL, (fd_set *)NULL, &timeout);        switch (result) {        case 0:            loopi++;//超时计数            break;        case -1:            loopi++;            break;        default:            if(FD_ISSET(FD, &testfds))            {                ioctl(FD, FIONREAD, &nread);//查看有多少字节可以读取                if(nread > 0)//如果可读字节数大于0                {                    if((cur_pos + nread) > datalength)                    {                        nread1 = datalength - cur_pos;                    }                    else {                        nread1 = nread;                    }                    nread = read(FD, &u8_buf[cur_pos], nread1);                    cur_pos = cur_pos + nread;                }            }            break;        }        if(cur_pos >= datalength)        {            break;        }    }while(loopi < 1);    if(cur_pos > 0)    {        memcpy(data, u8_buf, cur_pos);    }    return cur_pos; }

      通过这种方式,即可完美接收串口报文。

      完整的源代码、使用说明、自测报告等参见附件“最好的Linux串口接收驱动.zip”,请私信联系我获取。

4.问题总结

      本文对Linux中C/C++编写串口通信软件时,接收报文不完整的原因进行了详细分析。然后提出while循环+select监听机制的处理措施,解决了该问题。该方案通用性强,灵活性高,值得参考和使用。

最新文章

随机文章