0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在Arduino中使用CAN协议

科技观察员 来源:circuitdigest 作者:Pramoth Thangavel 2022-08-29 17:41 次阅读

如今,任何一辆普通汽车都包含大约 60 到 100 个传感器单元,用于传感和交换信息。随着汽车制造商不断通过自动驾驶、安全气囊系统、胎压监测、巡航控制系统等功能使他们的汽车更加智能,这个数字只会越来越高。与其他传感器不同,这些传感器处理关键信息,因此来自这些传感器的数据应使用标准汽车通信协议进行通信。例如,速度、油门位置等巡航控制系统数据是发送到电子控制单元 (ECU)的重要值为了决定汽车的加速水平,此处的错误通信或数据丢失可能导致严重故障。因此,与 UART、SPI或I2C等标准通信协议不同,设计人员使用更可靠的汽车通信协议,如 LIN、CAN、FlexRay 等。

在本文中,我们将再次研究基础知识,最后我们还将使用 CAN 通信在两个 Arduino 之间交换数据。

CAN简介

CAN aka Controller Area Network是一种串行通信总线,专为工业和汽车应用而设计。它是一种基于消息的协议,用于多个设备之间的通信。当多个 CAN 设备如下图所示连接在一起时,连接形成一个网络,就像我们的中枢神经系统一样,允许任何设备与节点中的任何其他设备通话。

pYYBAGMMiPqAPgJZAAAeoqviz7c288.png

CAN 网络将仅包含两条线CAN High 和 CAN Low,用于双向数据传输,如上所示。通常,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 的比较

既然我们已经学会了如何使用SPI 和 Arduino和IIC 和 Arduino,让我们比较一下 SPI 和 I2C 和 CAN 的特性

poYBAGMMiPSAfyPAAAAdMGTZmsw247.png

CAN 协议应用

由于 CAN 协议的稳健性和可靠性,它们被用于汽车、工业机械、农业、医疗设备等行业。

由于 CAN 中的布线复杂性降低,它们主要用于汽车等汽车应用。

实施成本低,硬件组件价格也较低。

易于添加和删除 CAN 总线设备。

如何在 Arduino 中使用 CAN 协议

由于 Arduino 不包含任何内置 CAN 端口,因此使用了一个名为MCP2515的 CAN 模块。该 CAN 模块通过 SPI 通信与 Arduino 连接。让我们详细了解 MCP2515 以及它如何与 Arduino 接口

MCP2515 CAN 模块:

poYBAGMMiPGAB1ozAARhYVuT3DA592.png

MCP2515 模块有一个 CAN 控制器 MCP2515,它是高速 CAN 收发器。MCP2515 与 MCU 之间通过 SPI 连接。因此,很容易与任何具有 SPI 接口的微控制器连接。

对于想要学习 CAN Bus 的初学者来说,这个模块将是一个好的开始。此 CAN SPI 板非常适合工业自动化、家庭自动化和其他汽车嵌入式项目。

MCP2515的特性和规格

使用高速CAN收发器TJA1050

尺寸:40×28mm

用于扩展多 CAN 总线接口的 SPI 控制

8MHZ晶振

120Ω终端电阻

具有独立按键、LED指示灯电源指示灯

支持 1 Mb/s CAN 操作

电流待机操作

最多可连接112个节点

MCP2515 CAN 模块的引脚排列:

pYYBAGMMiOuAWM_iAAAbZrfAh1k502.png

在本教程中,让我们看看如何通过 CAN总线模块 MCP2515从 Arduino Nano 向 Arduino Uno 发送湿度和温度 (DHT11) 传感器数据。

所需组件

Arduino UNO

阿杜诺纳米

DHT11

16x2 液晶显示器

MCP2515 CAN 模块 – 2

10k 电位器

面包板

连接电线

MCP2515 Arduino电路图

pYYBAGMMiOaAf6rkAAIkSzIU7N0971.png

CAN Transmitter 端的连接:

poYBAGMMiOKAe58BAAAf-JZEGFY664.png

CAN接收器侧的电路连接:

pYYBAGMMiN-AHtaDAAAiney4ESc837.png

poYBAGMMiNuAFqT8AAAbMZL-VBw614.png

两个 MCP2515 CAN 模块之间的连接

poYBAGMMiNeAQncfAAAMO5YzdtE591.png

完成所有连接后,我的硬件如下所示

pYYBAGMMiNSAarcyAAhwfB6rrOo469.png

为 CAN 通信编程 Arduino

首先,我们必须在 Arduino IDE 中安装 CAN 库。通过使用以下库,将 MCP2515 CAN 模块与 Arduino 连接变得更加容易。

在本教程中,编码分为两部分,一是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_1000KBPS。

可用时钟速度:

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 库和用于将 DHT 传感器与 Arduino 一起使用的 DHT 库。我们之前将 DHT11 与 Arduino 接口。

#include            
#include        
#include           

现在定义了与 Arduino Nano 的 A0 相连的 DHT11(OUT 引脚)的引脚名称

#define DHTPIN A0       

而且,DHTTYPE被定义为 DHT11。

#define DHTTYPE DHT11

用于存储 CAN 消息格式的canMsg结构数据类型。

结构 can_frame canMsg;

设置 SPI CS 连接的管脚号(默认为 10)

MCP2515 mcp2515(10);

此外,DHT 类的对象 dht 与 Arduino Nano 和 DHT 类型为 DHT11 的 DHT 引脚被初始化。

DHT dht(DHTPIN, DHTTYPE);     

接下来在 void setup() 中:

使用以下语句开始 SPI 通信

SPI.开始();               

然后使用以下语句开始接收来自 DHT11 传感器的温度和湿度值。

dht.begin();               

接下来,使用以下命令重置 MCP2515

mcp2515.reset();

现在 MCP2515 的速度设置为 500KBPS 和 8MHZ 作为时钟

mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);

并且 MCP2525 设置为正常模式

mcp2515.setNormalMode();

在无效循环()中:

以下语句获取湿度和温度值并存储在整数变量 h 和 t 中。

int h = dht.readHumidity();       
int t = dht.readTemperature();    

接下来,CAN ID 为 0x036(根据选择),DLC 为 8,我们将 h 和 t 数据分配给data[0] 和data[1] ,并将所有数据保留为 0。

canMsg.can_id = 0x036;           
canMsg.can_dlc = 8;               
canMsg.data[0] = h; //更新[0]中的湿度值
canMsg.data[1] = t; //更新[1]中的温度值
canMsg.data[2] = 0x00; //全部用 0 休息
canMsg.data[3] = 0x00; 
canMsg.data[4] = 0x00; 
canMsg.data[5] = 0x00; 
canMsg.data[6] = 0x00; 
canMsg.data[7] = 0x00;

毕竟,要将消息发送到 CAN BUS,我们使用以下语句。

  mcp2515.sendMessage(&canMsg);     

所以现在温度和湿度数据作为消息发送到 CAN 总线。

CAN接收端代码说明(Arduino UNO)

在接收器部分,Arduino UNO 与 MCP2515 和16x2 LCD 显示器连接。在这里,Arduino UNO 从 CAN 总线接收温度和湿度,并在 LCD 中显示接收到的数据。

首先包括所需的库,用于使用 SPI 通信的 SPI 库、用于使用 CAN 通信的 MCP2515 库和用于将 16x2 LCD 与 Arduino 一起使用的 LiquidCrsytal 库。

#include            
#include     

接下来定义用于连接 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);  

声明了一个结构数据类型用于存储CAN 消息格式。

结构 can_frame canMsg;

设置 SPI CS 连接的管脚号(默认为 10)

MCP2515 mcp2515(10);                  

在 void setup() 中:

首先将 LCD 设置为 16x2 模式并显示欢迎信息。

  lcd.开始(16,2);                   
lcd.setCursor(0,0);                
  lcd.print("电路文摘"); 
  lcd.setCursor(0,1); 
  lcd.print("CAN ARDUINO"); 
  延迟(3000);
  lcd.clear();

使用以下语句开始 SPI 通信。

 SPI.开始();                         

接下来,使用以下命令重置 MCP2515。

mcp2515.reset();

现在将 MCP2515 设置为 500KBPS 的速度和 8MHZ 作为时钟。

mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);

MCP2525 设置为正常模式。

mcp2515.setNormalMode();

接下来在 void loop() 中:

以下语句用于接收来自 CAN 总线的消息。如果收到消息,则进入if条件。

if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)

在if条件下,数据被接收并存储在 canMsg中,具有湿度值的数据 [0] 和具有温度值的数据 [1]。这两个值都存储在整数 x 和 y 中。

     int x = canMsg.data[0];         
     int y = canMsg.data[1];       

收到数值后,温度和湿度值使用以下语句显示在 16x2 LCD 显示屏上。

 lcd.setCursor(0,0);          
lcd.print("湿度:");     
lcd.print(x); 
lcd.setCursor(0,1); 
      lcd.print("温度:"); 
      lcd.print(y); 
      延迟(1000);
      lcd.clear();

Arduino中CAN通信的工作

硬件准备好后,将 CAN 发送器和 CAN 接收器的程序(完整程序如下)上传到各自的 Arduino 板上。通电后,您应该注意到 DHT11 读取的温度值将通过 CAN 通信发送到另一个 Arduino,并显示在第二个Arduino 的 LCD 上,如下图所示。我还使用交流遥控器检查液晶显示屏上显示的温度是否接近实际室温。

poYBAGMMiMmAX004AAbQ5ROmUBQ509.png
CAN 发射器代码(Arduino Nano):


#include //使用SPI通信的库

#include //使用CAN通信的库

#include //使用DHT传感器的库


#define DHTPIN A0

#define DHTTYPE DHT11


结构 can_frame canMsg;

MCP2515 mcp2515(10);


DHT dht(DHTPIN, DHTTYPE); //使用STM32的DHT引脚和DHT类型为DHT11的DHT类初始化对象dht


void setup()

{

while (!Serial);

序列号.开始(9600);



SPI.开始();//开始 SPI 通信

dht.begin(); //开始读取温湿度传感器



mcp2515.reset();

mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ); //将 CAN 设置为速度 500KBPS 和时钟 8MHz

mcp2515.setNormalMode();

}


void loop()

{

int h = dht.readHumidity(); //获取湿度值

int t = dht.readTemperature(); //获取温度值


canMsg.can_id = 0x036; //CAN id 为 0x036

canMsg.can_dlc = 8; //CAN数据长度为8

canMsg.data[0] = h; //更新[0]中的湿度值

canMsg.data[1] = t; //更新[1]中的温度值

canMsg.data[2] = 0x00; //全部用 0 休息

canMsg.data[3] = 0x00;

canMsg.data[4] = 0x00;

canMsg.data[5] = 0x00;

canMsg.data[6] = 0x00;

canMsg.data[7] = 0x00;

mcp2515.sendMessage(&canMsg); //发送CAN报文

delay(1000);

}






CAN接收器代码(Arduino UNO):


#include //使用SPI通信的库

#include //使用CAN通信的库

#include //使用LCD显示的库


const int rs = 3, en = 4, d4 = 5, d5 = 6, d6 = 7, d7 = 8;


LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //定义LCD显示引脚RS,E,D4,D5,D6,D7


结构 can_frame canMsg;

MCP2515 mcp2515(10); // SPI CS 引脚 10



void setup() {

lcd.begin(16,2); //设置 LCD 为 16x2 类型

lcd.setCursor(0,0); //显示欢迎信息

lcd.print("CIRCUIT DIGEST");

lcd.setCursor(0,1);

lcd.print("CAN ARDUINO");

延迟(3000);

lcd.clear();



SPI.开始();//开始SPI通信



Serial.begin(9600); //以 9600 波特率开始串行通信



mcp2515.reset();

mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ); //将 CAN 设置为 500KBPS 和 8MHz 时钟

mcp2515.setNormalMode(); //将CAN设置为正常模式

}


void loop()

{

if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) // 接收数据(轮询读取)

{

int x = canMsg.data[0];

int y = canMsg.data[1];



lcd.setCursor(0,0); //显示在 16x2 LCD 上接收到的温度和湿度值

lcd.print("Humidity : ");

lcd.print(x);

lcd.setCursor(0,1);

lcd.print("温度:");

lcd.print(y);

延迟(1000);

lcd.clear();

}

}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • CAN
    CAN
    +关注

    关注

    57

    文章

    2660

    浏览量

    462421
  • MCP2515
    +关注

    关注

    0

    文章

    23

    浏览量

    15734
  • Arduino
    +关注

    关注

    186

    文章

    6453

    浏览量

    185902
