读串口总结

来源:互联网 发布:矩阵行列式计算公式 编辑:程序博客网 时间:2024/05/24 16:14

       项目需求从串口中读取数据,刚开始方案是一次从串口中read 512字节的数据然后解析,代码写完后发现有时候接收的数据不是完整的一包数据,导致数据无法解析,为解决这个问题,修改方案为循环读取,一直读到需要的数据为止,最后实现了功能,但算法太复杂,影响效率。

    最后采用SLIP协议封装数据



   SLIP(Serial Line Internet Protocol)是一个简单的面向字符的协议,其规则如下:

1.   在每个用户信息帧的首尾各加-个特殊的标志字END ,封装成为 SLIP 帧。标识字节 END 的编码为($C0)。

2.        若用户信息帧中的某-个字节与标识字节END的编码($C0)-样,那么就要将这一个字节更换成($DB, $DC)这样的2字节序列。这里的特殊字符($DB)称为SLIP转义字符。

3.        若用户信息帧中的某个字节与SLIP转义字符($DB)-样,那么就要将这一个字节更换成($DB, $DD)这样的2字节序列。

    读取数据时每次从串口读取一个字节,进行解析,直到读取完一帧完整的数据,代码如下:

int read_local_panel_fd(int fd, unsigned char *cmd_buf, int *write_fifo){    int ret;    int frame = 0;    int rcv = 1;     int quit = FALSE;    unsigned char ch;    int2char(fd, cmd_buf, 1);   /*把端口写入cmd_buf中*/    while(1)    {        ret = read(fd, &ch, 1);        if(ret < 0)        {            D3100_PRINT("");            perror("read failure");        }        printf("***cmd buf  %2x\n", ch);        switch(ch)        {            case SLIP_FLG: //0xC0                frame++;                D3100_PRINT("\n");                if(2 == frame)                {                    quit = TRUE;                    frame =0;                    if(check_checksum(cmd_buf + 1, rcv - 1))   /*去掉端口号*/                    {                        D3100_PRINT("\n");                        *write_fifo = TRUE;                    }                    else                    {                        D3100_PRINT("");                        printf("error cmd\n");                        reply_cmd(fd, change_to_reply_cmd(cmd_buf[0]), REPLY_ERROR_CODE);                    }                }                break;            case SLIP_DB: //0xDB                          read(fd, &ch, 1);                switch(ch)                {                    case SLIP_DC:                        cmd_buf[rcv++] =SLIP_FLG; //0x0C                        break;                    case SLIP_DD:                        cmd_buf[rcv++] =SLIP_DB; //0x0C                        break;                }                break;            default:       //内容                   if(1 == frame)                {                    cmd_buf[rcv++] = ch;                }                break;        }        if(quit)        {            break;        }    }    return rcv;}

  在调试过程中遇到的问题主要有下面两个:

1、多次接受数据时,接受数目未初始化,导致数组越界

2、数据中有0时解析数据时会从0的地方断开,经过调试跟踪代码最后发现在copy数据时,copy的长度使用strlen计算,这样会出现问题。

  strlen不能用于有数据0 的字符串,但是memcpy可以。