总线协议从小工到专家之路学习笔记

2023-10-05

总线协议从小工到专家之路学习笔记。

根据维基百科的解释:总线(Bus)是指计算机组件间规范化的交换数据(data)的方式,即以一种通用的方式为各组件提供数据传送和控制逻辑。可能这样我们并不能很好理解总线,我们知道,计算机是由五大部件组成的:运算器、存储器、控制器、输入设备和输出设备,这个概念比较抽象,简单一点来说就是 CPU 包含运算器和控制器,存储器也就指的是内存,而输入输出设备分别指的是键盘和显示器。计算机这几个部件之间是需要共同协作完成信息处理的,那么,这几大部件之间如何进行通信呢?靠的是系统总线,这也是我们这篇文章讨论的重点。

0 总线概念

总线是将两个计算机或者多个功能单元连接在一起并允许它们相互交换数据的一种通路。总线还可以将计算机和外部设备连接在一起。总线是计算机系统非常重要的组成部分。关于需要知道下面这几个概念。

  • 总线宽度:一般用并行数据通路的数量来定义总线的宽度,一般总线的宽度有 8 位、16 位、32 位、64 位,我们现在最常用的就是 64 位总线,一条 64 位宽的总线一次能够传输 64 位也就是 8 个字节信息。
  • 带宽:带宽是衡量数据在总线上传输速率的一项指标。在保持数据传输速率不变的情况下提高并行通路的数量,可以提高总线的带宽。
  • 延迟:延迟是从发出数据传输请求到实际数据传输的时间间隔。

总线可同时传输的信息量就称为宽度(width),以比特为单位,总线宽度愈大,传输性能就愈佳。总线的带宽(即单位时间内可以传输的信息量)为:总线带宽 = 频率×宽度(Bytes/sec)。

主要介绍两种总线,一种是片内总线,一种是系统总线,片内总线一般指的是 CPU 芯片内部、寄存器和寄存器之间、寄存器和算术单元 ALU 之间的连接。而系统总线主要是指 CPU 和内存、内存和 IO 设备、CPU 和 IO 设备等各大部件的信息传输介质。系统总线按照传输信息的不同主要分为下面三类。

  • 地址线
  • 数据线
  • 控制线

0.1 MCU 外设IO串行总线

不像是PC机那样,MCU主要是针对各种IO设备访问的总线,常见的总线有:I2C、USART、SPI、I2C和CAN,当然还有一些不太常见的I2S、I2C-SMBus,甚至现在推出的I3C等等,这些东西看着貌似很简单,但其实如果要真正把握并不容易,需要时间慢慢消化。

总线 线数 通信类型 多主支持 数据率 总线上器件数量 线缆长度(米)
USART 2 同步/异步 不支持 3Kbps到4Mbps 2 1.5
SPI 3 同步 不支持 >1 Mbps < 10 <3
I2C 2 同步 支持 <3.4 Mbps < 10 <3
CAN 2或1 异步 支持 20Kbps ~ 1Mbps 128 40
LIN 1 异步 不支持 < 20Kbps 16 40
I2S 3 同步 不支持 8k ~ 44kHz 2 <3

一、片外总线概念

1.1 UART

  UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,如EEPROM通信。

1.1.1 接口

  在单片机中UART可以说是一种最基本的配置,很多与电脑进行通信的设备都采用到它,按计算机最常规的说法就是串行通信。

  • TX - 数据发送接口
  • RX - 数据接受接口

  两个设备间将TX与RX相连,RX与TX相连即可正常工作。最常用到的就是我们电脑上的USB那就是个最典型的UART接口。

1.1.2 工作原理

发送接收

  发送逻辑对从发送FIFO 读取的数据执行“并→串”转换。控制逻辑输出起始位在先的串行位流,并且根据控制寄存器中已编程的配置,后面紧跟着数据位(注意:最低位 LSB 先输出)、奇偶校验位和停止位。 在检测到一个有效的起始脉冲后,接收逻辑对接收到的位流执行“串→并”转换。此外还会对溢出错误、奇偶校验错误、帧错误和线中止(line-break)错误进行检测,并将检测到的状态附加到被写入接收FIFO 的数据中。


波特率产生

  波特率除数(baud-rate divisor)是一个22 位数,它由16 位整数和6 位小数组成。波特率发生器使用这两个值组成的数字来决定位周期。通过带有小数波特率的除法器,在足够高的系统时钟速率下,UART 可以产生所有标准的波特率,而误差很小。


