自己写的Linux下的串口操作
来源:互联网 发布:wind数据客户端 免费版 编辑:程序博客网 时间:2024/05/16 00:26
代码是纯C写的,大于115200的非标准波特率是和平台相关的,这里是基于PC104的,写读取操作时参考了AUPE,写非标准波特率时参考了stackoverflow的一个帖子,当时竟然忘了存了。。。
#ifndef USER_TYPE_H_#define USER_TYPE_H_#define SUCCESS0#define FAILURE1#define STRING(x)#xtypedef unsigned char UCHAR;typedef unsigned short USHORT;typedef unsigned int UINT;typedef unsigned long ULONG;typedef unsigned int uint24;#endif
#ifndef SERIAL_PORT_H_#define SERIAL_PORT_H_#include "user_type.h"/* * configuration of a serial port */struct Config{int baudRate; //baud rateint dataBits; //data bitschar parity; //parityint stopBits; //stop bitsint minToRead; //minimum bytes to return when calling readint timeoutBetweenBytes; //time out between bytes, unit in 100ms//baseAddr is used only when baudRate is supported nonstandard baud rateUSHORT baseAddr; //serial port's hardware base address};/* * This function is used to check if the baud rate is supported.*@param baudRate: baud rate to check*@return: 1 if the baud rate is supported 0 otherwise*/int isSupportedBaudRate(int baudRate);/* * This function is used to get the type of given baudRate*@param baudRate: baud rate to check*@return: 0 if given baud is supported standard baud rate 1 if given baud is supported nonstandard baud rate -1 if given baud is not supported */int getBaudRateType(int baudRate);/* * This function is used to check if the data bits is supported.*@param dataBits: data bits to check*@return: 1 if the dataBits is supported 0 otherwise*/int isSupportedDataBits(int dataBits);/* * This function is used to check if the parity is supported.*@param parity: parity to check*@return: 1 if the parity is supported 0 otherwise*/int isSupportedParity(char parity);/* * This function is used to check if the stop bits is supported.*@param stopBits: stop bits to check*@return: 1 if the stopBits is supported 0 otherwise*/int isSupportedDataBits(int stopBits);/* * This function is used to open a serial port.*@param dev: serial port's system file path*@param mode: "ReadOnly","WriteOnly","ReadWrite"*@param blocking: whether to set the read mode to be blocking or not*@return: corresponding file handle if open the serial port successfully a negative number otherwise*/int openSerialPort(const char* dev,const char* mode,int blocking);/* * This function is used to set configuration for the serial port.*@param fd: file handle of target serial port*@param baud: 38400, 19200, 9600, 4800, 2400, 1200, 300*@param dataBits: 7 or 8*@param stopBits: 1 or 2*@param parity: 'N' or 'E' or 'O' or 'S'*@param minToRead: minimum bytes to return when calling read*@param timeoutBetweenBytes: time out between bytes, unit in 100ms*@return: 0 if done configuration successfully negative numbers if error happens*/int configurateSerialPort(int fd,int baud,int dataBits,char parity,int stopBits,int minToRead,int timeoutBetweenBytes);/* * This function is used to open a serial port.*@param dev: serial port's system file path*@param mode: "ReadOnly","WriteOnly","ReadWrite"*@param blocking: whether to set the read mode to be blocking or not*@param pConfig: const pointer to a Config structure*@return: corresponding file handle if open the serial port successfully a negative number otherwise*/int openAndConfigurateSerialPort(const char* dev,const char* mode,int blocking,const struct Config* pConfig);/* * This function is used to close a serial port. * @param fd: serial port handle * @return: * SUCCESS if successfully closed the port * FAILURE if fail to close */int closeSerialPort(int fd);/* * This function is send frame.*@param fd: file descriptor of a serial port*@param frame: pointer of the frame*@param len: bytes to send*@return: bytes successfully sent*/int send(int fd,void* frame,int len);/* * This function is receive within given time limit.*@param fd: file descriptor of a serial port*@param buf: pointer to where to hold bytes received*@param nbytes: target bytes to receive*@param timeoutSec: second part of timeout*@param timeoutMicrosec: microsecond part of timeout*@return: if time runs out before nbytes has been received, returns how many actually received else return nbytes*/int treadn(int fd, void *buf, int nbytes, int timeoutSec, int timeoutMicrosec);/* * This function is receive frame.*@param fd: file descriptor of a serial port*@param frame: pointer to where to hold bytes received*@param maxlen: maximum bytes to receive*@return: bytes successfully read once*/int receive(int fd,void* frame,int maxLen);#endif /* SERIAL_PORT_H_ */
//local headers#include "user_type.h"#include "serial_port.h"//standard C headers#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>//linux headers#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/serial.h>#include <sys/io.h>#include <termios.h>#include <sys/time.h>int getBaudRateType(int baudRate){//if not in valid rangeif(baudRate <= 0 || baudRate > 1500000) return -1;//if supported standardif(baudRate == 110 || baudRate == 300 || baudRate == 600 || baudRate == 1200 || baudRate == 2400 || baudRate == 4800 || baudRate == 9600 || baudRate == 14400 || baudRate == 19200 || baudRate == 38400 || baudRate == 57600 || baudRate == 115200 ) return 0;//if supported nonstandardif(115200 % baudRate == 0 && 115200 / baudRate < 256) return 1;if(460800 % baudRate == 0 && 460800 / baudRate < 256) return 1;if(921600 % baudRate == 0 && 921600 / baudRate < 256) return 1;if(1500000 % baudRate == 0 && 1500000 / baudRate < 256) return 1;return -1;}int isSupportedBaudRate(int baudRate){return getBaudRateType(baudRate) >= 0;}int isSupportedDataBits(int dataBits){return dataBits >= 5 && dataBits <= 8;}int isSupportedParity(char parity){return parity == 'N' || parity == 'n' || parity == 'O' || parity == 'o' || parity == 'E' || parity == 'e' || parity == 'S' || parity == 's';}int isSupportedStopBits(int stopBits){return stopBits == 1 || stopBits == 2;}int closeSerialPort(int fd){if(0 == close(fd)) return SUCCESS;return FAILURE;}int openSerialPort(const char* dev, const char* mode, int blocking){int fd = -1;if(strcmp(mode, "ReadOnly") == 0)fd = open(dev, O_RDONLY | O_NOCTTY | O_NDELAY);else if(strcmp(mode, "WriteOnly") == 0)fd = open(dev, O_WRONLY | O_NOCTTY | O_NDELAY);else if(strcmp(mode, "ReadWrite") == 0)fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);elsefprintf(stderr, "error@openSerialPort: invalid open mode\n");if(fd > 0 && blocking){if(0 > fcntl(fd, F_SETFL, 0)) perror("fcntl F_SETFL");}return fd;}int configurateSerialPort(int fd, int baud, int dataBits, char parity, int stopBits, int minToRead, int timeoutBetweenBytes){struct termios config;//step 0: get current attribute of the serial portif(tcgetattr(fd, &config) != 0){fprintf(stderr, "error@configSerialPort: fail to tcgetattr(fd, &config)\n");return FAILURE;}//step 1: translate baud into a system parameterswitch(baud){case 115200: baud = B115200; break;case 57600: baud = B57600; break;case 38400: baud = B38400; break;case 19200: baud = B19200; break;case 9600: baud = B9600; break;case 4800: baud = B4800; break;case 2400: baud = B2400; break;case 1200: baud = B1200; break;case 300: baud = B300; break;case 110: baud = B110; break;default:fprintf(stderr, "error@configSerialPort: invalid baud rate\n");return FAILURE;}//step 2: set input/output baudif(cfsetispeed(&config, baud) != 0){fprintf(stderr, "error@configSerialPort: fail to cfsetispeed(&config, baud)\n");return FAILURE;} if(cfsetospeed(&config, baud) != 0){ fprintf(stderr, "error@configSerialPort: fail to cfsetospeed(&config, baud)\n");return FAILURE;}//step 3: set stream attribute//to disable input software stream controlconfig.c_iflag &= ~(IXON | IXOFF | IXANY);config.c_iflag &= ~(INLCR | ICRNL | IGNCR);//to let every char for every charconfig.c_oflag &= ~OPOST;config.c_oflag &= ~(ONLCR | OCRNL);//to make output no wait for a '\n' config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);//step 4: set data bitsconfig.c_cflag &= ~CSIZE;switch (dataBits){case 5: config.c_cflag |= CS5; break; case 6: config.c_cflag |= CS6; break; case 7: config.c_cflag |= CS7; break; case 8: config.c_cflag |= CS8; break; default: fprintf(stderr, "error@configSerialPort: invalid data bits\n"); return FAILURE; }//step 5: set parity switch (parity){ case 'n': case 'N': config.c_cflag &= ~PARENB; /* Clear parity enable */ config.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': config.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ config.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': config.c_cflag |= PARENB; /* Enable parity */ config.c_cflag &= ~PARODD; /* 转æ¢ä¸ºå¶æ•ˆéªŒ*/ config.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': config.c_cflag &= ~PARENB;/*as no parity*/ config.c_cflag &= ~CSTOPB; break; default: fprintf(stderr, "error@configSerialPort: invalid parity\n"); return FAILURE; }//step 6: set stop bits switch (stopBits){ case 1: config.c_cflag &= ~CSTOPB; break; case 2: config.c_cflag |= CSTOPB; break; default: fprintf(stderr, "error@configSerialPort: invalid stop bits\n"); return FAILURE;}//step 7: set read attributeconfig.c_cc[VMIN] = minToRead;config.c_cc[VTIME] = timeoutBetweenBytes;//step 8: set configuration to serial portif(tcsetattr(fd, TCSANOW, &config) != 0){fprintf(stderr, "error@configSerialPort: fail to tcsetattr(fd, TCSANOW, &config)\n");return FAILURE;}//step 9: flush input/output queuesif(tcflush(fd, TCIOFLUSH) != 0){fprintf(stderr, "error@configSerialPort: fail to tcflush(fd, TCIOFLUSH)\n");return FAILURE;}return SUCCESS;}static int getBaseBaud(int customBaud){if(customBaud <= 0) return 0;if(115200 % customBaud == 0 && 115200 / customBaud < 256) return 115200;if(460800 % customBaud == 0 && 460800 / customBaud < 256) return 460800;if(921600 % customBaud == 0 && 921600 / customBaud < 256) return 921600;if(1500000 % customBaud == 0 && 1500000 / customBaud < 256) return 1500000;return -1;}static void setSerialPortRegister(unsigned short serialPortAddr, int baseBaud, int customBaud){unsigned short enableRegAddr = serialPortAddr + 3;unsigned char DLM = 0x00, DLL = (baseBaud / customBaud) & 0xFF, tmp;//step 1: set high byte of divisor latchswitch(baseBaud){case 115200: DLM = 0x00; break;case 460800: DLM = 0x80; break;case 921600: DLM = 0xC0; break;case 1500000: DLM = 0x20; break;}//step 2: change permission and change registerioperm(enableRegAddr, 1, 1);tmp = inb(enableRegAddr);outb(0x80 | tmp, enableRegAddr);ioperm(serialPortAddr, 2, 1);outb(DLL, serialPortAddr + 0);outb(DLM, serialPortAddr + 1);//step 3: retrieve permissionoutb(tmp, enableRegAddr);ioperm(enableRegAddr, 1, 0);ioperm(serialPortAddr, 2, 0);}static int openSerialPortAtNonStandardBaud(const char* dev, const char* mode, int blocking, const struct Config* pConfig){int customBaud = pConfig->baudRate, baseBaud = getBaseBaud(pConfig->baudRate);//step 0: check if customBaud is supportedif(baseBaud < 0){fprintf(stderr, "error@openSerialPortAtNonStandardBaud: invalid baud rate\n");return -1;}//step 1: open serial portint fd = openSerialPort(dev, mode, blocking);if(fd < 0) return -2;//set hardware controlstruct serial_struct ss;if(ioctl(fd, TIOCGSERIAL, &ss) < 0){fprintf(stderr, "error@openSerialPortAtNonStandardBaud: fail to ioctl(fd, TIOCGSERIAL, &ss)\n");return -3;}ss.flags = ASYNC_SPD_CUST;ss.baud_base = baseBaud;ss.custom_divisor = ss.baud_base / customBaud;//add hardware controlif(ioctl(fd, TIOCSSERIAL, &ss) < 0){fprintf(stderr, "error@openSerialPortAtNonStandardBaud: fail to ioctl(fd, TIOCSSERIAL, &ss)\n");return -4;}if(ioctl(fd, TIOCGSERIAL, &ss) < 0){fprintf(stderr, "error@openSerialPortAtNonStandardBaud: fail to ioctl(fd, TIOCGSERIAL, &ss)\n");return -5;}//step 3: set configurationif(SUCCESS != configurateSerialPort(fd, 38400,//must set baud rate to 38400 to get custom baud pConfig->dataBits, pConfig->parity, pConfig->stopBits, pConfig->minToRead, pConfig->timeoutBetweenBytes)){fprintf(stderr, "error@openSerialPortAtNonStandardBaud: fail to configurateSerialPort(...)\n");return -6;}//step 4: change register to reinterpret 38400setSerialPortRegister(pConfig->baseAddr, baseBaud, customBaud);return fd;}int openAndConfigurateSerialPort(const char* dev, const char* mode, int blocking, const struct Config* pConfig){int fd, type = getBaudRateType(pConfig->baudRate);//check if baud rate supportedif(type < 0){fprintf(stderr, "error@openSerialPort: invalid baud rate\n");return -1;}//check if data bits supportedif(!isSupportedDataBits(pConfig->dataBits)){fprintf(stderr, "error@openSerialPort: invalid data bits\n");return -2;}//check if parity supportedif(!isSupportedParity(pConfig->parity)){fprintf(stderr, "error@openSerialPort: invalid parity\n");return -3;}//check if stop bits supportedif(!isSupportedStopBits(pConfig->stopBits)){fprintf(stderr, "error@openSerialPort: invalid stop bits\n");return -4;}//baud rate is supported nonstandard baud rateif(type == 1){fd = openSerialPortAtNonStandardBaud(dev, mode, blocking, pConfig);if(fd < 0) fprintf(stderr, "error@openSerialPort: fail to openSerialPortAtNonStandardBaud(dev, mode, pConfig)\n");return fd;}//baud rate is standard baud ratefd = openSerialPort(dev, mode, blocking);if(fd < 0){fprintf(stderr, "error@openSerialPort: fail to openSerialPort(dev, mode)\n");return -5;}if(SUCCESS != configurateSerialPort(fd,pConfig->baudRate,pConfig->dataBits,pConfig->parity,pConfig->stopBits,pConfig->minToRead,pConfig->timeoutBetweenBytes)){fprintf(stderr, "error@openSerialPort: fail to configurateSerialPort(...)\n");return -6;}return fd;}int send(int fd, void* frame, int len){int nsent = 0, alreadySent = 0;for(; alreadySent < len; alreadySent += nsent){nsent = write(fd, frame + alreadySent, len - alreadySent);if(nsent <= 0){fprintf(stderr, "error@sendFrame: fail to write(fd, frame + alreadySent, len - alreadySent)\n");break;}}return alreadySent;}static int tread(int fd, void *buf, int maxSize, struct timeval* ptv){int nfds; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); nfds = select(fd+1, &readfds, NULL, NULL, ptv); if(nfds <= 0){ if(nfds == 0) errno = ETIME; return -1; } return read(fd, buf, maxSize);}int treadn(int fd, void *buf, int nbytes, int timeoutSec, int timeoutMicrosec){int nleft; int nread; struct timeval tv; tv.tv_sec = timeoutSec; tv.tv_usec = timeoutMicrosec; nleft = nbytes; while(nleft > 0){ if((nread = tread(fd, buf, nleft, &tv)) < 0){ if (nleft == nbytes) return -1; /* error, received nothing at all return -1 */ else break; /* error, return amount received so far */ } else if (nread == 0) break; nleft -= nread; buf += nread; } return nbytes - nleft; /* return >= 0 */}int receive(int fd, void* frame, int maxLen){return read(fd, frame, maxLen);}
0 0
- 自己写的Linux下的串口操作
- linux下的串口操作
- linux下的串口操作
- linux下串口的操作
- 自己写的串口缓冲区
- 自己写Linux下的pwd命令
- linux下用qt写的的串口小程序
- linux串口的操作
- Linux系统下对树莓派镜像进行烧写操作。可搭建自己的迷你服务器
- linux在shell下的串口的一些操作
- linux在shell下的串口的一些操作
- 自己写的单链表操作
- 对串口的操作下
- 菜鸟学习笔记-----linux下的串口操作 嘿嘿
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- linux下串口的阻塞和非阻塞操作
- androd之绘制文本(FontMetrics)
- 第三周 项目1 三角形类(1)
- 黑马程序员——JAVA学习笔记(九)
- 【LeetCode】058.Length of Last Word
- 新手学JAVA(二)----String类与StringBuffer类的区别
- 自己写的Linux下的串口操作
- android项目性能优化之启动时间
- Java中String不可变性以及通过反射进行修改
- hdu-1242 Rescue
- 黑马程序员——JAVA学习笔记(十)
- Java多线程中join方法的理解
- ASP.NET 分页存储过程 及 调用
- C#web读取文件夹下面的所有文件夹和文件显示到TreeView中
- Eclipse4.3.0+jdk1.7+tomcat7.0配置出现的问题整理及解决