当两个控制子系统之间需要进行一些比较复杂的数据交互时, UART接口可以提供帮助。
UART(Universal Asynchronous Receiver Transmitter:通用异步收发器), 一对一数据交互,以byte为单位发送信息。
假设现在要完成一次握手请求:首先主控一方从UART读取握手请求信息, 然后分析/组装确认信息并返回。
假设握手规则如下:
请求数据: 0xa5 0x01 0x01 0x04 0x00 0x00 0x00 0xa5 0x00 0x00 0x00 0xb0
(其中最后一个字节为校验码, 忽略第二个字节, 校验码=~(0xa5+0x01+0x04+0x00+0x00+0x00+0xa5+0x00+0x00+0x00)&0xff)
需回复确认数据: 0xa5 0x01 0xff 0x04 0x00 0x00 0x00 0xa5 0x00 0x00 0x00 0xb2
(首先把第三个字节改为0xff, 忽略第二个字节, 然后修改校验码=~(0xa5+0xff+0x04+0x00+0x00+0x00+0xa5+0x00+0x00+0x00)&0xff)
以下为具体代码示例:
// author: xiaomo, at 2016/08/31
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define BUF_LEN 1024
void print_hex_array(int len, unsigned char* arr)
{
int i =0;
for (; i<len; ++i)
{
printf("0x%02x ", *(arr+i));
}
printf("\n");
}
int init_uart()
{
//-------------------------
//----- SETUP UART 0 -----
//-------------------------
int uart_fs = -1;
//OPEN THE UART
uart_fs = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY ); // | O_NDELAY);
if (uart_fs == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
else
{
printf("Opend UART port OK, number: %d\n", uart_fs);
}
//CONFIGURE THE UART
struct termios options;
tcgetattr(uart_fs, &options);
options.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart_fs, TCIFLUSH);
tcsetattr(uart_fs, TCSANOW, &options);
return uart_fs;
}
void do_transmit(int uart_fd, int send_bytes, unsigned char *p_tx_buffer)
{
if (uart_fd < 0)
{
return;
}
//Filestream, bytes to write, number of bytes to write
int count = write(uart_fd, p_tx_buffer, send_bytes);
if (count < 0)
{
printf("UART transmit error\n");
}
}
int checksum(int size, unsigned char* cur_line)
{
int i =0, checksum=0;
for (; i<size; ++i)
{
if (i!=1 && i!=size-1)
{
checksum += *(cur_line+i);
}
}
return ~checksum & 255;
}
void on_receive(int uart_fd)
{
if (uart_fd < 0)
return;
unsigned char rx_buf[BUF_LEN] = {0};
int rx_length = read(uart_fd, (void*)rx_buf, BUF_LEN-1);
if (rx_length < 3)
{
//An error will occur if there are not enough bytes
printf("Error occured, read_res: %d\n", rx_length);
return;
}
printf("ON RECEIVE: ");
print_hex_array(rx_length, rx_buf);
int checkres = checksum(rx_length, rx_buf);
*(rx_buf+2) = 0xff;
*(rx_buf+rx_length-1) = checksum(rx_length, rx_buf);
printf("TO RESPOND: ");
print_hex_array(rx_length, rx_buf);
do_transmit(uart_fd, rx_length, rx_buf);
}
void close_uart(int uart_fs)
{
close(uart_fs);
}
int main()
{
int uart = init_uart();
while (1)
{
on_receive(uart);
sleep(0.2);
}
close_uart(uart);
return 0;
}
运行效果:
root@beaglebone:/data/apps/UART# ./handshake
Opend UART port OK, number: 3
ON RECEIVE: 0xa5 0x01 0x01 0x04 0x00 0x00 0x00 0xa5 0x00 0x00 0x00 0xb0
TO RESPOND: 0xa5 0x01 0xff 0x04 0x00 0x00 0x00 0xa5 0x00 0x00 0x00 0xb2
========================
这里还有一个疑问未解决, 当我尝试以O_NDELAY非阻塞打开串口的时候, 程序在read时一直返回-1; 待继续探究。