数据收发

  发送时,数据被写入发送FIFO。如果UART 被使能,则会按照预先设置好的参数(波特率、数据位、停止位、校验位等)开始发送数据,一直到发送FIFO 中没有数据。一旦向发送FIFO 写数据(如果FIFO 未空),UART 的忙标志位BUSY 就有效,并且在发送数据期间一直保持有效。BUSY 位仅在发送FIFO 为空,且已从移位寄存器发送最后一个字符,包括停止位时才变无效。即 UART 不再使能,它也可以指示忙状态。BUSY 位的相关库函数是UARTBusy( ) 在UART 接收器空闲时,如果数据输入变成“低电平”,即接收到了起始位,则接收计数器开始运行,并且数据在Baud16 的第8 个周期被采样。如果Rx 在Baud16 的第8 周期仍然为低电平,则起始位有效,否则会被认为是错误的起始位并将其忽略。 如果起始位有效,则根据数据字符被编程的长度,在 Baud16 的每第 16 个周期(即一个位周期之后)对连续的数据位进行采样。如果奇偶校验模式使能,则还会检测奇偶校验位。 最后,如果Rx 为高电平,则有效的停止位被确认,否则发生帧错误。当接收到一个完整的字符时,将数据存放在接收FIFO 中。


中断控制

出现以下情况时,可使UART 产生中断:

  • FIFO 溢出错误
  • 线中止错误(line-break,即Rx 信号一直为0 的状态,包括校验位和停止位在内)
  • 奇偶校验错误
  • 帧错误(停止位不为1)
  • 接收超时(接收FIFO 已有数据但未满,而后续数据长时间不来)
  • 发送
  • 接收

  由于所有中断事件在发送到中断控制器之前会一起进行“或运算”操作,所以任意时刻 UART 只能向中断产生一个中断请求。通过查询中断状态函数UARTIntStatus( ),软件可以在同一个中断服务函数里处理多个中断事件(多个并列的if 语句)。

1.2 I2C

  I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。

  主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。

1.2.1 接口

  • SCL - 串行时钟线
  • SDA - 串行数据线接口

  SDA(串行数据线)和SCL(串行时钟线)都是双向I/O线,接口电路为开漏输出.需通过上拉电阻接电源VCC。 当总线空闲时.两根线都是高电平,连接总线的外同器件都是CMOS器件,输出级也是开漏电路.在总线上消耗的电流很小,因此,总线上扩展的器件数量主要由电容负载来决定,因为每个器件的总线接口都有一定的等效电容.而线路中电容会影响总线传输速度.当电容过大时,有可能造成传输错误.所以,其负载能力为400pF,因此可以估算出总线允许长度和所接器件数量。

  主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。

1.2.2 特点

I2C总线特点可以概括如下:

  • 在硬件上,I2C总线只需要一根数据线和一根时钟线两根线,总线接口已经集成在芯片内部,不需要特殊的接口电路,而且片上接口电路的滤波器可以滤去总线数据上的毛刺.因此I2C总线简化了硬件电路PCB布线,降低了系统成本,提高了系统可靠性。因为I2C芯片除了这两根线和少量中断线,与系统再没有连接的线,用户常用IC可以很容易形成标准化和模块化,便于重复利用。
  • I2C总线是一个真正的多主机总线,如果两个或多个主机同时初始化数据传输,可以通过冲突检测和仲裁防止数据破坏,每个连接到总线上的器件都有唯一的地址,任何器件既可以作为主机也可以作为从机,但同一时刻只允许有一个主机。数据传输和地址设定由软件设定,非常灵活。总线上的器件增加和删除不影响其他器件正常工作。
  • I2C总线可以通过外部连线进行在线检测,便于系统故障诊断和调试,故障可以立即被寻址,软件也利于标准化和模块化,缩短开发时问。
  • 连接到相同总线上的IC数量只受总线最大电容的限制,串行的8位双向数据传输位速率在标准模式下可达100Kbit/s,快速模式下可达400Kbit/s,高速模式下可达3.4Mbit/s。
  • 总线具有极低的电流消耗.抗高噪声干扰,增加总线驱动器可以使总线电容扩大10倍,传输距离达到15m;兼容不同电压等级的器件,工作温度范围宽。

1.2.3 数据传输方式

