现在的位置: 首页 > 综合 > 正文

Linux 串口编程

2013年04月24日 ⁄ 综合 ⁄ 共 3789字 ⁄ 字号 评论关闭

Linux 串口编程

本文档记述了如何在Linux设备上通过串口进行通信的程序开发

一、 简介

本文介绍了如何编写 Linux 串口程序,主要讨论如何在 Linux 环境下,编写串口与其它计算机设备进行通讯的程序。文中所谈到的技术包括: 标准的 I/O(只具备传送/接收线的),异步I/O, 以及等待来自多信号源输入的程序。本文是初始的 linux serial programming howto 的第一个升级版。主要升级了一些作者信息,把文件转换为 DocBook 格式。就技术内容而言,几乎没什么大的改变。大规模的技术内容的改变是不可能一夜之间发生的,如果时间允许,我会尽量做一些工作。如果你正在一边等着有谁来接管这份 HOWTO,那你的心愿达成了。我会感谢你发来的任何反馈信息。所有的示例都在 i386 Linux Kernel 2.0.29 下测试通过。

二、入门

2.1.调试
调试代码最好的方法,是另外建立一台Linux主机(Linux box),采用非调制解调器的串口线(null-modem)连接两台机器。还可以使用minicom (可以从 LDP 编程指南上获得:ftp://sunsite.unc.edu/pub/linux/docs/LDP/…/lpg-0.4.tar.gz里的examples 目录来传输字符到你的 Linux 主机。Miniterm 很容易编译而且会直接把键盘的输入不做处理(raw 方式)地传到串口。只需要把 定义申明 #define MODEMDIVICE “/dev/ttyS0” 改一下。 COM1 口就设置成 ttyS0, COM2 口就是 ttyS1, 以此类推… 测试是必需的,所有的字符直接通过缆线传输,不进行任何输出处理。为了测试你的连接,在你的两台机器上开启minicom,然后随意输入一些字符。从一台电脑中输入的字符应该能显示在另一台设备上,反之亦然。输入的字符不会回显(echo) 在本地的屏幕上.自制非调制解调器的串口连接线(null-modem cable)时,你需要将一端的传送端(TxD)与另一端的接收端(RxD)连接,一端的接收端与另外一端的传送端连接,详情见串口编程第七节。如果你的电脑有两个空闲的串行端口的话,那么只要使用一台机器就可以做这些试验了,你可以在两个虚拟控制台上各运行一个miniterm,分别用来发送和接收结果。如果你使用串口鼠标,记得在试验前将 /dev/mouse 复位向。如果你使用多端口的串口卡(multiport serial card),一定要确保此设备配置正确,我的电脑就曾因为配置错误,而出现这样的问题:当我在自己的机器上测试的时候一切正常,而连接到其它电脑上的时候,端口开始丢失数据。注意,在一台机器上运行两个串口应用程序,并不是完全异步的。
2.2.端口设置

设备 /dev/ttyS* 会被当作连接到你的 Linux 机器的终端设备,而且在系统启动后就已经配置好了。这一点是在你写 raw 设备的串口通信程序时必需牢记的. 举例来说,这个串口被设定为回显(echo)所有自此设备送出的字符, 通常在做数据传输时,需要改变这种工作模式。所有的参数都可以在程序中轻松配置。配置保存在结构体 struct termios 中,这个结构是在 <asm/termbits.h> 中定义的这个文件也包括了所有标志 (flag) 的定义。c_iflag 中的输入模式标志,进行所有的输入处理,也就是说从其它设备传来的字符,在被read函数读入之前,会先按照标志进行预处理。同样的,c_oflag 定义了所有的输出处理。c_cflag 包括了对端口的设置,比如波特率,停止符号等等。c_lflag 包括了,决定了字符是否回显,信号是否发送到你的程序,等等所有的本地工作方式。c_cc 定义了所有的控制符号,例如文件结束符和停止符等等,所有的这些参数的默认值都定义在<asm/termios.h>中,man手册页termios(3)中有这些参数的具体描述。termio结构体中还包括在不能在 POSIX 系统中使用的c_line参数(行控制)

 

2.3.串口设备的输入概念

这里将介绍串行设备三种不同的输入方式,你需要为你的程序选择合适的工作方式。任何可能的情况下,不要采用循环读取单字符的方式来获取一个字符串。我以前这样做的时候,就丢失了字符,而读取整个字符串的 read 方法,则没有这种错误。
2.3.1.标准输入模式

这是终端设备的标准处理模式, 在与其它 dl 的以行为单位的输入通讯中也很有用。这种方
式中, read 会传回一整行完整的输入. 一行的结束,默认是以 NL (ASCII值 LF), 文件结束符, 或是一个行结束字符。默认设置中, CR ( DOS/Windows 里的默认行结束符) 并不是行结束标志。标准的输入处理还可以处理 清除, 删除字, 重画字符, 转换 CR 为 NL 等等功能。
2.3.2.非标准输入模式

非标准输入处理可以用于需要每次读取固定数量字符的情况下, 并允许使用字符接收时间的定时器。这种模式可以用在每次读取固定长度字符串的程序中, 或者所连接的设备会突然送出大量字符的情况下。
2.3.3.异步输入模式

前面叙述的两种模式都可以用在同步与异步的传输模式。默认是在同步的模式下工作的, 也就是在尚未读完数据之前, read 的状态会被阻塞(block)。而在异步模式下,read 的状态会立即返回并送出一个信号到所调用的程序直到完成工作。这个信号可以由信号处理程序 handler来接收。
2.3.4.等待来自多信号源的输入

本节介绍的不是另一个输入模式,不过如果你要处理来自多个设备的数据的话,可能会很有用。在我的应用程序中,我需要同时通过一个 TCP/IP socket 和一个串口来处理其它计算机传来的输入。下面给出的示例程序将等待来自两个不同输入源的输入。如果其中一个信号源出现, 程序就会进行相应处理, 同时程序会继续等待新的输入。后面提出的方法看起来相当覆杂, 但请记住 Linux 是一个多进程的操作系统。 系统调用 select 并不会在等待输入信号时增加 CPU 的负担,而如果使用轮询方式来等待输入信号的话,则将拖慢其它正在执行的进程。

 

三、示例程序

所有的示例来自于 miniterm.c. The type ahead 缓存器限制在 255 字节的大小, 这与标准输入(canonical input)进程的字符串最大长度相同 (<linux/limits.h> 或 <posix1_lim.h>)。代码中的注释解释了不同输入模式的使用以希望这些代码能够易于理解。标准输入程序的示例做了最详细的注解, 其它的示例则只是在不同于标准输入示例的地方做了强调。叙述不是很完整, 但可以激励你对这范例做实验, 以延生出合于你所需应用程序的最佳解。不要忘记赋予串口正确的权限 (也就是: chmod a+rw /dev/ttyS1)! (程序略)
3.1. 标准输入模式
3.2.非标准输入模式

在非标准输入模式中,输入的数据并不组合成行,也不会进行 erase, kill, delete 等输入处理。我们只是用两个参数来控制这种模式的输入行为: c_cc[VTIME] 设定字符输入间隔时间的计时器,而 c_cc[VMIN] 设置满足读取函数的最少字节数。MIN > 0, TIME = 0 :读取函数在读到了 MIN 值的字符数后返回。MIN = 0, TIME > 0 : TIME 决定了超时值,读取函数在读到一个字节的字符,或者等待读取时间超过 TIME (t = TIME * 0.1s)以后返回,也就是说,即使没有从串口中读到数据,读取函数也会在 TIME 时间后返回。MIN > 0, TIME > 0 : 读取函数会在收到了 MIN 字节的数据后,或者超过 TIME 时间没收到数据后返回。此计时器会在每次收到字符的时候重新计时,也只会在收到第一个字节后才启动。MIN = 0, TIME = 0 :读取函数会立即返回。实际读取到的字符数,或者要读到的字符数,会作为返回值返回。根据 Antonino(参考 conditions), 可以使用 fcntl(fd, F_SETFL, FNDELAY), 在读取前获得同样的结果。改变了 nettio.c_cc[VTIME] 和 newtio.c_cc[VMIN], 就可以测试以上的设置了。
3.3.异步输入模式
3.4.等待来自多个源的输入

这一部分的内容很少,只是作为一个提示,因此这段代码也很简短。而且这部分内容不仅适用于串口编程,而且适用于任意的一组文件描述符。select 调用及其相应的宏,使用 fd_set. 这是一个比特数组,其中每一个比特代表了一个有效的文件描述符号。 select 调用接收一个有效的文件描述符结构,并返回 fd_set 比特数组,如果此比特数组中有某一个位设为1,就表示对应的文件描述符发生了输入,输出或者有例外事件。所有 fg_set 的处理都由宏提供了,具体参考 man select 2 。这个例子会导致未知的阻塞,知道其中一个源有数据输入。如果你需要为输入设置一个超时值,就用下面的select 替代:这个例子会在1秒以后超时退出,如果发生超时,select 返回0,请注意 Timeout 是根据select实际等待输入的时间递减的,如果把timeout 设为0, select 函数会立刻退出。

 

四、其它资源信息

Linux Serial HOWTO 介绍了如何安装串口,并包括了硬件信息。

POSIX 兼容的操作系统上的串口编程。

man termios 3 介绍了所有 termios 结构里的设置。

抱歉!评论已关闭.