在Linux系统中,设备文件或特殊文件是设备驱动程序的接口,出现在文件系统中就好像它是普通文件一样。表7.4文件打开方式取值......
2023-11-19
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参数可以解决。
有关ARM嵌入式系统原理与应用的文章
两台PC通过串口建立起COM1和COM2的配对连接,串口COM1在Windows系统中打开,串口2在Linux系统中打开,运行下面例子编译后的程序,与Windows系统的终端通信。Linux系统下串口操作实例。第62行~75行循环读取串口,如果搜到数据就打印到屏幕,并且在第71行判断接收到的字符串是否是“quit”,如果是就跳出循环,退出程序。当连接好两台PC以后,在Linux系统编译实例7-1的stty_echo.c文件生成应用程序。在Linux屏幕终端会打印用户在Windows中串口软件里输入的字符串。......
2023-11-19
内核初始化的主要任务则是加载并执行应用空间的初始化程序,由系统应用接管系统完成特定的功能,而Linux内核则开始为应用提供良好的服务。Linux内核初始化框架如图4-3所示。图4-3Linux内核初始化框架图4-3展示了Linux内核的初始化的基本流程,首先是与体系结构相关的head.o部分,然后跳入体系结构无关的代码start_ kernel,开始内核后续的初始化处理。......
2023-11-22
因为串口设备工作频率低且容易受到干扰,远距离传输会造成数据丢失。表7.5DB9(9针)接口的RS232串口数据线定义常见的串口工具软件都提供了RTS/CTS与XON/XOFF选项。这两个选项对应RS232串口的两种流量控制方式。RTS/CTS方式通过对串口控制器编程,设置接收缓冲区的高位标志和地位标志。高位标志和低位标志用于控制RTS和CTS信号线。......
2023-11-19
PCI总线树的枚举由pci_scan_child_bus函数完成,该函数的主要作用是分配PCI总线树的PCI总线号,而并不初始化PCI设备使用的BAR空间。subordinate总线号记载当前PCI总线树中最后一个PCI总线号,因此只有完成了对PCI总线树的枚举后,才能获得该参数。值得注意的是,在Linux系统中,许多PCIe设备并没有提供该结构。PCI总线规范规定了获取BAR空间的标准实现方法。......
2023-10-20
整个系统启动和初始化的过程,Linux内核是在主处理器启动之后才会执行。不同的处理器启动流程并不相同,这就要求Linux内核能支持各种处理器的初始化操作。Linux内核各个模块,大部分设计时做到了体系结构无关。Linux内核是一个庞大的系统,最终生成的操作系统代码的执行文件非常大。......
2023-11-22
打开文件的方法有很多,可以使用命令打开,也可以使用快捷键打开,还可以直接将图像拖入软件界面打开。接下来为用户介绍几种常用的打开方式。使用“打开”命令打开文件执行“文件>打开”命令,弹出“打开”对话框。在“打开”对话框中,可以对“查找范围”“文件名”和“文件格式”进行设置,如图2-13所示。图 2-13提示要打开连续的文件,可以单击第1个文件,然后按下Shift键,再单击需要同时选中的最后一个文件,单击“打开”按钮即可。......
2023-11-17
空间信息网络加权代数连通度最大化拓扑控制的初始化问题指的是:在网络初始状态下或网络需要完全重新构建时,构建具有最大加权代数连通度的网络拓扑问题。与原始问题相比,由于放宽了约束条件,松弛问题的可行解集更大,因此其最优解能够表示原始问题解的上界。另一方面,对于小规模的空间信息网络,可以采用穷举法来获得原始问题的最优解。......
2023-07-02
相关推荐