字节格式

  发送到SDA 线上的每个字节必须为8 位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位(MSB),如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL 保持低电平,迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL 后数据传输继续。


应答响应

   数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间发送器释放SDA 线(高)。在响应的时钟脉冲期间,接收器必须将SDA线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。通常被寻址的接收器在接收到的每个字节后,除了用CBUS 地址开头的数据,必须产生一个响应。当从机不能响应从机地址时(例如它正在执行一些实时函数不能接收或发送),从机必须使数据线保持高电平,主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输。

  如果从机接收器响应了从机地址,但是在传输了一段时间后不能接收更多数据字节,主机必须再一次终止传输。这个情况用从机在第一个字节后没有产生响应来表示。从机使数据线保持高电平,主机产生一个停止或重复起始条件。 如果传输中有主机接收器,它必须通过在从机发出的最后一个字节时产生一个响应,向从机发送器通知数据结束。从机发送器必须释放数据线,允许主机产生一个停止或重复起始条件。


时钟同步

  所有主机在SCL线上产生它们自己的时钟来传输I2C总线上的报文。数据只在时钟的高电平周期有效,因此需要一个确定的时钟进行逐位仲裁。

  时钟同步通过线与连接I2C 接口到SCL 线来执行。这就是说SCL 线的高到低切换会使器件开始数它们的低电平周期,而且一旦器件的时钟变低电平,它会使SCL 线保持这种状态直到到达时钟的高电平。但是如果另一个时钟仍处于低电平周期,这个时钟的低到高切换不会改变SCL 线的状态。因此SCL 线被有最长低电平周期的器件保持低电平。此时低电平周期短的器件会进入高电平的等待状态。

  当所有有关的器件数完了它们的低电平周期后,时钟线被释放并变成高电平。之后,器件时钟和SCL线的状态没有差别,而且所有器件会开始数它们的高电平周期。首先完成高电平周期的器件会再次将SCL线拉低。这样产生的同步SCL 时钟的低电平周期由低电平时钟周期最长的器件决定,而高电平周期由高电平时钟周期最短的器件决定。

1.3 SPI

  SPI接口的全称是”Serial Peripheral Interface”,意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM、FLASH、实时时钟、AD转换器,还有数字信号处理器和数字信号解码器之间。 SPI接口是在CPU和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,高位在前,低位在后,为全双工通信,数据传输速度总体来说比I2C总线要快,速度可达到几Mbps。

1.3.1 接口

  • MOSI – 主器件数据输出,从器件数据输入
  • MISO – 主器件数据输入,从器件数据输出
  • SCLK –时钟信号,由主器件产生,最大为fPCLK/2,从模式频率最大为fCPU/2
  • NSS – 从器件使能信号,由主器件控制,有的IC会标注为CS(Chip select)

  在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。在多个从器件的系统中,每个从器件需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。 SPI接口在内部硬件实际上是两个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。

​ SPI的主要构成有三根线,一个是数据输出线MOSI,一个是数据输入线MISO,一个是时钟线SCLK。

  SPI总线实现的方式分为两种:硬件IIC & 软件模拟SPI。硬件SPI有主从之分;当然,软件SPI也是标准的SPI协议,当然有分主从,但一般情况下,(MCU)软件SPI为主机模式,即发送请求接收从机的响应信息。

  可能大家不知道为什么我这MCU就是SPI主机,凭啥?你可以反过来想一下,MCU通讯的其他器件实质上都是从机,MCU要你的数据才会去找你;如果你MCU也是从机模式,从机与从机怎么通信?由于每种MCU的硬件SPI总线配置各不相同,故接下来主要讲 软件SPI。

  • SPI通信是串行同步全双工(同时收发)
  • IIC通信是串行同步半双工(单收或单发)
  • 无论是 硬件SPI 还是 软件SPI ,两种方式只是提供最基础的桥梁——提供了读、写1字节方式。如何调用IIC从器件,还是得查对应SPI从器件的datasheet。SPI总线好比中文的拼音,具体要怎么说话、说什么话,还是得看datasheet。

