应用程序(一)-linux应用程序学习之串口通讯编程
2017-06-05 17:30
363 查看
之前我们移植好了内核,并且支持了网卡驱动如下:
http://blog.csdn.net/fengyuwuzu0519/article/details/72846205
内核中已经默认支持了串口,启动内核后存在:/dev/ttySAC0、/dev/ttySAC1、/dev/ttySAC2。
这节的目的是使用串口驱动来与外界串口进行数据通讯。属于linux应用编程部分。
linux串口程序网上可谓一抓一大把,拷贝过来编译尝试使用,基本都能找到编译正常且能使用的,我遇到了一个国外提供的一个linux串口应用编程的网址。里面有提供实例代码,感觉很不错,这里贴出来
网址如下:
http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html
2、linux串口应用编程中的要点
这个后面在总结,直接先看下面代码。
1、select方式的linux串口应用代码
2、异步信号方式的linux串口应用代码
http://blog.csdn.net/fengyuwuzu0519/article/details/72846205
内核中已经默认支持了串口,启动内核后存在:/dev/ttySAC0、/dev/ttySAC1、/dev/ttySAC2。
这节的目的是使用串口驱动来与外界串口进行数据通讯。属于linux应用编程部分。
一、串口应用编程
1、网上串口资源linux串口程序网上可谓一抓一大把,拷贝过来编译尝试使用,基本都能找到编译正常且能使用的,我遇到了一个国外提供的一个linux串口应用编程的网址。里面有提供实例代码,感觉很不错,这里贴出来
网址如下:
http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html
2、linux串口应用编程中的要点
这个后面在总结,直接先看下面代码。
二、linux串口编程代码实现
通过对网上代码的参考和修改。写出如下两种方式的串口代码,经过测试,在前几节移植的linux中可以正常使用。代码如下:1、select方式的linux串口应用代码
#include <unistd.h> #include <stdio.h> #include <termios.h> #include <fcntl.h> #include <string.h> #include <time.h> //为了保证用户输入的波特率是个正确的值,所以需要这两个数组验证,对于设置波特率时候,前面要加个B int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; int name_arr[] = {115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; /*----------------------------------------------------------------------------- 函数名: set_speed 参数: int fd ,int speed 返回值: void 描述: 设置fd表述符的串口波特率 *-----------------------------------------------------------------------------*/ void set_speed(int fd ,int speed) { struct termios opt; int i; int status; tcgetattr(fd,&opt); for(i = 0;i < sizeof(speed_arr)/sizeof(int);i++) { if(speed == name_arr[i]) //找到标准的波特率与用户一致 { tcflush(fd,TCIOFLUSH); //清除IO输入和输出缓存 cfsetispeed(&opt,speed_arr[i]); //设置串口输入波特率 cfsetospeed(&opt,speed_arr[i]); //设置串口输出波特率 status = tcsetattr(fd,TCSANOW,&opt); //将属性设置到opt的数据结构中,并且立即生效 if(status != 0) perror("tcsetattr fd:"); //设置失败 return ; } tcflush(fd,TCIOFLUSH); //每次清除IO缓存 } } /*----------------------------------------------------------------------------- 函数名: set_parity 参数: int fd 返回值: int 描述: 设置fd表述符的奇偶校验 *-----------------------------------------------------------------------------*/ int set_parity(int fd) { struct termios opt; if(tcgetattr(fd,&opt) != 0) //或许原先的配置信息 { perror("Get opt in parity error:"); return -1; } /*通过设置opt数据结构,来配置相关功能,以下为八个数据位,不使能奇偶校验*/ opt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); opt.c_oflag &= ~OPOST; opt.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); opt.c_cflag &= ~(CSIZE | PARENB); opt.c_cflag |= CS8; tcflush(fd,TCIFLUSH); //清空输入缓存 if(tcsetattr(fd,TCSANOW,&opt) != 0) { perror("set attr parity error:"); return -1; } return 0; } /*----------------------------------------------------------------------------- 函数名: serial_init 参数: char *dev_path,int speed,int is_block 返回值: 初始化成功返回打开的文件描述符 描述: 串口初始化,根据串口文件路径名,串口的速度,和串口是否阻塞,block为1表示阻塞 *-----------------------------------------------------------------------------*/ int serial_init(char *dev_path,int speed,int is_block) { int fd; int flag; flag = 0; flag |= O_RDWR; //设置为可读写的串口属性文件 if(is_block == 0) flag |=O_NONBLOCK; //若为0则表示以非阻塞方式打开 fd = open(dev_path,flag); //打开设备文件 if(fd < 0) { perror("Open device file err:"); close(fd); return -1; } /*打开设备文件后,下面开始设置波特率*/ set_speed(fd,speed); //考虑到波特率可能被单独设置,所以独立成函数 /*设置奇偶校验*/ if(set_parity(fd) != 0) { perror("set parity error:"); close(fd); //一定要关闭文件,否则文件一直为打开状态 return -1; } return fd; } /*----------------------------------------------------------------------------- 函数名: serial_send 参数: int fd,char *str,unsigned int len 返回值: 发送成功返回发送长度,否则返回小于0的值 描述: 向fd描述符的串口发送数据,长度为len,内容为str *-----------------------------------------------------------------------------*/ int serial_send(int fd,char *str,unsigned int len) { int ret; if(len > strlen(str)) //判断长度是否超过str的最大长度 len = strlen(str); ret = write(fd,str,len); if(ret < 0) { perror("serial send err:"); return -1; } return ret; } /*----------------------------------------------------------------------------- 函数名: serial_read 参数: int fd,char *str,unsigned int len,unsigned int timeout 返回值: 在规定的时间内读取数据,超时则退出,超时时间为ms级别 描述: 向fd描述符的串口接收数据,长度为len,存入str,timeout 为超时时间 *-----------------------------------------------------------------------------*/ int serial_read(int fd, char *str, unsigned int len, unsigned int timeout) { fd_set rfds; struct timeval tv; int ret; //每次读的结果 int sret; //select监控结果 int readlen = 0; //实际读到的字节数 char * ptr; ptr = str; //读指针,每次移动,因为实际读出的长度和传入参数可能存在差异 FD_ZERO(&rfds); //清除文件描述符集合 FD_SET(fd,&rfds); //将fd加入fds文件描述符,以待下面用select方法监听 /*传入的timeout是ms级别的单位,这里需要转换为struct timeval 结构的*/ tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout%1000)*1000; /*防止读数据长度超过缓冲区*/ //if(sizeof(&str) < len) // len = sizeof(str); /*开始读*/ while(readlen < len) { sret = select(fd+1,&rfds,NULL,NULL,&tv); //检测串口是否可读 if(sret == -1) //检测失败 { perror("select:"); break; } else if(sret > 0) { ret = read(fd,ptr,1); if(ret < 0) { perror("read err:"); break; } else if(ret == 0) break; readlen += ret; //更新读的长度 ptr += ret; //更新读的位置 } else //超时 { printf("timeout!\n"); break; } } return readlen; } int main() { int fd; int ret; char str[]="hello linux serial!"; char buf[100]; fd = serial_init("/dev/ttySAC2",115200,1); if(fd < 0) { perror("serial init err:"); return -1; } ret = serial_send(fd,str,22); printf("send %d bytes!\n",ret); serial_read(fd,buf,100,5000); printf("the buf is :%s\n",buf); close(fd); return 0; }
2、异步信号方式的linux串口应用代码
#include <termios.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/signal.h> #include <sys/types.h> #include <stdlib.h> #define BAUDRATE B115200 #define MODEMDEVICE "/dev/ttySAC2" #define _POSIX_SOURCE 1 /* POSIX compliant source */ #define FALSE 0 #define TRUE 1 volatile int STOP=FALSE; void signal_handler_IO (int status); /* definition of signal handler */ int wait_flag=TRUE; /* TRUE while no signal received */ int main() { int fd,c, res; struct termios oldtio,newtio; struct sigaction saio; /* definition of signal action */ char buf[255]; /* open the device to be non-blocking (read will return immediatly) */ fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd <0) {perror(MODEMDEVICE); exit(-1); } /* install the signal handler before making the device asynchronous */ saio.sa_handler = signal_handler_IO; //saio.sa_mask = 0; sigemptyset(&saio.sa_mask); saio.sa_flags = 0; saio.sa_restorer = NULL; sigaction(SIGIO,&saio,NULL); /* allow the process to receive SIGIO */ fcntl(fd, F_SETOWN, getpid()); /* Make the file descriptor asynchronous (the manual page says only O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ fcntl(fd, F_SETFL, FASYNC); tcgetattr(fd,&oldtio); /* save current port settings */ /* set new port settings for canonical input processing */ newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; // newtio.c_iflag = IGNPAR | ICRNL; newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); newtio.c_oflag = 0; newtio.c_lflag &= ~(ICANON); newtio.c_cc[VMIN]=1; newtio.c_cc[VTIME]=0; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); /* loop while waiting for input. normally we would do something useful here */ while (STOP==FALSE) { //printf(".\n"); usleep(100000); /* after receiving SIGIO, wait_flag = FALSE, input is available and can be read */ if (wait_flag==FALSE) { res = read(fd,buf,255); buf[res]=0; printf(":%s:%d\n", buf, res); if (res==1) STOP=TRUE; /* stop loop if only a CR was input */ wait_flag = TRUE; /* wait for new input */ } } /* restore old port settings */ tcsetattr(fd,TCSANOW,&oldtio); return 0; } /*************************************************************************** * signal handler. sets wait_flag to FALSE, to indicate above loop that * * characters have been received. * ***************************************************************************/ void signal_handler_IO (int status) { printf("received SIGIO signal.\n"); wait_flag = FALSE; }
相关文章推荐
- Linux 串口编程学习
- linux下串口应用程序编程
- linux下串口应用程序编程
- 串口通讯-按键识别-ping程序-我的linux应用程序
- Linux应用程序学习之文件编程
- linux下串口应用程序编程
- GNU/Linux应用程序开发学习笔记(二)管道编程
- Linux应用程序串口编程
- Linux 程序设计学习笔记----终端及串口编程及实例应用
- 串口通讯-按键识别-ping程序-我的linux应用程序
- linux下串口应用程序编程
- linux 学习之应用程序和网络编程笔记(中)
- Linux 程序设计学习笔记----终端及串口编程基础之概念详解
- Linux下串口应用程序编程
- linux下串口应用程序编程
- GNU/Linux应用程序开发学习笔记(三)套接字编程
- 【代码参考网上的】linux串口编程学习笔记
- arm-linux_学习简单串口编程问题
- 详解linux下的串口通讯开发[转载]
- ASP.NET 2.0高级编程学习笔记-第3章 应用程序和页面框架