logo资料库

linux串口读写程序.doc

第1页 / 共19页
第2页 / 共19页
第3页 / 共19页
第4页 / 共19页
第5页 / 共19页
第6页 / 共19页
第7页 / 共19页
第8页 / 共19页
资料共19页,剩余部分请下载后查看
Linux 串口读写
串口简介
串口操作
Linux 串口读写 串口简介 串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使 用。常用的串口是 RS-232-C 接口(又称 EIA RS-232-C)它是在 1970 年 由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生 产厂家共同制定的用于串行通讯的标准。它的全名是"数据终端设备(DTE)和 数据通讯设备(DCE)之间串行二进制数据交换接口技术标准"该标准规定采用 一个 25 个脚的 DB25 连接器,对连接器的每个引脚的信号内容加以规定,还 对各种信号的电平加以规定。传输距离在码元畸变小于 4% 的情况下,传输电 缆长度应为 50 英尺。 Linux 操作系统从一开始就对串行口提供了很好的支持 流向 符号 功能 TXD DTE→DCEDTE 发送串行数据 RXD DTE←DCEDTE 接收串行数据 RTS DTE→DCEDTE 请求 DCE 将线路切换 CTS DTE←DCEDCE 告诉 DTE 线路已接通 到发送方式 序号 计算机串口的引脚说明 信号名称 发送数据 接收数据 2 3 4 5 6 7 8 20 22 请求发送 允许发送 信号地 载波检测 振铃指示 可以发送数据 数据设备准备好 DSR DTE←DCEDCE 准备好 DCD DTE←DCE表示 DCE 接收到远程载波 信号公共地 数据终端准备好 DTR DTE→DCEDTE 准备好 RI DTE←DCE表示 DCE 与线路接通,出现 振铃 串口操作 串口操作需要的头文件 #include #include #include #include /*标准输入输出定义*/ /*标准函数库定义*/ /*Unix 标准函数定义*/ /*数据类型,比如一些 XXX_t 的那种*/
#include #include #include #include /*定义了一些返回值的结构,没看明白*/ /*文件控制定义*/ /*PPSIX 终端控制定义*/ /*错误号定义*/ 打开串口 在 Linux 下串口文件是位于 /dev 下的 串口一 为 /dev/ttyS0 串口二 为 /dev/ttyS1 打开串口是通过使用标准的文件打开函数操作: int fd; /*以读写方式打开串口*/ fd = open( "/dev/ttyS0", O_RDWR); if (-1 == fd){ /* 不能打开串口一*/ perror(" 提示错误!"); } 设置串口 最基本的设置串口包括波特率设置,效验位和停止位设置。 串口的设置主要是设置 struct termios 结构体的各成员值。 struct termio { unsigned short c_iflag; /* 输入模式标志 */ unsigned short c_oflag; unsigned short c_cflag; unsigned short c_lflag; unsigned char c_line; unsigned char c_cc[NCC]; /* 输出模式标志 */ /* 控制模式标志*/ /* local mode flags */ /* line discipline */ /* control characters */ }; 设置这个结构体很复杂,我这里就只说说常见的一些设置: 波特率设置
下面是修改波特率的代码: struct termios Opt; tcgetattr(fd, &Opt); /*获得当前设备模式,与终端相关的参数。fd=0 标准输入*/ cfsetispeed(&Opt,B19200); /*设置结构 termios 输入波特率为 19200Bps*/ cfsetospeed(&Opt,B19200); /*fd 应该是文件描述的意思*/ tcsetattr(fd,TCANOW,&Opt);/*设置终端参数,TCANOW 修改立即发生*/ 设置波特率的例子函数: /** *@brief 设置串口通信速率 *@param fd 类型 int 打开串口的文件句柄 *@param speed 类型 int 串口速度 *@return void */ int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, void set_speed(int fd, int speed){ 19200, 9600, 4800, 2400, 1200, 300, }; int i; int status; struct termios Opt; tcgetattr(fd, &Opt); for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { /** * tcflush 函数刷清(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚
未读)或输出缓存(用户程序已经写,但尚未发送)。queue 参数应是下列三个常 数之一: * TCIFLUSH 刷清输入队列。 * TCOFLUSH 刷清输出队列。 * TCIOFLUSH 刷清输入、输出队列。 */ tcflush(fd, TCIOFLUSH);//设置前 flush cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); //通过 tcsetattr 函数把新的属性设置到串口上。 //tcsetattr(串口描述符,立即使用或者其他标示,指向 termios 的指 针) status = tcsetattr(fd, TCSANOW, &Opt); if (status != 0) { perror("tcsetattr fd1"); return; } tcflush(fd,TCIOFLUSH); //设置后 flush } } } 效验位和停止位的设置: 无效验 8 位 奇效验(Odd) 7 位 偶效验(Even) 7 位 Option.c_cflag &= ~PARENB; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= ~CSIZE; Option.c_cflag |= ~CS8; Option.c_cflag |= ~PARENB; Option.c_cflag &= ~PARODD; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= ~CSIZE; Option.c_cflag |= ~CS7; Option.c_cflag &= ~PARENB; Option.c_cflag |= ~PARODD;
Space 效验 7 位 Option.c_cflag &= ~CSTOPB; Option.c_cflag &= ~CSIZE; Option.c_cflag |= ~CS7; Option.c_cflag &= ~PARENB; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= &~CSIZE; Option.c_cflag |= CS8; 设置效验的函数: /** *@brief 设置串口数据位,停止位和效验位 *@param fd 类型 int 打开的串口文件句柄 *@param databits 类型 int 数据位 取值 为 7 或者 8 *@param stopbits 类型 int 停止位 取值为 1 或者 2 *@param parity 类型 int 效验类型 取值为 N,E,O,,S */ int set_Parity(int fd, int databits, int stopbits, int parity) { struct termios options; if (tcgetattr(fd, &options) != 0) { perror("SetupSerial 1"); return (FALSE); } options.c_cflag &= ~CSIZE; switch (databits) /*设置数据位数*/ { case 7: case 8: options.c_cflag |= CS7; break; options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return (FALSE); } switch (parity)
*/ */ */ */ { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验 options.c_iflag |= INPCK; /* Disnable parity checking break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity\n"); return (FALSE); } /* 设置停止位*/ switch (stopbits) { case 1: case 2: options.c_cflag &= ~CSTOPB; break; options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n");
return (FALSE); options.c_iflag |= INPCK; } /* Set input parity option */ if (parity != 'n') tcflush(fd, TCIFLUSH); options.c_cc[VTIME] = 150; /* 设置超时 15 seconds*/ options.c_cc[VMIN] = 0; /* Update the options and do it if (tcsetattr(fd, TCSANOW, &options) != 0) { NOW */ perror("SetupSerial 3"); return (FALSE); } return (TRUE); } 需要注意的是: 如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用 原始模式(Raw Mode)方式来通讯,设置方式如下: options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ options.c_oflag &= ~OPOST; /*Output*/ 读写串口 设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。  发送数据 char buffer[1024]; int int nByte = write(fd, buffer ,Length) Length; nByte;  读取串口数据 使用文件操作 read 函数读取,如果设置为原始模式(Raw Mode)传输 数据,那么 read 函数返回的字符数是实际串口收到的字符数。 可以使用操作文件的函数来实现异步读取,如 fcntl,或者 select 等来 操作。 char buff[1024]; int int readByte = read(fd,buff,Len); Len;
关闭串口 关闭串口就是关闭文件。 close(fd); 下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件 /******************************************************************** ** * 代码说明:使用串口二测试的,发送的数据是字符,但是没有发送字符串结 束符号, * 所以接收到后,后面加上了结束符号。我测试使用的是单片机发送数据到第 二个串口,测试通过。 ******************************************************************* -1 0 ***/ #define FALSE #define TRUE /******************************************************************** */ int OpenDev(char *Dev) { //Dev 就是设备,设备就是文件,就是给出该设备文件的路径 int fd = open(Dev, O_RDWR ); //| O_NOCTTY | O_NDELAY if (-1 == fd) { perror("Can't Open Serial Port"); return -1; } else return fd; } int main(int argc, char **argv) { int fd; int nread; char buff[512]; char *dev = "/dev/ttyS1"; //串口二 fd = OpenDev(dev); set_speed(fd, 19200); if (set_Parity(fd, 8, 1, 'N') == FALSE) {
分享到:
收藏