精华内容
下载资源
问答
  • POSIX串口编程文档

    2010-03-21 16:00:47
    POSIX串口编程文档 =====LINUX编程======
  • POSIX 串口编程指南

    2017-05-20 09:41:56
    介绍 第一章 串口通信基础 什么是串口通信 什么是 RS-232 信号定义 异步通信 什么是全双工和半双工 ...POSIX 终端接口 控制选项 本地选项 输入选项 输出选项 控制字符 第三章 MODEM 通信 什么是 MODEM 与

    介绍


    POSIX 串口编程指南将教会你在你的 UNIX 工作站或者 PC 上面如何成功、有效以及可移植性的对串口编程。每一章提供了使用 POSIX 终端控制函数的编程例程,可以基本不经修改地工作在 IRIX®, HP-UX, SunOS®, Solaris®, Digital UNIX®, Linux® 以及其他大多数 UNIX 操作系统。你会发现操作系统之间的最大差异是串口设备文件名和锁文件。
    本指南分为以下章节和附录:
    • 第一章 串口通信基础
    • 第二章 串口配置
    • 第三章 MODEM 通信
    • 第四章 高级串口编程
    • 附录A 引脚分布
    • 附录B ASCII 码

    第一章 串口通信基础


    本章介绍了串口通信,RS-232 和 大多数计算机上使用的其他标准,以及如何通过 C 程序操作串口。

    什么是串口通信


    计算机一次传输信息(数据)一位或多个比特位。串行是指传输数据一次只传输一位。当进行串口通信时你发送或者接收的每个字(即字节或字符)一次发送一位。每一位都是 on 或者 off。术语用 mark 代表 on,用 space 代表 off。
    串口数据速率使用 bits-per-second ("bps") 或者 baudot rate ("baud")。这表示一秒内可以传输多少逻辑 1 和 0。当波特率超过 1000,你会经常看到用 kilo baud 表示的速率。对于超过 1000000 的速率用 megabaud,或者 Mbps 来表示。
    当涉及到串口设备或者端口,它们被标识为“数据通讯设备”("DCE")或者“数据终端设备”("DTE")。两者之间的区别很简单 - 每个信号对,如发送和接收,是交叉的。

    什么是 RS-232


    RS-232 是由 EIA 定义的用于串口通信的标准电气接口。RS-232 实际上有三种不同的类型(A,B和C),每一种对于 on 和 off 电平定义了不同的电压范围。最常用的种类是 RS-232C,它定义mark位电压范围:-3V~-12V 和space位电压范围:+3V~+12V。RS-232C 规范上说,这些信号可以传输 25英尺(8m),通常你可以传输更远一些只要波特率足够低。
    除了数据输入和输出数据线,还有其他提供时序、状态与握手的信号线。这里我们仅列举最为常见的 DB-9 接口分布图,引脚和功能描述如下所示:
    • 1 - DCD - 数据载波检测
    • 2 - RXD - 接收数据
    • 3 - TXD - 发送数据
    • 4 - DTR - 数据终端就绪
    • 5 - GND - 地
    • 6 - DSR - 数据装置就绪
    • 7 - RTS - 请求发送
    • 8 - CTS - 清除发送
    • 9 - RI - 振铃指示
    你还可能遇到 RS-422 以及 RS-485 串口标准。RS-422 使用更低电压与差分信号允许线缆长达 1000英尺(300m)。在实际应用中,使用 TTL 电平逐渐成为趋势,在 MCU  与串口转接芯片提供的串口中比较常见,此时mark 电平:+5V或+3.3V等,space位:0V(逻辑地)。

    信号定义


    RS-232 标准针对串口通信定义了18种不同的信号。其中,在 UNIX 环境下通常只有 6 种可用。

    GND - 逻辑地
    从技术上讲,逻辑接地不是信号,但没有它,其他信号就不能工作。从根本上说,逻辑地充当一个参考电压,从而知道哪些电压为正或负。

    TXD - 发送数据
    mark 电平为逻辑 1,space 电平为逻辑 0。注意 RS232 电平与 TTL 电平反相。

    RXD - 接收数据
    同样的,mark 电平为逻辑 1,space 电平为逻辑 0。注意 RS232 电平与 TTL 电平反相。

    DCD - 数据载波检测
    DCD 信号接收自串口线缆的另一端的计算机或设备。信号线低电平表示计算机或设备当前已连接或在线。DCD 不经常使用。

    DTR - 数据终端就绪
    DTR 信号用于通知对端计算机或设备己方已就绪(space 电平)或未就绪(mark 电平)。DTR 通常在打开串口时自动使能。

    CTS - 清除发送
    CTS 信号接收自串口线缆的另一端。信号线 space  电平表示可以己方可以发送数据。CTS 通常用于串口数据流控。

    RTS - 请求发送
    RTS 设置为 space 电平表示己方准备好就接收数据。一般与 CTS 一起用于串口流控,通常被设置为默认有效状态。

    异步通信


    解析串口数据需要确定一个字符的结束与下一个字符的开始。本章专门讲述异步串口数据。
    在异步模式下串口数据线保持在 mark 状态(逻辑 '1')直到有字符发送,也即串口的空闲态是 mark 态。每个字节起始位在前,字节的每一位紧随其后,一位可选校验位以及一位或者两位停止位。起始位始终是 space 电平(逻辑'0'),通知对方有新串口数据可用。数据可以同时发送和接收,因此称为“异步”。

    可选校验位是数据位的简单累加和,指示数据是否包含奇数或者偶数个 1。偶校验时,如果一个字符中有偶数个 1 那么校验位是 0。奇校验时,如果一个字符中有奇数个 1 那么校验位是 0。除此之外,你还可能听过术语 space 校验,mark 校验以及无校验。Space 校验指示校验位永远是 0,而 mark 校验是指校验位一直为 1。无校验意味着没有校验位存在或被传输。
    剩下的位称作停止位。在字符之间可能会有 1,1.5 或者 2 位停止位并且这些位总为 1。停止位过去用于腾出时间为硬件处理之前的数据,但现在只用于接收字符与硬件设备的同步。异步数据格式通常表达成“8N1”,“7E1”等。

    什么是全双工和半双工


    全双工是指设备可以同时发送和接收数据 - 有两个独立数据通道(一路输入,一路输出)。
    半双工是指设备不能同时发送和接收数据。这通常意味着只有一路可以通讯。这并不代表有任何的 RS-232 信号未被使用,相反,这通常意味着使用的一些非 RS-232 标准的通讯链路不支持全双工操作。

    流控


    在两个串口设备间传输数据时经常有必要进行数据流控。这可能是受到中间串口通信线路、其中一个设备或者其他存储介质的限制。异步数据流控通常使用的有两种方法。
    第一种方法通常称为“软件”流控,使用特殊字符开始(XON or DC1)或者停止(XOFF or DC3)数据流。这些字符定义参见 ASCII 码表。这些码值在传输文本信息时很有用,但不能在未经特殊编程时用于传输其他类型的信息。
    第二种方法称作“硬件”流控,使用 CTS 和 RTS 信号线取代特殊字符。当接收方准备好接收数据时会将 RTS 置为 space 电压以请求对方发送数据,当未准备好时置为 mark 电压,因此发送方会通过检测 CTS 电平状态判断是否可以发送数据。由于硬件流控使用独立的信号集合,因此比软件流控速度要快。

    Break信号


    通常情况下收发数据信号线保持在 mark 电平状态直到传输一个新字节。如果信号拉低至 space 电压一段时间,通常是 1/4 到 1/2 秒,那么就说一个 break 条件满足。 一个 break 信号有时用于复位通讯或者改变通讯硬件的操作模式,如 MODEM。

    同步通信


    不同于异步数据,同步数据以恒定比特流显示。为了读取数据,通讯方必须提供或接收一通用位作为时钟使发送和接收者同步
    尽管有时钟同步,通讯方也必须以某种方式标记数据开始。实现的最常用方法是使用像“串行数据链路控制”(“SDLC”)或者“高速数据链路控制”(“HDLC”)的数据包协议。
    每种协议定义了一定的位序列来表示数据包的开始和结束,也定义了没有数据时的位序列。这些位序列使得通讯方明确数据包的开始。 由于同步协议不使用每字节同步位它们比异步通信有至少25%的性能提升并且在多余两个串口的情形下更适合于远程网络和配置。
    尽管同步通信有速度优势,由于需要额外的软硬件大多数 RS-232 硬件不支持。

    编程指南的其他章节内容我先前翻译过,但是由于内容和部分知识点较为陈旧,因此我用其他整录的博客系列 -《Linux 串口编程》中进行详细讲解,感兴趣的可以移步至:


    展开全文
  • Posix串口编程

    2011-11-29 09:22:52
    串口时嵌入式开发过程中比较简单,也是最容易出现问题的地方,掌握串口编程对嵌入式开发绝对有好处。
  • posix串口编程,我在学习QNX操作系统时找的,对于学习遵循POSIX的操作系统(QNX,LINUX等)很有帮助,论坛里有英文版的,我找到了一个中文翻译版,和英文版一并发出,祝大家看完之后能有所收获。
  • 简介posix 操作系统串口编程指南将教你如何在您的UNIX ®工作站或PC机成功,高效, 便携的编写串口程序。每章提供的编程示例使用的POSIX (可移植的UNIX标准)终端控制功能,并只要经过极少数的修改就可以运行在IRIX...

    简介

    posix 操作系统串口编程指南将教你如何在您的UNIX ®工作站或PC机成功,高效, 便携的编写串口程序。每章提供的编程示例使用的POSIX (可移植的UNIX标准)终端控制功能,并只要经过极少数的修改就可以运行在IRIX ® , HP - UX, SunOS ® ,以及Solaris ® ,Digital UNIX ® , Linux® ,和大多数其他的类UNIX操作系统。操作系统的最大的不同是用于串口设备和锁定的文件的文件名。

    这个指南有下面几章和附录组成

    第一章 串口编程基础

    第二章 配置串口

    第三章 调制解调器通信

    第四章 高级串口编程

    附录A RS-232引脚

    附录B ASCII控制流

    ----------------------------------------------------------------------

    第一章 串口编程基础

    本章介绍串口通信,RS232和用语大多数计算机的其他标准以及如何用c程序访问串行口。

    什么是串口通信?

    计算机可以每次传送1bit或者nbit信息(数据),串口指每次只传送1bit数据。串口通信包括多种网络设备:键盘,鼠标,猫,和终端。

    当用串口传送一个字(即字符或字节)数据,你接收和发送时每次传送一个bit.每个bit是1或者0.

    串口的数据传输速率大都是以bit/s(bps)或者波特率(baud)表示1和0在每秒内传输的个数。回到计算机开始的时代,300baud被认为是很快的,但现今电脑应用RS232速率可以达到43800baud(波特)。当波特率超过1000,你将经常看见速率为千boud,或者kbps(例如9.6k,19.2k等).当速度在1,000,000以上表示为megabaud或者Mbps(例如1.5Mbps)。

    当谈到串口设备和端口,他们被称为数据通信设备(DCE)或者数据终端设备(DTE)。他们之间的区别很简单-每对传输信号和接收,是交换。当两个DTE或者两个DCE设备连接在一起,一个无猫串口电缆或者适配器被用作交换信号对。

    什么是 RS-232?

    RS-232是电气工业组织(EIA)制定的为串口通信的电气化接口标准。RS-232实际上分三个等级(A,B,C),他们每个有不同的高低电压标准。填充应用最广泛的是RS-232C,他定义逻辑1的电压在-3V到-12V,逻辑0的电压在+3V到+12V。RS-232规格上讲这些信号在25英尺后就无法使用。你通常可以通过降低波特率将数据传得更远。

    除了电缆进出数据,还有其他时间,状态,握手:

    表1 - RS-232 引脚 管脚 描述

    1 地

    2 TXD-传输数据

    3 RXD-接收数据

    4 RTS-要求发送

    5 CTS-清除待发

    6 DSR-数据设置完成

    7 GND-逻辑地

    8 DCD-数据载波检测

    9 预留

    10 预留

    11 未分配

    12 备用DCD

    13 备用CTS

    14 备用 TXD

    15 传输时钟

    16 备用 RXD

    17 接收时钟

    18 未分配

    19 备用 RTS

    20 DTR-数据终端准备

    21 信号质量检查

    22 环路检查

    23 数据速率选择

    24 发送时钟

    25 未分配

    有两种接口标准RS-422和RS-422。RS-422用更低的电压和不同信号允许线缆长度上限为1000英尺(300米)。RS-574定义9引脚的串口连接和电压。

    信号定义

    RS-232标准定义串口中18中不同的信号。在这些中仅有6个是在UNIX环境中可用。

    GND - 逻辑地

    逻辑地不是信号,办事没有它却没有办法操作信号。基本上,逻辑地是一个参考电压已让电子管知道那些事正的和负的。

    TXD- 传输数据

    TXD信号载波数据从你的工作站到另一端的计算机或者设备(如猫)。一个高电平表示1,一个空电平表示0.

    RXD- 接收数据

    RXD载波信号将电脑或设备传输到工作站。像TXD,高低电平分别表示1和0.

    DCD-数据载波检测

    DCD信号接收来自电脑或者其他串口电缆。一个低电平在信号线上表示设备和电脑正在连接。DCD通常没有用。

    DTR- 数据终端准备

    DTR信号是工作站产生兵告诉计算机或者另一端的设备你正在准备(空电平)或者没有准备(高电平)。DTR能够自动运行当你打开在工作站上的串口。

    CTS- 清除发送

    CTS信号从其他串口电缆接收数据。

    空电平表示已经准备从工作站发送串口数据。CTS通常用来控制从工作站到终端的串行数据流。

    RTS- 请求发送

    TRS信号设置低电平被工作站用来表示更多的数据准备发送。

    像CTS,RTS辅助控制从工作站到计算机和另一端的串口设备的数据流。大部分工作站始终设置这种信号为低电平。

    异步通信

    对于计算机要知道什么时候串行数据传送进来,他需要一些方法决定从那个字符开始从哪里结束和下一个起始点。本指南专门处理异步串行数据。

    在异步模式下串口数据线保持高电平直到出现一个字符被传送。一个开始位之前每个字符和后边紧跟的位的字符性质,一个奇偶校验位,和一个或者多个停止位。开始位通常是一个空电平然后告诉电脑新的串行数据有用。数据然后被发送或者任何时间接收,因此称为异步。

    Figure 1 - Asynchronous Data Transmission

     

    奇偶校验位是这个数据位的和表示这些数据包含一个偶数或奇数个1。偶校验,奇偶校验位是0如果在字符里1的数目里是偶数0;奇校验,奇偶校验位是0如果数据中1的数目是1.你也许听过低电平校验,高电平校验,无奇偶校验。低校验是指奇偶校验位是全0,高校验指得是这些位全为1。无校验是指无校验位表示或者传输。 剩余的位被称为停止位。

    在连个字符间可以为1,1.5,或者2停止bits并且他们的值为1.停止位以前被用来给计算机时间处理前边的字符,但是现在只是为异步解释计算机接收字符服务。

    异步数据格式通常表示为"8N1", "7E1",和往前。这些分别代表“8位数据位,无奇偶校验,1bit停止位”和“7位数据位,偶校验,1bit停止位”。

    什么是全双工和半单工?

    全双工是指计算机能够同时接收和传输数据-有两个单独的数据信道(一进一出)。

    半双工是指计算机不能同时接收和传输数据。通常这意味着只有单一的信道通信。但是并不是所有的RS232信号都不使用。然而,他通常指得是通信链接用其他标准而不是RS232,RS232并不支持全双工操作。

    流控

    当在俩个串口间传输数据控制数据流是必须的。这是因为限制中间串口通信连接,一个是串口,或者另外一些是存储媒体。两种方法是常用的异步通信数据。

    第一个方法是通常被称为“软件”流控和应用专用字符开始(XON or DC1, 021 octal)或者停止(XOFF or DC3, 023 octal)数据流。这些字符定义在美国交换信息标准编码(ASCII).虽然这些代码传输文本信息很有用,但是他们在没有特殊程序转换的时候不能使用。

    第二种方法被称为“硬件”控制流,应用RS-232CTS和RTS信号代替特殊字符。接受者当它准备接受更多数据的时候设置CTS为低电压,同样的,还没有准备传输别的数据的时候,传送者设置RTS为低电平。因为硬件流控用一组分离的信号,他比软流控更快,同样需要发送和接收多位信心做同样的事情。CTS/RTS流控并非被所有的硬件和操作系统支持。

    什么是中断?

    通常一个接收或者传输数据信号保持在高电平知道一个新的字符传输。如果信号下降到低电平很长时间,常常是1/4,1/2秒,然后可以说产生中断。

    一个中断有时候用来重启一个通信线路或者改变操作系统的通信模式例如猫。第三章,调制解调器涵盖这些更加高级的应用。

    同步通信

    不像异步通信,同步通信表现为一个恒定的数据流。读取线上的数据,电脑必须提供或者接收一个同步时钟以至发送和接收同步。

    甚至这样的同步,电脑必须用某种方法标记开始数据。最常见的做法是用一个数据协议包例如串行数据链路控制(SDLC)或者高速数据链路控制(HDLC).

    每个协议定义确定的位序列来表示数据包的开始和结束。每个协议也定义一个bit序列,用在没有数据的时候;这些序列允许电脑开始查看开始的数据包。

    因为同步协议没有用每个字符同步位,他们通常提供至少25%的改进比异步通信,并且更加适合远程网络和配置更多的串行口。

    尽管同步通信的高速率优点,但是大多数RS-232硬件并不支持,因为还需要额外的硬件和软件。

    接入串行口

    像所有的设备一样,UNIX提供接入串口的设备文件。要接入串口只需有打开这些相应的设备文件。 串口文件 每个串口在UNIX系统上有一个或多个设备文件(文件在 /dev 目录)与它有关:

    表 2 - 串口和设备文件

    system                                     port1             prot2

    IRIX®                                   /dev/ttyf1       /dev/ttyf2

    HP-UX                                 /dev/tty1p0       /dev/tty2p0

    Solaris®/SunOS®                /dev/ttya           /dev/ttyb

    Linux®                                /dev/ttyS0          /dev/ttyS1

    Digital UNIX®                        /dev/tty01           /dev/tty02

    打开一个串口

    因为一个串口是一个文件,所以open()函数被用来接入它。一个问题是UNIX设备文件普通用户通常不能接入。工作区包括接口的权限到文件的问题,运行你的程序作为超级用户(root),或者设置程序的用户名以让普通用户也能运行设备文件。

    现在我们假设文件已经可以让所有用户使用。这个代码打开串口1工作区在IRIX操作系统上:

    Listing 1 - 打开串口

    #include /* 标准输入/输出定义 */

    #include /* 串函数定义 */

    #include /* UNIX 标准函数定义*/

    #include /* 文件控制定义 */

    #include /* 错误数定义 */

    #include /* POSIX 终端控制定义 */

    /* * 'open_port()' - 打开串口 1. * * 返回文件描述成功或者 -1表示错误。 */

    int open_port(void) {

            int fd;   /* 文件描述端口定义*/

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

            if (fd == -1){

                    /* * 不能打开端口。 */

                  perror("open_port: Unable to open /dev/ttyf1 - ");

            }

            else

                  fcntl(fd, F_SETFL, 0);

          return (fd);

    }

    其他的操作系统将需要相应的设备文件名,但是其他的代码是一样的。

    开放操作

    你将发现当你打开设备文件,我们通常使用两个标记除了read+write模式:

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

    O_NOCTTY标志告诉UNIX这个程序不想成为“控制终端”控制的端口,如果你不能明确说明这个,那么任何输入(像键盘中断信号等)将会影响你的程序。程序例如getty(1M/8)应用这个特征当开始登陆程序,但是通常一个用户程序不希望这个问题。

    O_NDELAY标志告诉UNIX这个程序不关心DCD信号线状态-是否其他的端口是否运行。如果不指定这个标号,你的程序将会在DCD信号线是低电平时停止。

    写数据到端口

    写入数据到端口很简单-只要应用write() 系统回叫发送数据给它:

                n = write(fd, "ATZ/r", 4);

                 if (n < 0)

                           fputs("write() of 4 bytes failed!/n", stderr);

    write函数返回位的数值或者当错误时为-1。通常这个错误只有当一个调制解调器或者数据连接丢数据载波检测行时,你将运行到EIO 。这个情况将会维持直到你释放端口。

    读端口数据

    读端口数据有点麻烦。当你操作这个端口在原始数据模式,每个read()系统回叫将返回串口输入缓存实际提供的无论多少字符。如果没有字符可用,回叫将会阻塞(等待)直到字符进入,一个间隔计时器失效,或者错误发送。read函数将会立即返回通过下面这样做:

                   fcntl(fd, F_SETFL, FNDELAY);

    FNDELAY选项使read函数返回0,当没有字符在端口上。存储正常(阻塞)动作,没有FNDELAY选项则回叫fcntl():

                    fcntl(fd, F_SETFL, 0);

    这个同样应用在操作 O_NDELAY选项打开串口。

    关闭串口

    关闭串口,使用close系统调用:

                   close(fd);

    关闭一个串口将会也设置DTR信号低电平,这会把调制解调挂起。

    ---------------------------------------------------------------------------------------第一章完(待续)

    第二章 配置串口

    这章讨论如何配置串口从C用POSIX终端接口。

    POSIX终端接口

    大多数系统支持POSIX终端(串)接口改变参数例如波特率,字符大小,等。首先你需要做的是包含头文件 <termios.h>; 这个文件定义终端控制结构和POSIX控制函数。

    最重要的POSIX函数是tcgetattr(3) 和 tcsetattr(3),这两个分别表示获取和设置终端属性。你提供一个指针到包含可用的所有串口选项控制台结构:

    表3-控制台结构成员

    Member       Description
    c_cflag        控制选项
    c_lflag          现行选项
    c_iflag          输入选项
    c_oflag        输出选项
    c_cc            控制字符

    c_ispeed      输入波特率 (new interface)
    c_ospeed 输出波特率(new interface)

    控制选项

    c_cflag成员控制波特率,一些数据位,奇偶校验,停止位和硬件控制流。有常数为所有的支持配置。

    Table 4 - c_cflag 成员常数描述

    常数         描述
    CBAUD Bit mask for baud rate
    B0            0 baud (drop DTR)
    B50          50 baud
    B75         75 baud
    B110       110 baud
    B134       134.5 baud
    B150        150 baud
    B200        200 baud
    B300       300 baud
    B600        600 baud
    B1200    1200 baud
    B1800     1800 baud
    B2400     2400 baud
    B4800     4800 baud
    B9600      9600 baud
    B19200 19200 baud
    B38400     38400 baud
    B57600    57,600 baud
    B76800    76,800 baud
    B115200 115,200 baud
    EXTA        External rate clock
    EXTB         External rate clock
    CSIZE        Bit mask for data bits
    CS5           5       data bits
    CS6            6 data bits
    CS7           7 data bits
    CS8             8 data bits
    CSTOPB     2 stop bits (1 otherwise)
    CREAD         Enable receiver
    PARENB       Enable parity bit
    PARODD    Use odd parity instead of even
    HUPCL        Hangup (drop DTR) on last close
    CLOCAL      Local line - do not change "owner" of port
    LOBLK        Block job control output
    CNEW_ RTSCTS
    CRTSCTS       Enable hardware flow control (not supported on all platforms)

    c_cflag成员包含两个选项应该常常应用,CLOCAL和CREAD.这将确保你的程序不被其他端口控制和挂起信号干扰,同时串口接口驱动将读取进入的数据。

    波特率常量 (CBAUD, B9600, etc.) 是用来为更老的接口,他们没有c_ispeed和c_ospeed 成员。参考下一节关于POSIX函数信息来设置波特率。

    没有直接初始化 c_cflag (或者其他flag)成员;你应该常常使用逐位与,或,非操作来设置或者清空成员位。不同的操作系统版本(和甚至补丁)应用各不相同,因此用位操作将会防止你使用错误的位标志,这些位标志需要更新一个串口驱动。

    设置波特率

    不同的操作系统波特率保存在不同的地方。老的接口依靠表4中的波特率常数存储波特率c_cflag成员,然而更新的应用提供c_ispeed和c_ospeed 成员,他们包含实际的波特率数值。

    cfsetospeed(3) 和cfsetispeed(3)函数不论在何种操作系统接口提供设置到控制台的波特率。典型的你最好应用下边的代码设置波特率:

    Listing 2 - 设置波特率
    struct termios options;

    /*
    * 得到现在端口的选项。。。。。。
    */

    tcgetattr(fd, &options);

    /*
    *设置波特率为19200。。。。

    */

    cfsetispeed(&options, B19200);
    cfsetospeed(&options, B19200);

    /*
    * 启动接收者和设置本地模式。。。。。。
    */

    options.c_cflag |= (CLOCAL | CREAD);

    /*
    * 设置新的端口选项。。。。。。。
    */

    tcsetattr(fd, TCSANOW, &options);

    tcgetattr(3) 函数装满你提供的串口配置到控制台。然后我们设置波特率和让本地模式运行和串口数据接收,我们用tcsetattr(3).选择新的配置。TCSANOW 常量规定所以的改变应该立即执行而不等待数据传送和接收结束。有其他的常量来等待输入和输出完成或者刷新输入输出缓存。

    大多数系统不支持不同的输入输出速率,所以要保证设置相同的值保证最大的可移植性。
    Table 5 - Constants for tcsetattr

    Constant                    Description
    TCSANOW               Make changes now without waiting for data to complete
    TCSADRAIN              Wait until everything has been transmitted
    TCSAFLUSH             Flush input and output buffers and make the change

    设置字符大小

    不像波特率,没有方便的函数来设置字符大小。你必须做一个小的位掩码设置。字符的尺寸在位中指定:

    options.c_cflag &= ~CSIZE;     /* 字符大小的位掩码*/
    options.c_cflag |= CS8;             /* 选中8位数据位*/

    设置奇偶校验

    Like the character size you must manually set the parity enable and parity type bits. UNIX serial drivers support even, odd, and no parity bit generation. Space parity can be simulated with clever coding.

    像字节大小一样你必须手动设置奇偶校验使能和校验类型。UNIX串口驱动支持奇数,偶数,和无校验位系列。空校验能用代码仿真。
    无校验(8N1):
    options.c_cflag &= ~PARENB
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    奇校验(7E1):
    options.c_cflag |= PARENB
    options.c_cflag &= ~PARODD
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    偶校验(7O1):
    options.c_cflag |= PARENB
    options.c_cflag |= PARODD
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    空校验设置和无校验相同(7S1):

    options.c_cflag &= ~PARENB
    options.c_cflag &= ~CSTOPB
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    设置硬件流控

    某些版本的UNIX支持使用CTS和RTS信号线的硬件流控。如果 CNEW_RTSCTS or CRTSCTS 常数被系统定义然后然后硬件流控才能被支持。按照下边能让硬件流控:
    options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */

    同样, 停止硬件流控l:
    options.c_cflag &= ~CNEW_RTSCTS;

    本地选项

    本地选项成员c——cflag控制串口驱动管理如何输入字符。通常你能配置c_lflag 成员对标准或者原始输入。

    展开全文
  • 这一章介绍怎样使用C语言的POSIX终端接口配置串口。   POSIX终端接口 多数系统支持使用POSIX终端接口改变波特率、字符数等参数。首先要包含头文件;这样就定义了终端控制结构和POSIX控制函数。 两...

    第二章:配置串口

    这一章介绍怎样使用C语言的POSIX终端接口配置串口。

     

    POSIX终端接口

    多数系统支持使用POSIX终端接口改变波特率、字符数等参数。首先要包含头文件<termios.h>;这样就定义了终端控制结构和POSIX控制函数。

    两个最重要的POSIX函数是tcgetattr(3)tcsetattr(3),用了获取和设置终端属性。你可以设置一个指向termios结构的指针,这个结构包含了所有可用的串口选项:

    Table 3 - Termios Structure Members

    Member

    Description

    c_cflag

    Control options

    c_lflag

    Line options

    c_iflag

    Input options

    c_oflag

    Output options

    c_cc

    Control characters

    c_ispeed

    Input baud (new interface)

    c_ospeed

    Output baud (new interface)

    控制选项

    c_cflag用来控制波特率、数据位、奇偶位、停止位和硬件流控制。下面是所有支持的配置的常量:

    Table 4 - Constants for the c_cflag Member

    Constant

    Description

    CBAUD

    Bit mask for baud rate

    B0

    0 baud (drop DTR)

    B50

    50 baud

    B75

    75 baud

    B110

    110 baud

    B134

    134.5 baud

    B150

    150 baud

    B200

    200 baud

    B300

    300 baud

    B600

    600 baud

    B1200

    1200 baud

    B1800

    1800 baud

    B2400

    2400 baud

    B4800

    4800 baud

    B9600

    9600 baud

    B19200

    19200 baud

    B38400

    38400 baud

    B57600

    57,600 baud

    B76800

    76,800 baud

    B115200

    115,200 baud

    EXTA

    External rate clock

    EXTB

    External rate clock

    CSIZE

    Bit mask for data bits

    CS5

    5 data bits

    CS6

    6 data bits

    CS7

    7 data bits

    CS8

    8 data bits

    CSTOPB

    2 stop bits (1 otherwise)

    CREAD

    Enable receiver

    PARENB

    Enable parity bit

    PARODD

    Use odd parity instead of even

    HUPCL

    Hangup (drop DTR) on last close

    CLOCAL

    Local line - do not change "owner" of port

    LOBLK

    Block job control output

    CNEW_RTSCTS 

    CRTSCTS

    Enable hardware flow control (not supported on all platforms)

    c_cflag有两个选项需要一直使能,CLOCAL:忽略所有调制解调器的状态信号;CREAD:启用字符接收器。

    波特率常数(CBAUDB9600,etc.)用于缺少c_ispeedc_ospeed 成员的旧接口。下一节介绍用于设置波特率的POSIX函数。

    注:决不能直接初始化c_cflag(或其他flag)。应该使用ANDORNOT等位操作符来置1或清0成员中的位。不同的操作系统版本的位操作可能不同,使用位操作符可以避免错误操作一个新串行设备所需要的标志位。

     

     

    1)设置波特率

    不同的操作系统中,波特率储存的位置也不同。旧的接口将波特率按照Table4中的常量保存c_cflag中。新的实现方法提供了c_ispeed c_ospeed 来保存实际的波特率值。

    cfsetospeed(3)cfsetispeed(3)函数用来设置termios结构中的波特率,从而屏蔽了底层的操作系统。你可以使用下面的代码设置波特率:

    Listing 2 - Setting the baud rate.

    struct termios options;

     

    /*

     * Get the current options for the port...

     */

     

    tcgetattr(fd, &options);

     

    /*

     * Set the baud rates to 19200...

     */

     

    cfsetispeed(&options, B19200);

    cfsetospeed(&options, B19200);

     

    /*

     * Enable the receiver and set local mode...

     */

     

    options.c_cflag |= (CLOCAL | CREAD);

     

    /*

     * Set the new options for the port...

     */

     

    tcsetattr(fd, TCSANOW, &options);

     

    tcgetattr(3)函数使用你提供的串口配置参数填充termios结构。设置了波特率、使能本地模式和串行数据接收后,使用tcsetattr3)使新的配置生效。常量TCSANOW指定了新的设置立即生效,不需要等待数据接收或发生结束。还有其他常量,可以等待输入或输出数据结束,或清空缓冲区。

    多数操作系统不支持不同的输入和输出速率,为了最好的可移植性,请确保相同的输入和输出速率。

    Table 5 - Constants for tcsetattr

    Constant

    Description

    TCSANOW

    Make changes now without waiting for data to complete

    TCSADRAIN

    Wait until everything has been transmitted

    TCSAFLUSH

    Flush input and output buffers and make the change

     

     

    2)设置字符大小

    与波特率设置不同,没有方便的函数用来设置字符大小,所有必须用位掩码。字符大小用位数指定。

    options.c_cflag &= ~CSIZE; /* Mask the character size bits */

    options.c_cflag |= CS8;    /* Select 8 data bits */

     

    3)设置奇偶校验

    类似设置字符大小,你必须手动设置使能奇偶校验和奇偶校验位数。UNIX的串口设备支持奇、偶和无校验。

    No parity (8N1):

    options.c_cflag &= ~PARENB

    options.c_cflag &= ~CSTOPB

    options.c_cflag &= ~CSIZE;

    options.c_cflag |= CS8;

     

    Even parity (7E1):

    options.c_cflag |= PARENB

    options.c_cflag &= ~PARODD

    options.c_cflag &= ~CSTOPB

    options.c_cflag &= ~CSIZE;

    options.c_cflag |= CS7;

     

    Odd parity (7O1):

    options.c_cflag |= PARENB

    options.c_cflag |= PARODD

    options.c_cflag &= ~CSTOPB

    options.c_cflag &= ~CSIZE;

    options.c_cflag |= CS7;

     

    Space parity is setup the same as no parity (7S1):

    options.c_cflag &= ~PARENB

    options.c_cflag &= ~CSTOPB

    options.c_cflag &= ~CSIZE;

    options.c_cflag |= CS8;

     

     

    4)硬件流控制

    有些UNIX版本支持使用CTS (Clear To Send)RTS (Request To Send)信号来控制硬件流。如果你的系统定义了CNEW_RTSCTSCRTSCTS常量 ,那就很可能支持硬件流控制。使用下面的代码可以使能硬件流控制:

    options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */

    关闭硬件流控制:

    options.c_cflag &= ~CNEW_RTSCTS;

     

    本地选项

    本地模式成员c_lflag用于控制串行设备如何管理输入字符。通常可以将c_lflag配置为canonicalraw 

    Table 6 - Constants for the c_lflag Member

    ISIG

    Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals

    ICANON

    Enable canonical input (else raw)

    XCASE

    Map uppercase /lowercase (obsolete)

    ECHO

    Enable echoing of input characters

    ECHOE

    Echo erase character as BS-SP-BS

    ECHOK

    Echo NL after kill character

    ECHONL

    Echo NL

    NOFLSH

    Disable flushing of input buffers after interrupt or quit characters

    IEXTEN

    Enable extended functions

    ECHOCTL

    Echo control characters as ^char and delete as ~?

    ECHOPRT

    Echo erased character as character erased

    ECHOKE

    BS-SP-BS entire line on line kill

    FLUSHO

    Output being flushed

    PENDIN

    Retype pending input at next read or input char

    TOSTOP

    Send SIGTTOU for background output

    选择Canonical Input

    Canonical Input是以行进行操作的。输入的字符被放在一个可以由用户进行交互编辑的缓冲区,知道收到回车(CR)或换行(LF)字符。选择这个模式的话,你需要选择ICANONECHOECHOE选项:

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

    选择Raw Input

    Raw input 是不做任何处理的。输入字符被收到后就直接传送。你需要取消ICANONECHOECHOEISIG选项来选择Raw Input模式:

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

    关于输入回显的说明

    决不能在发生命令给一个MODOM或电脑时使能输入回显,那样的话会在两个串口之间形成一个回环。

    输入选项

    输入模式成员变量c_iflag用于控制串口接收端的字符的处理过程。与c_cflag一样,c_iflag的值也是将需要的选项通过OR运算得到的。

    Table 7 - Constants for the c_iflag Member

    Constant

    Description

    INPCK

    Enable parity check

    IGNPAR

    Ignore parity errors

    PARMRK

    Mark parity errors

    ISTRIP

    Strip parity bits

    IXON

    Enable software flow control (outgoing)

    IXOFF

    Enable software flow control (incoming)

    IXANY

    Allow any character to start flow again

    IGNBRK

    Ignore break condition

    BRKINT

    Send a SIGINT when a break condition is detected

    INLCR

    Map NL to CR

    IGNCR

    Ignore CR

    ICRNL

    Map CR to NL

    IUCLC

    Map uppercase to lowercase

    IMAXBEL

    Echo BEL on input line too long

    设置输入奇偶校验选项

    如果已经在c_cflag中使能了奇偶校验,那你可以使能输入奇偶校验。与输入奇偶校验相关的常量是INPCK, IGNPAR, PARMRKISTRIP。通常你需要选择INPCK和ISTRIP来使能输入奇偶校验并去掉数据中的校验位:

    options.c_iflag |= (INPCK | ISTRIP);

    IGNPAR是一个危险的选项,它告诉串口忽略校验错误并让数据通过,就想没用发生错误一样。这在测试通信连接的质量时有用,通常没有实用价值。

    PARMRK会使校验错误被标记为“marked",并使用特殊的字符放入输入流中。如果使能IGNPAR,一个空字符(000 octal)会被加入到校验错误的前面。否则,DEL177 octal)和NUL字符会和错误字符一起发生。

    设置软件流控制

    使用IXONIXOFfIXANY常量来使能软件流控制:

    options.c_iflag |= (IXON | IXOFF | IXANY);

    取消软件流控制只需掩掉这些位:

    options.c_iflag &= (IXON | IXOFF | IXANY);

    XON(开始数据)和XOFF(停止数据)字符定义在下面描述的c_cc数组中。

    输出选项

    C_oflag成员包含了输出过滤选项。像输入模式一样,你可以选择processedraw数据输出。

    Table 8 - Constants for the c_oflag Member

    Constant

    Description

    OPOST

    Postprocess output (not set = raw output)

    OLCUC

    Map lowercase to uppercase

    ONLCR

    Map NL to CR-NL

    OCRNL

    Map CR to NL

    NOCR

    No CR output at column 0

    ONLRET

    NL performs CR function

    OFILL

    Use fill characters for delay

    OFDEL

    Fill character is DEL

    NLDLY

    Mask for delay time needed between lines

    NL0

    No delay for NLs

    NL1

    Delay further output after newline for 100 milliseconds

    CRDLY

    Mask for delay time needed to return carriage to left column

    CR0

    No delay for CRs

    CR1

    Delay after CRs depending on current column position

    CR2

    Delay 100 milliseconds after sending CRs

    CR3

    Delay 150 milliseconds after sending CRs

    TABDLY

    Mask for delay time needed after TABs

    TAB0

    No delay for TABs

    TAB1

    Delay after TABs depending on current column position

    TAB2

    Delay 100 milliseconds after sending TABs

    TAB3

    Expand TAB characters to spaces

    BSDLY

    Mask for delay time needed after BSs

    BS0

    No delay for BSs

    BS1

    Delay 50 milliseconds after sending BSs

    VTDLY

    Mask for delay time needed after VTs

    VT0

    No delay for VTs

    VT1

    Delay 2 seconds after sending VTs

    FFDLY

    Mask for delay time needed after FFs

    FF0

    No delay for FFs

    FF1

    Delay 2 seconds after sending FFs

    选择Processed输出

    通过设置c_oflag中的OPOST选项来选择Processed输出:

    options.c_oflag |= OPOST;

    在所有的选项中,你大概只需要用ONLCR选项将换行符映射到CR-LF上。

    选择Raw输出

    c_oflag中重新设置OPOST选项就选择了Raw输出:

    Options.c_oflag &= ~OPOST;

    取消OPOST选项时,c_oflag中的其他选项都将被忽略。

    控制字符

    c_cc字符数组包含控制字符的定义和超时参数。数组的元素都定义了常量。

    Table 9 - Control Characters in the c_cc Member

    Constant

    Description

    Key

    VINTR

    Interrupt

    CTRL-C

    VQUIT

    Quit

    CTRL-Z

    VERASE

    Erase

    Backspace (BS)

    VKILL

    Kill-line

    CTRL-U

    VEOF

    End-of-file

    CTRL-D

    VEOL

    End-of-line

    Carriage return (CR)

    VEOL2

    Second end-of-line

    Line feed (LF)

    VMIN

    Minimum number of characters to read

    VTIME

    Time to wait for data (tenths of seconds)

    展开全文
  • POSIX下的串口编程

    2009-07-02 17:40:00
    Serial Programming Guide for POSIX Operating Systems5th EditionMichael R. SweetCopyright 1994-1999, All Rights Reserved.IntroductionThe Serial Programming Guide for P

    5th Edition
    Michael R. Sweet
    Copyright 1994-1999, All Rights Reserved.


    Introduction

    The Serial Programming Guide for POSIX Operating Systems will teach you how to successfully, efficiently, and portably program the serial ports on your UNIX® workstation or PC. Each chapter provides programming examples that use the POSIX (Portable Standard for UNIX) terminal control functions and should work with very few modifications under IRIX®, HP-UX, SunOS®, Solaris®, Digital UNIX®, Linux®, and most other UNIX operating systems. The biggest difference between operating systems that you will find is the filenames used for serial port device and lock files.

    This guide is organized into the following chapters and appendices:


    Chapter 1, Basics of Serial Communications

    This chapter introduces serial communications, RS-232 and other standards that are used on most computers as well as how to access a serial port from a C program.

    What Are Serial Communications?

    Computers transfer information (data) one or more bits at a time. Serial refers to the transfer of data one bit at a time. Serial communications include most network devices, keyboards, mice, MODEMs, and terminals.

    When doing serial communications each word (i.e. byte or character) of data you send or receive is sent one bit at a time. Each bit is either on or off. The terms you'll hear sometimes are mark for the on state and space for the off state.

    The speed of the serial data is most often expressed as bits-per-second ("bps") or baudot rate ("baud"). This just represents the number of ones and zeroes that can be sent in one second. Back at the dawn of the computer age, 300 baud was considered fast, but today computers can handle RS-232 speeds as high as 430,800 baud! When the baud rate exceeds 1,000, you'll usually see the rate shown in kilo baud, or kbps (e.g. 9.6k, 19.2k, etc). For rates above 1,000,000 that rate is shown in megabaud, or Mbps (e.g. 1.5Mbps).

    When referring to serial devices or ports, they are either labeled as Data Communications Equipment ("DCE") or Data Terminal Equipment ("DTE"). The difference between these is simple - every signal pair, like transmit and receive, is swapped. When connecting two DTE or two DCE interfaces together, a serial null-MODEM cable or adapter is used that swaps the signal pairs.

    What Is RS-232?

    RS-232 is a standard electrical interface for serial communications defined by the Electronic Industries Association ("EIA"). RS-232 actually comes in 3 different flavors (A, B, and C) with each one defining a different voltage range for the on and off levels. The most commonly used variety is RS-232C, which defines a mark (on) bit as a voltage between -3V and -12V and a space (off) bit as a voltage between +3V and +12V. The RS-232C specification says these signals can go about 25 feet (8m) before they become unusable. You can usually send signals a bit farther than this as long as the baud is low enough.

    Besides wires for incoming and outgoing data, there are others that provide timing, status, and handshaking:

    Table 1 - RS-232 Pin Assignments
    PinDescriptionPinDescriptionPinDescriptionPinDescriptionPinDescription
    1Earth Ground6DSR - Data Set Ready11Unassigned16Secondary RXD21Signal Quality Detect
    2TXD - Transmitted Data7GND - Logic Ground12Secondary DCD17Receiver Clock22Ring Detect
    3RXD - Received Data8DCD - Data Carrier Detect13Secondary CTS18Unassigned23Data Rate Select
    4RTS - Request To Send9Reserved14Secondary TXD19Secondary RTS24Transmit Clock
    5CTS - Clear To Send10Reserved15Transmit Clock20DTR - Data Terminal Ready25Unassigned

    Two standards for serial interfaces you may also see are RS-422 and RS-574. RS-422 uses lower voltages and differential signals to allow cable lengths up to about 1000ft (300m). RS-574 defines the 9-pin PC serial connector and voltages.

    Signal Definitions

    The RS-232 standard defines some 18 different signals for serial communications. Of these, only six are generally available in the UNIX environment.

    GND - Logic Ground

    Technically the logic ground is not a signal, but without it none of the other signals will operate. Basically, the logic ground acts as a reference voltage so that the electronics know which voltages are positive or negative.

    TXD - Transmitted Data

    The TXD signal carries data transmitted from your workstation to the computer or device on the other end (like a MODEM). A mark voltage is interpreted as a value of 1, while a space voltage is interpreted as a value of 0.

    RXD - Received Data

    The RXD signal carries data transmitted from the computer or device on the other end to your workstation. Like TXD, mark and space voltages are interpreted as 1 and 0, respectively.

    DCD - Data Carrier Detect

    The DCD signal is received from the computer or device on the other end of your serial cable. A space voltage on this signal line indicates that the computer or device is currently connected or on line. DCD is not always used or available.

    DTR - Data Terminal Ready

    The DTR signal is generated by your workstation and tells the computer or device on the other end that you are ready (a space voltage) or not-ready (a mark voltage). DTR is usually enabled automatically whenever you open the serial interface on the workstation.

    CTS - Clear To Send

    The CTS signal is received from the other end of the serial cable. A space voltage indicates that is alright to send more serial data from your workstation.

    CTS is usually used to regulate the flow of serial data from your workstation to the other end.

    RTS - Request To Send

    The RTS signal is set to the space voltage by your workstation to indicate that more data is ready to be sent.

    Like CTS, RTS helps to regulate the flow of data between your workstation and the computer or device on the other end of the serial cable. Most workstations leave this signal set to the space voltage all the time.

    Asynchronous Communications

    For the computer to understand the serial data coming into it, it needs some way to determine where one character ends and the next begins. This guide deals exclusively with asynchronous serial data.

    In asynchronous mode the serial data line stays in the mark (1) state until a character is transmitted. A start bit preceeds each character and is followed immediately by each bit in the character, an optional parity bit, and one or more stop bits. The start bit is always a space (0) and tells the computer that new serial data is available. Data can be sent or received at any time, thus the name asynchronous.

    Figure 1 - Asynchronous Data Transmission

    The optional parity bit is a simple sum of the data bits indicating whether or not the data contains an even or odd number of 1 bits. With even parity, the parity bit is 0 if there is an even number of 1's in the character. With odd parity, the parity bit is 0 if there is an odd number of 1's in the data. You may also hear the terms space parity, mark parity, and no parity. Space parity means that the parity bit is always 0, while mark parity means the bit is always 1. No parity means that no parity bit is present or transmitted.

    The remaining bits are called stop bits. There can be 1, 1.5, or 2 stop bits between characters and they always have a value of 1. Stop bits traditionally were used to give the computer time to process the previous character, but now only serve to synchronize the receiving computer to the incoming characters.

    Asynchronous data formats are usually expressed as "8N1", "7E1", and so forth. These stand for "8 data bits, no parity, 1 stop bit" and "7 data bits, even parity, 1 stop bit" respectively.

    What Are Full Duplex and Half Duplex?

    Full duplex means that the computer can send and receive data simultaneously - there are two separate data channels (one coming in, one going out).

    Half duplex means that the computer cannot send or receive data at the same time. Usually this means there is only a single data channel to talk over. This does not mean that any of the RS-232 signals are not used. Rather, it usually means that the communications link uses some standard other than RS-232 that does not support full duplex operation.

    Flow Control

    It is often necessary to regulate the flow of data when transferring data between two serial interfaces. This can be due to limitations in an intermediate serial communications link, one of the serial interfaces, or some storage media. Two methods are commonly used for asynchronous data.

    The first method is often called "software" flow control and uses special characters to start (XON or DC1, 021 octal) or stop (XOFF or DC3, 023 octal) the flow of data. These characters are defined in the American Standard Code for Information Interchange ("ASCII"). While these codes are useful when transferring textual information, they cannot be used when transferring other types of information without special programming.

    The second method is called "hardware" flow control and uses the RS-232 CTS and RTS signals instead of special characters. The receiver sets CTS to the space voltage when it is ready to receive more data and to the mark voltage when it is not ready. Likewise, the sender sets RTS to the space voltage when it is ready to send more data. Because hardware flow control uses a separate set of signals, it is much faster than software flow control which needs to send or receive multiple bits of information to do the same thing. CTS/RTS flow control is not supported by all hardware or operating systems.

    What Is a Break?

    Normally a receive or transmit data signal stays at the mark voltage until a new character is transferred. If the signal is dropped to the space voltage for a long period of time, usually 1/4 to 1/2 second, then a break condition is said to exist.

    A break is sometimes used to reset a communications line or change the operating mode of communications hardware like a MODEM. Chapter 3, Talking to MODEMs covers these applications in more depth.

    Synchronous Communications

    Unlike asynchronous data, synchronous data appears as a constant stream of bits. To read the data on the line, the computer must provide or receive a common bit clock so that both the sender and receiver are synchronized.

    Even with this synchronization, the computer must mark the beginning of the data somehow. The most common way of doing this is to use a data packet protocol like Serial Data Link Control ("SDLC") or High-Speed Data Link Control ("HDLC").

    Each protocol defines certain bit sequences to represent the beginning and end of a data packet. Each also defines a bit sequence that is used when there is no data. These bit sequences allow the computer see the beginning of a data packet.

    Because synchronous protocols do not use per-character synchronization bits they typically provide at least a 25% improvement in performance over asynchronous communications and are suitable for remote networking and configurations with more than two serial interfaces.

    Despite the speed advantages of synchronous communications, most RS-232 hardware does not support it due to the extra hardware and software required.

    Accessing Serial Ports

    Like all devices, UNIX provides access to serial ports via device files. To access a serial port you simply open the corresponding device file.

    Serial Port Files

    Each serial port on a UNIX system has one or more device files (files in the /dev directory) associated with it:

    Table 2 - Serial Port Device Files
    SystemPort 1Port 2
    IRIX®/dev/ttyf1/dev/ttyf2
    HP-UX/dev/tty1p0/dev/tty2p0
    Solaris®/SunOS®/dev/ttya/dev/ttyb
    Linux®/dev/ttyS0/dev/ttyS1
    Digital UNIX®/dev/tty01/dev/tty02

    Opening a Serial Port

    Since a serial port is a file, the open(2) function is used to access it. The one hitch with UNIX is that device files are usually not accessable by normal users. Workarounds include changing the access permissions to the file(s) in question, running your program as the super-user (root), or making your program set-userid so that it runs as the owner of the device file.

    For now we'll assume that the file is accessable by all users. The code to open serial port 1 on an sgi® workstation running IRIX is:

    • Listing 1 - Opening a serial port.

      #include <stdio.h>   /* Standard input/output definitions */
      #include <string.h> /* String function definitions */
      #include <unistd.h> /* UNIX standard function definitions */
      #include <fcntl.h> /* File control definitions */
      #include <errno.h> /* Error number definitions */
      #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; /* File descriptor for the port */


      fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
      if (fd == -1)
      {
      /*
      * Could not open the port.
      */

      perror("open_port: Unable to open /dev/ttyf1 - ");
      }
      else
      fcntl(fd, F_SETFL, 0);

      return (fd);
      }

    Other systems would require the corresponding device file name, but otherwise the code is the same.

    Open Options

    You'll notice that when we opened the device file we used two other flags along with the read+write mode:

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

    The O_NOCTTY flag tells UNIX that this program doesn't want to be the "controlling terminal" for that port. If you don't specify this then any input (such as keyboard abort signals and so forth) will affect your process. Programs like getty(1M/8) use this feature when starting the login process, but normally a user program does not want this behavior.

    The O_NDELAY flag tells UNIX that this program doesn't care what state the DCD signal line is in - whether the other end of the port is up and running. If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.

    Writing Data to the Port

    Writing data to the port is easy - just use the write(2) system call to send data it:

    • n = write(fd, "ATZ/r", 4);
      if (n < 0)
      fputs("write() of 4 bytes failed!/n", stderr);

    The write function returns the number of bytes sent or -1 if an error occurred. Usually the only error you'll run into is EIO when a MODEM or data link drops the Data Carrier Detect (DCD) line. This condition will persist until you close the port.

    Reading Data from the Port

    Reading data from a port is a little trickier. When you operate the port in raw data mode, each read(2) system call will return however many characters are actually available in the serial input buffers. If no characters are available, the call will block (wait) until characters come in, an interval timer expires, or an error occurs. The read function can be made to return immediately by doing the following:

    • fcntl(fd, F_SETFL, FNDELAY);

    The FNDELAY option causes the read function to return 0 if no characters are available on the port. To restore normal (blocking) behavior, call fcntl() without the FNDELAY option:

    • fcntl(fd, F_SETFL, 0);

    This is also used after opening a serial port with the O_NDELAY option.

    Closing a Serial Port

    To close the serial port, just use the close system call:

    • close(fd);

    Closing a serial port will also usually set the DTR signal low which causes most MODEMs to hang up.


    Chapter 2, Configuring the Serial Port

    This chapter discusses how to configure a serial port from C using the POSIX termios interface.

    The POSIX Terminal Interface

    Most systems support the POSIX terminal (serial) interface for changing parameters such as baud rate, character size, and so on. The first thing you need to do is include the file <termios.h>; this defines the terminal control structure as well as the POSIX control functions.

    The two most important POSIX functions are tcgetattr(3) and tcsetattr(3). These get and set terminal attributes, respectively; you provide a pointer to a termios structure that contains all of the serial options available:

    Table 3 - Termios Structure Members
    MemberDescription
    c_cflagControl options
    c_lflagLine options
    c_iflagInput options
    c_oflagOutput options
    c_ccControl characters
    c_ispeedInput baud (new interface)
    c_ospeedOutput baud (new interface)

    Control Options

    The c_cflag member controls the baud rate, number of data bits, parity, stop bits, and hardware flow control. There are constants for all of the supported configurations.
    Table 4 - Constants for the c_cflag Member
    ConstantDescription
    CBAUDBit mask for baud rate
    B00 baud (drop DTR)
    B5050 baud
    B7575 baud
    B110110 baud
    B134134.5 baud
    B150150 baud
    B200200 baud
    B300300 baud
    B600600 baud
    B12001200 baud
    B18001800 baud
    B24002400 baud
    B48004800 baud
    B96009600 baud
    B1920019200 baud
    B3840038400 baud
    B5760057,600 baud
    B7680076,800 baud
    B115200115,200 baud
    EXTAExternal rate clock
    EXTBExternal rate clock
    CSIZEBit mask for data bits
    CS55 data bits
    CS66 data bits
    CS77 data bits
    CS88 data bits
    CSTOPB2 stop bits (1 otherwise)
    CREADEnable receiver
    PARENBEnable parity bit
    PARODDUse odd parity instead of even
    HUPCLHangup (drop DTR) on last close
    CLOCALLocal line - do not change "owner" of port
    LOBLKBlock job control output
    CNEW_RTSCTS
    CRTSCTS
    Enable hardware flow control (not supported on all platforms)

    The c_cflag member contains two options that should always be enabled, CLOCAL and CREAD. These will ensure that your program does not become the 'owner' of the port subject to sporatic job control and hangup signals, and also that the serial interface driver will read incoming data bytes.

    The baud rate constants (CBAUD, B9600, etc.) are used for older interfaces that lack the c_ispeed and c_ospeed members. See the next section for information on the POSIX functions used to set the baud rate.

    Never initialize the c_cflag (or any other flag) member directly; you should always use the bitwise AND, OR, and NOT operators to set or clear bits in the members. Different operating system versions (and even patches) can and do use the bits differently, so using the bitwise operators will prevent you from clobbering a bit flag that is needed in a newer serial driver.

    Setting the Baud Rate

    The baud rate is stored in different places depending on the operating system. Older interfaces store the baud rate in the c_cflag member using one of the baud rate constants in table 4, while newer implementations provide the c_ispeed and c_ospeed members that contain the actual baud rate value.

    The cfsetospeed(3) and cfsetispeed(3) functions are provided to set the baud rate in the termios structure regardless of the underlying operating system interface. Typically you'd use the following code to set the baud rate:

    • Listing 2 - Setting the baud rate.

      struct termios options;

      /*
      * Get the current options for the port...
      */

      tcgetattr(fd, &options);

      /*
      * Set the baud rates to 19200...
      */

      cfsetispeed(&options, B19200);
      cfsetospeed(&options, B19200);

      /*
      * Enable the receiver and set local mode...
      */

      options.c_cflag |= (CLOCAL | CREAD);

      /*
      * Set the new options for the port...
      */

      tcsetattr(fd, TCSANOW, &options);

    The tcgetattr(3) function fills the termios structure you provide with the current serial port configuration. After we set the baud rates and enable local mode and serial data receipt, we select the new configuration using tcsetattr(3). The TCSANOW constant specifies that all changes should occur immediately without waiting for output data to finish sending or input data to finish receiving. There are other constants to wait for input and output to finish or to flush the input and output buffers.

    Most systems do not support different input and output speeds, so be sure to set both to the same value for maximum portability.

    Table 5 - Constants for tcsetattr
    ConstantDescription
    TCSANOWMake changes now without waiting for data to complete
    TCSADRAINWait until everything has been transmitted
    TCSAFLUSHFlush input and output buffers and make the change

    Setting the Character Size

    Unlike the baud rate, there is no convienience function to set the character size. Instead you must do a little bitmasking to set things up. The character size is specified in bits:

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

    Setting Parity Checking

    Like the character size you must manually set the parity enable and parity type bits. UNIX serial drivers support even, odd, and no parity bit generation. Space parity can be simulated with clever coding.

    • No parity (8N1):
      options.c_cflag &= ~PARENB
      options.c_cflag &= ~CSTOPB
      options.c_cflag &= ~CSIZE;
      options.c_cflag |= CS8;
    • Even parity (7E1):
      options.c_cflag |= PARENB
      options.c_cflag &= ~PARODD
      options.c_cflag &= ~CSTOPB
      options.c_cflag &= ~CSIZE;
      options.c_cflag |= CS7;
    • Odd parity (7O1):
      options.c_cflag |= PARENB
      options.c_cflag |= PARODD
      options.c_cflag &= ~CSTOPB
      options.c_cflag &= ~CSIZE;
      options.c_cflag |= CS7;
    • Space parity is setup the same as no parity (7S1):
      options.c_cflag &= ~PARENB
      options.c_cflag &= ~CSTOPB
      options.c_cflag &= ~CSIZE;
      options.c_cflag |= CS8;

    Setting Hardware Flow Control

    Some versions of UNIX support hardware flow control using the CTS (Clear To Send) and RTS (Request To Send) signal lines. If the CNEW_RTSCTS or CRTSCTS constants are defined on your system then hardware flow control is probably supported. Do the following to enable hardware flow control:

    • options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */

    Similarly, to disable hardware flow control:

    • options.c_cflag &= ~CNEW_RTSCTS;

    Local Options

    The local modes member c_lflag controls how input characters are managed by the serial driver. In general you will configure the c_lflag member for canonical or raw input.

    Table 6 - Constants for the c_lflag Member
    ConstantDescription
    ISIGEnable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals
    ICANONEnable canonical input (else raw)
    XCASEMap uppercase /lowercase (obsolete)
    ECHOEnable echoing of input characters
    ECHOEEcho erase character as BS-SP-BS
    ECHOKEcho NL after kill character
    ECHONLEcho NL
    NOFLSHDisable flushing of input buffers after interrupt or quit characters
    IEXTENEnable extended functions
    ECHOCTLEcho control characters as ^char and delete as ~?
    ECHOPRTEcho erased character as character erased
    ECHOKEBS-SP-BS entire line on line kill
    FLUSHOOutput being flushed
    PENDINRetype pending input at next read or input char
    TOSTOPSend SIGTTOU for background output

    Choosing Canonical Input

    Canonical input is line-oriented. Input characters are put into a buffer which can be edited interactively by the user until a CR (carriage return) or LF (line feed) character is received.

    When selecting this mode you normally select the ICANON, ECHO, and ECHOE options:

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

    Choosing Raw Input

    Raw input is unprocessed. Input characters are passed through exactly as they are received, when they are received. Generally you'll deselect the ICANON, ECHO, ECHOE, and ISIG options when using raw input:

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

    A Note About Input Echo

    Never enable input echo (ECHO, ECHOE) when sending commands to a MODEM or other computer that is echoing characters, as you will generate a feedback loop between the two serial interfaces!

    Input Options

    The input modes member c_iflag controls any input processing that is done to characters received on the port. Like the c_cflag field, the final value stored in c_iflag is the bitwise OR of the desired options.

    Table 7 - Constants for the c_iflag Member
    ConstantDescription
    INPCKEnable parity check
    IGNPARIgnore parity errors
    PARMRKMark parity errors
    ISTRIPStrip parity bits
    IXONEnable software flow control (outgoing)
    IXOFFEnable software flow control (incoming)
    IXANYAllow any character to start flow again
    IGNBRKIgnore break condition
    BRKINTSend a SIGINT when a break condition is detected
    INLCRMap NL to CR
    IGNCRIgnore CR
    ICRNLMap CR to NL
    IUCLCMap uppercase to lowercase
    IMAXBELEcho BEL on input line too long

    Setting Input Parity Options

    You should enable input parity checking when you have enabled parity in the c_cflag member (PARENB). The revelant constants for input parity checking are INPCK, IGNPAR, PARMRK , and ISTRIP. Generally you will select INPCK and ISTRIP to enable checking and stripping of the parity bit:

    • options.c_iflag |= (INPCK | ISTRIP);

    IGNPAR is a somewhat dangerous option that tells the serial driver to ignore parity errors and pass the incoming data through as if no errors had occurred. This can be useful for testing the quality of a communications link, but in general is not used for practical reasons.

    PARMRK causes parity errors to be 'marked' in the input stream using special characters. If IGNPAR is enabled, a NUL character (000 octal) is sent to your program before every character with a parity error. Otherwise, a DEL (177 octal) and NUL character is sent along with the bad character.

    Setting Software Flow Control

    Software flow control is enabled using the IXON, IXOFF , and IXANY constants:

    • options.c_iflag |= (IXON | IXOFF | IXANY);

    To disable software flow control simply mask those bits:

    • options.c_iflag &= ~(IXON | IXOFF | IXANY);

    The XON (start data) and XOFF (stop data) characters are defined in the c_cc array described below.

    Output Options

    The c_oflag member contains output filtering options. Like the input modes, you can select processed or raw data output.

    Table 8 - Constants for the c_oflag Member
    ConstantDescription
    OPOSTPostprocess output (not set = raw output)
    OLCUCMap lowercase to uppercase
    ONLCRMap NL to CR-NL
    OCRNLMap CR to NL
    NOCRNo CR output at column 0
    ONLRETNL performs CR function
    OFILLUse fill characters for delay
    OFDELFill character is DEL
    NLDLYMask for delay time needed between lines
    NL0No delay for NLs
    NL1Delay further output after newline for 100 milliseconds
    CRDLYMask for delay time needed to return carriage to left column
    CR0No delay for CRs
    CR1Delay after CRs depending on current column position
    CR2Delay 100 milliseconds after sending CRs
    CR3Delay 150 milliseconds after sending CRs
    TABDLYMask for delay time needed after TABs
    TAB0No delay for TABs
    TAB1Delay after TABs depending on current column position
    TAB2Delay 100 milliseconds after sending TABs
    TAB3Expand TAB characters to spaces
    BSDLYMask for delay time needed after BSs
    BS0No delay for BSs
    BS1Delay 50 milliseconds after sending BSs
    VTDLYMask for delay time needed after VTs
    VT0No delay for VTs
    VT1Delay 2 seconds after sending VTs
    FFDLYMask for delay time needed after FFs
    FF0No delay for FFs
    FF1Delay 2 seconds after sending FFs

    Choosing Processed Output

    Processed output is selected by setting the OPOST option in the c_oflag member:

    • options.c_oflag |= OPOST;

    Of all the different options, you will only probably use the ONLCR option which maps newlines into CR-LF pairs. The rest of the output options are primarily historic and date back to the time when line printers and terminals could not keep up with the serial data stream!

    Choosing Raw Output

    Raw output is selected by resetting the OPOST option in the c_oflag member:

    • options.c_oflag &= ~OPOST;

    When the OPOST option is disabled, all other option bits in c_oflag are ignored.

    Control Characters

    The c_cc character array contains control character definitions as well as timeout parameters. Constants are defined for every element of this array.

    Table 9 - Control Characters in the c_cc Member
    ConstantDescriptionKey
    VINTRInterruptCTRL-C
    VQUITQuitCTRL-Z
    VERASEEraseBackspace (BS)
    VKILLKill-lineCTRL-U
    VEOFEnd-of-fileCTRL-D
    VEOLEnd-of-lineCarriage return (CR)
    VEOL2Second end-of-lineLine feed (LF)
    VMINMinimum number of characters to read
    VTIMETime to wait for data (tenths of seconds)

    Setting Software Flow Control Characters

    The VSTART and VSTOP elements of the c_cc array contain the characters used for software flow control. Normally they should be set to DC1 (021 octal) and DC3 (023 octal) which represent the ASCII standard XON and XOFF characters.

    Setting Read Timeouts

    UNIX serial interface drivers provide the ability to specify character and packet timeouts. Two elements of the c_cc array are used for timeouts: VMIN and VTIME. Timeouts are ignored in canonical input mode or when the NDELAY option is set on the file via open or fcntl.

    VMIN specifies the minimum number of characters to read. If it is set to 0, then the VTIME value specifies the time to wait for every character read. Note that this does not mean that a read call for N bytes will wait for N characters to come in. Rather, the timeout will apply to the first character and the read call will return the number of characters immediately available (up to the number you request).

    If VMIN is non-zero, VTIME specifies the time to wait for the first character read. If a character is read within the time given, any read will block (wait) until all VMIN characters are read. That is, once the first character is read, the serial interface driver expects to receive an entire packet of characters (VMIN bytes total). If no character is read within the time allowed, then the call to read returns 0. This method allows you to tell the serial driver you need exactly N bytes and any read call will return 0 or N bytes. However, the timeout only applies to the first character read, so if for some reason the driver misses one character inside the N byte packet then the read call could block forever waiting for additional input characters.

    VTIME specifies the amount of time to wait for incoming characters in tenths of seconds. If VTIME is set to 0 (the default), reads will block (wait) indefinitely unless the NDELAY option is set on the port with open or fcntl.


    Chapter 3, MODEM Communications

    This chapter covers the basics of dialup telephone Modulator/Demodulator (MODEM) communications. Examples are provided for MODEMs that use the defacto standard "AT" command set.

    What Is a MODEM?

    MODEMs are devices that modulate serial data into frequencies that can be transferred over an analog data link such as a telephone line or cable TV connection. A standard telephone MODEM converts serial data into tones that can be passed over the phone lines; because of the speed and complexity of the conversion these tones sound more like loud screeching if you listen to them.

    Telephone MODEMs are available today that can transfer data across a telephone line at nearly 53,000 bits per second, or 53kbps. In addition, most MODEMs use data compression technology that can increase the bit rate to well over 100kbps on some types of data.

    Communicating With a MODEM

    The first step in communicating with a MODEM is to open and configure the port for raw input:

    • Listing 3 - Configuring the port for raw input.

      int            fd;
      struct termios options;

      /* open the port */
      fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
      fcntl(fd, F_SETFL, 0);

      /* get the current options */
      tcgetattr(fd, &options);

      /* set raw input, 1 second timeout */
      options.c_cflag |= (CLOCAL | CREAD);
      options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
      options.c_oflag &= ~OPOST;
      options.c_cc[VMIN] = 0;
      options.c_cc[VTIME] = 10;

      /* set the options */
      tcsetattr(fd, TCSANOW, &options);

    Next you need to establish communications with the MODEM. The best way to do this is by sending the "AT" command to the MODEM. This also allows smart MODEMs to detect the baud you are using. When the MODEM is connected correctly and powered on it will respond with the response "OK".

    • Listing 4 - Initializing the MODEM.

      int                  /* O - 0 = MODEM ok, -1 = MODEM bad */
      init_modem(int fd) /* I - Serial port file */
      {
      char buffer[255]; /* Input buffer */
      char *bufptr; /* Current char in buffer */
      int nbytes; /* Number of bytes read */
      int tries; /* Number of tries so far */

      for (tries = 0; tries < 3; tries ++)
      {
      /* send an AT command followed by a CR */
      if (write(fd, "AT/r", 3) < 3)
      continue;

      /* read characters into our string buffer until we get a CR or NL */
      bufptr = buffer;
      while ((nbytes = read(fd, bufptr, buffer + sizeof(buffer) - bufptr - 1)) > 0)
      {
      bufptr += nbytes;
      if (bufptr[-1] == '/n' || bufptr[-1] == '/r')
      break;
      }

      /* nul terminate the string and see if we got an OK response */
      *bufptr = '/0';

      if (strncmp(buffer, "OK", 2) == 0)
      return (0);
      }

      return (-1);
      }

    Standard MODEM Commands

    Most MODEMs support the "AT" command set, so called because each command starts with the "AT" characters. Each command is sent with the "AT" characters starting in the first column followed by the specific command and a carriage return (CR, 015 octal). After processing the command the MODEM will reply with one of several textual messages depending on the command.

    ATD - Dial A Number

    The ATD command dials the specified number. In addition to numbers and dashes you can specify tone ("T") or pulse ("P") dialing, pause for one second (","), and wait for a dialtone ("W"):

    • ATDT 555-1212
      ATDT 18008008008W1234,1,1234
      ATD T555-1212WP1234

    The MODEM will reply with one of the following messages:

    • NO DIALTONE
      BUSY
      NO CARRIER
      CONNECT
      CONNECT baud

    ATH - Hang Up

    The ATH command causes the MODEM to hang up. Since the MODEM must be in "command" mode you probably won't use it during a normal phone call.

    Most MODEMs will also hang up if DTR is dropped; you can do this by setting the baud to 0 for at least 1 second. Dropping DTR also returns the MODEM to command mode.

    After a successful hang up the MODEM will reply with "NO CARRIER". If the MODEM is still connected the "CONNECT" or "CONNECT baud" message will be sent.

    ATZ - Reset MODEM

    The ATZ command resets the MODEM. The MODEM will reply with the string "OK".

    Common MODEM Communication Problems

    First and foremost, don't forget to disable input echoing. Input echoing will cause a feedback loop between the MODEM and computer.

    Second, when sending MODEM commands you must terminate them with a carriage return (CR) and not a newline (NL). The C character constant for CR is "/r".

    Finally, when dealing with a MODEM make sure you use a baud that the MODEM supports. While many MODEMs do auto-baud detection, some have limits (19.2kbps is common) that you must observe.


    Chapter 4, Advanced Serial Programming

    This chapter covers advanced serial programming techniques using the ioctl(2) and select(2) system calls.

    Serial Port IOCTLs

    In Chapter 2, Configuring the Serial Port we used the tcgetattr and tcsetattr functions to configure the serial port. Under UNIX these functions use the ioctl(2) system call to do their magic.

    The ioctl system call takes three arguments:

    • int ioctl(int fd, int request, ...);

    The fd argument specifies the serial port file descriptor. The request argument is a constant defined in the <termios.h> header file and is typically one of the following:

    Table 10 - IOCTL Requests for Serial Ports
    RequestDescriptionPOSIX Function
    TCGETSGets the current serial port settings.tcgetattr
    TCSETSSets the serial port settings immediately.tcsetattr(fd, TCSANOW, &options)
    TCSETSFSets the serial port settings after flushing the input and output buffers.tcsetattr(fd, TCSANOW, &options)
    TCSETSWSets the serial port settings after allowing the input and output buffers to drain/empty.tcsetattr(fd, TCSANOW, &options)
    TCSBRKSends a break for the given time.tcsendbreak, tcdrain
    TCXONCControls software flow control.tcflow
    TCFLSHFlushes the input and/or output queue.tcflush
    TIOCMGETReturns the state of the "MODEM" bits.None
    TIOCMSETSets the state of the "MODEM" bits.None
    FIONREADReturns the number of bytes in the input buffer.None

    Getting the Control Signals

    The TIOCMGET ioctl gets the current "MODEM" status bits, which consist of all of the RS-232 signal lines except RXD and TXD:

    Table 11 - Control Signal Constants
    ConstantDescription
    TIOCM_LEDSR (data set ready/line enable)
    TIOCM_DTRDTR (data terminal ready)
    TIOCM_RTSRTS (request to send)
    TIOCM_STSecondary TXD (transmit)
    TIOCM_SRSecondary RXD (receive)
    TIOCM_CTSCTS (clear to send)
    TIOCM_CARDCD (data carrier detect)
    TIOCM_CDSynonym for TIOCM_CAR
    TIOCM_RNGRNG (ring)
    TIOCM_RISynonym for TIOCM_RNG
    TIOCM_DSRDSR (data set ready)

    To get the status bits, call ioctl with a pointer to an integer to hold the bits:

    • Listing 5 - Getting the MODEM status bits.

      #include <unistd.h>
      #include <termios.h>

      int fd;
      int status;

      ioctl(fd, TIOCMGET, &status);

    Setting the Control Signals

    The TIOCMSET ioctl sets the "MODEM" status bits defined above. To drop the DTR signal you can do:

    • Listing 6 - Dropping DTR with the TIOCMSET ioctl.

      #include <unistd.h>
      #include <termios.h>

      int fd;
      int status;

      ioctl(fd, TIOCMGET, &status);

      status &= ~TIOCM_DTR;

      ioctl(fd, TIOCMSET, status);

    The bits that can be set depend on the operating system, driver, and modes in use. Consult your operating system documentation for more information.

    Getting the Number of Bytes Available

    The FIONREAD ioctl gets the number of bytes in the serial port input buffer. As with TIOCMGET you pass in a pointer to an integer to hold the number of bytes:

    • Listing 7 - Getting the number of bytes in the input buffer.

      #include <unistd.h>
      #include <termios.h>

      int fd;
      int bytes;

      ioctl(fd, FIONREAD, &bytes);

    This can be useful when polling a serial port for data, as your program can determine the number of bytes in the input buffer before attempting a read.

    Selecting Input from a Serial Port

    While simple applications can poll or wait on data coming from the serial port, most applications are not simple and need to handle input from multiple sources.

    UNIX provides this capability through the select(2) system call. This system call allows your program to check for input, output, or error conditions on one or more file descriptors. The file descriptors can point to serial ports, regular files, other devices, pipes, or sockets. You can poll to check for pending input, wait for input indefinitely, or timeout after a specific amount of time, making the select system call extremely flexible.

    Most GUI Toolkits provide an interface to select; we will discuss the X Intrinsics ("Xt") library later in this chapter.

    The SELECT System Call

    The select system call accepts 5 arguments:

    • int select(int max_fd, fd_set *input, fd_set *output, fd_set *error,
      struct timeval *timeout);

    The max_fd argument specifies the highest numbered file descriptor in the input, output, and error sets. The input, output, and error arguments specify sets of file descriptors for pending input, output, or error conditions; specify NULL to disable monitoring for the corresponding condition. These sets are initialized using three macros:

    • FD_ZERO(fd_set);
      FD_SET(fd, fd_set);
      FD_CLR(fd, fd_set);

    The FD_ZERO macro clears the set entirely. The FD_SET and FD_CLR macros add and remove a file descriptor from the set, respectively.

    The timeout argument specifies a timeout value which consists of seconds (timeout.tv_sec) and microseconds (timeout.tv_usec ). To poll one or more file descriptors, set the seconds and microseconds to zero. To wait indefinitely specify NULL for the timeout pointer.

    The select system call returns the number of file descriptors that have a pending condition, or -1 if there was an error.

    Using the SELECT System Call

    Suppose we are reading data from a serial port and a socket. We want to check for input from either file descriptor, but want to notify the user if no data is seen within 10 seconds. To do this we'll need to use the select system call:

    • Listing 8 - Using SELECT to process input from more than one source.

      #include <unistd.h>
      #include <sys/types.h>
      #include <sys/time.h>
      #include <sys/select.h>

      int n;
      int socket;
      int fd;
      int max_fd;
      fd_set input;
      struct timeval timeout;

      /* Initialize the input set */
      FD_ZERO(input);
      FD_SET(fd, input);
      FD_SET(socket, input);

      max_fd = (socket > fd ? socket : fd) + 1;

      /* Initialize the timeout structure */
      timeout.tv_sec = 10;
      timeout.tv_usec = 0;

      /* Do the select */
      n = select(max_fd, NULL, NULL, ;

      /* See if there was an error */
      if (n 0)
      perror("select failed");
      else if (n == 0)
      puts("TIMEOUT");
      else
      {
      /* We have input */
      if (FD_ISSET(fd, input))
      process_fd();
      if (FD_ISSET(socket, input))
      process_socket();
      }

    You'll notice that we first check the return value of the select system call. Values of 0 and -1 yield the appropriate warning and error messages. Values greater than 0 mean that we have data pending on one or more file descriptors.

    To determine which file descriptor(s) have pending input, we use the FD_ISSET macro to test the input set for each file descriptor. If the file descriptor flag is set then the condition exists (input pending in this case) and we need to do something.

    Using SELECT with the X Intrinsics Library

    The X Intrinsics library provides an interface to the select system call via the XtAppAddInput(3x) and XtAppRemoveInput(3x) functions:

    • int XtAppAddInput(XtAppContext context, int fd, int mask,
      XtInputProc proc, XtPointer data);
      void XtAppRemoveInput(XtAppContext context, int input);

    The select system call is used internally to implement timeouts, work procedures, and check for input from the X server. These functions can be used with any Xt-based toolkit including Xaw, Lesstif, and Motif.

    The proc argument to XtAppAddInput specifies the function to call when the selected condition (e.g. input available) exists on the file descriptor. In the previous example you could specify the process_fd or process_socket functions.

    Because Xt limits your access to the select system call, you'll need to implement timeouts through another mechanism, probably via XtAppAddTimeout(3x).


    Appendix A, Pinouts

    This appendix provides pinout information for many of the common serial ports you will find.

    RS-232 Pinouts

    RS-232 comes in three flavors (A, B, C) and uses a 25-pin D-Sub connector:

    Figure 2 - RS-232 Connector

    Table 12 - RS-232 Signals
    PinDescriptionPinDescription
    1Earth Ground14Secondary TXD
    2TXD - Transmitted Data15Transmit Clock
    3RXD - Received Data16Secondary RXD
    4RTS - Request To Send17Receiver Clock
    5CTS - Clear To Send18Unassigned
    6DSR - Data Set Ready19Secondary RTS
    7GND - Logic Ground20DTR - Data Terminal Ready
    8DCD - Data Carrier Detect21Signal Quality Detect
    9Reserved22Ring Detect
    10Reserved23Data Rate Select
    11Unassigned24Transmit Clock
    12Secondary DCD25Unassigned
    13Secondary CTS

    RS-422 Pinouts

    RS-422 also uses a 25-pin D-Sub connector, but with differential signals:

    Figure 3 - RS-422 Connector

    Table 13 - RS-422 Signals
    PinDescriptionPinDescription
    1Earth Ground14TXD+
    2TXD- - Transmitted Data15Transmit Clock-
    3RXD- - Received Data16RXD+
    4RTS- - Request To Send17Receiver Clock-
    5CTS- - Clear To Send18Unassigned
    6DSR - Data Set Ready19RTS+
    7GND - Logic Ground20DTR- - Data Terminal Ready
    8DCD- - Data Carrier Detect21Signal Quality Detect
    9Reserved22Unassigned
    10Reserved23DTR+
    11Unassigned24Transmit Clock+
    12DCD+25Receiver Clock+
    13CTS+

    RS-574 (IBM PC/AT) Pinouts

    The RS-574 interface is used exclusively by PC manufacturers and uses a 9-pin male D-Sub connector:

    Figure 4 - RS-574 Connector

    Table 14 - RS-574 (IBM PC/AT) Signals
    PinDescriptionPinDescription
    1DCD - Data Carrier Detect6Data Set Ready
    2RXD - Received Data7RTS - Request To Send
    3TXD - Transmitted Data8CTS - Clear To Send
    4DTR - Data Terminal Ready9Ring Detect
    5GND - Logic Ground

    SGI Pinouts

    Older SGI equipment uses a 9-pin female D-Sub connector. Unlike RS-574, the SGI pinouts nearly match those of RS-232:

    Figure 5 - SGI 9-Pin Connector

    Table 15 - SGI 9-Pin DSUB Signals
    PinDescriptionPinDescription
    1Earth Ground6DSR - Data Set Ready
    2TXD - Transmitted Data7GND - Logic Ground
    3RXD - Received Data8DCD - Data Carrier Detect
    4RTS - Request To Send9DTR - Data Terminal Ready
    5CTS - Clear To Send

    The SGI Indigo, Indigo2, and Indy workstations use the Apple 8-pin MiniDIN connector for their serial ports:

    Figure 6 - SGI 8-Pin Connector

    Table 16 - SGI 8-Pin MiniDIN Signals
    PinDescriptionPinDescription
    1DTR - Data Terminal Ready5RXD - Received Data
    2CTS - Clear To Send6RTS - Request To Send
    3TXD - Transmitted Data7DCD - Data Carrier Detect
    4GND - Logic Ground8GND - Logic Ground

    Appendix B, ASCII Control Codes

    This chapter lists the ASCII control codes and their names.

    Control Codes

    The following ASCII characters are used for control purposes:
    Table 17 - ASCII Control Codes
    NameBinaryOctalDecimalHexadecimal
    NUL00000000000000
    SOH00000001001101
    STX00000010002202
    ETX00000011003303
    EOT00000100004404
    ENQ00000101005505
    ACK00000110006606
    BEL00000111007707
    BS00001000010808
    HT00001001011909
    NL00001010012100A
    VT00001011013110B
    NP, FF00001100014120C
    CR00001101015130D
    SO00001110016140E
    SI00001111017150F
    DLE000100000201610
    XON, DC1000100010211711
    DC2000100100221812
    XOFF, DC3000100110231913
    DC4000101000242014
    NAK000101010252115
    SYN000101100262216
    ETB000101110272317
    CAN000110000302418
    EM000110010312519
    SUB00011010032261A
    ESC00011011033271B
    FS00011100034281C
    GS00011101035291D
    RS00011110036301E
    US00011111037311F


    正好要学学串口的操作, 找到这篇文章, 感觉很不错。 所以转载了。 Thanks you,  Michael R. Sweet!

     

     原文地址 http://digilander.libero.it/robang/rubrica/serial.htm#CONTENTS
    展开全文
  • 这一章介绍怎样使用C语言的POSIX终端接口配置串口。   POSIX终端接口 多数系统支持使用POSIX终端接口改变波特率、字符数等参数。首先要包含头文件;这样就定义了终端控制结构和POSIX控制函数。 两个最重要的...
  • Posix_QextserialPort 清空串口缓存

    千次阅读 2012-12-05 17:00:11
    网上找的串口通信类。开发过程中调用flush函数不起作用,缓冲区还是不能被清空,导致接收很多以前的数据。 修改如下: [cpp] view plaincopyprint? void Posix_QextserialPort::flush() { LOCK_...
  • 第一章,串行通讯基础这章介绍了串行通讯,RS-232和其它一些在计算机上广泛使用的标准,同时还有如何从C程序访问串口的内容。什么是串行通讯? 计算机一次传输一或多位的信息(数据)。串行是指一次传输一位数据。...
  • POSIX标准总体分析

    千次阅读 2013-09-05 11:26:49
    当前posix 还其它很多标准知识,如:posix socket ,posix 串口等等,以下介绍是,基础的。 仅供参考!!   POSIX标准总体分析  POSIX,全称为可移植性操作系统接口,是一种关于信息技术的IEEE标准。它包括了...
  • POSIX操作系统串口编程(1)

    千次阅读 2005-04-09 22:56:00
    原文为Serial Programming Guide for POSIX ... Sweet,Copyright 1994-1999, All Rights Reserved.)转载本翻译请与作者联系pangdae2005@yahoo.co.ukPOSIX操作系统串口编程介绍POSIX操作系统串口编程将指导您如何在UNIX
  • POSIX操作系统的串口编程指南》将会教你如何成功、高效和可移植的在UNIX环境或PC上对串口进行编程。每一章提供的例程都使用POSIX(Portable Standard for UNIX)终端控制函数,只需极少的修改就可运行在IRIX 、...
  • POSIX thread

    千次阅读 2012-11-20 19:37:05
    POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段。在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程。其中还涉及大量幕后细节,读完本系列文章,您完全可以运用 POSIX 线程创建多...
  • POSIX Threads Programming

    2017-12-06 17:21:33
    POSIX threads
  • <br /> POSIX终端接口 大多数系统都支持POSIX终端接口POSIX终端通过一个termios结构来进行控制,该结构定义在termios.h文件中。 termios结构 struct termios { tcflag_t c_iflag;...
  • Linux下串口编程手册

    2013-12-03 16:00:43
    Serial Programming Guide for POSIX Operating Systems, 详细解释POSIX串口编程.
  • POSIX操作系统的串行编程指南

    千次阅读 2005-11-17 00:28:00
    POSIX操作系统的串行编程指南第五版Michael R.SweetCopyright 1994-1999, Allrights Reserved目录序言第一章 基本的串口通讯 什么是串口通讯 什么是RS-232 信号定义 异步通讯 什么是双工和单工 流量控制 什么是...
  • 网上找的串口通信类。开发过程中调用flush函数不起作用,缓冲区还是不能被清空,导致接收很多以前的数据。 修改如下: void Posix_QextserialPort::flush() { LOCK_MUTEX(); if(isOpen()) { //Posix_File...
  • POSIX多线程

    2015-05-06 13:31:00
     POSIX多线程—概述 POSIX多线程—异步编程举例 POSIX多线程—线程基本概念 POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. 基础概念 2. 线程安全 3. 可重入 4. 并发系统基本功能 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,237
精华内容 3,694
关键字:

posix串口