[基础|理论|实验]linux下的RS232串口通讯

1.Linux把所有的外部终端设备都当做文件进行操作,通常分为块设备、字符设备、网络设备。串口是属于字符设备,是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是 RS-232-C 接口,传输距离在码元畸变小于 4% 的情况下传输电缆长度应为 50 英尺。通常的操作步骤为"打开串口文件"->"设置串口参数"->"读写串口操作"->"关闭串口文件"。

2.详解:

    需要头文件信息:

 1  
 2 #include     <stdio_ext.h>
 3 #include     <stdio.h>      /*标准输入输出定义*/
 4 #include     <stdlib.h>     /*标准函数库定义*/
 5 #include     <unistd.h>     /*Unix 标准函数定义*/
 6 #include     <sys/types.h>  /*系统类型定义*/
 7 #include     <sys/stat.h>   /*系统状态定义*/
 8 #include     <fcntl.h>      /*文件控制定义*/
 9 #include     <termios.h>    /*PPSIX 终端控制定*/
10 #include     <errno.h>      /*错误号定义/

    打开串口:

linux下的串口文件通常是位于/dev目录下,串口1为/dev/ttyS0,串口2为/dev/ttyS1,以此类推。其它终端还有usb0,py0等。

1     fd = open("/dev/ttyS0",O_RDWR| O_NOCTTY | O_NDELAY);
2     if(-1 == fd)
3     {
4         perror("can not open serial port");
5 
6     }

     设置串口:

最基本的设置串口包括波特率设置,效验位和停止位设置。主要是设置termios结构体的成员函数。
 1 struct termios
 2   {
 3     tcflag_t c_iflag;        /* input mode flags */
 4     tcflag_t c_oflag;        /* output mode flags */
 5     tcflag_t c_cflag;        /* control mode flags */
 6     tcflag_t c_lflag;        /* local mode flags */
 7     cc_t c_line;            /* line discipline */
 8     cc_t c_cc[NCCS];        /* control characters */
 9     speed_t c_ispeed;        /* input speed */
10     speed_t c_ospeed;        /* output speed */
11 #define _HAVE_STRUCT_TERMIOS_C_ISPEED 1
12 #define _HAVE_STRUCT_TERMIOS_C_OSPEED 1
13   };
波特率设置
1 struct  termios Opt;
2 tcgetattr(fd, &Opt);         /*获得文件句柄的termios结构*/
3 cfsetispeed(&Opt,B2400);     /*设置为2400Bps,通常串口IO是一致的波特率*/
4 cfsetospeed(&Opt,B2400);
5 tcsetattr(fd,TCANOW,&Opt);    /*设置文件句柄的termios结构,TCANOW为设置立即生效*/ 

 设置数据位

1 options.c_cflag &= ~CSIZE; 
2 option.c_cflag |= CS8; /*设置为8位数据位,其它如CS5->CS7*/

 设置校验位

 1 option.c_cflag |= PARENB; /*设置校验位使能*/
 2 option.c_cflag |= PARODD; /*设置为奇校验*/
 3 //option.c_cflag &= ~PARODD; /*设置为偶校验*/
 4 
 5 //以下设置仅限于linux系统
 6 option.c_cflag |= CMSPAR;  
 7 /*设置space校验,奇偶校验位恒为0*/
 8 //option.c_cflag &= ~PARODD;或者是直接没有设置 
 9 /*设置mark校验,奇偶校验位恒为1*/
10 //option.c_cflag |= PARODD;

 设置停止位

1 option.c_cflag &= ~CSTOPB; //一位停止位
2 //option.c_cflag |= CSTOPB; //两位停止位

 关闭文件

1 close(fd);

//增加关于RAW原始通信(非规范模式)详解

在使用非规范模式的时候,需要关闭c_lflag字段的ICANON标志就会使得终端出于非规范模式,在这个模式下,接受到的数据不是成行的。故这里区别与上面说明,需要使用c_cc数组的两个变量:MIN和TIME,数组元素名下标为VMIN和VTIME。

