精华内容
下载资源
问答
  • 串口通信协议

    2017-08-06 09:26:10
    串口通信协议,常用标准协议。
  • 1.了解RS232接口标准概况。 2.熟悉MSP430USCI模块UART模式的使用。 3.实现单片机与PC之间的串口通信。 4.按照指定的通信协议实现串口通信协议
  • 串口通信协议简介

    万次阅读 多人点赞 2019-07-19 14:02:04
    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。 在计算机科学里,大部分...

    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。

    • 在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设;STM32标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层规定我们用中文还是用英文来交流。

    电平标准
    根据通讯使用的电平标准不同,串口通信可分为TTL标准及RS-232标准,见如下表格:

    通讯标准 电平标准(发送端)
    5V TTL 逻辑1::2.4V ~ 5V —— 逻辑0: 0 ~ 0.5V
    RS-232 逻辑1::-15V ~ -3V —— 逻辑0: +3V ~ +15V

    我们常见的电子电路中常使用TTL的电平标准,如我们的计算机内部识别的就是TTL电平,理想状态下,使用5V表示二进制逻辑1,使用0V表示逻辑0,所以说计算机CPU也只能识别二进制的0和1;但TTL电平有个缺点就是它不适合远距离传输,所以为了增加串口通讯的远距离传输及抗干扰能力,我们通常会使用RS-232电平,RS-232电平使用-15V表示逻辑1,+15V表示逻辑0。

    RS-232信号线
    在这里插入图片描述
    因为控制器一般使用TTL电平标准,所以在传输过程中就需要用到MAX3232芯片或者CH340芯片对TTL及RS-232电平的信号进行相互转换;可以这样理解,假设有两台计算机需要进行串口通信,在发送端,计算机内部的TTL电平需经过电平转换芯片(MAX3232或CH340)将其转换为RS-232电平后再进行传输,到了另一台计算机,则需要电平转换芯片(MAX3232或CH340)将接收到的RS-232电平转换为TTL电平,这样计算机CPU才能识别到。

    RS-485电平
    RS485标准是为了弥补RS232通信距离短、速率低等缺点而产生的而产生的,该接口标准只规定了电气特性,并没有规定接插件,传输电缆和 应用层通信协议。

    RS485标准与RS232不一样,数据信号采用差分传输方式。
    

    通常情况下,发送发送器A、B之间的征地安排在+2+6V,是一个逻辑状态,负电平在-2-6V,是另一个逻辑状态。另外有一个信号地C,在RS485器件中,一般还有一个“使能”控制信号,“使能”信号用于控制“发送发送器”与传输线的切断和连接,当使能端起作用时,发送发送器处于高阻状态,称作“第三态”,它是有别于逻辑“1”和“0”的第三种状态。

    对于接收发送器,也作出 与发送发送器相对的规定,收、发端通过平衡双绞线,将A-A与B-B对应相连,当在接收端A-B之间有大于+200mV的电平时,输出正逻辑电平,小鱼-200mV时,输出负逻辑电平,在接收发送器的接收平衡线上,电平范围通常在200mV至6V之间

    协议层
    串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备的RXD接口。在串口通讯的协议层中,规定了数据包的内容,它由起始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据。

    在这里插入图片描述
    通俗理解就是,你通过一根信号线不断的给我发送高低电平,我这边需要确定哪些是我要的数据;首先你得给我的起始信号吧,告诉我你接下来要准备发送数据了,数据发送完了,检验一下发送得对不对,检验OK了,给个停止信号,告诉我你已经发送完毕了,那么这就是咱们双方约定好的协议了……

    数据信号传输中的几个概念:

    具体可查看《STM32F4xx中文参考手册》第22章通用同步异步收发器(USART)

    1. 波特率
    USART的全称是通(U)用同步(S)异(A)步收®发(T)器,每个字母都有它对应的含义;不过本次学习的是串口异步通讯,因为同步通讯是需要时钟信号来进行同步的,但我使用的串口线没有时钟信号;因此两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码。常见的波特率为4800、9600、115200等。
    2. 通讯的起始和停止信号
    串口通讯的一个数据包从起始信号开始,直到停止信号结束,数据包的起始信号有一个逻辑0的数据位表示,而数据包的停止位可由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。
    3. 有效数据
    在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度通常是8位。
    4. 数据校验
    在有效数据之后,有一个可选的数据校验位;由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程中加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0校验(space)、1校验(mark)以及无校验(noparity)。

    奇校验 要求有效数据和校验位中"1"的个数为奇数 ,比如一个8位长的有效数据为:01101001,此时总共有4个"1",为达到奇校验效果,校验位为"1" ,最后传输的数据是将8位的有效数据加上1位的校验位总共9位
    偶校验 偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数
    0校验 不管有效数据中的内容是什么,校验位总为“0”
    1校验 校验位总为“1”
    无校验 在无校验的情况下,数据包中不含校验位

    展开全文
  • ROS串口通信协议解析

    2020-08-12 11:27:04
    ROSserial 串口通信协议解析 1. 总览 ROS-serial是用于包装标准ROS序列化消息并在外部设备(例如串行端口或网络套接字)上多路复用多个主题和服务的协议。 2. 局限性 这里定义了发布主题消息的最大大小,发布者/订阅...

    ROSserial 串口通信协议解析

    1. 总览

    ROS-serial是用于包装标准ROS序列化消息并在外部设备(例如串行端口或网络套接字)上多路复用多个主题和服务的协议。

    2. 局限性

    这里定义了发布主题消息的最大大小,发布者/订阅者的最大数量
    对于rosserial_client,默认情况下,发布者和订阅者的数量限制为25,序列化和反序列化缓冲区的大小限制为512字节。

    但是,这些数目和大小对于SRAM有限的微控制器来说太大了。rosserial_arduino的缓冲区大小和发布者/订阅者的数量现在取决于所使用的芯片:

    AVR模型 输出缓冲区大小 发布者/订阅者
    ATMEGA168 150/150字节 6/6
    ATMEGA328P 280/280字节 25/25
    其他 512/512字节 25/25

    您可以更改这些数字和大小

    typedef NodeHandle_<HardwareType, MAX_PUBLISHERS, MAX_SUBSCRIBERS, IN_BUFFER_SIZE, OUT_BUFFER_SIZE> NodeHandle;
    

    但是,您应该注意不要消耗Arduino中有限的SRAM。如果Arduino的SRAM用完了,它只会挂起而没有调试信息。

    大于缓冲区大小的消息不会发送。ROS错误消息将被中继,告知该消息是来自设备还是来自设备。

    2.1 Float64

    Arduino不支持64位浮点数据类型。由make_library生成的序列化/反序列化代码将自动将64位浮点数转换为32位数据类型,但是,应注意,可能会导致精度损失!

    2.3 String

    为了节省宝贵的AVR内存,字符串不存储在消息实例内部,而是存储未签名的char *。这有两个影响:

    发布时,必须在其他位置分配存储字符串数据并设置指针:

     std_msgs::string str_msg; 
     unsigned char Hello [13] = "Hello world!" ; 
     str_msg.data = Hello;
    

    订阅包含字符串数据类型的消息时,不会从反序列化缓冲区中复制字符串本身。因此,尽管它在回调函数中有效,但在反序列化任何其他消息时它将消失。如果需要将字符串的值保留在回调之外,则必须手动将字符串复制到其他位置。

    2.4 数组

    数组与字符串具有相似的限制,但是,由于没有简单的方法来查找数组的终止(类似于在字符串末尾找到\ 0),因此我们需要指定数组的大小。一个额外的变量被添加到类定义中以完成此操作。例如,geometry_msgs / PoseArray声明为:

    Header header
    geometry_msgs/Pose[] poses
    

    在Arduino上,这将转换为一个类

    class PoseArray
    {
      Header header;
      int poses_length;
      Pose * poses;
    }
    

    因此,要发送数组消息,我们必须设置长度和指针。反序列化时,我们不能像字符串一样就地反序列化(因为消息的字节实际上是打包的,与以纯格式传递的字符串不同)。因此,反序列化功能将使用realloc()自动分配足够的存储空间,并在可能的情况下尝试重用内存位置,并且仅在收到的新消息大于先前的最大消息时才对其进行扩展。

    某些包含其他数组类型的数组类型将无法正确反序列化,因为子类型的所有元素都将指向同一内存。将来可能会解决此限制。

    3. 协议

    ROS-serial协议通过串口通信实现节点对节点通信。我们使用与标准ROS消息相同的序列化/反序列化,只需添加数据包头和尾即可,这使多个主题可以共享一个公共串行链接。这里描述了数据包头和包尾的详细协议信息,以及一些用于同步的特殊主题。

    串口通信协议采用小端模式,低位在前高位在后。

    3.1 封包格式:

    byte 长度 说明
    1 1 起始位
    2 1 协议版本
    3 2 消息长度(len)
    5 1 消息长度校验和
    6 2 主题ID
    8 len 串口消息数据
    len + 1 1 主题ID和数据校验和
    展开全文
  • 串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。 二、串口接头: 常见的串口接头有两种,一种是9针串口(简单DB-9),一种是25针串口(简称DB-25)。 以DB9为例为例,如图: ...

    一、串口通信介绍:
    串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节,尽管比按位字节(byte)的并行通信慢,但是串口可以使用一根线发送数据的同时用另一根线接收数据。串口通信属于异步串行通信方式。串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。

    二、串口接头:
    常见的串口接头有两种,一种是9针串口(简单DB-9),一种是25针串口(简称DB-25)。

    以DB9为例为例,如图:
    在这里插入图片描述

    母头:泛指所有带孔状的接头(5针朝下,从左到右依次是1~9)
    公头:泛指所有带针状的接头(5针朝下,从右到左依次是1~9)

    各引脚的功能如下图
    在这里插入图片描述
    三、TTL电平和RS232电平:

    1、TTL(Transistor-Transistor Logic),即晶体管-晶体管逻辑的简称,它是计算机处理器控制的设备内部各部分之间通信的标准技术。TTL电平信号应用广泛,是因为其数据表示采用二进制规定,+5V等价于逻辑”1”,0V等价于逻辑”0”。
    数字电路中,由TTL电子元器件组成电路的电平是个电压范围,规定:
    输出高电平>=2.4V,输出低电平<=0.4V;
    输入高电平>=2.0V,输入低电平<=0.8V。

    2、RS232电平
    RS232电平是串口的一个标准。

    在TXD和RXD数据线上:
      (1)逻辑1为-3~-15V的电压
      (2)逻辑0为3~15V的电压
    在RTS、CTS、DSR、DTR和DCD等控制线上:
      (1)信号有效(ON状态)为3~15V的电压
      (2)信号无效(OFF状态)为-3~-15V的电压
    这是由通信协议RS-232规定的。
    RS-232:标准串口,最常用的一种串行通讯接口。有三种类型(A,B和C),它们分别采用不同的电压来表示on和off。最被广泛使用的是RS-232C,它将mark(on)比特的电压定义为-3V到-12V之间,而将space(off)的电压定义到+3V到+12V之间。传送距离最大为约15米,最高速率为20kb/s。RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kΩ。所以RS-232适合本地设备之间的通信。

    注意:RS-232 是用正负电压来表示逻辑状态,与晶体管-晶体管逻辑集成电路(TTL)以高低电平表示逻辑状态的规定正好相反。而我们 STM32 芯片使用的就是 TTL 电平,所以要实现 STM32 与计算机的串口通信,需要进行 TTL与 RS-232C 电平转换,通常使用的电平转换芯片是 MAX3232

    四、串口通信

    两台计算机进行通信时,最少可以只要三根线,分别为RXD,TXD GND。

    在这里插入图片描述
    串口通信属于异步串行通信方式
    异步通信是指发送和接收端使用的是各自的时钟,并且它是一种不连续的传输通信方式,一次通信只能传输一个字符数据(字符帧)。字符帧之间的间隙可以是任意的,下图是异步串行通信帧格式:
    在这里插入图片描述
    起始位:接收方探测, 默认总线空闲时是高电平,一旦来一个位的低电平,说明一帧数据开始了。紧接着就是数据位,一帧数据有多少个数据位,由通信双方定义。

    数据位:在起始位之后,发送端发出的就是数据位,数据位的位数没有严格限制(5-8位都可以)。低位在前,高位在后。由低位向高位逐位发送。

    校验位:数据位发完了,一般会跟奇偶校验位(奇校验、偶校验、无校验),验证收发双方的数据是否正常。

    奇校验: 数据位加上校验位保证1的个数为奇数;

    偶校验: 数据位加上校验位保证1的个数为偶数

    停止位:数据发完之后,会发一个停止位,停止位的宽度一般是: 1, 1.5, 2

    空闲位:空闲位是指从一个字符的停止位结束到下一个字符的起始位开始,表示线路处于空闲状态,必须由高电平来填充。

    五、Linux串口编程

    在Linux系统中,一切皆文件,所以串口设备也是一类文件,学习过Linux驱动程序的学员都知道,Linux有三类设备:字符设备,块设备,网络设备。那么串口设备属于字符设备。所以串口设备的命名一般为/dev/ttySn(n = 0、1、2…),如果该串口为USB转串口,可能名称为/dev/ttyUSBn(n = 0、1、2…),不同的平台下串口的名称是不同的,且串口的名称也是可以更改的。如何更改?在板卡对应的Linux驱动中更改。

    在Linux下操作串口,那么也就是跟操作一个文件一样,既然是文件,也就可以使用标准的文件操作API来操作。

    在进行文件操作时,我们先看一下操作串口需要包含的有文件:

    #include <stdio.h>   /*标准输入输出的定义*/
    #include <errno.h>  /*错误号定义*/
    #include <sys/stat.h>
    #include <fcntl.h>  /*文件控制定义*/
    #include <termios.h>    /*PPSIX 终端控制定义*/
    #include <stdlib.h> /*标准函数库定义*/
    #include <sys/types.h>
    #include <unistd.h> /*UNIX 标准函数定义*/
    

    1、打开串口

    fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY|O_NDELAY);
    open的第二个参数可以设置为如下:

    O_RDONLY:以只读方式打开文件

    O_WRONLY:以只写方式打开文件

    O_RDWR:以读写方式打开文件
    O_RDONLY和O_WRONLY和O_RDWR三个中必选一个

    O_APPEND:写入数据时添加到文件末尾

    O_CREATE:如果文件不存在则产生该文件,使用该标志需要设置访问权限位mode_t

    O_EXCL:指定该标志,并且指定了O_CREATE标志,如果打开的文件存在则会产生一个错误

    O_TRUNC:如果文件存在并且成功以写或者只写方式打开,则清除文件所有内容,使得文件长度变为0

    O_NOCTTY:如果打开的是一个终端设备,这个程序不会成为对应这个端口的控制终端,如果没有该标志,任何一个输入,例如键盘中止信号等,都将影响进程。

    O_NONBLOCK:该标志与早期使用的O_NDELAY标志作用差不多。程序不关心DCD信号线的状态,如果指定该标志,进程将一直在休眠状态,直到DCD信号线为0。

    2、写串口

    write(fd, buf,sizeof(buf) );

    和写入其他设备文件的方式相同,write函数也会返回发送数据的字节数或者发生错误的时候返回-1。通常,发送数据最常见的错误就是EIO,当调制解调器或者数据链路将Data Carrier Detect(DCD)信号线弄掉了,就会发生这个错误,而且,直至关闭端口这个情况会一直持续。

    3、读串口

    read( fd, buf, sieof(buf));

    当端口在raw data mode操作模式下,那么read系统调用将返回从串口输入缓冲区中实际得到的字节数,如果没有数据可读,那么该系统调用将会被阻塞(block)直到有数据为止,如果超过一定时间仍然没有数据可读,那么将返回一个错误(读错误)。read函数也可以立即返回(即在没有数据可读的情况下也能立即返回,而不是被阻塞),需要做如下工作:
    fcntl(fd, F_SETFL, FNDELAY);

    FNDELAY选项的意思是read函数在没有数据可读的情况下立即返回0。需要重新回到阻塞模式(blocking)下,那么在调用fcntl()的时候不要加上FNDELAY这个选项:
    fcntl(fd, F_SETFL, 0);

    4、关闭串口

    关闭串口使用close系统调用,例如:
    close(fd);

    5、串口属性配置

    如果不设置串口的波特率,数据位,停止位,校验位的情况下,Linux下默认设置的属性值为:

    波特率:9600

    数据位:8

    校验位:n(表示无)

    停止位:1

    在不设置串口属性值的情况下,也可以读写串口值。

    但是在实际产品开发过程中,还是会根据不同的应用场景来设置串口的属性。很多系统都支持POSIX终端(串口)接口,程序可以利用这个接口来改变终端的参数,比如波特率,字符大小等,要利用这个端口的话,你必须将<termios.h>头文件包含到你的程序中,这个头文件中定义了终端控制结构体和POSIX控制函数。

    设置串口属性先要tcgetattr()用来取得设备终端属性,然后中间设置波特率,设置停止位,校验位,数据位等,最后用tcsetattr()设置终端的属性。调用这两个函数的时候,需要提供一个包含着所有串口选项的tremios结构体:

    struct termios
     
          {
     
          tcflag_t  c_iflag;  //输入选项
     
          tcflag_t  c_oflag;  //输出选项
     
          tcflag_t  c_cflag;  //控制选项
     
          tcflag_t  c_lflag;  //行选项
     
          cc_t      c_cc[NCCS]; //控制字符
           
           };
    

    通过termios结构体的c_cflag成员可以控制串口波特率、数据位、校验位、停止位以及硬件流控制等等,位成员有:
    在这里插入图片描述在这里插入图片描述
    1)设置串口波特率
    使用函数cfsetispeed设置输入波特率cfsetospeed设置输出波特率

    struct termios options;

    tcgetattr(fd, &options);

    cfsetispeed(&options, B19200);

    cfsetospeed(&options, B19200);

    2)通过位掩码的方式激活本地连接和接受使能选项:CLOCAL和CREAD

    options.c_cflag | = CLOCAL | CREAD;

    3)设置数据位

    数据位指的是每字节中实际数据所占的比特数。要修改数据位可以通过修改termios结构体中c_cflag成员来实现。CS5、CS6、CS7和CS8分别表示数据位为5、6、7和8。值得注意的是,在设置数据位时,必须先使用CSIZE做位屏蔽。

    options.c_cflag &= ~CSIZE;

    options.c_cflag |= CS8;

    4)设置校验位

    奇偶校验可以选择偶校验、奇校验等方式,也可以不使用校验。如果要设置为偶校验的话,首先要将termios结构体中c_cflag设置PARENB标志,并清除PARODD标志。如果要设置奇校验,要同时设置termios结构体中c_cflag设置PARENB标志和PARODD标志。激活c_iflag中的奇偶效验使能,如果不想使用任何校验的话,清除termios结构体中c_cflag的PARENB位。

    设置奇校验

    options.c_cflag |= PARENB;

    options.c_cflag |= PARODD;

    options.c_iflag |= (INPCK | ISTRIP); //INPCK 打开输入奇偶校验,ISTRIP 去掉字符第8位

    设置偶校验

    options.c_iflag |= (INPCK|ISTRIP);

    options.c_cflag |= PARENB;

    options.c_cflag |= ~PARODD;

    设置无校验位

    options.c_cflag &= ~PARENB;

    5)设置停止位

    用CSTOPB只能设置1位或2位,通过设置c_cflag中的CSTOPB设置停止位。若停止位为1,则清除CSTOPB;若停止位为2,则激活CSTOPB。

    一位停止位

    options.c_cflag &=~CSTOP;

    两位停止位

    options.c_cflag |=CSTOPB;

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

    在对接收字符和等待时间没有特别要求的情况下,可以将其设置位0.

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

    7)调用函数”tcflush(fd,queue_selector)”来处理要写入引用的对象

    queue_selector可能的取值有以下几种

    TCIFLUSH:刷新收到的数据但是不读

    TCOFLUSH:刷新写入的数据但是不传送

    TCIOFLUSH:同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送。

    7)最后tcsetattr()设置终端的属性

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

    第一个参数:fd为打开的终端文件描述符

    第二个参数:optional_actions用于控制修改起作用的时间。
    可以取如下值:
    optional_actions可以取如下的值:

    TCSANOW:不等数据传输完毕就立即改变属性。

    TCSADRAIN:等待所有数据传输结束才改变属性。

    TCSAFLUSH:等待所有数据传输结束,清空输入输出缓冲区才改变属性。

    第三个参数:结构体termios_p中保存了要修改的参数。

    调用该函数出现的错误信息:

    EBADF:非法的文件描述符。

    EINTR:tcsetattr函数调用被信号中断。

    EINVAL:参数optional_actions使用了非法值,或参数termios中使用了非法值。

    六、简单的Linux串口编程

    读串口程序

    #include <sys/time.h>
    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h> //标准函数库定义
    #include <unistd.h> //unix标准函数定义
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h> //文件控制定义
    #include <termios.h> //POSIX终端控制定义
    
    int main(int argc, char **argv)
    {
            int fd = -1;
            int rv = -1;
            char buf[128];
    
            struct termios options;//该结构体包含串口的选项
            /*struct termios
             {
                tcflag_t  c_iflag;  //输入选项
                tcflag_t  c_oflag;  //输出选项
                tcflag_t  c_cflag;  //控制选项
                tcflag_t  c_lflag;  //行选项
                cc_t      c_cc[NCCS]; //控制字符
             }*/
    
            fd_set rset;
    
            fd = open("/dev/ttyUSB3",O_RDWR|O_NOCTTY|O_NDELAY);//打开串口设备
            if(fd < 0)
            {
                    printf("open ttyUSB3 failure:%s\n",strerror(errno));
                    close(fd);
                    return -1;
            }
    
            printf("open ttyUSB3 successfuly\n");
    
            memset(&options, 0, sizeof(options));
    
            rv = tcgetattr(fd, &options);//获取原有的串口属性的配置
    
            if(rv != 0 )
            {
                    printf("tcgetattr failure:%s\n", strerror(errno));
                    return -2;
            }
            options.c_cflag|=(CLOCAL|CREAD);//CREAD开启串行数据接收,CLOCAL并打开本地连接模式
            //options.c_cflag &= ~(ECHO |ICANON |ECHOE);
            options.c_cflag &= ~CSIZE;//先使用CSIZE做位屏蔽
            options.c_cflag |= CS8;//设置8位数据位
            options.c_cflag &= ~PARENB;//无校验位
    
            /*设置115200波特率*/
            cfsetispeed(&options,B115200);//设置输入波特率
            cfsetospeed(&options,B115200);//设置输出波特率
    
            options.c_cflag &= ~CSTOPB;//设置一位停止位
            options.c_cc[VTIME] = 0;//非规范模式读取时的超时时间
            options.c_cc[VMIN] = 0;//非规范模式读取时的最小字符数
    
            tcflush(fd, TCIFLUSH);//tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不>
    读取出来
    
            rv=tcsetattr(fd, TCSANOW, &options);//设置终端的属性
            if(rv != 0)
            {
                    printf("tcsetattr failure:%s\n",strerror(errno));
                    close(fd);
                    return -3;
            }
    
    
            while(1)
            {
                    FD_ZERO(&rset);
                    FD_SET(fd, &rset);
    
                    rv = select(fd+1, &rset, NULL, NULL,NULL);
                    if(rv < 0)
                    {
                            printf("select failure:%s\n",strerror(errno));
                            close(fd);
                    }
                    if(rv ==0)
                    {
                            printf("select timeout\n");
                            close(fd);
                            }
    
                    memset(buf, 0, sizeof(buf));
    
                    rv = read(fd, buf, sizeof(buf));
                    if(rv <0)
                    {
                            printf("read from buf failure:%s\n",strerror(errno));
                            close (fd);
                    }
                    printf("read from buf %d  %s bytes\n",rv, buf);
                    sleep(3);
            }
    
            close(fd);
            return 0;
    }
    

    写串口程序

    #include <sys/time.h>
    #include <errno.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h> //标准函数库定义
    #include <unistd.h> //unix标准函数定义
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h> //文件控制定义
    #include <termios.h> //POSIX终端控制定义
    
    #define BUF   "makun1394987689@qq.com"
    int main(int argc, char **argv)
    {
            int fd = -1;
            int rv = -1;
    
    
            struct termios options;//该结构体包含串口的选项
            /*struct termios
             {
                tcflag_t  c_iflag;  //输入选项
                tcflag_t  c_oflag;  //输出选项
                tcflag_t  c_cflag;  //控制选项
                tcflag_t  c_lflag;  //行选项
                cc_t      c_cc[NCCS]; //控制字符
             }*/
    
    
    
            fd = open("/dev/ttyUSB3",O_RDWR|O_NOCTTY|O_NDELAY);//打开串口设备
            if(fd < 0)
            {
                    printf("open ttyUSB3 failure:%s\n",strerror(errno));
                    close(fd);
                    return -1;
            }
    
            printf("open ttyUSB3 successfuly\n");
    
            memset(&options, 0, sizeof(options));
    
            rv = tcgetattr(fd, &options);//获取原有的串口属性的配置
    
            if(rv != 0 )
            {
                    printf("tcgetattr failure:%s\n", strerror(errno));
                    return -2;
            }
            options.c_cflag|=(CLOCAL|CREAD);//CREAD开启串行数据接收,CLOCAL并打开本地连接模式
            //options.c_cflag &= ~(ECHO |ICANON |ECHOE); 
            options.c_cflag &= ~CSIZE;//先使用CSIZE做位屏蔽
            options.c_cflag |= CS8;//设置8位数据位
            options.c_cflag &= ~PARENB;//无校验位
    
            /*设置115200波特率*/
            cfsetispeed(&options,B115200);//设置输入波特率
            cfsetospeed(&options,B115200);//设置输出波特率
    
            options.c_cflag &= ~CSTOPB;//设置一位停止位
    
            options.c_cc[VTIME] = 0;//非规范模式读取时的超时时间
             options.c_cc[VMIN] = 0;//非规范模式读取时的最小字符数
    
            tcflush(fd, TCIFLUSH);//tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不>
    读取出来
    
            rv=tcsetattr(fd, TCSANOW, &options);//设置终端的属性
            if(rv != 0)
            {
                    printf("tcsetattr failure:%s\n",strerror(errno));
                    close(fd);
                    return -3;
            }
    
            while(1)
            {
    
                    rv = write(fd, BUF,strlen(BUF)) ;
                    if(rv < 0)
                    {
                            printf("write error:%s\n",strerror(errno));
                            close(fd);
                    }
                    printf("write to read successfuly %d %s \n",rv, BUF);
    
                    sleep(3);
            }
    
           close(fd);
            return 0;
    }
    

    总的来说进行串口通信总有一个是主动方一个是被动方,而且二者传输数据时,会有一定的协商好的数据格式,二者发送接收都按照此数据格式进行。此篇记录自己学习串口编程的学习,更多关于串口的学习,请关注我接下来的博客

    展开全文
  • UART串口通信协议概述

    万次阅读 2018-12-12 22:05:38
    1.UART协议介绍 UART是一种通用串行数据总线,用于...而RS232等式对应各种异步串行通信口的接口标准和总线标准,它们规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容,实际上是属于通信网络中的...

    1.UART协议介绍

    UART是一种通用串行数据总线,用于异步通信。UART能实现双向通信,在嵌入式设计中,常用于主机与辅助设备通信。UART包括RS232、RS449、RS423等接口标准规范和总线标准规范,即UART是异步串行通信口的总称。而RS232等式对应各种异步串行通信口的接口标准和总线标准,它们规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容,实际上是属于通信网络中的物理层(最底层)的概念,与通信协议并没有关系。

    UART传输中,相关名词解释如下:

    (1)波特率:每秒钟发送的符号数

    (2)起始位:先发出一个逻辑0的信号,表示传输数据的开始

    (3)数据位:衡量通信中实际数据位的参数。标准的数据位可以是5、7、8位,从最低位开始传输

    (4)奇偶校验位:UART发送时,检查发送数据中1的个数,自动在奇偶校验位上添上1或0,用于发送数据的校验

    数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。就比如传输“A”(01000001)为例: 
    当为奇数校验:”A”字符的8个bit位中有两个1,那么奇偶校验位为1才能满足1的个数为奇数(奇校验);
    当为偶数校验:”A”字符的8个bit位中有两个1,那么奇偶校验位为0才能满足1的个数为偶数(偶校验);

    (5)停止位:数据结束的标志,可以是1位、1.5位、2位的高电平

    (6)空闲位:处于逻辑1的状态,表示当前线路上无数据传输

    发送数据过程:空闲状态,线路处于高电平,当收到发送数据指令后,拉低电平一个数据位的时间,接着数据按低位到高位依次发送,数据位发送完毕,接着发送奇偶校验位和停止位,停止位为高电平,一帧数据发送结束;

    接收数据过程:空闲状态,线路处于高电平,当检测到线路的下降沿,说明线路有数据传输,按照约定的波特率从低位到高位接收数据,数据接收完毕后接着接收奇偶校验位并比较,看奇偶校验位是否正确,如果正确则通知接收端设备准备接收数据;

    由于UART是异步传输,没有同步传输时钟,为了保证传输数据的正确性,UART采用16倍波特率的时钟进行采样,每个数据有16个时钟采样,取中间的采样值,以保证不会滑码或误码;

    展开全文
  • RS-232串口通信协议

    千次阅读 2020-09-16 10:57:52
    1 串口通讯协议简介 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。 通讯协议,我们以分层的方式来理解,最基本的是把它分为物理...
  • 对于装备而言,选择串行通信接口是合理的,串行通信接口(RS232)是计算机标准配置的通信接口,可以根据具体的情况构建计算机与装备之间的通信,实现在串口之上的数据传输。
  • 自定义串口通信协议(16进制)

    万次阅读 多人点赞 2018-08-27 16:02:38
    1.1串口通信标准 通过RS-232接口进行两个设备间的通信(异步传输,全双工通信)。 接口标准:两种接口9pin(DB-9),25pin(DB-25),通常只有三根线:TXD(发送)、RXD(接收)、GND(接地)。 传输距离:150pF/m的通信电缆...
  • CH9329 是一款串口转标准设备(键盘、鼠标、自定义 HID)芯片,根据不同的...通过提供的上位机软件,用户也可自行配置芯片工作模式、串口通信模式、串口通信波特率、多种超时时间、VID、PID,以及各种 USB 字符串描述符。
  • 串行口通信以RS-232标准为基础,数据格式固定为18N1,即1位起始位,8位数据,无校验,1位停止位。 数据包格式:0123456-78- 0x7E协议版本属性目的地址源地址命令字长度数据累加和0x7E1、数据包以0x7E开始,以ox7E...
  • 几个串口通信协议的整理

    万次阅读 多人点赞 2019-02-18 09:55:21
    一、UART UART是一个大家族,其包括了RS232、RS499、RS423、RS422和RS485等接口标准规范和总线标准规范。它们的主要区别在于其各自的电平范围不相同。...1.2 通信协议 将传输数据的每个字符一位接一位地传输。 h...
  • 三菱PLC下载口的通信协议,可用于与PLC通信编程;PLC 是被动设备,与之连接的设备主动发起请求命令对 PLC 进行读写。通 过指令可以操作和读取 PLC 内部所有的软元件。
  • 不同串口通信协议比较 UART UART是通用异步收发传输器,使用RxD和TxD两根线实现异步全双工通信;为确保通信可靠,可以在通信两边接共地;因此,完整的UART通信只需最少3根线即可。 RxD是发送数据线,TxD是接收数据线...
  • 一、串口通信协议的组成部分 1、起始帧头 2、帧长(包含帧头帧尾的长度) 3、指令位 4、数据位 5、校验 6、结束帧尾 二、关于CRC循环冗余校验 将多项式按阶数定义为一串二进制数,与待校验数做模二除法,...
  • 串口通信的物理层有很多标准和变种,以RS232标准为例,规定了信号的用途、通讯接口、电平标准。 电平标准 串口通讯分为TTL标准和RS232标准 因为控制器一般使用TTL电平标准,所以常常会使用MA3232芯片对TTL及RS232...
  • RS422串口通信协议

    万次阅读 2008-12-11 21:56:00
    RS-422标准全称是“平衡电压数字接口电路的电气特性”,它定义了接口电路的特性。实际上还有一根信号地线,共5根线。由于接收器采用高输入阻抗和发送驱动器比RS232更强的驱动能力,故允许在相同传输线上连接多个接收...
  • 关于 Modbus 通信,这里不再多赘述,网上有很多教程讲的很详细,对于通信协议,推荐这个文章,Modbus+RTU标准通信协议可以较为详细的了解具体的通信协议 以下为我的代码实现,注释很详细,相信大家都能看明白 using ...
  • 在简单的认识及使用串口通信之后,在实际应用中应该是配合硬件,和负责硬件通信的同事沟通好通信协议,来进行设备的控制及数据获取。 常用的串行通信协议有TTL电平(普通MCU芯片输出的串口电平)、RS232(工业上常用...
  • 设计中也考虑了扩展通信板的通用性,所设计的通信板符合PC/104标准,支持即插即用,用户可根据需要和系统资源条件设置串行口地址和中断请求号,因此,本设计也可作为开发PC/104标准串口通信板的参考。另外,在本设计...
  • 串口通信

    2018-08-03 14:47:34
    1、什么是串口通信?  串口通信(Serial CommunicaTIon),是指外设和计算机间,通过... 2、串口通信协议  在串口通信中,常用的协议包括RS-232、RS-422和RS-485。  •RS-232:标准串口,最常用的一种串行通...
  • 串口(USART)通信-串口通讯协议简介 物理层:规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。其实就是硬件部分。 协议层:协议层主要规定通讯逻辑,统一收发双方的数据打包、解包...
  • 本节对串口编程时如何设计串口通信协议,以及对RS232接口进行了说明。 1. 通信协议设计 在进行通信时,每次需要传送的信息一般超过1字节。为此,通信双方必须约定通信数据的排列格式,即通信协议。通常把一次通信...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 718
精华内容 287
关键字:

标准串口通信协议