嵌入式Linux 串口编程系列1——基本知识、termios结构体

    对于嵌入式系统开发而言,串口应用编程几乎是使用最 广泛的,应用案例如下:

(1)串口与 外围设备通信,比如串口作为主设备,访问各种仪表从设备,协议一般有自有协议、Modbus通信协议。

 (2)开发的设备作为从设备,外部设备通过串口进行相关通信,也比如Modbus通信协议及各种其他 私有协议。

 (3)通过串口实现 交互,本质上也是通信,我们使用的shell,最 常见的通信渠道 就是串口。

   可以说, 串口几乎是所有嵌入式设备的必备功能。关于串口的硬件层面的相关规定,可以参考之前的文章

  《串口的一些基本概念--RS485 RS422 RS232 流控制》

  无论在任何的系统环境下开发,串口的配置是必不可少的,包括串口通信参数:波特率、数据位、奇偶校验等,这些都是比较简单的,理解起来也是很容易的,串口配置的难点在于“接收中断”,之所以有这个难点的 原因是在于应用场景,因为所有的应用程序通过串口进行通信,都必然涉及到协议,所谓 协议就是 两个设备之间 对话的 规则,而成功通信的基础就是彼此都遵守通信协议,比如 工业上常用的 Modbus通信协议,主设备A只有发送 符合Modbus通信框架的数据,从设备B才会相应设备A,而从设备B 也需要符合Modbus协议标准,设备A才会认可,进而A、B之间才能成功通信。所以这就带来了一些难点,比如最常见的串口接收数据长度不定,怎么去处理?这个一般是通过固定结束字符、定时器空闲中断、DMA接收中断 等等。

    在非linux下进行 串口配置,大多通过配置相应的 控制寄存器来实现,而接收层面,则是通过上面说的,对各种中断的处理,具体场景 具体分析。

   在Linux下进行串口的配置,主要是通过 对结构体 termios 进行配置,这个就类似于 上面说的 寄存器,只不过Linxu的开发是采用多级分层的,应用 程序员是不用考虑底层CPU的寄存器的,只需要关注 专用 结构体 termios即可。因为应用层下面还有驱动层,只有驱动工程师才需要解除实际的硬件。

termios结构体

    我们通过官方 手册里可以看到, 这个结构体内容如下:

The  header shall define the termios structure, which
       shall include at least the following members:

           tcflag_t  c_iflag     Input modes.   
           tcflag_t  c_oflag     Output modes.  
           tcflag_t  c_cflag     Control modes.
           tcflag_t  c_lflag     Local modes.
           cc_t      c_cc[NCCS]  Control characters.

   其中 tcflag_t 是 unsigned short类型,cc_t 是 unsigned char类型,翻译过来如下:

struct termios
{
    unsigned short c_iflag;  //输入模式
    unsigned short c_oflag;  //输出模式
    unsigned short c_cflag;  //控制模式
    unsigned short c_lflag;  //本地模式
    unsigned char c_cc[NCC]; //控制 字符 数据
}

 1、 c_iflag 输入模式控制

     该参数如要是 实现 串口接收到的数据  传给应用程序 之前,进行先一步的处理,比如将输入中的 NL 翻译为CR,去掉第8位、忽略帧错误和奇偶校验错误,启用输入 奇偶校验检测等。具体宏定义如下:

INPCK                 奇偶校验使能
IGNPAR                忽略奇偶校验错误
PARMRK                奇偶校验错误掩码
ISTRIP                裁剪掉第8比特
IXON                  启动输出软件控制流
IXOF                  启动输入软件控制流
IXANY                 输入任意字符可以重新启动输入(默:起始字符)
IGNBRK                忽略输入终止条件
BRKINT                当检测到输入终止条件时发送SIGINT信号
INLCR                 当收到NL(换行符)转换CR(回车符)
IGNCR                 忽略收到的CR
ICRNL                 当收到CR转换为NL
IUCLC                 讲接收到的大写字符映射为小写字符
IMAXBEL               当输入队列满时响铃

   2、 c_oflag 输出模式控制

      与输入模式控制相对应,负责控制输出单元的处理方式,具体参数宏定义如下:

OPOST                启动输出处理功能,如果不设置,其他位忽略
OLCUC                将输出中的大写字符转换成小写字符
ONLCR                将输出中的换行符(‘\n’)转换成回车符(‘\r’)
ONOCR                如果当前列号为0,则不输出回车字符
OCRNL                将输出中的回车符转换成换行
ONLRET               不输出回车符
OFILL                发送填充字符以提供延时
OFDEL                如果设置该标志,则表示填充字符为DEL字符,否则为NUL
NLDLY                换行延时掩码
CRDLY                回车延时掩码
TABDLY               制表符延时掩码
BSDLY                水平退格符延时掩码
VTDLY                垂直退格符延时掩码
FFLDY                换页符延时掩码

   3、 c_cflag 控制模式标志

     该元素主要是 用于控制终端设备的硬件设备,波特率、数据位等,这也是最需要配置的元素,宏定义如下:

