zoukankan      html  css  js  c++  java
  • 11、串口编程

    1、串口的介绍1a65764b-de40-4fad-bcad-2d648e6b8930

        串口的介绍,

    串口发送的顺序;

    1.空闲位:这里是连续的 1

    2.起始位:低电平

    3.数据位:对于传输的数据位这里是自己去设定传输位数,可以5、6、7、8位,但是我们一般设置为  8位

    串口的数据是从低位开始发送

    4.奇偶校验位:保证传输数据位中的 1 的个数是奇数还是偶数。奇校验;保证数据位中的‘1’是奇数个,当数据位中的‘1’是奇数个的时候,那么校验位填零;当数据位中的‘1’是偶数个的时候,则校验位填为‘1’。

    5.停止位:低电平。持续时间为一个或者 1.5 个字符的时间。

     

     

    2、硬件引脚的认识

    bc473254-68c1-4aaa-b08d-5889536cd4a0

     

    3、Linux 下端口 /dev/ttyn、/dev/pts/n、/dev/ttySn:

      终端的查看,是借用了 tty 命令去查看。

    /dev/ttyn : 终端,一般就是我们在 ubuntu 里面终端的时候,就是 ttyn

        /dev/pts/n : 虚拟终端 ,比如当我们使用 secureCRT 连接 ubuntu 的时候,这个时候 secureCRT 的终端。

        /dev/ttySn: 使用串口登录串行端口终端,也就是设备通过串口端连接终端,ttyS0、ttyS1,分别对应了 COM1 和 COM 2

     

    4、串口的基本知识

    4.1、串口传输模式

        串口传输的模式,可以分为两种,标准输入模式(规范模式)和非标准输入模式(非规范模式)

    标准输入模式:

        这种模式是终端设备标准的处理模式。通信中,是以行为单位进行传输,行的结束是以 enter 为结束符。read 的时候,会将一行的数据,完整地进行输入,一行的结束默认是 enter (ASCII 是  LF,既换行 ,回车是 cr,)。在标准输入模式下,字符被输入终端之后,还可以进行清除,删除,重写,换行等操作,所以,根据自己的实际需求,写好字符之后,按下 enter 作为作为一行输入的结束。

    非标准输入模式:

        这种模式一般是用于需要每次读取固定字符的情况下(比如一个字符),并允许使用,字符接收时间的定时器。也就是说,可以在每次读取固定长度字符串的程序中,或者连接的设备会突然发送大量的字符内容的情况下。

    4.2、流控

        流控,可以分为硬件流控和软件流控。流控实现的是,当接收端不能接收串口数据的时候,通知数据的发送端,使其不再发送数据的这么一种机制。软件流控,实现的方法是通过一些特殊的字符进行定义,X0N(DC1,八进制的话是,021) 和 结束,X0FF(DC3,八进制是,023),来开始和结束数据流的进行。开始和结束的这个特殊的字符,是被定义在 ASCII 。所以,当传输的信息是文本信息的时候,软件流控是非常的好用的。但是,流控是不被建议运用在传输二进制文件。

        硬件流控,是通过硬件特定的管脚,发送电平实现的。

    4.3、ASCII

    CR---------od(十六进制)------回车------- (C语言)

    NL(LF)-----oa(new line、line feed)-----换行---- (C语言)

    5、串口的操作

    5.1、文件的打开

    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);
    }

    O_NOCTTY  : 告诉系统,当前的程序上不受终端的控制,所以就不会受到  ctrl+ c 的影响。

    NDELAY : 和 NONBLOCK 类似。NDELAY 不会受到 DCD 信号的影响。非阻塞

    5.2、串口读

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

    5.3、串口的写

        相比于串口读,串口写的操作,还是存在一点的技巧的。当 read 一个以 原始模式的传输数据串口的时候,read 的返回值,是串口实际接收字符的个数。当没有 read 到字符的时候,read 操作会编程阻塞模式,直到字符的到来,或者错误的发生。所以,为了 read 的时候,读取不到字符的时候,立即马上返回,可以进行下面的操作:

        fcntl( fd,  F_SETFL,  FNDELAY)

    FNDELAY 会导致,当串口没有字符被读取到的时候,立即返回 零。如果需要设置阻塞模式的话:

        fcntl( fd,  F_SETFL,  0);

    5.4、关闭

        close( fd )

    6、接口

    struct termios {

    tcflag_t c_iflag; /* input mode flags */ 输入模式标志

    tcflag_t c_oflag; /* output mode flags */输出模式标志

    tcflag_t c_cflag; /* control mode flags */控制模式标志

    tcflag_t c_lflag; /* local mode flags */本地模式标志

    cc_t c_line; /* line discipline */

    cc_t c_cc[NCCS]; /* control characters */ 控制字符

    };、

    6.1、control flag

        控制模式,主要是对,波特率,传输的数据位,校验位、停止位、和流控进行设置。对于控制标志的设置,是通过下面的常量(宏)进行配置。

    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    // 8 bit 数据位
    CSTOPB               2 stop bits (1 otherwise)   // 2 个停止位
    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      // CNEW_RTSCTS 和CRTSCTS    使能硬件流控           
    CRTSCTS              Enable hardware flow control (notsupported on all platforms)

        CLOCAL  和 CREAD 这两个选项,应该被选中。而对标志的设置,永远也不要对这些标志做初始化的操作,而应该是使用与、或 的操作,达到清零或者置一的操作。

    6.1.1、波特率的设置

        tcgetattr(fd, &options);

        struct termios options;

        options.c_cflag |= (CLOCAL | CREAD);

        tcgetattr(fd, &option);

        cfsetispeed(fd, B115200);

        tcsetattr(fd, TCSANOW, &options);

        tcgetattr 函数,实现获取当前串口的配置信息。当完成新的配置之后,就需要将这些信息进行激活。,就使用tcsetattr。

       

        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

        TCSANOW   标志,表明所做的更改设置,会立即生效,不会等待数据发送或者接收完毕,

    6.1.2、设置字符大小

        传输字符大小的设置,没有函数接收可以使用,而是通过 宏代码 实现。

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

        实现传输字符的设置,一定先要进行 options.c_cflag &= ~CSIZE 之后,才可以进行位数的设置。

    6.1.3、校验位和停止位的设置

         校验位可以设置为,无校验、奇校验、偶校验,三种。

    • No parity (8N1):  // 8bitdata 无校验,1个停止位
        options.c_cflag &= ~PARENB   // 关闭校验
        options.c_cflag &= ~CSTOPB   // 一个停止位
        options.c_cflag &= ~CSIZE;   // 8个数据位
        options.c_cflag |= CS8;
    • Even parity (7E1):   // 7个 数据位,偶校验,一个停止位
        options.c_cflag |= PARENB   // 校验使能
        options.c_cflag &= ~PARODD   // 偶校验
        options.c_cflag &= ~CSTOPB  // 一个停止位
        options.c_cflag &= ~CSIZE;  // 7个数据位
        options.c_cflag |= CS7;
    • Odd parity (7O1):
        options.c_cflag |= PARENB    // 校验使能
        options.c_cflag |= PARODD  // 奇校验
        options.c_cflag &= ~CSTOPB  // 一个停止位

        options.c_cflag |= CS7;

        停止位的设定是通过 CSTOPB 实现的。如停止位为 1 ,则清除 CSTOPB。如停止位为 2,则激活 CSTOPB。

    6.1.4、硬件流控的设置

         一些 Linux 系统是支持硬件流控的。如果 CNEW_RTSCTS 和 CRTSCTS 在自己的系统中,是被定义的话,就可以借助他们来实现硬件流控的开启:

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

    当然,也可以进行关闭:

        options.c_cflag &= ~CNEW_RTSCTS

    6.2、local flag

        本地模式,c_lflag 用于控制串口输入的字符,比如终端输入的字符是否支持回显。通常上,需要对 c_lflag 设置,实现,规范模式,或者原始模式。

    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

       

       如果终端的模式,设置为规范模式(标准输入),那么需要设置 ICANNO ECHO ECHOE选项。

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

        如果终端是原始模式(非标准输入),那么就需要进行不选中ICANNO ECHO ECHOE,同时添加 ISIG 选项。

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

    注意:

        当传输的命令是传送给 MODEN 的时候,或者传送的命令是发送给已经开启了回显的 B 电脑的时候,发送端 A ,绝对不要打开回显功能(不要打开 ECHO 和 ECHOE ),因为会在两个串口之间生成回环的反馈。

       

    6.3、输入模式

        输入模式的,c_iflag ,对串口接收的 字符 进行的操作。

    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 isdetected
    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

    6.3.1、设置输入校验

        如果在 c_cflag 中使能了 PARENB,也就是使能了校验位,那么就需要在输入模式,使能校验检测。

    一般是:

         options.c_iflag |= (INPCK | ISTRIP);

    6.3.2、软件流控

        软件流控的实现是,需要 IXON, IXOFF, and IXANY 常量

    打开软件流控:

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

    关闭:

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

        IXON 和 IXOFF 是被定义在 c_cc 数组当中。

    6.4、输出模式

        设置 c_oflag 控制的是当串口完成数据的接收,并且完成输入模式操作之后,如果将数据进行数据。数据的输出,可以进行操作,或者直接以原始的模式进行输出。

    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

    6.4.1、 输出的字符,如果进行操作的话,需要对 OPOST 进行设置:

        options.c_oflag |= OPOST;

    6.4.2、如果选择为原始数据输出的话:

        options.c_oflag &= ~OPOST;

        当 OPOST 被关闭之后,那么对于 c_oflag  所有的设置将会被忽略。

    6.5、字符控制

         在 c_cc 数组中,实现了对定时器等一些操作,下面是配置信息:

    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)

    6.5.1、设置软件流控的字符

         当使用了软件流控的时候,需要对,c_cc[VSTART] 和 c_cc[VSTOP] 进行设置,他们应该被设置为 DC1 和 DC3,DC1 和  DC3 在 SCII 中,代表了  XON 和 XOFF。

    6.5.2、定时和字符个数的设置

    MIN > 0, TIME = 0 : 读取函数在读到了 MIN 值的字符数后返回。
    MIN = 0, TIME > 0 : TIME 决定了超时值,读取函数在读到一个字节的字符,或者等待读
    取时间超过 TIME (t = TIME * 0.1s)以后返回,也就是说,即使没有从串口中读到数
    据,读取函数也会在 TIME 时间后返回。
    MIN > 0, TIME > 0 : 读取函数会在收到了 MIN 字节的数据后,或者超过 TIME 时间没收
    到数据后返回。此计时器会在每次收到字符的时候重新计时,也只会在收到第一个字节后才
    启动。
    MIN = 0, TIME = 0 : 读取函数会立即返回。实际读取到的字符数,或者要读到的字符
    数,会作为返回值返回。根据 Antonino(参考 conditions), 可以使用 fcntl(fd, F_SETFL, 
    FNDELAY), 在读取前获得同样的结果。

    7、串口的操作介

    (1)头文件

    #include<stdio.h>

    #include<unistd.h>

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<termios.h>

    #include<errno.h>

     

    常用串口设置函数:
    (1)属性的获取与设置
      int tcgetattr(int fd, struct termios *termios_p);   
            获取属性存放在 struct termios  里面,而 fd 是打开串口的的文件描述符。
     int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); 设置属性(termios结构) // 激活自己的配置
     
     cfgetispeed 得到输入速度
     Cfgetospeed 得到输出速度
     
     Cfsetispeed 设置输入速度
     Cfsetospeed 设置输出速度

     
     Tcdrain  等待所有输出都被传输

     
     tcflow  挂起传输或接收
     tcflush  刷清未决输入和/或输出

     
     Tcsendbreak 送BREAK字符
     tcgetpgrp 得到前台进程组ID
     tcsetpgrp 设置前台进程组ID

     
     

    8、串口流程


    (1)保存原先串口的配置

    struct termios newtio,oldtio;

    tcgetattr(fd, &oldtio);

        获取原先串口的配置。

     

    (2)激活本地连接和接收使能

        这一步,是用于本地进行接收的。

     
    newtio.c_cflag |= CLOCAL | CREAD;
     

    (3)设置波特率

     
    cfsetispeed(&Opt,B19200);     /*设置为19200Bps*/
    cfsetospeed(&Opt,B19200);     // 设置输出的波特率为 19200
        波特率的设置,都是 BXXXXX
     

    (4)设置数据位的位数

    newtio.c_cflag &= ~CSIZE;
    newtio.c_cflag |= CS8;  // 设置数据位为 8 位
     

    (5)设置奇偶校验

     
    设置奇校验
    newtio.c_cflag |= PARENB;
    newtio.c_cflag |= PARODD;
    newtio.c_iflag |= (INPCK | ISTRIP);
    设置偶校验:
    newtio.c_iflag |= (INPCK|ISTRIP);
    newtio.c_cflag |= PARENB;
    newtio.c_cflag |= ~PARODD;
     

    (6)设置停止位

        设置停止位,通过激活 c_cflag 中的 CSTTOPB 实现。若停止位为1,则清除 CSTOPB,若停止位为 2,则激活 CSTOPB。

     
    newtio.c_cflag &= ~CSTOPB;
     

    (7)设置最少字符和等待时间

        对于字符接收和等待的时间,一般没有太多的要求,一般全部设置为零。

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

    (8)清空缓存区域

        tcflush 函数会清空输入的缓存区域(底层驱动已经结合到数据,但是用户还没有接收到数据)和情况输出缓存区域(用户空间将数据写入缓存区域,但是串口协议缓存还没有将数据发出)。

     
    int tcflush(int filedes,int quene)
    quene数应当是下列三个常数之一:
      *TCIFLUSH  刷清输入队列
      *TCOFLUSH  刷清输出队列
      *TCIOFLUSH 刷清输入、输出队列
     

    (9)激活配置

        在前面已经设置好的各种配置的进行激活。

     
    int tcsetattr(int filedes,int opt,const struct termios *termptr);
       opt使我们可以指定在什么时候新的终端属性才起作用,

     
    *TCSANOW:更改立即发生
    *TCSADRAIN:发送了所有输出后更改才发生。若更改输出参数则应使用此选项
    *TCSAFLUSH:发送了所有输出后更改才发生。更进一步,在更改发生时未读的
     

     

    5、串口初始化的基本例操作

    (1)串口的初始化

    //打开串口并初始化设置

    init_serial(void)

    {

    serial_fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

    if (serial_fd < 0) {

    perror("open");

    return -1;

    }

    //串口主要设置结构体termios <termios.h>

    struct termios oldtio;

    struct termios newtio;

    bzero(&newtio,sizeof(struct termios));

    /**1. tcgetattr函数用于获取与终端相关的参数。

    *参数fd为终端的文件描述符,返回的结果保存在termios结构体中

    */

    tcgetattr(serial_fd, &oldtio);


    /**2. 修改所获得的参数*/

    newtio.c_cflag |= (CLOCAL | CREAD);//设置控制模式状态,本地连接,接收使能

    // 3. 设置串口输入输出的波特率

    cfsetispeed(&newtio,B115200);

    cfsetospeed(&newtio,B115200);

    // 4.设置数据位的位数

    newtio.c_cflag &= ~CSIZE;//字符长度,设置数据位之前一定要屏掉这个位,其实是将对应的位进行清理

    newtio.c_cflag &= ~CRTSCTS;//无硬件流控

    newtio.c_cflag |= CS8;//8位数据长度 ,设置对应的位

    //5. 设置奇偶校验

    newtio.c_iflag |= IGNPAR;//无奇偶检验位


    //6.设置停止位

    newtio.c_cflag &= ~CSTOPB;//1位停止位 停止位

    // 7.设置最少字符和等待的时间

    newtio_c.cc[VTIME] = 0;

    newtio_c.cc[VMIN] = 0;

    // 8.清空缓存区域

    tcflush(serial_fd, TCIOFLUSH);//刷新输入输出的缓存

    // 9. 激活配置

    tcsetattr(serial_fd, TCSANOW, &newtio);


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

      // options.c_oflag  &= ~OPOST;   /*Output*/

    return 0;

    }

    注意:

        当设置的串口不是终端的话(我们经常使用的串口是集成自己串口代码的使用上,每次串口的数据不是使用 ENTER 作为结束标志之类的),只是拿来作为串口传输数据的,那么就使用原始的方式进行通信。

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

    options.c_oflag &= ~OPOST; /*Output*/

     

    当然设置也可以为终端模式:

     
    options.c_lflag  |= (ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    options.c_oflag  |= OPOST;   /*Output*/
     

    (2)串口的读写

        因为Linux 一切设备皆文件,所以可以直接对串口的文件使用 write 和 read 进行串口数据的读写。

    int buf[1024];

    int readByte = read(fd,buf,1024);

        就可以将串口的数据读取到 buf 中,而返回值为读取到字符的数目。

    (3)串口的关闭

        串口的关闭,其实就是关闭文件了。

    close(fd);

        一般来说,关闭了串口,先要将之前的串口的配置进行还原。

    6、串口测试

        开发板和PC 的连接因为串口要被使用用于测试,所以串口和板子的连接改为 telnet 的方式。

    (1)设置开发板和 PC 在同一个网段

    (2)使用 SecureCRT 连接上开发板

    (3)

    二、串口 + MODEM

        MODEM 与串口之间的通信,是采用的 AT 命令,其实就是 AT + 内容 形式。串口与 MODEM 之间产口数据通信,需要注意一下的问题

    2.1、将打开的串口设置为原始输入模式

    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);   // 输入的本地输入是非规范
    options.c_oflag &= ~OPOST;   // 数据的输出也是非规范

        数据的输入和输出,设置为非规范,也就是 raw input 模式

    2.2、设备的初始化

        当与 MODEM 设备建立通信的时候,最好的初始化设备的方法是,先发送“AT”给 MODEM,当 MODEM 接收到的时候,就会回复“OK”。这个过程,完成设备的初始化。

    int 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 ", 3) < 3)    // 完成  ATR,也就是 AT + 回车 的命令的发送,当没有发送出去的话,就 continue,重新再发
                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] == ' ' || bufptr[−1] == ' ')  // 判定接收的数据,最后的是以回车或者换行结束
                            break;  // 就可以退出,编码数据接收完毕
                    }
                    /* nul terminate the string and see if we got an OK response */
                    *bufptr = '';   // 将
                    if (strncmp(buffer, "OK", 2) == 0)   // 将接收到 OK ,表明设备初始化争取
                            return (0);
               }
                    return (−1);
    }

    2.3、MODEM 通信的问题

    A、必须关闭本地模式的回显功能(同时设置输出模式为 原始输出模式),因为回显的话,会导致 MODEM 和计算机之间产生循环的反馈。

    也就是必须设置为:

    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);   // 输入的本地输入是非规范
    options.c_oflag &= ~OPOST;

    B、当发送 MODEM 命令的时候,必须以回车键(CR)进行结束,而并不是换行(NL:new line 或者 lf : line feed)。回车键的 C字符常量在是 ‘ ’。

    C、比特率的问题。确保与 MODEM 进行通信的波特率是得到支持。一般较为常用的是 19200。

    A、遇到的奇怪的问题

    (1)接收返回模式: 如果串口没有接收到数据,read()函数不返回。
    (2) 数据接收 才返回接收的数据,否则read()函数返回0
    (3) 特殊字符解析问题,部分特殊字符接收/发送时,会被屏蔽或者转义。如发送0x0A 接收变为0x0A 0x0A ,0x0D被屏蔽等。
    (4) 接收反馈:如串口接收到数据,立即将该数据发送出去。

    A、如何区分232 串口的直连线和交叉线

        RS232 的管脚中,2管脚: RXD,接收数据的管脚;3管脚:TXD,发送数据的管脚。所以在不同的使用功能的区分,就存在直连线和交叉线的区分。

    直连线:也就是2对2,3对3,这种连接线的接法是用在串口延长线。

    交叉线:2对3,3对2,这种接法是在电脑和设备之间的连接。直接使他们可以进行数据的通信。

        很显然,使用场合的不同,就需要使用不同的连接线。当需要延长串口数据线的时候,很显然必须使用串口的至联系;而当需要进行不同设备之间的数据通信的话,就必须使用交叉线进行连接。

        那么如何进行判断,一根串口线是直连线还是交叉线呢?

        我们将一个串口线分为 A端和B端,那么当这个串口线是直连线的时候,也就是A、B端对应的2口、3口都是在同一个位置的。而当是交叉线的话,A、B段对应的2口和3口是在不同的位置。因此可以通过万用表去帮助测量: 当A端的2口与B端的2口是否短接(短路),那么这根串口线就是直连线;而如果A端的2口与B端的3口是短路的话,那么这根串口线则是交叉的。

  • 相关阅读:
    C#实现ASE加密解密
    c# 深复制
    Jenkins + Git +IIS 部署
    c#模拟Http请求
    TCP/IP学习
    c# 字符串中包含 "" 时提示:无法识别的转义序列
    部署.net core项目到IIS后HTTP 错误 500.19
    .net core读取配置文件appsetting.json
    asp.net提示“未能加载文件或程序集“XXXXXXXX.dll”或它的某一个依赖项。找不到指定的模块。”
    WCF错误404.17 请求的内容似乎是脚本,因而无法由静态文件处理程序来处理
  • 原文地址:https://www.cnblogs.com/qxj511/p/5509781.html
Copyright © 2011-2022 走看看