《串口硬件分类》中已经说明了几种串口的类型,并在《串口通信协议》中说明了几种串口协议形式,这里就常用的串口协议进一步做一个说明。
工业上我们最常见的MODBUS RTU/ASCII通信协议是一种典型的起止型异步协议。之前在《串口通信协议》中已经解释过,起止型异步协议的特点是一个字符一个字符传输,并且传送一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求。
这里需要强调的就是对于起止型通信协议,每一个字符的前面都有一位起始位(低电平,逻辑值0),字符本身有5~7位数据位组成,接着字符后面是一位校验位(也可以没有校验位),最后是一位,或一位半,或二位停止位,停止位后面是不定长度的空闲位。停止位和空闲位都规定为高电平(逻辑值),这样就保证起始位开始处一定有一个下跳沿。
这段话可能讲的有点理论了,对于我们工作中所常见的一个情况就是选择一个串口的校验位、数据位与停止位(这里没有起始位,因为起始位一般是默认的)。
对应到一个如上图的具体通信格式上,就是8个数据位,无校验位➕一位停止位。也就是我们说的8N1通信格式。当然,这里也会用到奇偶校验的变化,如西门子V90在使用串口通信控制时便要求为8O1(8位数据,偶校验,1位停止)。
不考虑串口的传输线数量,单以一根线来理解,即每传输(扫描)一个位,信号线上便给出一个(高或低)电平,即0或1。对于一个8N1格式的传输,每一次传输周期电平将扫描1起始位+8数据位+1停止位共10次电平变化,而扫描的频率就是串口的波特率。因此,虽然理论上说起止型协议依托于起止信号来判断数据的开始和结束,数据间没有固定的时间间隔要求,但在实际应用的过程中,对于一个既定的串口协议,通信站之间还是要保持相同的收发波特率的,否则扫描口将会对同样的电平变化做出可能完全不同的解读而导致通信失败。
综上,串口数据格式存在的意义是限定了串口传输数据的时间间隔、每次传输的数据量以及传输的起始和结束。它解决了“怎么传”的问题。
而串口通信报文,则是定义“传什么”的问题。
一个典型的modbus报文格式如下:
设备地址(8位)➕功能码(8位)➕起始操作地址(16位)➕操作数量(16位)➕CRC(16位)
我在工作中遇到一个比较多的就是关于数据格式与报文的概念混淆。如上述的一串格式报文,曾经被误解为与8N1的数据格式相矛盾,因为很明显,它完全就超出了我们所说的8位数据或10位数据的格式,那么怎么来解释这个问题呢?
澄清一个概念,数据格式中的8位,指的是8bit而不是8byte,对于上述modbus,当采取8N1格式通信时,串口将会以1byte(8位)为单位对报文进行包装并传输。比如最开始,串口芯片或发射端会将8位设备地址提出,然后对这个字节进行包装(加1位起始码,加1位停止码),形成一个10位的数据包,并将数据发送出去,然后继续提取功能码,进行同样的包装发送,以此类推,直至所有数据发送完毕。
因此,报文指的是数据字符,而数据格式,只是表明如何来包装这个数据字符。而我们通过各种软件所看到的,是经过计算机串口处理的数据,因而无法看到起始码停止码一类的信号,而仅有我们所需要的数据。
由此还可以推导出串口通信的效率。依旧以8N1格式来说,每个数据包的长度为10位,若选择波特率为9600,即每秒传输9600个位信号,那么8N1数据格式每传输1个数据包所需要的时间10/9600约为1ms,对于一串MODBUS典型报文,需要8个字节(根据指令决定),故信号发出时间为8ms。modbus规定从站必须在指定时间内反馈相应的数据方可认为通信成功,因而需要再加回报时间,如只操作一个字节,那么往返数据时间应该在20ms左右,根据操作的数据量通信时间会相应的加长。
因此,还可以了解到的是在多站轮询时需要根据数据量进行一次核算,若对实时性要求较高,则要考虑进行主站的独立处理。
经验之谈,欢迎指正。