CBAUD                波特率的位掩码
B0                   0波特率(放弃DTR)
…
…
B1800                1800的波特率
B2400                2400的波特率
B4800                4800的波特率
B9600                9600的波特率
B19200               19200的波特率
B38400               38400的波特率
B57600               57600的波特率
B115200              115200的波特率
EXTA                 外部时钟率
EXTB                 外部时钟率
CSIZE                数据位的位掩码
CS5                  5个数据位
CS6                  6个数据位
CS7                  7个数据位
CS8                  8个数据位
CSTOPB               2个停止位(不设置则是一个)
GREAD                接收使能
PARENB               校验使能位
PARODD               使用奇校验而不是偶校验
HUPCL                最后关闭时挂线(放弃DTR)
CLOCAL               本地连接(不改变端口所有者)
CRTSCTS              硬件流控

  4、 c_lflag 本地控制模式

ISIG                若收到信号字符(INTR,QUIT等)则会产生相应的信号
ICANON              启动规范模式
ECHO                启动本地回显功能
ECHOE               若设置ICANON则允许退格操作
ECHOK               若设置ICANON,则KILL字符会删除当前行
ECHONL              若设置ICANON,则允许回显换行符
ECHOCTL             若设置ECHO,则控制字符会显示成^x,其中x的ASCII码等于给相应的控制字符的ASCII码
                    加上0x40.
ECHOPRT             若设置ICANON和IECHO,则删除字符和被删除的字符都会被显示
ECHOKE              若设置ICANON,则允许回显在ECHOE和ECHOPRT中设定的KILL字符
NOFLASH             在通常情况下,当接收到INTR,QUIT,SUSP控制字符时,会清空输入和输出队列。如果
                    设置改标志,则所有的队列不会被清空
TOSTOP              若一个后台进程师徒向他的控制终端进行写操作,则系统向改后台进程的进程组发送SIGTTOU             该信号通常终止进程的执行
IEXTEN              启动输入处理功能

5、c_cc 数组:特殊控制字元可提供使用者设定一些特殊的功能,定义如下:

VINTR            中断控制字符,对应的键位ctrl+c
VQUIT            退出操作符,对应的键为ctrl+z
VERASE           删除操作符,对应Backspace
VKILL            删除行符,对应的键为ctrl+u
VEOF             文件结尾符,对应的键为ctrl+d
VEOL             附加行结尾符,对应的键为carriage return
VEOL2            第二行结尾符,对应的键为line feed
VMIN             指定最少读取的字符数
VTIME            指定读取的每个字符之间的超时时间

    这里面,最常用的是VMIN和VTIME,

   VMIN  指定了 串口至少要读取VMIN个字符,才会不阻塞,也就是 串口接收超过VMIN个字符,read函数才会有返回,

             使用该功能,可以实现 定长 数据的接收。

   VTIME 指定了字符超时,也就是需要等待几百毫秒的值,read才会返回,单位是100ms,

   VMIN和VTIME的组合,可以实现特定接收 处理,关系如下:

VMIN = 0 和 VTIME = 0 :在这种情况下,read 调用总是立刻返回。如果有等待处理的字符,read 就会立
                        刻返回;如果没有字符等待处理,read 调用返回0,并且不读取任何字符;
VMIN = 0 和 VTIME > 0 :在这种情况下,只要有字符可以处理或者是经过 VTIME 个十分之一秒的时间间        
                        隔,read 调用就返回。如果因为超时而未读到任何字符,
                        read 返回0,否则 read 返回读取的字符数目。
VMIN > 0 和 VTIME = 0 :在这种情况下,read 调用将一直等待,直到有 MIN 个字符可以读取时才返回,
                        返回值是读取的字符数量。到达文件尾时返回0。
VMIN > 0 和 VTIME > 0 :在这种情况下,当 read 被调用时,它会等待接收一个字符。在接收到第一个字
                        符及后续的每个字符后,一个字符间隔定时器被启动(如果定时器已经运行,则
                        重启它)。当有 MIN 个字符可读或两个字符之间的时间间隔超过 TIME 个十分
                        之一秒时,read 调用返回。这个功能可用于区分是单独按下了 Escape 键还是
                        按下一个 Escape 键开始的功能组合键。但要注意的是,网络通信或处理器的高
                        负载将使得类似这样的定时器失去作用。

  

你可能感兴趣的:(Linux)