UART 串口示例代码
/* uart_tx.c */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <getopt.h> #include <termios.h> #define TEST_LEN (1024 * 400) static char *dev_name = "/dev/ttyS2"; static int baud_rate = 9600; static struct option opts[] = { {"device", required_argument, NULL, 'd'}, {"baud", required_argument, NULL, 'b'}, {"help", no_argument, NULL, 'h'}, }; static void parse_cmd(int argc, char *argv[]) { int ch; while ((ch = getopt_long(argc, argv, "d:b:l:h", opts, NULL)) != -1) { switch (ch) { case 'd': //printf("dev_name: %s\n", optarg); dev_name = optarg; break; case 'b': //printf("baud_rate: %s\n", optarg); baud_rate = atoi(optarg); break; case 'h': printf("Usage: %s -d dev_name -b baud_rate\n", argv[0]); printf("like:\n"); printf("\t %s -d /dev/ttyS2\n", argv[0]); printf("\t %s --device /dev/ttyS2 -b 9600\n", argv[0]); break; default: printf("Unknown option or invalid format!\n"); printf("Pls: %s --help for more info\n", argv[0]); break; } } } int set_serial(int fd, int baud_rate, int nBits, char nEvent, int nStop) { struct termios tty_cfg; memset(&tty_cfg, 0, sizeof(tty_cfg)); tty_cfg.c_cflag |= (CLOCAL|CREAD); /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式 */ tty_cfg.c_cflag &= ~CSIZE; /* 设置数据位 */ switch(baud_rate) { case 2400: cfsetispeed(&tty_cfg, B2400); cfsetospeed(&tty_cfg, B2400); break; case 4800: cfsetispeed(&tty_cfg, B4800); cfsetospeed(&tty_cfg, B4800); break; case 9600: cfsetispeed(&tty_cfg, B9600); cfsetospeed(&tty_cfg, B9600); break; case 115200: cfsetispeed(&tty_cfg, B115200); cfsetospeed(&tty_cfg, B115200); break; case 460800: cfsetispeed(&tty_cfg, B460800); cfsetospeed(&tty_cfg, B460800); break; default: cfsetispeed(&tty_cfg, B9600); cfsetospeed(&tty_cfg, B9600); break; } switch(nBits) { case 7: tty_cfg.c_cflag |= CS7; break; case 8: tty_cfg.c_cflag |= CS8; break; } switch(nEvent) { case '0': /* 奇校验 */ tty_cfg.c_cflag |= PARENB; /* 开启奇偶校验 */ tty_cfg.c_iflag |= (INPCK | ISTRIP); /*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特 */ tty_cfg.c_cflag |= PARODD; /*启用奇校验(默认为偶校验)*/ break; case 'E': /*偶校验*/ tty_cfg.c_cflag |= PARENB; /*开启奇偶校验 */ tty_cfg.c_iflag |= ( INPCK | ISTRIP); /*打开输入奇偶校验并去除字符第八个比特*/ tty_cfg.c_cflag &= ~PARODD; /*启用偶校验*/ break; case 'N': /*无奇偶校验*/ tty_cfg.c_cflag &= ~PARENB; break; } /* 设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB */ if(nStop == 1) tty_cfg.c_cflag &= ~CSTOPB; /*默认为一位停止位; */ else if( nStop == 2) tty_cfg.c_cflag |= CSTOPB; /* CSTOPB表示送两位停止位 */ /* flow control option */ tty_cfg.c_cflag |= CRTSCTS; /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/ tty_cfg.c_cc[VTIME] = 0; /* 非规范模式读取时的超时时间;*/ tty_cfg.c_cc[VMIN] = 0; /* 非规范模式读取时的最小字符数*/ tcflush(fd, TCIFLUSH); /* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */ /*激活配置使其生效*/ if((tcsetattr(fd, TCSANOW, &tty_cfg)) != 0) { printf("com set error"); exit(1); } return 0; } char buff[TEST_LEN]; int main(int argc, char *argv[]) { int fd=0; int cnt=0; int sum=0; static int num=0; char *p=NULL; parse_cmd(argc, argv); printf("TX: dev_name=%s, baud_rate=%d\n", dev_name, baud_rate); fd = open(dev_name,O_RDWR|O_NOCTTY|O_NDELAY); if(fd < 0) { printf("Can't Open %s\n", dev_name); return -1; } set_serial(fd, baud_rate, 8, 'N', 1); sleep(1); memset(buff, 0x55, TEST_LEN); //printf("start send: %ds\n", time(NULL)); p = &buff[0]; while(1) { cnt = write(fd, p, (TEST_LEN-sum)); if(cnt < 0) { //sleep(1); continue; } sum += cnt; if(sum >= TEST_LEN) break; p += cnt; printf("TX%d: cnt = %d, sum = %d\n", num++, cnt, sum); } printf("send %d: %ds\n", sum, time(NULL)); close(fd); return 0; }
/* uart_rx.c */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <getopt.h> #include <termios.h> #define TEST_LEN (1024 * 400) static char *dev_name = "/dev/ttyS2"; static int baud_rate = 9600; static struct option opts[] = { {"device", required_argument, NULL, 'd'}, {"baud", required_argument, NULL, 'b'}, {"help", no_argument, NULL, 'h'}, }; static void parse_cmd(int argc, char *argv[]) { int ch; while ((ch = getopt_long(argc, argv, "d:b:l:h", opts, NULL)) != -1) { switch (ch) { case 'd': //printf("dev_name: %s\n", optarg); dev_name = optarg; break; case 'b': //printf("baud_rate: %s\n", optarg); baud_rate = atoi(optarg); break; case 'h': printf("Usage: %s -d dev_name -b baud_rate\n", argv[0]); printf("like:\n"); printf("\t %s -d /dev/ttyS2\n", argv[0]); printf("\t %s --device /dev/ttyS2 -b 9600\n", argv[0]); break; default: printf("Unknown option or invalid format!\n"); printf("Pls: %s --help for more info\n", argv[0]); break; } } } int set_serial(int fd, int baud_rate, int nBits, char nEvent, int nStop) { struct termios tty_cfg; memset(&tty_cfg, 0, sizeof(tty_cfg)); tty_cfg.c_cflag |= (CLOCAL|CREAD); /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式 */ tty_cfg.c_cflag &= ~CSIZE; /* 设置数据位 */ switch(baud_rate) { case 2400: cfsetispeed(&tty_cfg, B2400); cfsetospeed(&tty_cfg, B2400); break; case 4800: cfsetispeed(&tty_cfg, B4800); cfsetospeed(&tty_cfg, B4800); break; case 9600: cfsetispeed(&tty_cfg, B9600); cfsetospeed(&tty_cfg, B9600); break; case 115200: cfsetispeed(&tty_cfg, B115200); cfsetospeed(&tty_cfg, B115200); break; case 460800: cfsetispeed(&tty_cfg, B460800); cfsetospeed(&tty_cfg, B460800); break; default: cfsetispeed(&tty_cfg, B9600); cfsetospeed(&tty_cfg, B9600); break; } switch(nBits) { case 7: tty_cfg.c_cflag |= CS7; break; case 8: tty_cfg.c_cflag |= CS8; break; } switch(nEvent) { case '0': /* 奇校验 */ tty_cfg.c_cflag |= PARENB; /* 开启奇偶校验 */ tty_cfg.c_iflag |= (INPCK | ISTRIP); /*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特 */ tty_cfg.c_cflag |= PARODD; /*启用奇校验(默认为偶校验)*/ break; case 'E': /*偶校验*/ tty_cfg.c_cflag |= PARENB; /*开启奇偶校验 */ tty_cfg.c_iflag |= ( INPCK | ISTRIP); /*打开输入奇偶校验并去除字符第八个比特*/ tty_cfg.c_cflag &= ~PARODD; /*启用偶校验*/ break; case 'N': /*无奇偶校验*/ tty_cfg.c_cflag &= ~PARENB; break; } /* 设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB */ if(nStop == 1) tty_cfg.c_cflag &= ~CSTOPB; /*默认为一位停止位; */ else if( nStop == 2) tty_cfg.c_cflag |= CSTOPB; /* CSTOPB表示送两位停止位 */ /* flow control option */ tty_cfg.c_cflag |= CRTSCTS; /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/ tty_cfg.c_cc[VTIME] = 0; /* 非规范模式读取时的超时时间;*/ tty_cfg.c_cc[VMIN] = 0; /* 非规范模式读取时的最小字符数*/ tcflush(fd, TCIFLUSH); /* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */ /*激活配置使其生效*/ if((tcsetattr(fd, TCSANOW, &tty_cfg)) != 0) { printf("com set error"); exit(1); } return 0; } void dump_data(char *buf) { int i; for(i=0; i<TEST_LEN; i++) { if(i%16 == 0) printf("\n"); printf("0x%x, ", buf[i]); } } char buff[TEST_LEN]; int main(int argc, char *argv[]) { int fd=0; int cnt=0; int sum=0; static int num=0; char *p=NULL; parse_cmd(argc, argv); printf("RX: dev_name=%s, baud_rate=%d\n", dev_name, baud_rate); fd = open(dev_name,O_RDWR|O_NOCTTY|O_NDELAY); if(fd < 0) { printf("Can't Open %s\n", dev_name); return -1; } set_serial(fd, baud_rate, 8, 'N', 1); sleep(1); memset(buff, 0x0, TEST_LEN); //printf("start recv: %ds\n", time(NULL)); p = &buff[0]; while(1) { cnt = read(fd, p, TEST_LEN); if(cnt <= 0) { //sleep(1); continue; } sum += cnt; if(sum >= TEST_LEN) break; p += cnt; printf("RX%d: cnt = %d, sum = %d\n", num++, cnt, sum); } printf("recv %d: %ds\n", sum, time(NULL)); p = NULL; close(fd); //dump_data(buff); return 0; }