Ps:硬件SPI总线 & 软件SPI总线 速率方面是有点差距的。具体没有实测,但是既然是用了软件SPI总线,就不要纠结速度问题了。但是硬件SPI总线的速度也不是无上限的,而且还要根据主、从机的配置。

  以W5500为例,该芯片的SPI总线速率最高达到80Mhz。如果主控采用stm32f103,主频为72Mhz,SPI时钟最大为18Mhz。因此stm32f103无法发挥W5500完全的性能。当然,主要是受IO口翻转速率的上限限制。

  而如果使用STM40x处理器,SPI时钟使用42Mhz,使用DMA方式,可以达到回环测试17Mbps的速率(收+发),单独发送可以达到13Mbps的速率。

  也就是说,SPI的速率本身就受器件限制。如果从机SPI时钟较低,主机被限制;主机时钟较低,从机性能被限制。编写硬件SPI驱动的时候,要多注意主控芯片、从机器件 的datasheet。

Ps:外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

img

由上图的(硬件)SPI通信协议可知,时钟信号的相位和极性,决定了获取数据的方式;2*2=4,于是有四种模式;

img

CPOL决定时钟空闲状态(1为空闲高电平,0为空闲低电平)

img

CPHA决定获取数据的时钟相位(1为延迟一个相位,第二次SCLK突变为空闲状态获取数据;0为直接相位,SCLK空闲状态突变时,直接获取数据)。

​ 以上就是软件SPI的要点;实现具体的软件SPI,需要对器件的datasheet进行查阅,看是哪种模式。

模式 CPOL CPHA
MODE0 0 0
MODE1 0 1
MODE2 1 0
MODE3 1 1

下面简单列一个 CPOL=1,CPHA=1的SPI写操作

1.3.2 编程实现

  FM25L256支持SPI模式的0和3,下面为CPOL=1,CPHA=1。基本的字节读写操作如下:

/************************************************** 
* 函数名 :  FRAM_Write8bits
* 功  能 :  向存储器中写入一个字节
**************************************************/ 
static void FRAM_Write8bits(uint8_t u8Data)
{
    uint8_t i;

    for(i = 0; i < 8; i++)
    {
        FRAM_SCLK_L;
        if(u8Data & 0x80)         
            FRAM_SDI_H;
        else          
            FRAM_SDI_L;
        DelayTime(SPI_DELAY_TIME);
        FRAM_SCLK_H;
        u8Data <<= 1;
        DelayTime(SPI_DELAY_TIME);
    }
    FRAM_SCLK_L;
}

/************************************************** 
* 函数名 :  FRAM_Read8bits
* 功  能 :  从存储器中读出一个字节的数据
**************************************************/ 
static uint8_t FRAM_Read8bits(void)
{
    uint8_t i;
    uint8_t u8Data=0;
    
    for(i = 0; i < 8; i++)
    {
        FRAM_SCLK_L;
        u8Data <<= 1;
        DelayTime(SPI_DELAY_TIME);
        FRAM_SCLK_H;
        if(FRAM_SDO_READ)
            u8Data |= 0x01;
        DelayTime(SPI_DELAY_TIME);
    }
    FRAM_SCLK_L;
    return  u8Data;
}

FRAM_FM25L256程序扩展——datasheet

/************************************************** 
* 函数名 :  FRAM_Write16bits
* 功  能 :  发送16位数据
**************************************************/ 
static void FRAM_Write16bits(uint16_t u16Data)
{   
    uint32_t i;
    
    for(i = 0; i < 16; i++)
    {
        FRAM_SCLK_L;
        if(u16Data & 0x8000) 
            FRAM_SDI_H;
        else                 
            FRAM_SDI_L;
        DelayTime(SPI_DELAY_TIME);
        FRAM_SCLK_H;
        u16Data <<= 1;
        DelayTime(SPI_DELAY_TIME);
    }
    FRAM_SCLK_L;
}
/************************************************** 
* 函数名 :  FRAM_Write32bits
* 返  回 :  写入的32位数据
**************************************************/ 
static void FRAM_Write32bits(uint32_t u32Data)
{   
    uint32_t i;
    
    for(i = 0; i < 32; i++)
    {
        FRAM_SCLK_L;
        if(u32Data & 0x80000000) 
            FRAM_SDI_H;
        else              
            FRAM_SDI_L;
        DelayTime(SPI_DELAY_TIME);
        FRAM_SCLK_H;
        u32Data <<= 1;
        DelayTime(SPI_DELAY_TIME);
    }
    FRAM_SCLK_L;
}

