【一文吃透】常见通信协议(SPI、IIC、UART、CAN)[面试重点]
目录一、四种通信方式区别二、SPI协议全双工、速度快1.SPI特性2.SPI工作流程3.SPI四种工作模式数据传输流程三、IIC协议半双工、速度中等1.IIC数据接口2.IIC主要特点3.工作流程介绍1主机向从机写入数据过程2主机读取从机数据过程4.IIC常见问题1为什么Open-Drain开漏输出需要上拉电阻2为什么IIC需要漏极开路3软件IIC和硬件IIC的区别四、URAT协议全双工、速度慢1.UART协议概念2.UART的帧格式1为什么UART的传输需要起始位2UART基本的数据形式3.UART的波特率1什么是波特率2如何换算波特率4.RS232标准5.RS485标准6.三者的优缺点五、CAN通信半双工1.CAN通信概念2.CAN通信工作流程3. CAN通信的应用领域4. CAN帧格式与标识符5. CAN通信模式6. 使用HAL库实现CAN通信6.1 STM32 CAN通信配置:6.2 整体代码一、四种通信方式区别首先介绍一下四种通信方式的区别在面试中也常见这些问题方便大家理解记忆。SPISerial Peripheral Interface是一种同步的串行通信协议需要4根线MISO、MOSI、SCLK和CS。SPI通信速度快但只能在短距离内通信且只能支持单主设备和多从设备的通信方式。IICInter-Integrated Circuit是一种同步的串行通信协议需要2根线SCL和SDA。IIC通信速度较慢但可以在长距离内通信且可以支持多主设备和多从设备的通信方式。UARTUniversal Asynchronous Receiver/Transmitter是一种异步的串行通信协议需要2根线TX和RX。UART通信速度较慢但可以在长距离内通信且可以支持点对点的通信方式。CAN为了保证传输的安全性相较于前面三种方法使用了大量的手段保证数据及时、准确的传输。同时使用识别码解决总线冲突的问题。这保证的优先级高的设备先通讯。这也是为什么CAN能够用于工业、汽车等需要安全性高的领域。二、SPI协议全双工、速度快SPI 是英语Serial Peripheral interface的缩写顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。SPI是一种高速的全双工同步的通信总线可以在同一时间发送和接收数据并且没有定义速度限制通常能达到甚至超过10M/bps。在芯片的管脚上只占用四根线节约了芯片的管脚同时为PCB的布局上节省空间提供方便主要应用在 EEPROMFLASH实时时钟AD转换器还有数字信号处理器和数字信号解码器之间。1.SPI特性SPI总线包括4条逻辑线定义如下MISOMaster input slave output主机输入从机输出数据来自从机MOSIMaster output slave input主机输出从机输入数据来自主机SCLKSerial Clock串行时钟信号由主机产生发送给从机SSSlave Select片选信号由主机发送以控制与哪个从机通信通常是低电平有效信号。其他制造商可能会遵循其他命名规则但是最终他们指的相同的含义。以下是一些常用术语MISO也可以是SDIDIN或DI;MOSI也可以是SDODOUT或DO;NSS也可以是CECS或SSEL;SCLK也可以是SCK;本文将按照以下命名进行讲解[MISO, MOSI, SCKCS]2.SPI工作流程SPI是一个同步的数据总线它是用一条单独的数据线和一条单独的时钟信号来保证发送端和接收端的完美同步。时钟是一个振荡信号它告诉接收端在确切的时机对数据线上的信号进行采样。SPI有主、从两种模式通常由一个主模块主机和一个或多个从模块丛机组成SPI不支持多主机主模块选择一个从模块进行同步通信从而完成数据的交换。提供时钟的为主设备Master接收时钟的设备为从设备SlaveSPI接口的读写操作都是由主设备发起当存在多个从设备时通过各自的片选信号进行管理。数据的采集时机可能是时钟信号的上升沿从低到高或下降沿从高到低。整体的传输大概可以分为以下几个过程1、主设备发起信号将CS/SS拉低启动通信。2、主设备通过发送时钟信号来告诉从设备进行写数据或者读数据操作采集时机可能是时钟信号的上升沿从低到高或下降沿从高到低因为SPI有四种模式后面会讲到它将立即读取数据线上的信号这样就得到了一位数据1bit。3、主机Master将要发送的数据写到发送数据缓存区Menory缓存区经过移位寄存器缓存长度不一定看单片机配置串行移位寄存器通过MOSI信号线将字节一位一位的移出去传送给从机同时MISO接口接收到的数据经过移位寄存器一位一位的移到接收缓存区。4、从机Slave也将自己的串行移位寄存器缓存长度不一定看单片机配置中的内容通过MISO信号线返回给主机。同时通过MOSI信号线接收主机发送的数据这样两个移位寄存器中的内容就被交换。例如下图示例中简单模拟SPI通信流程主机拉低CS片选信号启动通信并且产生时钟信号上升沿触发边沿信号主机在MOSI线路一位一位发送数据0X53在MISO线路一位一位接收数据0X46如下图所示SPI是“全双工”具有单独的发送和接收线路 SPI只有主模式和从模式之分没有读和写的说法可以在同一时间发送和接收数据。另外SPI的接收硬件可以是一个简单的移位寄存器。这比异步串行通信所需的完整UART要简单得多并且更加便宜如果只进行写操作主机只需忽略接收到的字节反之若主机要读取从机的一个字节就必须发送一个空字节来引发从机的传输。也就是说你发一个数据必然会收到一个数据你要收一个数据必须也要先发一个数据。数据在传输中高位在先还是低位在先SPI协议并无明确规定但是数据要在主从机中正确传输自然双方要先约定好一般会采用高位在先(MSB)方式传输。3.SPI四种工作模式除了配置串行时钟速率频率外SPI主设备还需要配置时钟极性和时钟相位。时钟极性 CKP/Clock Polarit根据硬件制造商的命名规则不同时钟极性通常写为CKP或CPOL。时钟极性和相位共同决定读取数据的方式比如信号上升沿读取数据还是信号下降沿读取数据CKP可以配置为1或0。这意味着您可以根据需要将时钟的默认状态IDLE设置为高或低。极性反转可以通过简单的逻辑逆变器实现。您必须参考设备的数据手册才能正确设置CKP和CKE。CKP 0时钟空闲IDLE为低电平 0CKP 1时钟空闲IDLE为高电平1时钟相位 CKE /Clock Phase (Edge)除配置串行时钟速率和极性外SPI主设备还应配置时钟相位或边沿。根据硬件制造商的不同时钟相位通常写为CKE或CPHA顾名思义时钟相位/边沿也就是采集数据时是在时钟信号的具体相位或者边沿CKE 0在时钟信号SCK的第一个跳变沿采样CKE 1在时钟信号SCK的第二个跳变沿采样此处附上一组软件模拟SPI 通信传输数据的代码方便各位理解其实现的方法。//SPI发送数据val为要发送的数据 void SPI_Send(u8 val) { u8 recv_data 0, i 0;//将接受数据清零方便直接或运算接受数据 SCK 0;//时钟线拉低 for(i0; i8; i) //传输数据先发高位 { //准备数据 if(val (1(7-i))) //通过1左移7位然后相与,判断数据最高位是1还是0 { MOSI 1; //数据为1 } else { MOSI 0; //数据为0 } delay_us(5); SCK 1; //时钟线拉高准备接收数据 delay_us(5); //高电平区间接收数据此处不重要但必须有 if(MISO 1) //收到的为1 { recv_data | (1(7-i));//将数据位通过或运算保存。先保持高位 } SCK 0;//时钟线拉低 } } //SPI接收数据 u8 SPI_Receive(void) { u8 recv_data 0, i 0; // u8 val 0x00; RC522_SCK 0; for(i0; i8; i) //发送数据此处不重要但必须有 { //准备数据 // if(val (1(7-i))) //1 // { // MOSI 1; //数据为1 // } // else // { // MOSI 0; //数据为0 // } MOSI 0; //输出线清零 delay_us(5); SCK 1; //时钟线拉高准备接收数据 delay_us(5); //高电平区间接收数据 if(MISO 1) //收到的为1 { recv_data | (1(7-i));//将数据位通过或运算保存。先保持高位 } SCK 0; } return recv_data; //返回接收到的数据 }数据传输流程首先主机和从机都选择同一传输模式。然后主机片选拉低选中从机。接着在时钟的驱动下 MOSI发送数据同时MISO读取接收数据。最后完成传输取消片选。/* * 函数名 void SPI_WriteByte(uint8_t data) * 输入参数 data - 要写的数据 * 输出参数无 * 返回值无 * 函数作用模拟 SPI 写一个字节 */ SPI写1 Byte循环8次每次发送1 Bit void SPI_WriteByte(uint8_t data) { uint8_t i 0; uint8_t temp 0; for(i0; i8; i) { temp ((data0x80)0x80)? 1:0; //将data最高位保存到temp data data1; //data左移一位将次高位变为最高位用于下次取最高位 SPI_CLK(0); //CPOL0 //拉低时钟即空闲时钟为低电平 CPOL0 SPI_MOSI(temp); //根据temp值设置MOSI引脚的电平 SPI_Delay(); //简单延时可以定时器或延时函数实现 SPI_CLK(1); //CPHA0 //拉高时钟 W25Q64只支持SPI模式0或1即会在时钟上升沿采样MOSI数据 SPI_Delay(); } SPI_CLK(0); //最后SPI发送完后拉低时钟进入空闲状态 } /* * 函数名 uint8_t SPI_ReadByte(void) * 输入参数 * 输出参数无 * 返回值读到的数据 * 函数作用模拟 SPI 读一个字节 */ SPI读1 Byte循环8次每次接收1 Bit uint8_t SPI_ReadByte(void) { uint8_t i 0; uint8_t read_data 0xFF; for(i0; i8; i) { read_data read_data 1; //“腾空” read_data最低位8次循环后read_data将高位在前 SPI_CLK(0); //拉低时钟即空闲时钟为低电平 SPI_Delay(); SPI_CLK(1); SPI_Delay(); if(SPI_MISO()1) { read_data read_data 1; } } SPI_CLK(0); //最后SPI读取完后拉低时钟进入空闲状态 return read_data; }前面提到SPI传输可以看作一个虚拟的环形拓扑结构即输入和输出同时进行。在前面“ SPI_WriteByte()”函数里发送了1 Byte也应该接收1 Byte只是代码中忽略了接收引脚MISO的状态 在前面“ SPI_ReadByte()”函数里接收了1 Byte也应该发送1 Byte只是代码中忽略了发送引脚MOSI的内容。有些场景 SPI需要同时读写因此还需要编写SPI同时读写函数。/* * 函数名 uint8_t SPI_WriteReadByte(uint8_t data) * 输入参数 data - 要写的一个字节数据 * 输出参数无 * 返回值读到的数据 * 函数作用模拟 SPI 读写一个字节 */SPI读和写1 Byte循环8次每次发送和接收1 Bit uint8_t SPI_WriteReadByte(uint8_t data) { uint8_t i 0; uint8_t temp 0; uint8_t read_data 0xFF; for(i0;i8;i) { temp ((data0x80)0x80)? 1:0; //将data最高位保存到temp data data1; //data左移一位将次高位变为最高位用于下次取最高位 read_data read_data1; //“腾空” read_data最低位8次循环后read_data将高位在前 SPI_CLK(0); SPI_MOSI(temp); SPI_Delay(); SPI_CLK(1); SPI_Delay(); if(SPI_MISO()1) { //读取MISO上的数据保存到当前read_data最低位 read_data read_data 1; } } SPI_CLK(0); return read_data; }三、IIC协议半双工、速度中等IIC(InterIntegrated Circuit)总线是一种由NXP原PHILIPS公司开发的两线式串行总线用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信在小数据量场合使用传输距离短任意时刻只能有一个主机等特性。在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送高速 IIC 总线一般可达 400kbps 以上。IIC是为了与低速设备通信而发明的所以IIC的传输速率比不上SPI1.IIC数据接口IIC只有两个总线 一条是双向的串行数据线SDA一条是串行时钟线SCLSDA(Serial data)是数据线D代表Data也就是数据Send Data也就是用来传输数据。SCL(Serial clock line)是时钟线C代表Clock也就是时钟用来控制数据发送的时序。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上各设备的时钟线SCL接到总线的SCL上。I2C总线上的每个设备都自己一个唯一的地址来确保不同设备之间访问的准确性。2.IIC主要特点通常我们为了方便把IIC设备分为主设备和从设备基本上谁控制时钟线即控制SCL的电平高低变换谁就是主设备。IIC主设备功能主要产生时钟产生起始信号和停止信号IIC从设备功能可编程的IIC地址检测停止位检测IIC的一个优点是它支持多主控(multimastering) 其中任何一个能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然在任何时间点上只能有一个主控。支持不同速率的通讯速度标准速度(最高速度100kHZ),快速最高400kHZ。SCL和SDA都需要接上拉电阻 (大小由速度和容性负载决定一般在3.3K-10K之间) 保证数据的稳定性减少干扰。IIC是半双工而不是全双工 同一时间只可以单向通信为了避免总线信号的混乱要求各设备连接到总线的输出端时必须是漏极开路OD输出或集电极开路OC输出。IIC的高阻态漏极开路Open Drain即高阻状态适用于输入/输出其可独立输入/输出低电平和高阻状态若需要产生高电平则需使用外部上拉电阻高阻状态高阻状态是三态门电路的一种状态。逻辑门的输出除有高、低电平两种状态外还有第三种状态——高阻状态的门电路。电路分析时高阻态可做开路理解。我们知道IIC的所有设备是接在一根总线上的那么我们进行通信的时候往往只是几个设备进行通信那么这时候其余的空闲设备可能会受到总线干扰或者干扰到总线怎么办呢为了避免总线信号的混乱IIC的空闲状态只能有外部上拉 而此时空闲设备被拉到了高阻态也就是相当于断路 整个IIC总线只有开启了的设备才会正常进行通信而不会干扰到其他设备。3.工作流程介绍1主机向从机写入数据过程Start: IIC开始信号表示开始传输。DEVICE_ADDRESS:: 从设备地址,就是7位从机地址。R/W W(write)为写R(read)为读。ACK 应答信号。WORD_ADDRESS 从机中对应的寄存器地址 比方说访问 OLED中的 某个寄存器。DATA: 发送的数据。STOP: 停止信号。结束IIC通信。流程介绍1、主机首先产生START信号2、然后发送一个从机地址这个地址共有7位紧接着的第8位是数据方向位(R/W)“0”表示主机向从机发送数据(写)“1”表示主机从从机接收数据(读)3、主机发送地址时总线上的每个从机都将这7位地址码与自己的地址进行比较若相同则认为自己正在被主机寻址根据R/W位将自己确定为发送器和接收器4、这时候主机等待从机的应答信号(ACK)5、当主机收到应答信号时发送要访问从机的那个地址 继续等待从机的应答信号6、当主机收到应答信号时发送N个字节的数据继续等待从机的N次应答信号7、主机产生停止信号结束传输过程。还有一种情况是从机发送非应答信号表示接受完毕后主机产生停止信号结束传输过程。2主机读取从机数据过程1、主机首先产生START信号2、然后紧跟着发送一个从机设备地址注意此时该地址的第8位为0表明是向从机写命令3、这时候主机等待从机的应答信号(ACK)4、当主机收到应答信号时发送要访问的寄存器地址继续等待从机的应答信号5、当主机收到应答信号后主机重新发送一个开始start信号然后紧跟着发送一个从机设备地址注意此时该地址的第8位为1表明将主机设置成接收模式开始读取数据从机由接收变为发送6、这时候主机等待从机的应答信号当主机收到应答信号时就可以接收n个字节的数据当接收完成后主机发送非应答信号NACK表示不再接收数据7、主机进而产生停止信号结束传送过程。4.IIC常见问题1为什么Open-Drain开漏输出需要上拉电阻开漏Pin不连接外部的上拉电阻则只能输出低电平。当输出电平为低时N沟道MOS管是导通的这样在Vcc和GND之间有一个持续的电流流过上拉电阻R和三极管Q1。这会影响整个系统的功耗。采用较大值的上拉电阻可以减小电流。但是大的阻值会使输出信号的上升时间变慢。即上拉电阻R pull-up的阻值 决定了逻辑电平转换的沿的速度。阻值越大速度越低功耗越小。反之亦然。2为什么IIC需要漏极开路防止短路如果不设为开漏而设为推挽几个设备连在同一条总线上这时某一设备的某个IO输出高电平另有一台设备的某一个IO输出低电平这时你会发现这两个IO的VCC和GND短路了但是开漏就不会有这个问题。增强端口扇出能力、降低功耗IC为增强端口扇出能力而设计为漏极开路样式使用时将该端口设为低电平有效的灌电流模式能得到最大输出电流同时IC功耗最低。此类端口当输出高电平则需要外接上拉电阻。利用“线与”判断总线占用状态可以将多个开漏输出的Pin脚连接到一条线上形成“与逻辑”关系,即“线与”功能任意一个变低后开漏线上的逻辑就为0了。这也是I2CSMBus等总线判断总线占用状态的原理。如果总线上的一个A设备将SDA拉高这时总线上另一个B设备已将SDA拉低这时由于100所以A设备检查SDA的时候会发现不是高电平而是低电平这就表明总线上已经有其他设备占用总线了A只好放弃如果检测是高电平那就可以使用。增加驱动能力如果在漏极drain_output接上拉电阻则可以进行电平转换且驱动能力较强。利用外部电路的驱动能力减少IC内部的驱动。当IC内部MOSFET导通时驱动电流是从外部的VCC流经R pull-up MOSFET到GND。IC内部仅需很下的栅极驱动电流。控制输出高电平大小可以利用改变上拉电源的电压改变传输电平。3软件IIC和硬件IIC的区别软件IIC软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC用软件控制管脚状态以模拟I2C通信波形软件模拟寄存器的工作方式。硬件IIC一块硬件电路硬件I2C对应芯片上的I2C外设有相应I2C驱动电路其所使用的I2C管脚也是专用的硬件固件I2C是直接调用内部寄存器进行配置。硬件I2C的效率要远高于软件的而软件I2C由于不受管脚限制接口比较灵活。STM32硬件I2C与软件模拟I2C超详解_stm32 i2c-CSDN博客四、URAT协议全双工、速度慢1.UART协议概念UART的全称是通用异步收发器Universal Asynchronous Receiver/TransmitterUniversal通用性体现在UART使用范围广上作为一个通用的接口协议UART广泛的应用在各类MCU和SOC产品上。Asynchronous异步性体现在“不需要额外的时钟线进行数据的同步传输”即只要信号拉低即可开始传送数据而另一些通讯协议需要引入时钟信号来进行操作如SPI需要在时钟的边沿发送数据。Receiver/Transmitter收发器则更好理解即一个数据的发送方和一个数据的接收方也意味着在数字IC设计中需要分别设计Receiver和Transmitter。2.UART的帧格式UART的一帧由起始位、数据位、校验位和停止位组成。数据逐位传输如下图所示1为什么UART的传输需要起始位因为UART没有控制线要让接收方知道什么时候开始接收数据需要一些手段UART数据的传输中只有一根线所以在发送数据之前先发一位逻辑“0”作为数据发送的起始标志接收方在空闲时当检测到有一个低电平则开始接逐位接收数据。2UART基本的数据形式默认无传输数据时为高电平当信号拉低传输线上的电平拉低意味着开始进行数据传输紧接着起始位的是数据位它可以是5、6、7或8位。UART的“校验位”紧挨着“数据位”采用奇偶校验方式根据设置校验位可以存在也可以不存在。UART将停止位作为停止标志是在数据位没有校验位和校验位有校验位之后发送1~2位的逻辑“1”高电平。当发送完停止位之后UART总线进入空闲。3为什么UART的数据位可变因为UART是一种低速总线每多发一位都占用不少的时间由传输波特率决定所以可以根据传输数据的特点采用不同位宽以节约数据传输的时间。3.UART的波特率如果从更高的level审视UART传输协议如嵌入式开发者的角度我们会发现在使用具体的UART协议前我们需要对发送端和接收端进行波特率的同步以此来确保发射端的数据可以在接收端得到正确的采集。常用的波特率可以是3001200240096001920038400115200这些数意味着什么呢别着急我们接下来要讨论这个内容。1什么是波特率波特率等于每秒钟传输的数据位数假如我们的全局时钟频率为100MHz波特率设置为9600那么意味着每秒该UART传输协议可以传输9600bits的数据换句话说传输1比特需时间约为10^9(ns)/9600104166(ns)。2如何换算波特率书接上文时钟频率假如为100MHz这意味着我们的时钟周期为10ns因此10416个时钟周期我们就可以传输1bit数据换言之我们需要一个大小为10416的分频电路来对100MHz时钟进行处理因此在设计UART的过程中我们需要使用分频电路依据波特率处理全局时钟依据分频后的时钟节奏来发送数据和接收数据。4.RS232标准RS232 是美国电子工业协会制定的短距离串行通信物理层标准规定了接口的引脚定义、电气特性如电平和机械结构需配合 UART 使用。工作流程信号转换UART 输出的 TTL 电平0V 低3.3V/5V 高通过 MAX232 等芯片转换为 RS232 电平-15V~-3V 高3V~15V 低。数据传输通过 DB9/DB25 接口的 TX/RX 引脚在两个设备间直接传输单端信号以地为参考。反向转换接收端通过 MAX232 将 RS232 电平转回 TTL 电平传给本地 UART 解析。5.RS485标准RS485 也是物理层标准主打长距离、多节点串行通信同样需依赖 UART 实现数据处理。工作流程信号转换UART 输出的 TTL 电平通过 MAX485 等芯片转换为差分信号A、B 两根线的电压差表示逻辑AB 为高AB 为低。总线控制发送时使能 MAX485 的发送端将差分信号传入总线接收时切换为接收端读取总线上的差分信号。反向转换接收端 MAX485 将差分信号转回 TTL 电平交给 UART 解析后传给 CPU。6.三者的优缺点UART通用异步收发传输器优缺点UART 的核心价值是 “处理串行数据格式”而非直接负责长距离传输优缺点均围绕其 “模块属性” 展开。优点集成度高成本低几乎所有 MCU微控制器、芯片都内置 UART 模块无需额外购买独立芯片能大幅降低硬件成本和 PCB 面积。协议灵活适配性强可自定义数据帧格式如数据位 5-9 位、停止位 1-2 位、校验位有无能适配不同速率如 9600bps、115200bps的简单通信需求。硬件逻辑简单仅需 TX发送、RX接收两根信号线即可实现点对点通信无需复杂的总线控制或电平转换逻辑板级内。缺点电气接口不统一UART只是对信号的时序进行了定义而未定义接口的电气特性;UART通信时一般直接使用处理器使用的电平即TTL电平但不同的处理器使用的电平存在差异所以不同的处理器使用UART通信时一般不能直接相连;UART没有规定不同器件连接时连接器的标准所以不同器件间通过UART通信时连接很不方便。传输距离极短输出的是 TTL 电平0V/3.3V/5V信号衰减快仅支持板级通信1 米或近距离点对点10 米需优化布线无法满足长距离需求。抗干扰能力弱TTL 电平信号幅度低易受外部电磁干扰如电机、电源噪声影响导致数据传输错误。不支持多节点本质是 “点对点” 通信无法直接实现多设备共线连接需额外加总线协议如 MODBUS 才能扩展节点。RS232短距离物理层标准优缺点RS232 的核心价值是 “解决短距离点对点的电平匹配”优缺点聚焦 “短距离场景的适用性”。优点兼容性强应用广泛是传统设备的经典接口如早期 PC 的 DB9 串口、Modem、路由器配置口市面上大量老旧设备仍保留 RS232 接口适配成本低。实现简单无需总线控制仅需 TX、RX、GND 三根线即可实现点对点通信无需像 RS485 那样控制 “发送 / 接收使能”软件逻辑简单。电平辨识度高采用 ±3V~±15V 的宽电平范围与 TTL 电平0V/3.3V差异大能减少 “电平模糊” 导致的误判如轻微噪声不会触发逻辑翻转。缺点传输距离短速率受限最大传输距离仅15 米速率 20kbps 时速率提升后距离会进一步缩短如 115200bps 时可能仅 1-2 米无法满足长距离需求。抗干扰能力弱采用 “单端信号”以 GND 为参考易受 “共模干扰”如两根设备地线电位差影响工业环境如工厂电机附近中传输稳定性差。仅支持点对点节点数少一个 RS232 接口只能连接两个设备无法实现多设备共线通信如多个传感器无法共用一根 RS232 总线。电平要求特殊需 ±15V 电源供电部分芯片如 MAX232 可通过电荷泵从 5V 转换但会增加电路复杂度无法直接使用 MCU 的 3.3V/5V 电源。RS485长距离多节点物理层标准优缺点RS485 的核心价值是 “解决长距离、多节点的稳定传输”优缺点围绕 “工业级可靠性” 展开。优点传输距离长速率适配性好最大传输距离可达1200 米速率 100kbps 时速率提升后仍能保持中距离传输如 115200bps 时约 100 米兼顾 “长距离” 和 “高速率” 需求。抗干扰能力极强采用 “差分信号”通过 A、B 两根线的电压差判断逻辑能抵消外部共模干扰如地线噪声、电磁辐射是工业控制如工厂、变电站的首选。支持多节点布线成本低采用总线型结构一根总线可连接最多 128 个设备部分芯片支持 256 个无需为每个设备单独布线大幅降低复杂场景的线材和施工成本。电平兼容性好多数 RS485 芯片如 MAX485支持 3.3V/5V 供电可直接与 MCU 的 UART 引脚对接无需额外电源转换。缺点实现复杂度高需总线控制采用半双工通信同一时间只能发或收需通过 “使能引脚”DE/RE控制芯片的发送 / 接收状态软件需额外处理 “收发切换逻辑”易出现冲突。需额外匹配终端电阻传输距离较长100 米或速率较高时需在总线两端加120Ω 终端电阻匹配阻抗减少信号反射增加硬件调试成本。不支持全双工默认标准 RS485 为半双工若需全双工同时收发需额外增加 A、B 线对即 4 根线布线复杂度和成本会上升。总结如何根据需求选择若需板级 / 近距离点对点通信如 MCU 与蓝牙模块、传感器优先用 UART成本低、实现简单。若需短距离连接传统设备如 PC 与调试器、老旧打印机用 RS232兼容性强无需复杂控制。若需工业级长距离 / 多节点通信如多个传感器、PLC、变频器组网必须用 RS485抗干扰和稳定性是核心优势。选型总结五、CAN通信半双工1.CAN通信概念CAN通信是一种多节点通信协议最早由Bosch公司开发并在1986年首次推出。它被广泛应用于汽车电子控制系统、工业自动化领域以及其他需求多节点通信的应用场中。CAN通信的特点之一是支持多节点之间的高速数据传输适用于需要高实时性和高可靠性的系统。CAN总线由两根线组成分别是CAN_HCAN High和CAN_LCAN Low。CAN总线使用不同的电压电平来表示0和1并通过差分信号传输来抗干扰。2.CAN通信工作流程CAN通信采用CSMA/CDCarrier Sense Multiple Access with Collision Detection的工作原理。这意味着每个节点都可以在总线上发送消息但在发送之前需要先监听总线上的通信情况。当一个节点要发送消息时首先会监听总线如果没有其他节点正在发送消息它就可以开始发送。如果同时有多个节点尝试发送消息就会发生冲突。在CAN总线上使用的是非毁坏性冲突检测机制冲突的节点会立即停止发送并在发送完自己的消息后再次来检测冲突。CAN通信中还使用了位定时传输方式即总线上的每个位都有固定的时间段。发送节点将每个位的电平保持一段时间接收节点则在相应的时间段内检测位的电平。这种位定时传输方式确保了数据的同步和准确性。此外CAN通信还通过帧的优先级来管理消息的传输。较低优先级的帧会在总线上等待较高优先级的帧发送完毕后再发送确保重要消息的及时传输。3. CAN通信的应用领域CAN通信被广泛应用于各种领域特别是在汽车和工业控制系统中。在汽车领域CAN通信用于连接汽车的各个控制单元如发动机控制单元ECU、刹车系统、仪表盘等。CAN总线提供了高速、实时的数据传输使得这些控制单元能够相互通信和协调工作实现车辆的高效控制和监测。在工业控制系统中CAN通信被用于连接各种设备和传感器例如机器人、PLC可编程逻辑控制器、传感器网络等。通过CAN总线这些设备可以实现实时数据交换和远程控制从而提高生产效率和系统的可靠性。除了汽车和工业控制CAN通信还应用于其他领域包括航空航天、医疗设备、能源管理等。CAN通信的高可靠性和抗干扰能力使其成为处理实时数据和多节点通信的理想选择。4. CAN帧格式与标识符CAN通信使用帧格式来传输数据。CAN帧分为标准帧和扩展帧两种格式。标准帧由11位标识符、数据域、控制域和CRC循环冗余校验组成。标识符用于标识消息的优先级和内容数据域用于传输实际的数据控制域包含帧的控制信息而CRC用于发送节点计算校验和接收节点用于验证数据的完整性。扩展帧使用29位标识符其他组成部分与标准帧相同。扩展帧的使用使得CAN网络能够处理更多的节点和更大的数据量。标识符的选择对于CAN通信至关重要。帧使用的标识符决定了其在总线上的优先级较低的标识符意味着较高的优先级。在设计和配置CAN网络时需要合理设置标识符以确保系统的正确运行。5. CAN通信模式CAN通信有几种不同的模式可以通过配置CAN控制器的寄存器来选择适合应用需求的模式。常见的CAN通信模式包括正常模式Normal Mode用于实际通信节点能够发送和接收数据。监听模式Listen-Only Mode节点只能监听总线上的通信但不能发送消息。回环模式Loopback Mode发送的帧会回环到本地接收用于自测和调试。静默模式Silent Mode节点只能监听总线上的通信不能发送消息并向其他节点传递错误状态。6. 使用HAL库实现CAN通信对于使用HALHardware Abstraction Layer库进行STM32开发的用户HAL库提供了高级的抽象接口和简洁的函数调用方便编写和管理CAN通信。6.1 STM32 CAN通信配置:a. 使能CAN外设在初始化阶段需要使能所选择的CAN外设并配置相应的时钟。b. 配置CAN控制器通过设置CAN控制器的特殊寄存器配置CAN通信的参数包括波特率、工作模式、过滤器等。c. 配置GPIO引脚将相关的GPIO引脚配置为CAN模式以实现CAN数据的收发。d. 初始化CAN通信通过初始化CAN控制器的寄存器准备CAN通信的环境包括清除任何悬空状态和错误标志。e. 开始CAN通信使能CAN控制器的接收和发送功能使其处于工作状态。6.2 整体代码// 包含所需的头文件 #include stm32f4xx_hal.h // CAN消息结构体 CAN_TxHeaderTypeDef TxHeader; CAN_RxHeaderTypeDef RxHeader; uint8_t TxData[8]; uint8_t RxData[8]; void CAN_Configuration(void) { // 初始化CAN控制器 hcan.Instance CAN1; hcan.Init.Prescaler 10; hcan.Init.Mode CAN_MODE_NORMAL; hcan.Init.SyncJumpWidth CAN_SJW_1TQ; hcan.Init.TimeSeg1 CAN_BS1_8TQ; hcan.Init.TimeSeg2 CAN_BS2_7TQ; hcan.Init.TimeTriggeredMode DISABLE; hcan.Init.AutoBusOff ENABLE; hcan.Init.AutoWakeUp DISABLE; hcan.Init.AutoRetransmission ENABLE; hcan.Init.ReceiveFifoLocked DISABLE; HAL_CAN_Init(hcan); // 配置CAN过滤器 CAN_FilterTypeDef sFilterConfig; sFilterConfig.FilterBank 0; sFilterConfig.FilterMode CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh 0x0000; sFilterConfig.FilterIdLow 0x0000; sFilterConfig.FilterMaskIdHigh 0x0000; sFilterConfig.FilterMaskIdLow 0x0000; sFilterConfig.FilterFIFOAssignment CAN_FILTER_FIFO0; sFilterConfig.FilterActivation ENABLE; sFilterConfig.SlaveStartFilterBank 14; HAL_CAN_ConfigFilter(hcan, sFilterConfig); // 启动CAN通信 HAL_CAN_Start(hcan); // 配置CAN消息头 TxHeader.StdId 0x123; TxHeader.ExtId 0x00; TxHeader.RTR CAN_RTR_DATA; TxHeader.IDE CAN_ID_STD; TxHeader.DLC 8; TxHeader.TransmitGlobalTime DISABLE; } void CAN_SendData(uint8_t* data, uint32_t length) { // 填充发送消息的数据 for (uint8_t i 0; i length; i) { TxData[i] data[i]; } // 发送消息 if (HAL_CAN_AddTxMessage(hcan, TxHeader, TxData, TxMailbox) HAL_OK) { HAL_CAN_Transmit(hcan, 100); } } void CAN_ReceiveData(void) { // 接收消息 if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) 0) { if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, RxHeader, RxData) HAL_OK) { // 处理接收到的数据 // … } } } int main(void) { // 初始化HAL库和其他外设 // 配置CAN通信 CAN_Configuration(); while (1) { // 发送数据 uint8_t sendData[] {0x01, 0x02, 0x03}; CAN_SendData(sendData, sizeof(sendData)); // 接收数据 CAN_ReceiveData(); } }

