- CAN简介
- CAN over SPI和I2C的比较
- CAN协议应用
- 如何在Arduino中使用CAN协议
- 所需组件
- 电路原理图
- 两个MCP2515 CAN模块之间的连接
- 编程Arduino以进行CAN通信
- CAN发送器侧码说明(Arduino Nano)
- CAN接收器端代码说明(Arduino UNO)
- Arduino中的CAN通信工作
如今,每辆普通汽车中都包含约60至100个传感器单元,用于感应和交换信息。随着汽车制造商不断通过自动驾驶,安全气囊系统,胎压监测,巡航控制系统等功能使汽车变得更加智能,这个数字只会越来越高。与其他传感器不同,这些传感器处理关键信息,因此,应使用标准汽车通信协议来传递来自这些传感器的数据。例如,巡航控制系统数据(例如速度,油门位置等)是至关重要的值,这些数据将发送到电子控制单元(ECU)为了确定汽车的加速度水平,此处的通讯错误或数据丢失可能会导致严重故障。因此,与UART,SPI或I2C等标准通信协议不同,设计人员使用了许多可靠的汽车通信协议,例如LIN,CAN,FlexRay等。
在所有可用协议中,CAN更为广泛使用和流行。我们已经讨论了什么是CAN以及CAN如何工作。因此,在本文中,我们将再次研究基础知识,最后,我们还将使用CAN通信在两个Arduino之间交换数据。听起来很有趣吧!因此,让我们开始吧。
CAN简介
CAN aka控制器局域网是一种用于工业和汽车应用的串行通信总线。它是用于多个设备之间通信的基于消息的协议。当多个CAN设备如下图所示连接在一起时,该连接形成了一个网络,其作用类似于我们的中枢神经系统,允许任何设备与节点中的任何其他设备进行通话。
甲CAN网络将仅由两条导线可在高和低CAN用于双向数据传输如上所示。通常,CAN的通信速度范围从50 Kbps到1Mbps,距离范围从1Mbps的40米到50kpbs的1000米。
CAN消息格式:
在CAN通信中,数据以特定的消息格式在网络中传输。该消息格式包含许多段,但是两个主要段是标识符和数据,它们有助于在CAN总线中发送和响应消息。
标识符或CAN ID:标识符也称为CAN ID或PGN(参数组编号)。它用于识别CAN网络中存在的CAN设备。根据所使用的CAN协议的类型,标识符的长度为11位或29位。
标准CAN:0-2047(11位)
扩展CAN:0-2 29 -1(29位)
数据:这是必须从一台设备发送到另一台设备的实际传感器/控制数据。大小数据的长度可以在0到8个字节之间。
数据长度代码(DLC):0至8,用于显示数据字节数。
CAN中使用的电线:
CAN协议由两条线组成,即CAN_H和CAN_L,用于发送和接收信息。两条线都充当差分线,这意味着CAN信号(0或1)由CAN_L和CAN_H之间的电位差表示。如果差为正且大于某个最小电压,则为1;如果差为负,则为0。
通常,双绞线电缆用于CAN通信。如图所示,通常在CAN网络的两端使用一个120欧姆的电阻,这是因为需要平衡线路并将其绑在相同的电位上。
CAN over SPI和I2C的比较
由于我们已经学习了如何在Arduino上使用SPI和在Arduino上使用IIC,因此让我们比较一下SPI和I2C和CAN的功能
参数 | SPI | I2C | 能够 |
速度 | 3Mbps至10Mbps | 标准:100Kbps | 10KBps至1MBps也取决于所用电线的长度 |
快:400 Kbps | |||
高速:3.4Mbps | |||
类型 | 同步 | 同步 | 异步 |
线数 | 3+(MISO,MOSI,SCK,SS1,SS2…SS(n)) | 2线(SDA,SCL) | 2线(CAN_H,CAN_L) |
双工 | 全双工 | 半双工 | 半双工 |
CAN协议应用
- 由于CAN协议的鲁棒性和可靠性,它们被用于汽车,工业机器,农业,医疗设备等行业。
- 随着CAN中布线复杂性的降低,它们主要用于汽车等汽车应用。
- 实施成本低,而且硬件组件价格也更低。
- 易于添加和删除CAN总线设备。
如何在Arduino中使用CAN协议
由于Arduino不包含任何内置的CAN端口,因此使用了称为MCP2515的CAN模块。该CAN模块通过SPI通信与Arduino接口。让我们详细了解MCP2515,以及如何与Arduino接口。
MCP2515 CAN模块:
MCP2515模块具有一个CAN控制器MCP2515,它是高速CAN收发器。MCP2515和MCU之间的连接是通过SPI进行的。因此,很容易与具有SPI接口的任何微控制器接口。
对于想学习CAN总线的初学者,此模块将是一个很好的开始。该CAN SPI板非常适合工业自动化,家庭自动化和其他汽车嵌入式项目。
MCP2515的功能和规格:
- 使用高速CAN收发器TJA1050
- 尺寸:40×28mm
- SPI控制以扩展Multi CAN总线接口
- 8MHZ晶体振荡器
- 120Ω终端电阻
- 具有独立按键,LED指示灯,电源指示灯
- 支持1 Mb / s CAN操作
- 低电流待机操作
- 最多可以连接112个节点
MCP2515 CAN模块的引脚排列:
引脚名称 |
采用 |
VCC |
5V电源输入引脚 |
地线 |
接地脚 |
CS |
SPI SLAVE选择引脚(低电平有效) |
所以 |
SPI主机输入从机输出线 |
SI |
SPI主机输出从机输入引线 |
时钟 |
SPI时钟引脚 |
INT |
MCP2515中断引脚 |
在本教程中,让我们看看如何通过CAN总线模块MCP2515从Arduino Nano向Arduino Uno发送湿度和温度(DHT11)传感器数据。
所需组件
- Arduino UNO
- Arduino的纳米
- DHT11
- 16x2 LCD显示屏
- MCP2515 CAN模块– 2
- 10k电位器
- 面包板
- 连接线
电路原理图
CAN变送器侧的连接:
组件-引脚 |
Arduino纳米 |
MPC2515-VCC |
+5伏 |
MPC2515-GND |
地线 |
MPC2515-CS |
D10(SPI_SS) |
MPC2515-SO |
D12(SPI_MISO) |
MPC2515-SI |
D11(SPI_MOSI) |
MPC2515-SCK |
D13(SPI_SCK) |
MPC2515-INT |
D2 |
DHT11-VCC |
+5伏 |
DHT11-接地 |
地线 |
DHT11-输出 |
A0 |
CAN接收器侧的电路连接:
组件-引脚 |
Arduino UNO |
MPC2515-VCC |
+5伏 |
MPC2515-GND |
地线 |
MPC2515-CS |
10(SPI_SS) |
MPC2515-SO |
12(SPI_MISO) |
MPC2515-SI |
11(SPI_MOSI) |
MPC2515-SCK |
13(SPI_SCK) |
MPC2515-INT |
2 |
LCD-VSS |
地线 |
LCD-VDD |
+5伏 |
液晶屏-V0 |
至10K电位计中心PIN |
液晶显示器-RS |
3 |
液晶显示器-RW |
地线 |
液晶屏-E |
4 |
液晶屏-D4 |
5 |
液晶屏-D5 |
6 |
液晶屏-D6 |
7 |
液晶屏-D7 |
8 |
液晶屏-A |
+5伏 |
液晶屏-K |
地线 |
两个MCP2515 CAN模块之间的连接
H – CAN高
L – CAN低
MCP2515(Arduino纳米) |
MCP2515(Arduino UNO) |
H |
H |
大号 |
大号 |
完成所有连接后,我的硬件如下所示
编程Arduino以进行CAN通信
首先,我们必须在Arduino IDE中安装CAN库。通过使用以下库,MCP2515 CAN模块与Arduino的接口变得更容易。
- 下载Arduino CAN MCP2515库的ZIP文件。
- 从Arduino IDE:草图->包含库->添加.ZIP库
在本教程中,编码分为两部分,一部分作为CAN发送器代码(Arduino Nano),另一部分作为CAN接收器代码(Arduino UNO),都可在本页底部找到。相同的解释如下。
在编写用于发送和接收数据的程序之前,请确保已按照上述步骤安装了库,并且已按照以下步骤在程序中初始化了CAN模块MCP2515。
初始化MCP2515 CAN模块:
为了创建与MCP2515的连接,请遵循以下步骤:
1.设置连接SPI CS的引脚号(默认为10)
MCP2515 mcp2515(10);
2.设置波特率和振荡器频率
mcp2515.setBitrate(CAN_125KBPS,MCP_8MHZ);
可用的波特率:
CAN_5KBPS,CAN_10KBPS,CAN_20KBPS,CAN_31K25BPS,CAN_33KBPS,CAN_40KBPS,CAN_50KBPS,CAN_80KBPS,CAN_83K3BPS,CAN_95KBPS,CAN_100KBPS,CAN_125KBPS,CAN_200KBPS,CAN_250KBPS,CAN_500KBPS,CAN_1000
可用时钟速度:
MCP_20MHZ,MCP_16MHZ,MCP_8MHZ
3.设置模式。
mcp2515.setNormalMode(); mcp2515.setLoopbackMode(); mcp2515.setListenOnlyMode();
CAN发送器侧码说明(Arduino Nano)
在发送器部分,Arduino Nano通过SPI引脚与MCP2515 CAN模块连接,DHT11将温度和湿度数据发送到CAN总线。
首先包括所需的库,用于SPI通信的SPI库,用于CAN通信的MCP2515库,以及用于Arduino的DHT传感器的DHT库。我们之前将DHT11与Arduino连接。
#包括
现在定义与Arduino Nano的A0连接的DHT11(OUT引脚)的引脚名称
#定义DHTPIN A0
而且, DHTTYPE 被定义为DHT11。
#define DHTTYPE DHT11
一个 canMsg 结构数据类型,用于存储CAN消息格式。
struct can_frame canMsg;
设置连接SPI CS的引脚号(默认为10)
MCP2515 mcp2515(10);
此外,还初始化了具有DHT引脚且具有Arduino Nano和DHT类型作为DHT11的DHT类的对象dht。
DHT dht(DHTPIN,DHTTYPE);
接下来是void setup():
使用以下语句开始SPI通信
SPI.begin();
然后使用以下语句开始从DHT11传感器接收温度和湿度值。
dht.begin();
接下来,使用以下命令对MCP2515进行复位
mcp2515.reset();
现在,MCP2515的速度设置为500KBPS,时钟设置为8MHZ
mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
并且MCP2525设置为正常模式
mcp2515.setNormalMode();
在void loop()中:
以下语句获取“湿度和温度”值并将其存储在整数变量h和t中。
int h = dht.readHumidity(); int = dht.readTemperature();
接下来,将CAN ID设为0x036(根据选择),并将DLC设为8,然后将h和t数据赋予 数据 和 数据, 并将所有数据保留为0。
canMsg.can_id = 0x036; canMsg.can_dlc = 8; canMsg.data = h; //更新 canMsg.data = t中的 湿度值;//更新canMsg.data = 0x00;中的 温度值 //其余全部为0 canMsg.data = 0x00; canMsg.data = 0x00; canMsg.data = 0x00; canMsg.data = 0x00; canMsg.data = 0x00;
毕竟,要将消息发送到CAN BUS,我们使用以下语句。
mcp2515.sendMessage(&canMsg);
因此,现在温度和湿度数据已作为消息发送到CAN总线。
CAN接收器端代码说明(Arduino UNO)
在接收器部分,Arduino UNO与MCP2515和16x2 LCD显示器接口。Arduino UNO在这里从CAN总线接收温度和湿度,并在LCD上显示接收到的数据。
首先包括所需的库,用于SPI通信的SPI库,用于CAN通信的MCP2515库,以及用于Arduino的16x2 LCD的LiquidCrsytal库。
#包括
接下来,定义用于与Arduino UNO连接的LCD引脚。
const int rs = 3,en = 4,d4 = 5,d5 = 6,d6 = 7,d7 = 8; LiquidCrystal LCD(rs,en,d4,d5,d6,d7);
声明了一个 struct 数据类型以存储CAN消息格式。
struct can_frame canMsg;
设置连接SPI CS的引脚号(默认为10)
MCP2515 mcp2515(10);
在无效设置()中:
首先,LCD设置为16x2模式,并显示欢迎信息。
lcd.begin(16,2); lcd.setCursor(0,0); lcd.print(“电路图摘要”); lcd.setCursor(0,1); lcd.print(“ CAN ARDUINO”); 延迟(3000); lcd.clear();
使用以下语句开始SPI通信。
SPI.begin();
接下来,使用以下命令对MCP2515进行复位。
mcp2515.reset();
现在,MCP2515的速度设置为500KBPS,时钟设置为8MHZ。
mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
MCP2525设置为普通模式。
mcp2515.setNormalMode();
无效循环中的下一个:
以下语句用于从CAN总线接收消息。如果收到消息,则进入 if 条件。
如果(mcp2515.readMessage(&canMsg)== MCP2515:: ERROR_OK)
在 if 条件下,数据被接收并存储在c anMsg中 ,具有湿度值的数据和具有温度值的数据。这两个值都存储在整数x和y中。
int x = canMsg.data; int y = canMsg.data;
接收到这些值后,将使用以下语句将温度和湿度值显示在16x2 LCD显示屏中。
lcd.setCursor(0,0); lcd.print(“ Humidity:”); lcd.print(x); lcd.setCursor(0,1); lcd.print(“ Temp:”); lcd.print(y); 延迟(1000); lcd.clear();
Arduino中的CAN通信工作
硬件准备好后,在相应的Arduino板上上传CAN发射器和CAN接收器的程序(下面提供完整的程序)。通电后,您应该注意到DHT11读取的温度值将通过CAN通讯发送到另一个Arduino,并显示在第二个Arduino的LCD上,如下图所示。我还使用了交流遥控器检查液晶显示屏上显示的温度是否接近实际室温。
可以在下面的视频中找到完整的工作。如果您有任何疑问,请将其留在评论部分或将我们的论坛用于其他技术问题。