在linux下, 串口也被当做一个文件来使用, 所以串口传输数据实际上也就是对文件进行read/write操作.
UART串口基本知识:
一般, 串口至少有三根线:
地线GND, 接收线RX和发送线TX. 有的开发板还可能把控制线CTS/RTS也引出来.
串口查看方式:
在PC端, 如果用USB口连接, 一般显示为/dev/ttyUSBx, 其中x为0, 1, 2...
在开发板上,一般显示为/dev/ttySx, 其中x为0, 1, 2...
在电脑上可以使用下面的方法查看或者设置串口属性:
串口常用参数:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define UART_NAME "/dev/ttyS0"
static int g_quit;
static int g_speed;
static void handle_signal(int sig)
{
if (SIGINT == sig || SIGTERM == sig)
g_quit = 1;
}
static struct sigaction sigact = {
.sa_handler = handle_signal,
};
static struct option longopts[] = {
{"help", no_argument, NULL, 'h'},
{"baudrate", required_argument, NULL, 'r'},
{0, 0, 0, 0},
};
static void print_usage(void)
{
fprintf(stdout, "usage:\n");
fprintf(stdout, "\t-r | --baudrate the serial baud rate\n");
fprintf(stdout, "\t-h | --help show this help and exit\n");
}
static int parse_arg(int argc, char **argv)
{
int ret = 0;
char c = '0';
while (
(c = getopt_long(argc, argv, "-:r:h", longopts, NULL))
!= -1) {
switch (c) {
case 'r':
g_speed = atoi(optarg);
break;
case 'h':
ret = -1;
break;
case ':':
fprintf(stdout, "%c require argument\n", optopt);
ret = -1;
break;
case '?':
fprintf(stdout, "%c invalid argument\n", optopt);
ret = -1;
break;
default:
break;
}
}
return ret;
}
static int uart_open(char *filename)
{
int fd;
//fd = open(filename, O_RDWR);
fd = open(filename, O_RDWR|O_NOCTTY|O_NDELAY);
if (fd < 0) {
printf("%s %d: failed to open output file\n",
__FILE__, __LINE__);
return -1;
}
//nonblock
if (fcntl(fd, F_SETFL, 0) < 0) {
printf("fcntl failed\n");
close(fd);
return -1;
}
return fd;
}
static int uart_set(int fd, int speed, int flow_ctrl,
int databits, int parity, int stopbits)
{
struct termios options;
int ret = 0;
if (tcgetattr(fd, &options) != 0) {
printf("Setup serial fialed!\n");
return -1;
}
int i;
int speed_arr[] = {B1500000, B1152000, B1000000, B921600,
B576000, B500000, B460800, B230400, B115200, B57600,
B38400, B19200, B9600, B4800, B2400, B1800, B1200,
B600, B300, B200, B150, B134, B110, B75, B50, B0};
int name_arr[] = {1500000, 1152000, 1000000, 921600,
576000, 500000, 460800, 230400, 115200, 57600,
38400, 19200, 9600, 4800, 2400, 1800, 1200,
600, 300, 200, 150, 134, 110, 75, 50, 0};
if (tcgetattr(fd, &options) != 0) {
printf("Setup serial fialed!\n");
return -1;
}
printf("speed = %d\n", speed);
for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if (speed == name_arr[i]) {
ret = cfsetispeed(&options, speed_arr[i]);
if (ret) {
perror("cfsetispeed");
printf("set in speed failed\n");
}
ret = cfsetospeed(&options, speed_arr[i]);
if (ret) {
perror("cfsetispeed");
printf("set out speed failed\n");
}
break;
}
}
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
switch (flow_ctrl) {
case 0: // no flow control
options.c_cflag &= ~CRTSCTS;
break;
case 1: // hardware flow control
options.c_cflag |= CRTSCTS;
break;
case 2: //software flow control
options.c_cflag |= IXON|IXOFF|IXANY;
break;
default:
printf("Unsupported flow control\n");
return -1;
}
options.c_cflag &= ~CSIZE;
switch (databits) {
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
printf("Unsupported databits!\n");
return -1;
}
switch (parity) {
case 'n': //no parity
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o': //odd parity
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag &= INPCK;
break;
case 'e': //even parity
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
case 's': //blank
case 'S':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~CSTOPB;
break;
default:
printf("Unsupported parity\n");
return -1;
}
switch (stopbits) {
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
printf("Unsupported stop bits\n");
return -1;
}
//mode
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
options.c_oflag &= ~OPOST; /*Output*/
//wait_time: 0.1s; min char to read:1
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 1;
//if data overflow, receive data, but not read
tcflush(fd, TCIFLUSH);
//save configuration
if (tcsetattr(fd, TCSANOW, &options) != 0) {
printf("set serial error!\n");
return -1;
}
return 0;
}
static int recv_data(int fd, int fdtest)
{
int inflg = 0;
int ret, size;
int *data = NULL;
do {
if (g_quit)
break;
inflg = 0;
ret = 0;
size = 0;
int hsize = read(fd, &size, 4);
if (hsize < 0) {
printf("read header size error\n");
ret = -1;
break;
}
if (size <= 0)
continue;
printf("size = %d\n", size);
if (data) {
free(data);
data = NULL;
}
data = calloc(1, size);
if (!data) {
printf("calloc failed\n");
ret = -1;
break;
}
int len = 0;
int left_size = size - len;
do {
len = read(fd, data, left_size);
if (len < 0) {
printf("read fd error\n");
ret = -1;
break;
}
//printf("real read size = %d\n", len);
int n = write(fdtest, data, len);
if (n < 0) {
printf("write error!\n");
ret = -1;
break;
}
left_size = left_size - len;
} while (left_size > 0);
inflg = 1;
} while (!inflg);
if (data) {
free(data);
data = NULL;
}
return ret;
}
int main(int argc, char **argv)
{
int ret = 0;
int fd, fdtest;
char send[1] = {'a'};
ret = sigaction(SIGINT, &sigact, NULL);
ret |= sigaction(SIGTERM, &sigact, NULL);
if (ret) {
printf("%s line%d: %s\n",
__FILE__, __LINE__, strerror(errno));
return -1;
}
g_speed = 9600;
ret = parse_arg(argc, argv);
if (ret) {
print_usage();
return -1;
}
fd = uart_open("/dev/ttyS0");
if (fd < 0)
return -1;
int speed = g_speed;
int flow_ctrl = 0;
int databits = 8;
int stopbits = 1;
int parity = 'O';
ret = uart_set(fd, speed, flow_ctrl, databits, parity, stopbits);
if (ret) {
printf("uart_set failed\n");
goto out;
}
fdtest = open("/mnt/recv.h264", O_RDWR|O_SYNC);
if (fdtest < 0) {
printf("open fdtest failed\n");
goto out;
}
int n = write(fd, send, 1);
if (n <= 0) {
printf("send a failed\n");
close(fdtest);
goto out;
}
do {
if (g_quit)
break;
ret = recv_data(fd, fdtest);
usleep(1000*10);
send[0] = 'b';
int res = write(fd, send, 1);
if (res < 0)
break;
/* printf("%s: %s: %d\n", __FILE__, __func__, __LINE__); */
} while (!ret);
close(fdtest);
out:
close(fd);
return ret;
}
#!/usr/bin/python
import serial
import time
import struct
def w():
baud = 115200
fd = open("/home/sarah/2newh264/test15.h264", "w+")
ser = serial.Serial('/dev/ttyUSB1', baud, timeout=8)
print "baud: ", baud
cmd0 = 'a'
cmd1 = 'b'
ser.write(cmd0)
print "send \""+cmd0+"\" to remotes"
while (1):
print "send \""+cmd1+"\" to remotes"
h = ser.read(4)
if not h:
continue
size = struct.unpack("i", h)
print "size: ", size[0]
input = ser.read(size[0])
fd.write(input)
print "\n"
ser.write(cmd1)
ser.close()
close(fd)
w()
cfsetispeed 中文man页面 http://os.51cto.com/art/201108/286606.htm
python serial 介绍 http://blog.csdn.net/u011577439/article/details/51762041