相关新闻

十进制与二进制互转全解:原理、位运算与工程实战

十进制与二进制互转全解:原理、位运算与工程实战

平时写代码的时候,估计不少人和我一样,看到一串二进制标志位就头皮发麻,尤其是和底层设备、协议报文打交道的时候,十六进制倒是能混个眼熟,但一旦要求把十进制与二进制互转,脑子里就开始翻算法书。前阵子同…

2026/10/19 2:25:39 阅读更多 →
【代码随想录】LC 1. 两数之和

【代码随想录】LC 1. 两数之和

文章目录前言一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解前言 本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记,如有侵权,立即删除。 一、题目 1、原题链接 1. 两数之和 2、题目描述 二、解题报告 1、思路…

2026/10/19 2:25:39 阅读更多 →
SDC命令详解:使用set_disable_timing命令进行约束

SDC命令详解:使用set_disable_timing命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定对象列表/集合 指定源、目的引脚 指定恢复 简单使用 Multicorner-Multimode支持 写在最后 上一章中,我们学习了如何使用set_case_analysis模…

2026/10/19 2:25:39 阅读更多 →

最新新闻

Flink有界流与无界流:核心区别、运行时行为差异与选型避坑指南

Flink有界流与无界流:核心区别、运行时行为差异与选型避坑指南

