当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 >
Linux下的串口编程一
时间:2018-08-16作者:华清远见

从我们上大学学习单片机开始的时候,我们就经常用串口打印一些调试的信息。但是我们对于linux下的串口编程了解多少呢,咱们应该怎么玩呢?

和其他设备一样,Linux也是通过设备文件来提供访问串口的功能。当需要访问串口的时候,你只需要open相应的文件。

Linux系统上一般有一个或者多个串口,而这些串口设备文件名字比较奇怪,如比下面这样

串口设备文件名

因为串口和其他设备一样,在类Unix系统中都是以设备文件的形式存在的,所以,理所当然得你可以使用open(2)系统调用/函数来访问它。

#include <stdio.h>
        #include <string.h>
        #include <unistd.h>
        #include <errno.h>
        #include <termios.h> /* POSIX terminal control definitions */

        /*
        * 'open_port()' - Open serial port 1
        * Returns the file descriptor on success or -1 on error.
        */

        int open_port(void)
        {
                int fd; //文件描述符

                fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
                if (fd == -1)
                {
                        perror("open_port: Unable to open /dev/ttyS0 -");
                }

        }

打开串口连接的时候,程序在open函数中除了Read+Write模式以外还指定了两个选项;

fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

标 志O_NOCTTY可以告诉UNIX这个程序不会成为这个端口上的“控制终端”。如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等 等,会影响到你的进程。O_NDELAY标志则是告诉UNIX,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接。如果不指定这个标志的话,除非DCD信号线上有space电压否则这个程序会一直睡眠。

配置串口

很多系统都支持POSIX终端(串口)接口。程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等。要使用这个端口的话,你必须将头文件包含到你的程序中。这个头文件中定义了终端控制结构体和POSIX控制函数。

与串口操作相关的重要的两个POSIX函数可能就是tcgetattr(3)和tcsetattr(3)。顾名思义,这两个函数分别用来取得设设置终端的属性。调用这两个函数的时候,你需要提供一个包含着所有串口选项的termios结构体:

termios结构体成员

串口的初始化

void serial_init(int fd)
        {
                struct termios options;
                tcgetattr(fd, &options);
                options.c_cflag |= ( CLOCAL | CREAD );
                options.c_cflag &= ~CSIZE;
                options.c_cflag &= ~CRTSCTS;
                options.c_cflag |= CS8;
                options.c_cflag &= ~CSTOPB; 
                options.c_iflag |= IGNPAR;
                options.c_iflag &= ~(ICRNL | IXON);
                options.c_oflag = 0;
                options.c_lflag = 0;

                cfsetispeed(&options, B115200);
                cfsetospeed(&options, B115200);
                tcsetattr(fd,TCSANOW,&options);
        }

控制选项

通过termios结构体的c_cflag成员可以控制波特率,数据的比特数,parity,停止位和硬件流控制。下面这张表列出了所有可以使用的常数。

在 传统的POSIX编程中,当连接一个本地的(不通过调制解调器)或者远程的终端(通过调制解调器)时,这里有两个选项应当一直打开,一个是CLOCAL, 另一个是CREAD。这两个选项可以保证你的程序不会变成端口的所有者,而端口所有者必须去处理发散性作业控制和挂断信号,同时还保证了串行接口驱动会读 取过来的数据字节。

设置字符大小

设置字符大小的时候,这里却没有像设置波特率那么方便的函数。所以,程序中需要一些位掩码运算来把事情搞定。字符大小以比特为单位指定:

options.c_flag &= ~CSIZE; /* Mask the character size bits */
        options.c_flag |= CS8; /* Select 8 data bits */

c_iflag成员可以使用的常量

选择经典输入

经典输入是以面向行设计的。在经典输入模式中输入字符会被放入一个缓冲之中,这样可以以与用户交互的方式编辑缓冲的内容,直到收到CR(carriage return)或者LF(line feed)字符。

选择使用经典输入模式的时候,你通常需要选择ICANON,ECHO和ECHOE选项:

options.c_lflag |= (ICANON | ECHO | ECHOE);

选择原始输入

原始输入根本不会被处理。输入字符只是被原封不动的接收。一般情况中,如果要使用原始输入模式,程序中需要去掉ICANON,ECHO,ECHOE和ISIG选项:

options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

输出选项

成员变量c_oflag之中包括了输出过滤选项。和输入模式相似,程序可以选择使用经过加工的或者原始的数据输出。

选择加工过的输出

通过在c_oflag成员变量中设置OPOST选项的方法程序可以选择加工过的输入。

options.c_oflag |= OPOST;

在所有选项当中,你可能只需要使用ONLCR选项来将行分隔符映射到CR-LF组合对上。其他选项主要是历史遗留,仅仅与行打印机和终端跟不上串行数据的年代有关。

选择原始输出

原始输出方式可以通过在c_oflag中重置OPOST选项来选择:

options.c_oflag &= ~OPOST;

如果OPOST选项被设置成无效的话,其他c_oflag中的选项都会失效。

设置波特率

cfsetispeed(&options, B115200); /*设置输入波特率 */ 
        cfsetospeed(&options, B115200); /*设置输出波特率 */


发表评论

全国咨询电话:400-611-6270,双休日及节假日请致电值班手机:15010390966

在线咨询: 曹老师QQ(3337544669), 徐老师QQ(1462495461), 刘老师 QQ(3108687497)

企业培训洽谈专线:010-82600901,院校合作洽谈专线:010-82600350,在线咨询:QQ(248856300)

Copyright 2004-2018 华清远见教育科技集团 版权所有 ,京ICP备16055225号,京公海网安备11010802025203号