自定义串口通信协议(16进制)

1.1 串口通信标准

通过RS-232接口进行两个设备间的通信(异步传输,全双工通信)。

接口标准:两种接口9pin(DB-9),25pin(DB-25),通常只有三根线:TXD(发送)、RXD(接收)、GND(接地)。

传输距离:150pF/m的通信电缆,最大传输距离15m;普通双绞屏蔽线(9600pbs),最大传输距离35m。

电气特性:对于TXD、RXD 逻辑1:-3V~-15V;逻辑0:+3~+15V (负逻辑电平)。对于RTS、CTS、DSR、DTR和DCD 信号有效(接通,ON状态,正电压)=+3V~+15V ;信号无效(断开,OFF状态,负电压)=-3V~-15V(正逻辑电平)

 

*****(1)TTL电平与RS-232电平有很大不同,若要连接,通常使用MAX3232 芯片进行电平转换。

*****(2)硬件连接,如图1。

 

                                                    自定义串口通信协议(16进制)_第1张图片

                                                                               图 1

1.2 通信协议

       根据实际要求,确定通信协议传输格式。

Head

0x22334455

4字节

Command

0x00

1字节

Data

0x00

1字节

Num

0x0000

2字节

Reply(应答)

0x00

1字节

Verify(校验)

0x0000

2字节

(1) 通信采用十六进制传输,将传输的数据转换成unsigned char 或者signed char型进行传输,也可以将要传输的数据放入unsigned char 或者signed char型的数组中,再进行传输;例如 :unsigned char table[] = {0x22,0x33,0x44,0x55,0x00,0x00,0x00,0x00,0x00,0x00};

十六进制传输的优点:假如传输数字64,通过字符串传输,需要现将其拆成字符64’进行ASCII传输;而十六进制传输,直接进行0x40 传输即可。

                                              自定义串口通信协议(16进制)_第2张图片

由图可以看出,十六进制传输更高效,更简单,避免繁琐的转换,解析数据也更加容易。

(2) 通信协议格式:

        Head : 协议头部,标记一帧传输的开始(自定义字节数)。

        Command:需要传输的控制命令,可以定义成结构体形式(自定义字节数)。

        Data:需要传输的数据,不管什么类型,都转换成16进制进行传输(自定义字节数)。

        Num:需要传输的数据(自定义字节数)。

        Reply:应答信号(一般1个字节即可)。

        Verify:校验(自定义字节数),常采用CRC校验,和校验,奇偶校验,异或校验等。

typedef struct serial_data{ 
    signed int       head;             (假设4字节)
    signed char      command;          (假设1字节)
    signed char      data;             (假设2字节)
    signed short     num;              (假设1字节)
    signed char      reply;            (假设1字节)
    signed short     verify;           (假设2字节)
} data_s;
data_s dat;//声明结构体变量

(3) 根据协议头和总帧长度(总传输字节数),完整接收一帧数据。四字节头部(0x22334455)举例:

static unsigned int flag = 0;
unsigned char Hex_receive(unsigned rece_data) {
	unsigned int i;	
	if(verification_head(Hex_head,head_buf) == 0) {
		for(i = 1;i < 4;i++)  {
                    head_buf[i - 1] = head_buf[i];
                }
		head_buf[3] = rece_data;   //接收头部四个字节
	}else {		
		Hex_data[flag + 4] = rece_data;  
		flag++;
		if(flag == 7) {     //接收剩余7个字节
			flag = 0;
			for(i = 0;i < 4;i++) {
                head_buf[i] = 0;
            }
        }
    }
}  //一帧数据共11字节 保存在数组Hex_data[11] 中

(4) 解析数据

*****(1) 解析出来的16进制数据一律按照unsigned char接收。

  1. 对于两个字节(16位)数据,高位左移八位加上低位,组合成16位数据。
  2. 将组合后的数据,强制转换成所需要的signed char 或者signed short,进行和校验。

(5) 头部校验与和校验

//头校验
unsigned char Hex_head[4] = {0x22,0x33,0x44,0x55};
unsigned char verify_head(unsigned char *head,unsigned char *str) {
	
    unsigned char count;
    for(count = 0;count < 4;ount++) {
        if(!(str[count] == head[count])) {
            return 0;  	 //匹配失败
        }
    }
    return 1;       	     //匹配成功
}
//解析接收的字符数据
void analyze_data(unsigned char *data) {
	dat.command = (signed char)(data[4]);
	dat.data = (signed char)(data[5]);
	dat.num = (signed short)((data[6]<<8) + (data[7]));
	dat.reply = (signed char)(data[8]<<8);
	dat.verify = (signed short)((data[9]<<8) + (data[10]));
}
//和校验
unsigned char verify_sum() {
	
	if (dat.verify == dat.command + dat.command + dat.num + dat.reply) {
		return 1;
	}else {
		return 0;
	}
}

 

(6) 正确接收一帧数据完整过程。

//接收数据
unsigned char head_buf[4] = {0};
unsigned char Hex_receive(unsigned rece_data) {
	unsigned int i;	
	if(verification_head(Hex_head,head_buf) == 0) {
		for(i = 1;i < 4;i++) {
			head_buf[i - 1] = head_buf[i];
		}
		head_buf[3] = rece_data;
	}else {		
		Hex_data[flag + 4] = rece_data;
		flag++;
		if(flag == 7) {
			flag = 0;
			for(i = 0;i < 4;i++) {
				head_buf[i] = 0;
			}
			analyze_data(Hex_data);
			if(verify_sum() == 1) {
				printf("analyze success!!!");
				return 1;
			}else {
				printf("analyze fail!!!");
				return 0;
			}
		}
	}
return 0;
}

 

你可能感兴趣的:(通信协议)