填坑之串口接受數據不完整包的解決辦法

通過串口收發包時,遇到了一個包多次才接收完整的問題,猜測是串口的接收buffer大小的問題,這種問題採取的是拼包的形式解決,代碼看起來略微繞,主要是申請了一定大小的buffer,外加兩個指針實現。代碼如下:

#include <liblog.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/select.h>
#include <termios.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <math.h>


#define PACKET_SIZE 1024


unsigned int fp_count = 0,data_len = 0;
unsigned char data_buf[PACKET_SIZE] = {0};


static unsigned int covert16_to_10(char *s){
	int sum = 0;
	int size = 0;
	int i = 0 ,j = 0;	
	unsigned char num[100] = {'\0'};
	while(*s != '\0'){
		num[size++] = *(s++);
	}
	if(num[0] == '0' && (num[1] == 'x' || num[1] == 'X'))
		j = 2;
	else if((num[0] >= 'a' && num[0] <= 'z') || (num[0] >= 'A' && num[0] <= 'Z')){
		printf("Not is number\r\n");
		return -1;
	}
	else if((num[0] >= '0' && num[0] <= '9')){
		j = 0;
	}
	for(i = j;i < size;i++){
		//printf("%c",num[i]);
		if(num[i] >='0' &&num[i] <='9')
			sum  += (num[i] - '0') * pow(16,size-i-1);	
		if(num[i] >='a' &&num[i] <='f')
			sum  += (num[i] - 'a' + 10) * pow(16,size-i-1);
		if(num[i] >='A' &&num[i] <='F')
			sum  += (num[i] - 'A' + 10) * pow(16,size-i-1);
	}
	//printf(" sum %d\n",sum);
	return sum;
}




static int send_bd_packet(unsigned char *buf,int len)
{
    int ret = 0;
    ret = write(g_bd_dev.uart_fd,buf,len);
    if(ret < 0){
        pr_info("send packet faild");
        return -1;
    }

    return ret;
}


int bd_packet_parse(unsigned char *bd_buf)
{
	
}

int bd_packet_handle(int fd)
{
    int ret = 0,i = 0,j = 0;
	int len = 0;
	unsigned char tmp = 0;
    unsigned char recv_buf[PACKET_SIZE] = {0};
	unsigned char tmp_buf[PACKET_SIZE] = {0};
	memset(recv_buf,0,PACKET_SIZE);
	memset(tmp_buf,0,PACKET_SIZE);
	
    ret = read(fd,recv_buf,sizeof(recv_buf));
    if(ret < 0){
        pr_info("bd read buf faild");
        return ret;
    }
	
#if 0
	printf("ret %d\n",ret);
	printf("recv_buf :%s\n",recv_buf);
#endif

	if(data_len + ret >= PACKET_SIZE || fp_count >= PACKET_SIZE){
		memset(data_buf,0,PACKET_SIZE);
		data_len = 0;
		fp_count = 0;
	}
	i = 0;
	while(i < ret){
		data_buf[data_len] = recv_buf[i];
		i++;
		data_len++;
	}
	
#if 0
	printf("data_buf :%s\n",data_buf);
	printf("fp_count :%d\n",fp_count);
#endif

do_cpy:
	i = fp_count;
	tmp = 0;
	while(tmp != '$' && i < data_len){
		tmp = data_buf[i];
		i++;
	}
	fp_count = i - 1;
	
#if 0
	printf("fp_count :%d\n",fp_count);
	printf("data_len :%d\n",data_len);
#endif
	memset(tmp_buf,0,PACKET_SIZE);
	i = fp_count;
	j = 0;
	tmp = 0;
	tmp = data_buf[i++];
	tmp_buf[j++] = tmp;
	tmp = 0;
	while(tmp != 0x0a && i < data_len ){
	
		tmp = data_buf[i];
		if(tmp == '$'){
			fp_count = i;
			i = 0;
			goto do_cpy;
		}
		tmp_buf[j] = tmp;
		i++;
		j++;
	}
	
#if 0
	printf("tmp_buf :%s\n",tmp_buf);
	printf("i :%d , j :%d\n",i,j);
#endif

	if(tmp_buf[j-2] != 0x0d && tmp_buf[j-1] != 0x0a){
		//printf("Invalid data\n");
		return -1;
	}
	fp_count = i;
	//printf("fp_count :%d\n",fp_count);
	memset(recv_buf,0,PACKET_SIZE);
	memcpy(recv_buf,tmp_buf,strlen((const char * )tmp_buf));
	len = strlen((const char * )recv_buf);
	if(recv_buf[0] == '$' && recv_buf[len - 2] == 0x0d && recv_buf[len - 1] == 0x0a){
		//printf("recv_buf %s\n",recv_buf);
		ret = bd_packet_parse(recv_buf);
		if(ret < 0){
			//pr_info("bd packet_parse faild");
			return ret;
		}
	}
	if(i < data_len){
		goto do_cpy;
	}
	
	return ret;
}

bd_packet_handle是主要的處理函數,拼包的代碼就在這裏,包頭是$,結尾是0x0d 0x0a,具體可以分析代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章