VTIME定义要求等待的时间(百毫米,通常是unsigned char变量),而VMIN定义了要求等待的最小字节数(相比之下,read函数的第三个参数指定了要求读的最大字节数)。
如果VTIME=0,VMIN=要求等待读取的最小字节数,read必须在读取了VMIN个字节的数据或者收到一个信号才会返回。
如果VTIME=时间量,VMIN=0,不管能否读取到数据,read也要等待VTIME的时间量。
如果VTIME=时间量,VMIN=要求等待读取的最小字节数,那么将从read读取第一个字节的数据时开始计时,并会在读取到VMIN个字节或者VTIME时间后返回。
如果VTIME=0,VMIN=0,不管能否读取到数据,read都会立即返回。

另外要想以上设置生效,还需要在打开文件的时候,不要指定O_NDELAY或者是O_NONBLOCK参数。

 1 #include     <stdio.h>      /*标准输入输出定义*/
 2 #include     <stdlib.h>     /*标准函数库定义*/
 3 #include     <unistd.h>     /*Unix 标准函数定义*/
 4 #include     <sys/types.h>     /*系统类型定义*/
 5 #include     <sys/stat.h>         /*系统状态定义*/
 6 #include     <fcntl.h>      /*文件控制定义*/
 7 #include     <termios.h>    /*PPSIX 终端控制定义*/
 8 #include     <errno.h>      /*错误号定义*/
 9 
10 int main(void)
11 {
12 
13     
14     int fd;
15     struct termios option;
16     int status = 0;
17     char buff[512];//这样定义buff的内容是随机数
18     int num = 0;
19 
20     fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY );
21     if (-1 == fd)
22     {
23         perror("can not open serial port");
24 
25     }
26     tcgetattr(fd, &option);
27     option.c_cflag |= CLOCAL; //保证程序不会成为端的占有者
28     option.c_cflag |= CREAD; //使端口能读取输入的数据
29     cfsetispeed(&option, B2400);
30     cfsetospeed(&option, B2400);
31 
32     option.c_cflag &= ~CSIZE;
33     option.c_cflag |= CS8;
34     option.c_cflag |= PARENB;
35     //option.c_cflag &= ~PARODD;
36 
37     option.c_cflag |= PARODD; //奇校验
38     option.c_cflag |= CMSPAR; //标记校验位
39     option.c_cflag &= ~CSTOPB; //一位停止位
40     option.c_iflag |= INPCK; /* Disnable parity checking */
41 
42     //    一下是添加测试
43     ///////////////////////////////////////////////////////////////////////////////////
44 
45     option.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
46 
47     option.c_oflag &= ~OPOST;
48     option.c_oflag &= ~(ONLCR | OCRNL); //添加的
49 
50     option.c_iflag &= ~(ICRNL | INLCR);
51     option.c_iflag &= ~(IXON | IXOFF | IXANY); //添加的
52     ///////////////////////////////////////////////////////////////////////////////////////
53 
54     option.c_cc[VTIME] = 0//设置超时
55     option.c_cc[VMIN] = 1//设置最小字节数
56     tcflush(fd, TCIFLUSH);
57 
58     
59     status = tcsetattr(fd, TCSANOW, &option);
60     if (-1 == status)
61     {
62         perror("tcsetattr false");
63     }
64  
65     write(fd, "\x02"sizeof("\x02"));
66     num = read(fd, buff, 512);
67     printf("%d\n", num);
68     printf("%d\n", errno);
69     printf("%x", buff[0]);//注意这里,如果读取不成功,将是随机值。
70 }
71     
 

作者:xiaoxia

出处:http://cnblogs.com/xiaoxia

本文遵从GNU 的自由文档许可证(Free Document License)的条款,欢迎转载、修改、散布。 

原文地址:https://www.cnblogs.com/xiaoxia/p/2095448.html