1. 从一个反直觉的现象说起:为什么批处理跑得好好的,换成流处理就出问题刚接触 Flink 的人,十有八九会在某个时刻被一个看似简单的问题绊住:我明明写的是同一套算子逻辑,为什么换成流模式跑,结果要么迟迟不…

2026/10/19 3:14:03 阅读更多 →
Hadoop期末复习全攻略:HDFS、MapReduce与YARN核心考点精讲

Hadoop期末复习全攻略:HDFS、MapReduce与YARN核心考点精讲

1. 这门课到底在考什么:从一张复习卷看Hadoop知识体系的全貌每年到了期末季,总有一批同学在群里哀嚎:“Hadoop这东西,课上听懂了,一到做题就懵。”我当年带过几届大数据方向的课程助教,也帮不少朋友梳理过复…

2026/10/19 3:14:03 阅读更多 →
Halcon基于形状的模板匹配:原理、参数调优与实战经验

Halcon基于形状的模板匹配:原理、参数调优与实战经验

做视觉项目这些年,经常碰到有人问我:Halcon 里做定位用哪个方法最稳?我的回答往往不是特征点,也不是深度学习,而是那个看起来有点“老派”的——基于形状的模板识别。尤其当你面对的是低纹理的金属件、注塑件&#xff…

2026/10/19 3:14:03 阅读更多 →
基于PSO的LLC变换器PI参数自动寻优MATLAB仿真项目解析

