美文网首页
【转】Linux串口编程

【转】Linux串口编程

作者: RonZheng2010 | 来源:发表于2019-03-02 21:45 被阅读0次

参考资料

嵌入式Linux 串口应用编程
http://www.hqyj.com/news/emb174.htm

1. termios 介绍

termios是在POSIX规范中定义的标准接口,表示终端设备,包括虚拟终端、串口等。串口通过termios进行配置。

struct termios
{
    unsigned short c_iflag;  // 输入模式标志
    unsigned short c_oflag;  // 输出模式标志
    unsigned short c_cflag;  // 控制模式标志
    unsigned short c_lflag;  // 本地模式标志
    unsigned char c_line;    // 线路规程
    unsigned char c_cc[NCC]; // 控制特性
    speed_t c_ispeed;        // 输入速度
    speed_t c_ospeed;        // 输出速度
}
  • 终端有三种工作模式:规范模式(canonical mode)、非规范模式(non-canonical mode)和原始模式(raw mode)。
  • 通过设置 struct termios.c_lflag 的 ICANNON 位,定义终端的工作模式。规范模式则设置ICANNON标志,非规范模式则清除ICANNON标志。前者是默认值。下面的代码设置非规范模式:
tios.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG);

1.1 规范模式

  • 在规范模式下,输入数据基于行进行处理。
    • 在用户输入一个行结束符(回车符、EOF等)之前,系统调用read()读不到用户输入的任何字符。
    • 除了EOF之外的行结束符(回车符等),与普通字符一样会被read()读到缓冲区中。
    • 在规范模式中,可以进行行编辑,而且一次调用read()最多只能读取一行数据。
    • 如果read()请求读取的数据字节少于当前行可读取的字节,则read()只读取被请求的字节数,剩下的字节下次再读。

1.2 非规范模式

非规范模式下,所有的输入即时有效,用户不需要另外输入行结束符,不能进行行编辑。

c_cc[VMIN](这里简称为MIN) 和 c_cc[VTIME](这里简称为TIMEOUT)的值决定read()的工作模式。TIMEOUT的单位是1/10秒。

MIN TIMEOUT 工作模式
=0 =0 read()立即返回。若有数据可读,则读取并返回读取的字节数,否则返回0。
>0 =0 read()被阻塞,直到 MIN 个字节数据可被读取。
=0 >0 若数据可读,或超过TIMEOUT无数据,则read()返回。
>0 >0 若MIN个字节可读,或者超过TIMEOUT无数据,则read()返回。

1.3 原始模式

原始模式是一种特殊的非规范模式。这种模式下,所有输入数据以字节为单位处理。

调用cfmakeraw()函数可将终端设置为原始模式。

2. 串口配置步骤

2.1 保存老配置

使用函数tcgetattr()得到原来的配置。该函数也可以测试该串口是否可用。

struct termios tios;
tcgetattr (fd, &tios);

2.2 设置一般控制选项

CLOCAL和CREAD分别用于本地连接和接收使能。如下代码激活这两个选项。

tios.c_cflag |= CLOCAL | CREAD;

2.3 设置波特率 Baudrate

cfsetispeed()和cfsetospeed()分别设置输入和输出方向的波特率。波特率是一组定义好的常量值。通常两个方向使用同样的值。

cfsetispeed (&tios, B115200); 
cfsetospeed (&tios, B115200); 

2.4 设置字符大小 Character Size

字符大小可以是CS5、CS6、CS7、和CS8。CSIZE是这些值的组合。一般的做法先清除再重新设置。

tios.c_cflag &= ~CSIZE;
tios.c_cflag |= CS8; 

2.5 设置奇偶校验位 Parity

分两步:

  • 设置c_cflag指出是否要进行校验。
  • 设置c_iflag指出输入时是否做校验。

设置奇校验:

tios.c_cflag |= (PARODD | PARENB);
tios.c_iflag |= INPCK; 

设置偶校验:

tios.c_cflag |= PARENB;
tios.c_cflag &= ~PARODD;
tios.c_iflag |= INPCK; 

不校验:

tios.c_cflag &= ~PARENB;
tios.c_iflag &= ~INPCK; 

2.6 设置停止位 Stop Bits

设置c_cflag。

若停止位为两个bit,则激活CSTOPB:

tios.c_cflag |= CSTOPB;  

若停止位为一个bit,则清除CSTOPB:

tios.c_cflag &= ~CSTOPB; 

2.7 设置 MIN 和 TIMEOUT

这个取决于串口数据的特性。低延迟则需要设置一个较小的TIMEOUT;如果延时要求不高则可以设置较大TIMEOUT。MIN的值一般与最小数据包大小接近。

tios.c_cc[VTIME] = 0;
tios.c_cc[VMIN] = 0; 

2.8 清除数据缓冲

在启用新的设置之前,调用tcflush()清空缓存中的残留数据。

int tcflush (int fd, int queue_selector);

