首页 理论教育Linux串口的打开和初始化方法

Linux串口的打开和初始化方法

【摘要】:Linux操作系统为串行口提供了很好的支持。Linux系统中串口设备被当做一个字符设备处理。图7.6m inicom配置端口结束如图7.6所示,串口被设置为tty0,波特率是38 400,其他配置为默认设置。图7.7m inicom命令界面2.操作串口需要用到的头文件在Linux系统操作串口需要用到以下头文件:在编写串口操作程序的最开始引用这些文件即可。串口的打开和关闭和文件相同。

Linux操作系统为串行口提供了很好的支持。Linux系统中串口设备被当做一个字符设备处理。PC安装Linux系统后在/dev目录下有若干个ttySx(x代表从0开始的正整数)设备文件。ttyS0对应第一个串口,也就是Windows系统下的串口设备COM1,以此类推。

1.串口工具m inicom

Linux系统提供了一个串口工具minicom,可以完成复杂的串口通信工作。本节介绍minicom的使用。首先是安装minicom,在Ubuntu Linux系统终端下将系统权限切换至root权限,然后输入“sudo apt-get install minicom”,按回车键后即可安装minicom软件。软件安装好之后,第一次使用之前需要配置minicom。

(1)在终端中输入sudo minicom-s,出现minicom配置界面,如图7.3所示。Minicom配置菜单在屏幕中央,每个菜单项都包括了一组配置。

图7.3 m inicom配置界面

(2)用光标键移动高亮条到Serial Port setup菜单项,按回车键后进入串口参数配置界面,如图7.4所示。

图7.4 m inicom配置端口界面

串口配置界面列出了串口的配置,每个配置前都有一个英文字母,代表进入配置项的快捷键。首先配置端口,输入小写字母a,光标移动到了/dev/tty8字符串最后,并且进入到编辑模式。以作者使用的计算机为例,修改为/dev/tty0,代表连接到系统的第一个串口。

(3)设置好串口设备后按回车键,保存参数并且回到提示界面。输入小写字母e,进入串口参数配置界面,如图7.5所示。

图7.5 m inicom配置串口参数

串口参数界面可以配置串口波特率、数据位、停止位等信息。一般情况下,只需要配置波特率,例如需要配置串口波特率为38 400时,输入小写字母d,屏幕上方current字符串后的波特率改变为38 400。

(4)设置好波特率后按回车键,保存退出,回到串口配置界面,如图7.6所示。

图7.6 m inicom配置端口结束

如图7.6所示,串口被设置为tty0,波特率是38 400,其他配置为默认设置。如果保存配置,直接按回车键退出。选择Save setup as dfl选项后按回车键,配置信息被保存为默认配置文件,下次启动的时候会自动加载。

保存默认设置后,选择Exit选项后按回车键,退出配置界面,minicom自动进入终端界面。在终端界面会自动连接到串口,如果串口没有连接任何设备,屏幕右下角的状态显示为Offline。

(5)退出minicom,使用Ctrl+a键,然后输入字母z,出现minicom的命令菜单,如图7.7所示。

命令菜单列出了minicom的命令,输入大写字母Q,屏幕提示是否退出,选择Yes选项按回车键退出minicom。

图7.7 m inicom命令界面

2.操作串口需要用到的头文件

在Linux系统操作串口需要用到以下头文件:

在编写串口操作程序的最开始引用这些文件即可。

3.串口操作方法

操作串口的方法与文件类似,可以使用与文件操作相同的方法打开和关闭串口、读写,以及使用select()函数监听串口。不同的是,串口是个字符设备,不能使用fseek()之类的文件定位函数。此外,串口是个硬件设备,还可以设置串口设备的属性。

实例7-1 打开和关闭串口:

程序的main()函数中,使用open()函数打开串口,方法与打开普通文件相同,并且指定了读写属性。打开串口设备后,判断文件句柄的值是否正确。如果正确将打印打开串口成功的信息。最后使用close()函数关闭串口。串口的打开和关闭和文件相同。

程序编译后需要root权限才可以执行,否则会报错open ttyS0:Permissiondenied,表示权限不足。

4.串口属性设置

串口的基本属性包括:波特率、数据位、停止位和奇偶校验位等参数。Linux系统通常使用termios结构存储串口参数,该结构在termios.h头文件定义如下:

termios结构比较复杂,每个成员都有多个选项值,表7.6列出了每个成员常用的选项值,成员取值均符合POSIX标准,凡是符合POSIX标准的系统都是通用的。

表7.6 term ios结构的各成员常用取值

