串口对传测试
来源:互联网 发布:苹果4s如何变成4g网络 编辑:程序博客网 时间:2024/06/16 23:43
app.c
#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <termio.h>#include <time.h>#include <sys/epoll.h>#include <pthread.h>#include <time.h> #include<sys/time.h> //#define UART_DEV "/dev/ttyS2"#define UART_DATABITS 8#define UART_PARITY 0#define UART_STOPBITS 1#define UART_FLOW 0#define UART_BAUD 115200#define MAX_BUF_SIZE 1024 //4096#define TTYS1_SEND_FILE "/cache/uart_test/ttys1_send.bin"#define TTYS1_RECV_FILE "/cache/uart_test/ttys1_recv.bin"#define TTYS2_SEND_FILE "/cache/uart_test/ttys2_send.bin"#define TTYS2_RECV_FILE "/cache/uart_test/ttys2_recv.bin"int epfd;struct epoll_event event; char *send_file_name = NULL;char *recv_file_name = NULL;/*** 设置串口属性 ***/int setup_port(int fd, int baud, int flow_ctrl, int databits, int parity, int stopbits);int reset_port(int fd);int write_data(int fd, void *buf, int len);void print_usage(char *program_name);void *send_file(void *arg);void recv_file(int fd);void epoll_init(int fd) //fd为需要epoll监控的文件描述符{ int ret = -1; epfd = epoll_create(1); if (epfd < 0){ printf("Epoll_create fail: %s(errno: %d)\n", strerror(errno), errno); return ; }memset(&event, 0, sizeof(event)); event.data.fd = fd; event.events = EPOLLIN | EPOLLET; ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); if (ret < 0){ printf("Epoll_ctl fail: %s(errno: %d)\n", strerror(errno), errno); return ; } return ;}int main(int argc, char *argv[]){int fd;int baud;int ret = -1;int flow_ctrl;int databits;int stopbits;int parity;int read_or_write; struct timeval startTime,endTime; float Timeuse; if (argc != 4) {fprintf(stderr, "Usage: %s /dev/ttySx xx(baud) xx(flow_control) \n", argv[0]);return 1;}baud = atoi(argv[2]);if ((baud < 0) || (baud > 1500000)) { //1 波特率baud fprintf(stderr, "Invalid baudrate!\n");return 1;} //flow_ctrl = UART_FLOW;flow_ctrl = atoi(argv[3]); //2 流控flow_ctrl if(flow_ctrl < 0 || flow_ctrl > 2){fprintf(stderr, "Invalid flow_ctrl!\n");return 1;}databits = UART_DATABITS;//3 数据位databits if ((databits < 5) || (databits > 8)) {fprintf(stderr, "Invalid databits!\n");return 1;}parity = UART_PARITY; //4 鸡狗效验 parity if ((parity < 0) || (parity > 2)) {fprintf(stderr, "Invalid parity!\n");return 1;}stopbits = UART_STOPBITS;//5 停止位stopbitsif ((stopbits < 1) || (stopbits > 2)) {fprintf(stderr, "Invalid stopbits!\n");return 1;}#if 0read_or_write = atoi(argv[4]);//6 读写方向read_or_write if(read_or_write < 0 || read_or_write > 1){fprintf(stderr, "Invalid read_or_write!\n");return 1;}#endif gettimeofday(&startTime,NULL); printf("gettimeofday-----\n");printf("Open the recv uart%s \n",argv[1]);fd = open(argv[1], O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) {fprintf(stderr, "open <%s> error %s\n", argv[1], strerror(errno));return 1;}printf("Open uart%s success\n",argv[1]);if (setup_port(fd, baud, flow_ctrl, databits, parity, stopbits)) {fprintf(stderr, "setup_port error %s\n", strerror(errno));close(fd);return 1;}tcflush(fd,TCIOFLUSH);epoll_init(fd);#if 1if (!strcmp(argv[1], "/dev/ttyS1")) {send_file_name = TTYS1_SEND_FILE;recv_file_name = TTYS1_RECV_FILE;} else if (!strcmp(argv[1], "/dev/ttyS2")) {send_file_name = TTYS2_SEND_FILE;recv_file_name = TTYS2_RECV_FILE;} else {fprintf(stderr, "device invalid\n");return -1;}pthread_t tid;ret = pthread_create(&tid, NULL, send_file, (void *)&fd);//线程发送测试if (ret != 0){fprintf(stderr, "Create a thread error!\n");exit(1);}printf("Begin to recv data\n");recv_file(fd);//进程文件接收测试 pthread_join(tid, NULL);#else//只做接收测试 printf("Begin to recv data\n");recv_file(fd);//printf("Begin to send data\n");//send_file((void *)&fd);#endifreset_port(fd);close(fd); gettimeofday(&endTime,NULL); Timeuse = 1000000*(endTime.tv_sec - startTime.tv_sec) + (endTime.tv_usec - startTime.tv_usec); Timeuse /= 1000000; printf("Time use = %f !!!!!\n",Timeuse);printf("Process end.\n");return 0;}void recv_file(int fd){ int nfds = 0; int read_num = 0; int time_out = 1000; //msint out_times = 0; struct epoll_event ev; int ret = -1;int count = 0;int len;int recv_fd = 0;char buf[MAX_BUF_SIZE];fprintf(stderr, "Begin to recv:\n");recv_fd = open(recv_file_name, O_RDWR | O_CREAT | O_TRUNC, 0764);if (recv_fd < 0) {fprintf(stderr, "Open recv file error: %s(errno: %d)\n", strerror(errno), errno);return ;}len = MAX_BUF_SIZE; // ---------------while(1) {nfds = epoll_wait(epfd, &ev, 1, time_out); if (nfds == 0){printf("Epoll time out.\n");if ((out_times ++) == 5) {break;}} else if (nfds > 0 && (ev.events & EPOLLIN)){ //detect object uart out_times = 0;while (1) {memset(buf, 0, sizeof(buf));/*** read data from file to buf ***/read_num = read(ev.data.fd, (char *)buf, len);if (read_num < 0){if (errno == EAGAIN) {//printf("NOthing data in uart FIFO\n");break;}printf("Read data error: %s(errno: %d) \n", strerror(errno), errno);return ;} else if (read_num == 0) {break;} else { // printf("read_num: %d\n", read_num);count = 0;while (count < read_num) {ret = write(recv_fd, buf + count, read_num - count);if (ret < 0) {fprintf(stderr, "Write data to rev_file error: %s(errno: %d)\n", strerror(errno), errno);return ;}count += ret;}}}}else {printf("epoll_wait happen some error(ret: %d)!\n", nfds);return ;}}printf("Receive file end.\n");return ;}void *send_file(void *arg){int fd = *(int *)arg;intret = -1;int send_fd = 0;char buf[MAX_BUF_SIZE];//4096 4K int len = 0; //unsigned int readcount = 0;printf("Ready send data to serial...\n");#if 1sleep(1);send_fd = open(send_file_name, O_RDWR);//打开所要发送的文件(local file) if (send_fd < 0) {fprintf(stderr, "Open send file error: %s(errno: %d)\n", strerror(errno), errno);return NULL;}#endifwhile (1) {memset(buf, 0, sizeof(buf));len = read(send_fd , buf, sizeof(buf));if (len == 0) { printf("read 0 byte from send_file ! \n");break; } else if (len < 0) {printf("read send_file error ! \n");}// else// printf("read %d byte from %s to buff ! \n",len,send_file_name); /*** write send_data to buff ***/ret = write_data(fd, buf, len);if (ret != len){ printf("write %d byte from buff to uart)\n",ret);fprintf(stderr, "Write Serial error: %s(errno: %d)!\n", strerror(errno), errno);return NULL;}// else // printf("write %d byte from buff to uart ! \n",len); }printf("send data end\n");return NULL;}static int baudflag_arr[] = {B921600, B460800, B230400, B115200, B57600, B38400,B19200, B9600, B4800, B2400, B1800, B1200,B600, B300, B150, B110, B75, B50,B500000, B1500000};static int speed_arr[] = {921600, 460800, 230400, 115200, 57600, 38400,19200, 9600, 4800, 2400, 1800, 1200,600, 300, 150, 110, 75, 50,500000, 1500000};int speed_to_flag(int speed){int i;for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) {if (speed == speed_arr[i]) {return baudflag_arr[i];}}fprintf(stderr, "Unsupported baudrate, use 115200 instead!\n");return B115200;}static struct termio oterm_attr;/************************************************************************************ * 名称 :setup_port * 功能 :设置串口数据位,停止位和效验位 * 入口参数: * @fd 串口文件描述符 * @baud 串口波特率 * @flow_ctrl 数据流控制 * 0:无流控 * 1:硬件流控 * 2:软件流控 * @databits 数据位 取值为 5,6,7,8 * @stopbits 停止位 取值为 1,2 * @parity 效验类型 取值为 0,1,2 * 出口参数: * 正确返回为0,错误返回为-1 **************************************************************************************/int setup_port(int fd, int baud, int flow_ctrl, int databits, int parity, int stopbits){struct termios term_attr;/* Get current setting */if (ioctl(fd, TCGETA, &term_attr) < 0) {return -1;}/* Backup old setting */memcpy(&oterm_attr, &term_attr, sizeof(struct termios));term_attr.c_iflag &= ~(INLCR | IGNCR | ICRNL | ISTRIP | IXON);term_attr.c_oflag &= ~(OPOST | ONLCR | OCRNL);term_attr.c_lflag &= ~(ISIG | ECHO | ICANON | NOFLSH);term_attr.c_cflag &= ~CBAUD;term_attr.c_cflag |= CREAD | speed_to_flag(baud); printf("current term_attr.c_cflag = 0x%x \n",term_attr.c_cflag); printf("CRTSCTS = 0x%x \n",CRTSCTS);/*Set flow_ctrl*/switch(flow_ctrl){case 0:term_attr.c_cflag &= ~CRTSCTS; //no flow control printf("no flow_ctrl term_attr.c_cflag = 0x%x \n",term_attr.c_cflag);break; case 1:term_attr.c_cflag |= CRTSCTS; //flow control by hardware printf("hard flow_ctrl term_attr.c_cflag = 0x%x \n",term_attr.c_cflag); break;case 2:term_attr.c_cflag |= IXON | IXOFF | IXANY; //flow control by software printf("soft flow_ctrl \n"); break;}term_attr.c_cflag &= ~(CSIZE);/* Set databits */switch (databits) {case 5:term_attr.c_cflag |= CS5;break;case 6:term_attr.c_cflag |= CS6;break;case 7:term_attr.c_cflag |= CS7;break;case 8:default:term_attr.c_cflag |= CS8;break;}/* Set parity */switch (parity) {case 1: /* Odd parity */term_attr.c_cflag |= (PARENB | PARODD);break;case 2: /* Even parity */term_attr.c_cflag |= PARENB;term_attr.c_cflag &= ~(PARODD);break;case 0: /* None parity */default:term_attr.c_cflag &= ~(PARENB);break;}/* Set stopbits */switch (stopbits) {case 2: /* 2 stopbits */term_attr.c_cflag |= CSTOPB;break;case 1: /* 1 stopbits */default:term_attr.c_cflag &= ~CSTOPB;break;} printf("setup term_attr.c_cflag = 0x%x \n",term_attr.c_cflag);term_attr.c_cc[VMIN] = 1;term_attr.c_cc[VTIME] = 0;tcflush(fd,TCIFLUSH);if((tcsetattr(fd,TCSANOW,&term_attr))!=0){printf("fcntl is error\n");}/*if (ioctl(fd, TCSETAW, &term_attr) < 0) {return -1;}if (ioctl(fd, TCFLSH, 2) < 0) {return -1;}*/return 0;}int reset_port(int fd){if (ioctl(fd, TCSETAW, &oterm_attr) < 0) {return -1;}return 0;}int write_data(int fd, void *buf, int len){int count;int ret;ret = 0;count = 0;while (count < len) {//open fd noblock ret = write(fd, (char*)buf + count, len - count); if (ret < 0) {if (errno == EAGAIN) {continue;} fprintf(stderr, "Write error %s\n", strerror(errno)); break; } count += ret;}return count;}void print_usage(char *program_name){fprintf(stderr,"*************************************\n"" A Simple Serial Port Test Utility\n""*************************************\n\n""Usage:\n %s <device> <baud> <flow_ctrl> <read_or_write>\n"" flow_ctrl:0(None), 1(hard), 2(soft)"" read_or_write: 0(read), 1(write)\n""Example:\n %s /dev/ttyS2 115200 0 0\n\n",program_name, program_name );return ;}
阅读全文