queue_selector 可能的取值有以下几种:

  • TCIFLUSH:清空已经接收但未读取的输入数据。
  • TCOFLUSH:清空尚未传送的输出数据。
  • TCIOFLUSH:前两个值的组合。

一般使用TCIOFLUSH:

tcflush (fd, TCIFLUSH);

2.9 激活新配置

使用tcsetattr()激活新配置。

tcsetattr (int fd, int optional_actions, const struct termios *termios_p);

optional_actions指定新配置生效的时机。可能的取值有以下几种:

  • TCSANOW。立即生效。
  • TCSADRAIN。所有输出数据都已传送。
  • TCSAFLUSH。丢弃所有输出数据,所有输出数据已传送。
tcsetattr (fd, TCSANOW, &tios);

3. 示例

如下的例子中,串口工作在非规范模式下工作。

int configSerialPort (int fd, unsigned int baudrate, unsigned int databits, char parity, 
                     unsigned int stopbits, unsigned int flowcntl)
{
    struct termios tis;
    int ret = 0;

    // get old terminos
    ret = tcgetattr (fd, &tis);
    if (ret < 0)
        return ret;
    
    tis.c_cflag |= (CLOCAL | CREAD);

    // baudrate
    cfsetispeed (&tis, baudrate);
    cfsetospeed (&tis, baudrate);

    // databits
    tis.c_cflag &= ~CSIZE;
    switch (databits)
    {
        case 5:  tis.c_cflag |= CS5;  break;
        case 6:  tis.c_cflag |= CS6;  break;        
        case 7:  tis.c_cflag |= CS7;  break;
        case 8:  tis.c_cflag |= CS8;  break;
        default:  return -1;
    }

    // parity
    switch (parity)
    {
        case 'n':
        case 'N':
            tis.c_cflag &= ~PARENB;
            tis.c_iflag &= ~INPCK;
            break;
        case 'o':
        case 'O':
            tis.c_cflag |= (PARODD | PARENB);
            tis.c_iflag |= INPCK;
            break;
        case 'e':
        case 'E':
            tis.c_cflag |= PARENB;
            tis.c_cflag &= ~PARODD;
            tis.c_iflag |= INPCK;
            break;
        default:
            return -1;
    }

    // stopbits
    switch (attr.stopbits)
    {
        case 1:  tis.c_cflag &= ~CSTOPB;  break;
        case 2:  tis.c_cflag |= CSTOPB;   break;
        default:  return -1;
    }

    // flow control
    switch (attr.flowcntl)
    {
        case FLOW_CNTL_NONE:  tis.c_cflag &= ~CRTSCTS;             break;
        case FLOW_CNTL_HW:    tis.c_cflag |= CRTSCTS;              break;
        case FLOW_CNTL_SW:    tis.c_cflag |= IXON | IXOFF | IXANY; break;
        default:            return -1;
    }

    //tis.c_oflag = 0;
    tis.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG);
    tis.c_cc[VTIME] = 0;
    tis.c_cc[VMIN] = 0;

    tcflush (fd, TCIFLUSH);

    ret = tcsetattr (fd, TCSANOW, &tis);
    if (ret < 0)
        return ret;
}

相关文章

  • 【转】Linux串口编程

    参考资料 嵌入式Linux 串口应用编程http://www.hqyj.com/news/emb174.htm 1...

  • 2018-10-09 Mac的Terminal窗口之TTY

    PC上的串口一般是ttyS,板子上Linux的串口一般叫做ttySAC,是usb口转串口的是ttyUSB,外插串口...

  • linux下的串口编程

    本文转自:http://www.cnblogs.com/jason-lu/articles/3173988.htm...

  • 2019-07-11

    串口及串口编程 1、串口编程界面 (2)功能效果实现 2、使用串口调试工具实现数据传输 (1)在下拉列表中列出本机...

  • Linux高级环境编程之6资源_设备文件管理 终端编程

    本课目标 (1) 深入理解Linux设备文件的概念。(2)掌握终端属性控制。(3)掌握串口设备文件编程。(4)掌握...

  • Android USB转串口通信

    一、引用 1、Git上最火的USB转串口通信2、Android之USB转串口通信3、安卓开发中的USB转串口通讯 ...

  • QT串口编程 - QSerialPort类

    QT串口编程 - QSerialPort类 提供对串口的访问 头文件:#include qmake: QT += ...

  • 3月5日的面试题.md

    [TOC] 驱动模块类 串口驱动 Linux把每个串行端口都看做是一个字符设备串口初始化 、打开串口、串口写操作、...

  • 串口编程

    串口连接界面 主要控件 打开串口 自动获取串口列表并显示 初始化串口 写入卡片 插入打卡记录并显示打卡成功

  • 2019-11-02 Linux下USB-串口的使用

    在实验室配置一台设备要用到串口,但串口线只连到了linux服务器上,又不想跑一趟实验室,就直接用linux串口连吧...

网友评论

      本文标题:【转】Linux串口编程

      本文链接:https://www.haomeiwen.com/subject/pprduqtx.html