/************************************************** 
* 函数名 :  FRAM_Read4Bytes
* 功  能 :  读取指定地址的4字节数据
* 入  参 :  address  : 读取数据的首地址
* 返  回 :  uint32_t : 读出的32位数据
**************************************************/ 
uint32_t FRAM_Read4Bytes(uint32_t address)
{
    uint32_t i = 0;
    uint32_t temp = 0;
    
    FRAM_SCLK_L;
    FRAM_CS_L;
    FRAM_Write8bits(FRAM_CMD_READ);
    FRAM_Write16bits((uint16_t)(address));
    for(i = 0; i < 4; i++)
    {
        temp  = temp << 8;
        temp |= FRAM_Read8bits();
    }
    FRAM_SCLK_L;
    FRAM_CS_H;
    
    return temp;
}

/************************************************** 
* 函数名 :  FRAM_Write4Bytes
* 功  能 :  写入指定地址的4字节数据
* 入  参 :  address  : 写入数据的首地址
*           FramData : 写入的32位数据
**************************************************/ 
void FRAM_Write4Bytes(uint32_t address, uint32_t FramData)
{
    uint8_t u8Temp = 0;
    
    FRAM_SCLK_L;
    FRAM_CS_L;
    FRAM_Write8bits(FRAM_CMD_WREN);
    FRAM_SCLK_L;
    FRAM_CS_H;
    
    FRAM_SCLK_L;
    FRAM_CS_L;
    FRAM_Write8bits(FRAM_CMD_WRITE);
    FRAM_Write16bits((uint16_t)(address));
    FRAM_Write32bits(FramData);
    FRAM_SCLK_L;
    FRAM_CS_H;
    
    while(1)
    {
        FRAM_SCLK_L;
        FRAM_CS_L;
        FRAM_Write8bits(FRAM_CMD_RDSR);	//读取状态寄存器
        u8Temp = FRAM_Read8bits();
        FRAM_SCLK_L;
        FRAM_CS_H;
		
		//该位表示写入启用状态(为0时,WPEN和 /WP 寄存器标志位不起作用)
		//防止软件误改动铁电芯片寄存器配置
        if(!(u8Temp & 0x02))	
        {
            break;
        }
    }
}

1.3.3 优缺点

  • 协议简单,相对数据速率高。
  • 占用的Pin口较多
  • 没有指定的流控制,没有应答机制确认是否接收到数据。

二、速率对比

  • UART: 无限制,常用9600、115200bps等保证双方通信速度相同。
  • IIC:通讯速率400Kbps
  • CAN:一般为1Mbps
  • SPI:通信速率为 fosc/4;其理论传输速度可达几Mb/s(其速率可以通过限制其SPI的时钟来实现限制速率)
    • 缺点:抗干扰能力差。SPI采用的是单端非平衡的传输方式,即传输的数据位的电压电平是以公共地作为参考的。在这种传输方式中对于已进入信号中的干扰是无法消除和减弱的。而信号在传输过程中总会受到干扰,而且距离越长干扰越严重,以致于信号传输产生错误。在这种条件下,信号传输就变得毫无意义了。另外,由于单端非平衡传输方式以公共地作为参考点,地线作为信号回流线,因此也存在信号电流。当传输线两端的系统之间存在交流电位差时,这个电位差将直接窜到信号中,形成噪声干扰。所以,为了解决抗干扰问题,通常采用平衡传输(balanced transmission)方式,这里采用比较常见的RS-422。
    • 应用:读写flash(存有字库,图片等等)芯片,与触摸屏控制器通信,还有就是读写sd卡了,你手机里的sd卡就是通过spi和处理器传数据的,目前高速都用SDIO了。
  • SDIO: 10M及已上
  • SDRAM:(非总线)16位的,100m频率就是1.6Gbit读写
  • PCI:(网卡)传输速率高最大数据传输率为132MB/s(工作在33MHz 频率之下),当数据宽度升级到64位,数据传输率可达264MB/s。这是其他总线难以比拟的。它大大缓解了数据I/O瓶颈,使高性能CPU的功能得以充分发挥,适应高速设备数据传输的需要。
  • PCI Express 2.0 : 理论值 10Gbps,实际大于100MB
  • USB2.0 : 一般30~40MB
  • Ethenet :一般70~80MB

三、常见通讯总线疑问

3.1 USART & UART

  • USART:通用同步和异步收发器
  • UART:通用异步收发器

  当进行异步通信时,这两者是没有区别的。区别在于USART比UART多了同步通信功能。 这个同步通信功能可以把USART当做SPI来用,比如用USART来驱动SPI设备。

  • 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
  • 异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

