如何使用MCP2515和Arduino模块创建CAN总线网络
如何使用MCP2515和Arduino模块创建CAN总线网络
CAN总线是一种广泛应用于汽车和工业领域的串行通信协议。本文将详细介绍如何使用MCP2515模块和Arduino创建CAN总线网络,包括硬件连接、软件编程以及网络规划要点。
什么是CAN总线?
CAN总线(Controller Area Network)是一种串行通信协议,允许不同的设备相互通信。它由博世于1986年开发,专为汽车应用而设计,但其用途已扩展到工业自动化等其他领域。在这种类型的网络中,连接的设备无需中央主机或控制器即可发送和接收消息,这使其成为通信和可靠性至关重要的环境中非常有效的协议。
现代汽车包含70多个控制设备,称为ECU(电子控制单元),通过CAN总线相互连接。借助该协议,ECU可以交换汽车运行的关键信息,例如车速数据或油门位置。
CAN总线拓扑和信号
CAN系统的拓扑结构为多主机,这意味着连接到网络的任何设备都可以控制总线来发送消息。所有节点都会监听这些消息并决定是否响应或忽略它们。
从物理角度来看,通信是通过两条电缆进行的:CAN_H和CAN_L。这些电缆经过编织以最大限度地减少电磁干扰。此外,网络末端必须使用120欧姆电阻器进行端接,以避免信号反射。
CAN信号传输
CAN系统使用两种逻辑状态进行通信:显性和隐性。在显性状态下,CAN_H的电压为3.5V,CAN_L的电压为1.5V。在此状态下,传输逻辑“0”。另一方面,在隐性状态下,两根线的电压均为2.5V,表明总线空闲,可以传输逻辑“1”。正是两根电缆之间的电压变化允许数据在网络上传输。
MCP2515模块
ElMCP2515模块它是为Arduino添加CAN连接的理想解决方案。它由CAN控制器(MCP2515,遵循CAN 2.0B规范)和CAN收发器(TJA1050,处理物理通信)组成。这两个芯片协同工作,因此您可以通过SPI接口使用Arduino发送和接收CAN消息。
MCP2515支持标准(11位)和扩展(29位)消息,并能够通过使用掩码和过滤器过滤掉不需要的消息,从而减轻微控制器的工作负担。对于需要可靠通信的项目来说,无论是在嘈杂的环境中还是长距离,它都是一个绝佳的选择。
MCP2515模块组件
MCP2515模块包括以下部分:
- MCP2515 CAN控制器:负责执行所有CAN协议功能,例如发送和接收消息。
- TJA1050 CAN收发器:负责将来自CAN控制器的数据转换为物理CAN总线的信号,反之亦然。
- SPI通信引脚:MCP2515使用SCK、MOSI、MISO和CS引脚,通过其SPI接口与Arduino进行通信。
- CAN总线端子:这个小螺丝接线端子标有“H”和“L”。CAN_H和CAN_L必须连接到CAN网络电缆。
如何使用Arduino建立CAN网络
使用MCP2515模块,设置CAN网络相对简单。下面我将解释如何将模块连接到Arduino板以及如何配置软件。
MCP2515模块连接
首先,按如下方式连接Arduino的SPI引脚:
- MISO(模块输出)连接到Arduino的D12引脚
- MOSI(模块输入)到Arduino的引脚D11
- SCK(时钟)至Arduino引脚D13
- CS(片选)至Arduino引脚D10
您还需要将MCP2515的INT引脚连接到Arduino数字引脚,例如D2,因为该引脚用于在收到有效消息时处理中断。
不要忘记为模块供电。VCC引脚应连接至5V,GND引脚应接地。
对于CAN总线端子,在要互连的不同节点之间将CAN_H连接到CAN_H,将CAN_L连接到CAN_L。请记住,CAN总线两端必须使用120欧姆电阻进行端接。
Arduino编程
连接节点后,就可以对Arduino进行编程,使其通过MCP2515模块与CAN总线进行通信。最好的方法是使用合适的库,例如库'mcp2515'。
首先,您需要安装这个库。如果您使用的是Arduino IDE,请转至Sketch > Include Library > Manage Libraries。搜索“mcp2515”并选择安装选项。
安装库后,您可以继续为发射器节点和接收器节点编写代码。下面我向您展示两者的基本示例。
发送节点的代码示例
此代码每秒通过CAN总线发送一条“Hello World”消息。
#include <mcp2515.h>
MCP2515 CAN(SS);
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Nodo transmisor CAN");
if (!CAN.begin(500E3)) {
Serial.println("Error al iniciar CAN");
while (1);
}
}
void loop() {
Serial.print("Enviando mensaje... ");
CAN.beginPacket(0x12);
CAN.write('H');
CAN.write('o');
CAN.write('l');
CAN.write('a');
CAN.write(' ');
CAN.write('M');
CAN.write('u');
CAN.write('n');
CAN.write('d');
CAN.write('o');
CAN.endPacket();
Serial.println("Mensaje enviado correctamente");
delay(1000);
}
接收节点的代码示例
该代码接收来自CAN总线的消息并将其显示在串行监视器上。
#include <mcp2515.h>
MCP2515 CAN(SS);
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Nodo receptor CAN");
if (!CAN.begin(500E3)) {
Serial.println("Error al iniciar CAN");
while (1);
}
CAN.onReceive(onReceive);
}
void loop() {}
void onReceive(int packetSize) {
Serial.print("Mensaje recibido con ID: 0x");
Serial.print(CAN.packetId(), HEX);
Serial.print(" | Tamaño: ");
Serial.print(packetSize);
Serial.print(" | Datos: ");
while (CAN.available()) {
Serial.print((char)CAN.read());
}
Serial.println();
}
CAN网络中的速度和距离
CAN总线允许以各种速度进行通信。MCP2515支持的最大速度为1 Mbit/s,但总线的长度限制了传输速度。例如,在1 Mbit/s时,最大总线长度约为40米。但是,如果您需要行驶更远的距离,则可以降低速度。在125 kbit/s时,总线长度可达500米。
良好规划网络并根据总线长度和使用环境使用适当的速度非常重要,因为嘈杂的环境会影响通信质量。
另请记住CAN_H和CAN_L电缆使用双绞线,因为这有助于减少电磁干扰并提高网络可靠性。
多节点CAN网络
如果要形成具有多个节点的网络,过程非常相似。您唯一需要做的就是确保将所有节点并行连接到CAN_H和CAN_L线。还要记住仅将终端电阻放置在主线的末端,而不是中间节点。
在更复杂的网络中,您可能有多个节点充当发送器和接收器。每个节点给总线增加的负载最小,允许在CAN网络上连接多达112个节点,而不会显着影响性能。
无论您是在汽车中使用CAN总线读取发动机数据,还是在工业项目中使用CAN总线与多个传感器进行通信,MCP2515模块都可以轻松高效地添加此功能。这种类型的网络非常适合需要低延迟和数据传输可靠性的应用。