基于PSO的LLC变换器PI参数自动寻优MATLAB仿真项目解析

简介:本资源为基于MATLAB的PSO-PID控制器参数优化实现工程,面向控制工程初学者、自动化专业学生及需要摆脱人工试凑整定PID参数的开发人员。压缩包内共3个文件,其中2个m脚本分别实现粒子群优化主程序与PID参数求解逻辑,1个mdl模型…

2026/10/19 3:14:03 阅读更多 →
SenseNova-U1.5-8B-MoT-pose-bf16完全介绍:跑在Apple Silicon上的开源AI姿态迁移模型是什么

SenseNova-U1.5-8B-MoT-pose-bf16完全介绍:跑在Apple Silicon上的开源AI姿态迁移模型是什么

【免费下载链接】SenseNova-U1.5-8B-MoT-pose-bf16 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/SenseNova-U1.5-8B-MoT-pose-bf16 点击查看 免费下载 SenseNova-U1.5-8B-MoT-pose-bf16 是一款跑在 Apple Silicon(M 系列芯片&#xff0…

2026/10/19 3:14:03 阅读更多 →
AI可复现性挑战:固定随机种子、锁定环境,让训练结果稳定复现

AI可复现性挑战:固定随机种子、锁定环境,让训练结果稳定复现

1. 从一次“幽灵复现失败”说起:到底什么是AI的可复现性挑战前阵子我把一台GPU服务器上的旧训练任务重新跑了一遍,用的确实是当时的代码、当时的数据文件、当时的依赖环境,结果AUC从0.713变成了0.704。当时我的第一反应不是“代码写错了”&am…

2026/10/19 3:13:03 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →