读串口总结

       项目需求从串口中读取数据,刚开始方案是一次从串口中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可以。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值