• 串口编程(一) :理论基础


    1. 终端设备

    Linux具备多种终端设备类型:

    • 当前终端
    • 前台控制台终端
    • 串口
    • 虚拟终端
    /dev/tty             /dev/tty        5       0 system:/dev/tty      //当前终端
    /dev/console         /dev/console    5       1 system:console       //前台控制台终端
    /dev/ptmx            /dev/ptmx       5       2 system               //用于创建虚拟终端
    /dev/vc/0            /dev/vc/0       4       0 system:vtmaster
    rfcomm               /dev/rfcomm   216 0-255 serial
    ttyprintk            /dev/ttyprintk   5       3 console
    serial               /dev/ttyS       4 64-111 serial                //物理串口
    pty_slave            /dev/pts      136 0-1048575 pty:slave          //虚拟终端从设备
    pty_master           /dev/ptm      128 0-1048575 pty:master         //虚拟终端主设备
    

    以上这些终端设备统一由TTY(TeleTYpewriter进行管理,从而可以屏蔽硬件的实现。

    1.1 物理串口

    物理串行接口,即 /dev/ttyS[n],(ttyS0为com1,ttyS1为com2),其主、从设备号(主设备号:系统用来确定驱动程序(如USB、硬盘设备);从设备号:驱动程序用来确定具体的设备)如下:

    jimmy@jimmy-vm:~$ cat /sys/class/tty/ttyS0/dev
    4:64
    jimmy@jimmy-vm:~$ ls /dev/ttyS0 -l
    crw-rw---- 1 root dialout 4, 64 3月  31 14:23 /dev/ttyS0
    

    mark

    如果你使用虚拟机开发串口程序,可以采用windows的文件代替串口,然后windows下打开该串口既可以看到串口输出的内容,设置方式如下:
    VM --> Setting :
    mark
    如果没有串口,可关机之后自行添加!

    1.2 控制台终端

    tty1-tty6为控制台终端,即无图形界面的命令行输入模式。一般使用Alt+[F1-F6]可进行终端切换。
    查看tty[1-6]终端的属性如下:
    mark

    1.3 虚拟终端

    现在一般都是通过网络连接Linux服务器,如telnet和SSH;另外,有时候在图形界面下打开一个虚拟终端(如shell口);这两类情况的终端类型皆为虚拟终端

    1.3.1 /dev/ptmx虚拟设备

    该设备用于创建虚拟网络终端设备master/slave配对设备。要打开一个未使用的虚拟终端,通过调用posix_openpt(),来打开设备/dev/ptmx,每次open这个文件,会返回一个独立的master设备文件描述符,通过它可以找到slave设备,且slave设备会在/dev/pts目录下被创建。

    1.3.2 /dev/pts虚拟终端

    通过网络telnet或SSH到linux,将在/dev/pts下依次创建一个虚拟终端;相反,关闭将减少一个。
    mark

    1.4 当前终端

    1.4.1 当前控制终端

    /dev/console代表当前系统前台所使用的实际控制台终端(tty1-tty6).

    1.4.2 当前终端

    /dev/tty,无论是控制终端(tty1-tty6),还是通过SSH连接的虚拟终端,它都代表自己。

    2. 终端属性

    为了控制终端正常的工作,终端的属性一般包含如下:

    • 输入属性:由终端驱动程序控制输入属性
    • 输出属性:由终端驱动程序控制输出属性,如新行映射成CR/NL等
    • 控制属性:影响物理串口的特征,如:停止位、波特率等
    • 本地属性:影响驱动程序与用户之间的界面,如:向终端发送信息是否回显
    • 线路规程属性:用来设置是否为标准的线路规程
    • 控制字符:设置专用字符

    可以使用 stty -a来查看终端所有属性:

    jimmy@jimmy-vm:~$ stty -a
    speed 38400 baud; rows 59; columns 207; line = 0;
    intr = ^C; quit = ^; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
    -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
    -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
    opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
    isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
    

    2.1 设置/获取终端属性

    为了方便统一管理,Linux使用了一个结构体管理这些属性:

    /* /usr/include/asm-generic/termbits.h */
    
    #define NCC 8
    struct termio {
            unsigned short c_iflag;         /* input mode flags */
            unsigned short c_oflag;         /* output mode flags */
            unsigned short c_cflag;         /* control mode flags */
            unsigned short c_lflag;         /* local mode flags */
            unsigned char c_line;           /* line discipline */
            unsigned char c_cc[NCC];        /* control characters */
    };
    
    

    2.1.1 tcgetattr()

    #include <termios.h>
    
    int tcgetattr(int fd, struct termios *termios_p)
    
    参数:
        1. fd: 打开的终端设备的文件描述符
        2. termios_p:存储获取的属性信息
    返回值:
        1. 0    on success
        2. 1    on failure
    

    2.1.2 tcsetattr()

    #include <termios.h>
    
    int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
    
    参数:
        1. fd: 打开的终端设备的文件描述符
        2. optional_actions
            2.1 TCSANOW: 改变立刻生效;
            2.2 TCSADRAIN: 改变在所有写入fd的输出都被传输后生效;
            2.3 TCSAFLUSH: 改变在所有写入fd所指向的对象的输出传输后生效;所有已接收但未读入的消息在改变发生前丢弃;
        3. termios_p:存储设置的属性信息
    返回值:
        1. 0    on success
        2. 1    on failure
    

    2.2 终端属性选项

    2.2.1 c_iflag 输入选项

    mark

    2.2.2 c_oflag 输出选项

    mark

    2.2.3 c_cflag 控制选项

    控制选项设置串行通信的波特率、数据位长度、停止位长度、奇偶校验等。
    mark

    2.2.4 c_lflag 本地选项

    mark
    设置输入字符的方式:

    • 标准模式:回显由客户端完成,用户输入的字符首先缓存到buf中,直到用户输入回车或换行后发送到服务端;用户每输入一个字符,直接本地回显。
    • 原始模式:回显由服务器完成,用户每输入一个字符,立刻发送到服务端,服务端将该字符回显到客户端。

    2.2.5 c_cc 控制字符

    mark

    2.3 设置波特率

    所谓波特率,即单位时间内传输的字符数(Byte/s).
    mark
    串口通信两端的波特率必须设置一致,否则无法通信

    typedef unsigned char   cc_t;
    typedef unsigned int    speed_t;
    typedef unsigned int    tcflag_t;
    
    /*获取输入、输出波特率*/
    speed_t cfgetispeed(const struct termios *termios_p);
    speed_t cfgetospeed(const struct termios *termios_p);
    
    返回值:
        返回输入/出波特率
        
    /*设置输入、输出波特率*/
    int cfsetispeed(struct termios *termios_p, speed_t speed);
    int cfsetospeed(struct termios *termios_p, speed_t speed);
    int cfsetspeed(struct termios *termios_p, speed_t speed);
    
    返回值:
        0:  on success
        1:  on failure
    
    

    2.4 设置帧数据位宽

    可以设置每帧的数据位宽为5-8bit,通信前,双方必须约定好位宽。

    struct termios options; 
    
    options.c_cflag &= ~CSIZE;  //清除现有的数据位宽
    options.c_cflag |= CS8;     //设置数据位宽为8bit
    

    2.5 设置奇偶校验

    奇偶校验为串行通信中简单的差错校验机制;通信前,通信双发约定使用奇校验还是偶校验,多少位的校验位。

    设置为8N1, 即数据位宽8bit,无奇偶校验,1位停止位:

    struct termios options; 
    
    options.c_cflag &= ~PARENB;     //去除奇偶校验
    options.c_cflag &= ~CSTOPB;     //清除停止位
    options.c_cflag &= ~CSIZE;      //清除现有的数据位宽
    options.c_cflag |= CS8;         //设置位宽为8bit
    

    设置为7E1, 即数据位宽7bit,偶(EVEN)校验,1位停止位:

    struct termios options; 
    
    options.c_cflag |= PARENB;      //开启奇偶校验
    ptions.c_cflag &= ~PARODD;       //关闭奇校验
    options.c_cflag &= ~CSTOPB;     //清除停止位
    options.c_cflag &= ~CSIZE;      //清除现有的数据位宽
    options.c_cflag |= CS7;         //设置位宽为8bit
    

    设置为7O1, 即数据位宽7bit,奇(odd)校验,1位停止位:

    struct termios options; 
    
    options.c_cflag |= PARENB;     //开启奇偶校验
    ptions.c_cflag |= PARODD;       //开启奇校验
    options.c_cflag &= ~CSTOPB;     //清除停止位
    options.c_cflag &= ~CSIZE;      //清除现有的数据位宽
    options.c_cflag |= CS7;         //设置位宽为8bit
    

    2.6 数据流控制

    使用何种方式来标记数据传输的开始和结束。

    设置 具体代码
    不使用数据流控制 options.c_cflag &= ~CRTSCTS
    硬件 options.c_cflag
    软件 options.c_cflag
  • 相关阅读:
    安装Hive2及配置HiveSever2
    sqoop语句
    Sqoop配置
    IO流的概述
    List集合的简单使用
    包装类
    访问权限修饰符
    接口
    抽象类
    final关键字
  • 原文地址:https://www.cnblogs.com/Jimmy1988/p/8683050.html
Copyright © 2020-2023  润新知