Makefile文件内容
SOURCE = $(wildcard *.c)TARGETS = $(patsubst %.c, %, $(SOURCE))CC = arm-linux-gccPREFIX=/usr/lib/alsa-lib#CFLAGS = -Wallall:$(TARGETS)$(TARGETS):%:%.c$(CC) $< -o $@.PHONY:clean allclean:-rm -rf $(TARGETS)
源文件uart_test.c
#include<stdio.h>#include<stdlib.h>#include<fcntl.h>#include<unistd.h>#include<assert.h>#include<termios.h>#include<string.h>#include<sys/time.h>#include<sys/types.h>#include<errno.h>static int ret;static int fd;/** 安全读写函数*/ssize_t safe_write(int fd, const void *vptr, size_t n){size_t nleft;ssize_t nwritten;const char *ptr;ptr = vptr;nleft = n;printf("%s, %d\n", ptr, nleft);while(nleft > 0){if((nwritten = write(fd, ptr, nleft)) <= 0){if(nwritten < 0&&errno == EINTR)nwritten = 0;elsereturn -1;}nleft -= nwritten;ptr += nwritten;}return(n);}ssize_t safe_read(int fd,void *vptr,size_t n){size_t nleft;ssize_t nread;char *ptr;ptr=vptr;nleft=n;while(nleft > 0){if((nread = read(fd,ptr,nleft)) < 0){if(errno == EINTR)//被信号中断nread = 0;elsereturn -1;}elseif(nread == 0)break;printf("%s", ptr);fflush(stdout);nleft -= nread;ptr += nread;}return (n-nleft);}int uart_open(int fd,const char *pathname){assert(pathname);/*打开串口*/fd = open(pathname,O_RDWR|O_NOCTTY);if(fd == -1){perror("Open UART failed!");return -1;}/*清除串口非阻塞标志*//* if(fcntl(fd,F_SETFL,0) < 0){fprintf(stderr,"fcntl failed!\n");return -1;}*/return fd;}int uart_set(int fd,int baude,int c_flow,int bits,char parity,int stop){struct termios options;/*获取终端属性*/if(tcgetattr(fd,&options) < 0){perror("tcgetattr error");return -1;}/*设置输入输出波特率,两者保持一致*/switch(baude){case 4800:cfsetispeed(&options,B4800);cfsetospeed(&options,B4800);break;case 9600:cfsetispeed(&options,B9600);cfsetospeed(&options,B9600);break;case 19200:cfsetispeed(&options,B19200);cfsetospeed(&options,B19200);break;case 38400:cfsetispeed(&options,B38400);cfsetospeed(&options,B38400);break;case 115200:cfsetispeed(&options,B115200);cfsetospeed(&options,B115200);break;default:fprintf(stderr,"Unkown baude!\n");return -1;}/*设置控制模式*/options.c_cflag |= CLOCAL;//保证程序不占用串口options.c_cflag |= CREAD;//保证程序可以从串口中读取数据,表启用字符接收器,目的是能够从串口中读取输入的数据/*设置数据流控制*/switch(c_flow){case 0://不进行流控制options.c_cflag &= ~CRTSCTS;break;case 1://进行硬件流控制options.c_cflag |= CRTSCTS;break;case 2://进行软件流控制options.c_cflag |= IXON|IXOFF|IXANY;break;default:fprintf(stderr,"Unkown c_flow!\n");return -1;}/*设置数据位*/switch(bits){case 5:options.c_cflag &= ~CSIZE;//屏蔽其它标志位options.c_cflag |= CS5;break;case 6:options.c_cflag &= ~CSIZE;//屏蔽其它标志位options.c_cflag |= CS6;break;case 7:options.c_cflag &= ~CSIZE;//屏蔽其它标志位options.c_cflag |= CS7;break;case 8:options.c_cflag &= ~CSIZE;//屏蔽其它标志位options.c_cflag |= CS8;break;default:fprintf(stderr,"Unkown bits!\n");return -1;}/*设置校验位*/switch(parity){/*无奇偶校验位*/case 'n':case 'N':options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验printf("N\n");break;/*设为空格,即停止位为2位*/case 's':case 'S':options.c_cflag &= ~PARENB;//PARENB:产生奇偶位,执行奇偶校验options.c_cflag &= ~CSTOPB;//CSTOPB:使用两位停止位break;/*设置奇校验*/case 'o':case 'O':options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验options.c_cflag |= PARODD;//PARODD:若设置则为奇校验,否则为偶校验options.c_cflag |= INPCK;//INPCK:使奇偶校验起作用options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节,否则保留全部8位break;/*设置偶校验*/case 'e':case 'E':options.c_cflag |= PARENB;//PARENB:产生奇偶位,执行奇偶校验options.c_cflag &= ~PARODD;//PARODD:若设置则为奇校验,否则为偶校验options.c_cflag |= INPCK;//INPCK:使奇偶校验起作用options.c_cflag |= ISTRIP;//ISTRIP:若设置则有效输入数字被剥离7个字节,否则保留全部8位break;default:fprintf(stderr,"Unkown parity!\n");return -1;}/*设置停止位*/switch(stop){case 1:options.c_cflag &= ~CSTOPB;//CSTOPB:使用一位停止位break;case 2:options.c_cflag |= CSTOPB;//CSTOPB:使用两位停止位break;default:fprintf(stderr,"Unkown stop!\n");return -1;}/*设置输出模式为原始输出*/options.c_oflag &= ~(OPOST| ONLCR | OLCUC | OCRNL | ONOCR | ONLRET | OFILL);//OPOST:若设置则按定义的输出处理,否则所有c_oflag失效/*设置本地模式为原始模式*/options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);/**ICANON:允许规范模式进行输入处理*ECHO:允许输入字符的本地回显*ECHOE:在接收EPASE时执行Backspace,Space,Backspace组合*ISIG:允许信号*//*设置等待时间和最小接受字符*/options.c_cc[VTIME] = 0;//可以在select中设置options.c_cc[VMIN] = 1;//最少读取一个字符/*如果发生数据溢出,只接受数据,但是不进行读操作*/tcflush(fd,TCIFLUSH);/*激活配置*/if(tcsetattr(fd,TCSANOW,&options) < 0){perror("tcsetattr failed");return -1;}return 0;}int uart_read(int fd,char *r_buf,size_t len){ssize_t cnt = 0;fd_set rfds;struct timeval time;/*将文件描述符加入读描述符集合*/FD_ZERO(&rfds);FD_SET(fd,&rfds);/*设置超时为15s*/time.tv_sec = 15;time.tv_usec = 0;/*实现串口的多路I/O*/ret = select(fd+1,&rfds,NULL,NULL,&time);switch(ret){case -1:fprintf(stderr,"select error!\n");return -1;case 0:fprintf(stderr,"time out!\n");return -1;default:cnt = safe_read(fd,r_buf,len);printf(" in uart_read");if(cnt == -1){fprintf(stderr,"read error!\n");return -1;}return cnt;}}int uart_write(int fd,const char *w_buf,size_t len){ssize_t cnt = 0;cnt = safe_write(fd,w_buf,len);if(cnt == -1){fprintf(stderr,"write error!\n");return -1;}return cnt;}int uart_close(int fd){assert(fd);close(fd);/*可以在这里做些清理工作*/return 0;}int main(int argc, char *argv[]){const char *w_buf = "hello";size_t w_len = strlen(w_buf);const char *tty = NULL;int baude;int c_flow;int bits;char parity;int stop;char r_buf[1024];bzero(r_buf,1024);tty = argv[1];printf("%s\n", tty);fd = uart_open(fd, tty);/*串口号/dev/ttySn,USB口号/dev/ttyUSBn*/if(fd == -1){fprintf(stderr,"uart_open error\n");exit(EXIT_FAILURE);}printf("open OK\n");if( argc < 2){printf("format uart_test /dev/ttySx baude stop data_bits parity config_stream\n");printf("such as:./uart_test /dev/ttySx 115200 1 8 N 0\n");exit(EXIT_FAILURE);}baude = atoi(argv[2]);stop = atoi(argv[3]);bits = atoi(argv[4]);parity = *argv[5];c_flow = atoi(argv[6]);printf("%s\n", tty);printf("%d, %d, %d, %c, %d\n", baude, stop, bits, parity, c_flow);if(uart_set(fd,baude,c_flow,bits,parity,stop) == -1){fprintf(stderr,"uart set failed!\n");exit(EXIT_FAILURE);}printf("uart_set OK\n");ret = uart_write(fd,w_buf,w_len);if(ret == -1){fprintf(stderr,"uart write failed!\n");exit(EXIT_FAILURE);}printf("uart_write OK\n");while(1){ret = uart_read(fd,r_buf,1024);printf("loop");if(ret == -1){fprintf(stderr,"uart read failed!\n");exit(EXIT_FAILURE);}printf("loop");}ret = uart_close(fd);if(ret == -1){fprintf(stderr,"uart_close error\n");exit(EXIT_FAILURE);}exit(EXIT_SUCCESS);}