同步是阻塞模式,异步是非阻塞模式。

Ps:其中SPI 、IIC为同步通信,Uart为异步通信, Usart为同步&异步通信。

3.2 单工、半双工、全双工

  • 单工数据传输只支持数据在一个方向上传输;
  • 半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输;它实际上是一种切换方向的单工通信;
  • 全双工数据通信允许数据同时在两个方向上传输;因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

Ps:I2C是半双工,SPI的全双工,Usart是全双工;串口232是全双工 ,串口485是半双工。

3.3 波特率 计算 发送速率

  • B = byte表示“字节”
  • b = bit表示“比特”
  • bps就是比特每秒

1 Kb=1024 bit,1 KB=1024 byte,1 byte=8 bit

举例,115200bps就是每秒传输115200比特(115200bit),所以115200bps=每秒112.5kb=每秒14.0625kB。


举例计算速率

  • 波特率115200 = 115200 (位/秒)
  • 根据常规串口发送协议,一个起始位,8个数据位,0个校验位,1个停止位,共计10位二进制数
  • 如果没有校验位,就应该除以 10,得到的是每秒字节数:
    • 波特率115200 = 115200 (位/秒) = 11520 (字节/秒)
    • 再除以 1024,就是每秒 KB 数
    • 波特率115200 = 115200 (位/秒) = 11.25 (KB/秒)
  • 如果有一位奇偶校验位,就应该除以 11,得到的是每秒字节数。
    • 最后:波特率115200 = 115200 (位/秒) = 10.27 (KB/秒)

3.4 RS485 & Modbus

  • RS485 :是一个物理接口,简单的说是硬件。
  • MODBUS :是一种国际标准的通讯协议,用于不同厂商之间的设备交换数据(一般是工业用途);所谓协议,也可以理解为上面有人说的“语言”吧,简单的说是软件。

  • RS485属于有线传输,所以就要硬件传输媒介,实际就是两根线就可以了,在这两根线上传输的实际是同一个信号,只是发送端把这个信号一分为二,不过在接收端会把它还原为原来的信号,这样做的好处还要得和RS232来比较;RS232也需要两根线,更多的时候还要加上地线,所以是三根线,地线咱不管它,其余的两根只有一根线传输的数据信号,而另一根传输的时钟,也就是信号原来什么样发送端就怎样发送出来,同样接收端也做同样的处理。所以485的接收端可以把信号在传输过程中引入的干扰就可以抵消掉,而232的接收端不能,所以485的抗干扰能力强可以传输信号上千米,而232只能传输十几米。
  • MODBUS只是通信协议的一种,就像汉语和英语一样,就是一种交流的语言,一种机器之间交流的语言。那么在交流之前肯定要有沟通的桥梁吧,那就是传输媒介485或232或其他电气规则,同一种协议可以用不同的传输媒介方式,如485或232;但是同一传输线路上不能同时存在两种协议。

  一般情况下,两台设备通过MODBUS协议传输数据: 最早是用RS232C作为硬件接口(也就是普通电脑上的串行通讯口(串口)); 也有用RS422的;也有常用的RS485,这种接口传输距离远,在一般工业现场用的比较多。

3.5 RS485 & CAN

  为什么会有这个的比较?

其实,RS485和CAN是很相似的:

  1. 均为差分信号,抗干扰强;(即,都为半双工)
  2. 均为双线连接
  3. 均可挂多个子设备

CAN总线特点:

  1. 国际标准的工业级现场总线,传输可靠,实时性高;
  2. 传输距离远(最远10Km),传输速率快(最高1MHz bps);
  3. 单条总线最多可接110个节点,并可方便的扩充节点数;
  4. 多主结构,各节点的地位平等,方便区域组网,总线利用率高;
  5. 实时性高,非破坏总线仲裁技术,优先级高的节点无延时;
  6. 出错的CAN节点会自动关闭并切断和总线的联系,不影响总线的通讯;
  7. 报文为短帧结构并有硬件CRC校验,受干扰概率小,数据出错率极低;
  8. 自动检测报文发送成功与否,可硬件自动重发,传输可靠性很高;
  9. 硬件报文滤波功能,只接收必要信息,减轻cpu负担,简化软件编制;
  10. 通讯介质可用普通的双绞线,同轴电缆或光纤等;
  11. CAN总线系统结构简单,有极高的性价比。