收藏 人收藏

    评论

    相关推荐

    何在Arduino中使用KY-037声音检测传感器

    这个项目将教你如何在 Arduino 中使用 KY-037 声音检测传感器,并且测量环境中声音强度的变化。
    发表于 08-02 15:41 4594次阅读
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用KY-037声音检测传感器

    何在Linux中使用htop命令

    本文介绍如何在 Linux 中使用 htop 命令。
    的头像 发表于 12-04 14:45 1373次阅读
    如<b class='flag-5'>何在</b>Linux<b class='flag-5'>中使</b>用htop命令

    何在Arduino IDE中使用ESP-100进行开发?

    上没有任何规范或驱动程序(请参阅 )。此外,搜索 ESP-100 并没有让我了解如何在 Arduino IDE 中使用这个东西进行开发的重要事实。 到目前为止,我已经使用 Arduino
    发表于 05-12 08:06

    如何将MCP2515CAN总线控制器与Arduino接口

    在这个项目中,我们将了解MCP2515 CAN控制器模块,如何将MCP2515 CAN总线控制器与Arduino接口,以及如何在两个MCP2515
    的头像 发表于 07-30 10:51 2w次阅读

    何在Arduino中使用流行的GT511C3指纹传感器

    在本教程中,我们将学习如何在Arduino 中使用流行的 GT511C3 指纹传感器 (FPS)。有许多可用的 FPS,我们已经学会了如何使用它们来构建考勤系统、投票机、安全系统等设计。但
    发表于 09-05 15:48 1326次阅读
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用流行的GT511C3指纹传感器

    何在Arduino中使用NRF24L01模块

    电子发烧友网站提供《如何在Arduino中使用NRF24L01模块.zip》资料免费下载
    发表于 10-19 09:16 13次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用NRF24L01模块

    何在Arduino中使用伺服电机

    电子发烧友网站提供《如何在Arduino中使用伺服电机.zip》资料免费下载
    发表于 10-24 09:46 3次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用伺服电机

    何在arduino中使用I2c LCD模块

    电子发烧友网站提供《如何在arduino中使用I2c LCD模块.zip》资料免费下载
    发表于 10-26 14:29 1次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>arduino</b><b class='flag-5'>中使</b>用I2c LCD模块

    何在Arduino中使用LDR

    电子发烧友网站提供《如何在Arduino中使用LDR.zip》资料免费下载
    发表于 10-31 09:50 0次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用LDR

    何在Arduino中使用Modbus

    电子发烧友网站提供《如何在Arduino中使用Modbus.zip》资料免费下载
    发表于 11-22 11:21 14次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用Modbus

    何在Arduino中使用微型伺服

    电子发烧友网站提供《如何在Arduino中使用微型伺服.zip》资料免费下载
    发表于 11-28 09:50 0次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用微型伺服

    何在Arduino中使用20x4 I2C字符LCD显示器

    电子发烧友网站提供《如何在Arduino中使用20x4 I2C字符LCD显示器.zip》资料免费下载
    发表于 06-28 15:57 0次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用20x4 I2C字符LCD显示器

    何在Arduino中使用APDS9960手势传感器

    电子发烧友网站提供《如何在Arduino中使用APDS9960手势传感器.zip》资料免费下载
    发表于 06-28 16:01 0次下载
    如<b class='flag-5'>何在</b><b class='flag-5'>Arduino</b><b class='flag-5'>中使</b>用APDS9960手势传感器

    何在测试中使用ChatGPT

    Dimitar Panayotov 在 2023 年 QA Challenge Accepted 大会 上分享了他如何在测试中使用 ChatGPT。
    的头像 发表于 02-20 13:57 640次阅读

    何在汽车CAN应用中使用负边缘触发触发器节省电力

    电子发烧友网站提供《如何在汽车CAN应用中使用负边缘触发触发器节省电力.pdf》资料免费下载
    发表于 09-13 10:06 0次下载
    如<b class='flag-5'>何在</b>汽车<b class='flag-5'>CAN</b>应用<b class='flag-5'>中使</b>用负边缘触发触发器节省电力