续表

表7.7 term ios结构c_cc成员数组下标取值及其含义

续表(www.chuimin.cn)

termios.h头文件为termios结构提供了一组设置的函数,函数定义如下:

#include<termios.h>

#include<unistd.h>

int tcgetattr(int fd,struct termios*termios_p);

int tcsetattr(int fd,int optical_actions,struct termios*termios_p);

int tcsendbreak(int fd,int duration);

int tcdrain(int fd);

int tcflush(int fd,int queue_selector);

int tcflow(int fd,int action);

int cfmakedraw(struct termios*termios_p);

speed_t cfgetispeed(struct termios*termios_p);

speed_t cfgetospeed(struct term ios*termios_p);

int cfsetispeed(struct termios*termios_p,speed_t speed);

int cfsetospeed(struct termios*termios_p,speed_t speed);

tcgetattr()函数读取串口的参数设置,tcgetattr()函数设置指定串口的参数。串口参数一般可以通过tcsetattr()函数设置,其他的函数是一些辅助函数。

tcgetattr()函数和tcsetattr()函数,参数fd指向已打开的串口设备句柄,termios_p指向存放串口参数的termios结构首地址。tcsetattr()函数中,参数optional_actions指定了参数什么时候起作用:TCSANOW表示立即生效;TCSADRAIN表示在fd上所有的输出都被传输后生效;TCSAFLUSH表示所有引用fd对象的数据都在传输出去后生效。

tesendbreak()函数传送连续的0值比特流,持续一段时间。如果终端使用异步串行数据传输且duration是0,它至少传输0.25秒,不会超过0.5秒。如果duration非0,它发送的时间长度由实现定义。

tcdrain()函数会等待直到所有写入fd引用对象的输出都被传输。如果终端未使用异步串行数据传输,tcsendbreak()函数什么都不做。

tcflush()函数丢弃要写入引用的对象但是尚未传输的数据,或者收到但是尚未读取的数据,取决于参数queue_selector的值:

TCIFLUSH 刷新收到的数据但不是读

TCOFLUSH 刷新写入的数据但是不传送

TCIOFLUSH 同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送

tcflow() 函数挂起fd引用对象上的数据传输或接收,取决于action的值:

TCOOFF 挂起输出

TCOON 重新开始被刮起的输出

TCIOFF 发送一个STOP字符,停止终端设备向系统传送数据

TCION 发送一个START字符,使终端设备向系统传输数据

打开一个终端设备时的默认设置是输入和输出都没有挂起。cfmakeraw()函数设置终端属性为原始数据方式,相当于对参数termios_p配置:

termiso_p->c_iflag&=~(IGNBBK|brkint|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);

termios_p->c_oflag&~OPOST;

termios_p->c_lflag&~(ECHO|ECHOL|ICANON|ISIG|IEXTEN);

termios_p->c_cflag&~(CSIZE|PARENB)

termios_p->c_cflag|~ CSS;

termios结构各成员的参数取值可以参考表7.8。

表7.8 speed_t类型的取值及含义

当设置串口波特率为B0的时候,会使modem产生“挂机”操作。波特率和通信距离是反比关系,当波特率越高的时候,数据有效传输距离就越短。

cfsetispeed()函数和cfsetospeed()函数函数设置输入和输出的波特率,参数termios_p指向termios结构的内存首地址,参数speed是要设置的波特率,取值请参考表7.4。

termios结构相关的函数,除cfgetispeed()函数和cfgetospeed()函数外,其余函数返回0表示执行成功,返回-1表示失败,并且设置全局变量errno。

还有一点需要说明,Linux系统对串口的设置主要是通过termios这个结构体实现的,但是这个结构体却没有提供控制RTS或获得CTS等串口引脚状态的接口,可以通过ioctl系统调用来获得或控制。参考代码如下:

其实TICOM_RTS有效后是把串口的RTS设置为有信号,但串口的电平为低时是有信号,为高时为无信号,和用TIOCMGET获得的状态正好相反。也就是说TIOCMGET/TIOCMSET只是获得/控制串口的相应引脚是否有信号,并不反映当前串口的真实电平高低。

在许多Linux串口编程的示例代码中,都没有对termios结构的c_iflag成员做有效设置,在传输ASCII码时不会有问题,如果传输二进制数据就会遇到麻烦,比如值为0x0d、0x11、0x13数据会被丢掉,因为这几个字符是特殊字符,如果不特别设置一下,会被当做控制字符处理掉。设置关闭ICRNL和IXON参数可以解决。