RS485接口标准特点:

  1. RS-485的电气特性:逻辑”1”以两线间的电压差为+(2-6)V表示;逻辑”0”以两线间的电压差为-(2-6)V表示。接口信号电平比RS-232-C降低了,就不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL 电路连接。
  2. RS-485的数据最高传输速率为10Mbps
  3. RS-485接口是采用平衡驱动器和差分接收器的组合,抗共模干能力增强,即抗噪声干扰性好。
  4. RS-485接口的最大传输距离标准值为4000英尺,实际上可达 3000米,另外RS-232-C接口在总线上只允许连接1个收发器,即单站能力。而RS-485接口在总线上是允许连接多达128个收发器。即具有多站能力,这样用户可以利用单一的RS-485接口方便地建立起设备网络。但RS-485总线上任何时候只能有一发送器发送。
  5. 因RS-485接口具有良好的抗噪声干扰性,长的传输距离和多站能力等上述优点就使其成为首选的串行接口。
  6. 因为RS485接口组成的半双工网络,一般只需二根连线,所以RS485接口均采用屏蔽双绞线传输。

CAN总线与RS485的比较:

  • 速度与距离:CAN与RS485以1Mbit/S的高速率传输的距离都不超过100M,可谓高速上的距离差不多。但是在低速时CAN以5Kbit/S时,距离可达10KM,而485再低的速率也只能到1219米左右(都无中继)。可见CAN在长距离的传输上拥有绝对的优势。
  • 总线利用率:RS485是单主从结构,就是一个总线上只能有一台主机,通讯都由它发起的,它没有下命令,下面的节点不能发送,而且要发完即答,受到答复后,主机才向下一个节点询问,这样是为了防止多个节点向总线发送数据,而造成数据错乱。而CAN-bus是多主从结构,每个节点都有CAN控制器,多个节点发送时,以发送的ID号自动进行仲裁,这样就可以实现总线数据不错乱,而且一个节点发完,另一个节点可以探测到总线空闲,而马上发送,这样省去了主机的询问,提高了总线利用率,增强了快速性。所以在汽车等实性要求高的系统,都是用CAN总线,或者其他类似的总线。
  • 错误检测机制:RS485只规定了物理层,而没有数据链路层,所以它对错误是无法识别的,除非一些短路等物理错误。这样容易造成一个节点破坏了,拼命向总线发数据(一直发1),这样造成整个总线瘫痪。所以RS485一旦坏一个节点,这个总线网络都挂。而CAN总线有CAN控制器,可以对总线任何错误进行检测,如果自身错误超过128个,就自动闭锁。保护总线。如果检测到其他节点错误或者自身错误,都会向总线发送错误帧,来提示其他节点,这个数据是错误的。大家小心。这样CAN总线一旦有一个节点CPU程序跑飞了,它的控制器自动闭锁。保护总线。所以在安全性要求高的网路,CAN是很强的。
  • 价格与培训成本:CAN器件的价格大约是485的2倍这样,485的通讯从软件上是很方便的,只要懂串行通讯,就可以编程,而CAN需要底层工程师了解CAN复杂的层,编写上位机软件也要了解CAN的协议。可谓培训成本较高。
  • CAN总线通过CAN控制器接口芯片82C250的两个输出端CANH和CANL与物理总线相连,而CANH端的状态只能是高电平或悬浮状态,CANL端只能是低电平或悬浮状态。这就保证不会出现象在RS-485网络中,当系统有错误,出现多节点同时向总线发送数据时,导致总线呈现短路,从而损坏某些节点的现象。而且CAN节点在错误严重的情况下具有自动关闭输出功能,以使总线上其他节点的操作不受影响,从而保证不会出现象在网络中,因个别节点出现问题,使得总线处于“死锁”状态。
  • CAN具有完善的通信协议,可由CAN控制器芯片及其接口芯片来实现,从而大大降低了系统的开发难度,缩短了开发周期,这些是只仅仅有电气协议的RS-485所无法比拟的。
特性 RS-485 CAN-bus
单点成本 低廉 稍高
系统成本 较低
总线利用率
网络特性 单主网络 多主网络
数据传输率
容错机制 可靠的错误处理和检错机制
通讯失败率 极低
节点错误的影响 导致整个网络的瘫痪 无任何影响
通讯距离 <1.5km 可达10km(5kbps)
网络调试 困难 非常容易
开发难度 标准Modbus协议 标准CAN-bus协议
后期维护成本