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。
图 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,通过字符串传输,需要现将其拆成字符’6’和’4’进行ASCII传输;而十六进制传输,直接进行0x40 传输即可。
由图可以看出,十六进制传输更高效,更简单,避免繁琐的转换,解析数据也更加容易。
(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接收。
(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;
}