如今,任何一輛普通汽車都包含大約 60 到 100 個傳感器單元,用于傳感和交換信息。隨著汽車制造商不斷通過自動駕駛、安全氣囊系統(tǒng)、胎壓監(jiān)測、巡航控制系統(tǒng)等功能使他們的汽車更加智能,這個數(shù)字只會越來越高。與其他傳感器不同,這些傳感器處理關(guān)鍵信息,因此來自這些傳感器的數(shù)據(jù)應(yīng)使用標(biāo)準(zhǔn)汽車通信協(xié)議進(jìn)行通信。例如,速度、油門位置等巡航控制系統(tǒng)數(shù)據(jù)是發(fā)送到電子控制單元 (ECU)的重要值為了決定汽車的加速水平,此處的錯誤通信或數(shù)據(jù)丟失可能導(dǎo)致嚴(yán)重故障。因此,與 UART、SPI或I2C等標(biāo)準(zhǔn)通信協(xié)議不同,設(shè)計人員使用更可靠的汽車通信協(xié)議,如 LIN、CAN、FlexRay 等。
在本文中,我們將再次研究基礎(chǔ)知識,最后我們還將使用 CAN 通信在兩個 Arduino 之間交換數(shù)據(jù)。
CAN簡介
CAN aka Controller Area Network是一種串行通信總線,專為工業(yè)和汽車應(yīng)用而設(shè)計。它是一種基于消息的協(xié)議,用于多個設(shè)備之間的通信。當(dāng)多個 CAN 設(shè)備如下圖所示連接在一起時,連接形成一個網(wǎng)絡(luò),就像我們的中樞神經(jīng)系統(tǒng)一樣,允許任何設(shè)備與節(jié)點中的任何其他設(shè)備通話。
CAN 網(wǎng)絡(luò)將僅包含兩條線CAN High 和 CAN Low,用于雙向數(shù)據(jù)傳輸,如上所示。通常,CAN 的通信速度范圍從 50 Kbps 到 1Mbps,距離范圍可以從 1Mbps 的 40 米到 50kpbs 的 1000 米。
CAN報文格式:
在 CAN 通信中,數(shù)據(jù)以特定的消息格式在網(wǎng)絡(luò)中傳輸。這種消息格式包含許多段,但兩個主要段是標(biāo)識符和有助于在 CAN 總線中發(fā)送和響應(yīng)消息的數(shù)據(jù)。
標(biāo)識符或 CAN ID:標(biāo)識符也稱為 CAN ID 或也稱為 PGN(參數(shù)組編號)。它用于識別 CAN 網(wǎng)絡(luò)中存在的 CAN 設(shè)備。根據(jù)使用的 CAN 協(xié)議類型,標(biāo)識符的長度為 11 位或 29 位。
標(biāo)準(zhǔn) CAN:0-2047(11 位)
擴(kuò)展 CAN:0-2 29 -1(29 位)
數(shù)據(jù):這是必須從一個設(shè)備發(fā)送到另一個設(shè)備的實際傳感器/控制數(shù)據(jù)。大小數(shù)據(jù)的長度可以是 0 到 8 個字節(jié)。
數(shù)據(jù)長度代碼 (DLC):0 到 8 表示存在的數(shù)據(jù)字節(jié)數(shù)。
CAN中使用的電線:
CAN 協(xié)議由兩條線組成,即CAN_H 和 CAN_L,用于發(fā)送和接收信息。兩條線都充當(dāng)差分線,這意味著 CAN 信號(0 或 1)由 CAN_L 和 CAN_H 之間的電位差表示。如果差為正且大于某個最小電壓,則為 1,如果差為負(fù),則為 0。
通常使用雙絞線電纜進(jìn)行 CAN 通信。如圖所示,CAN 網(wǎng)絡(luò)的兩端通常使用一個 120 歐姆的電阻,這是因為線路需要平衡并連接到相同的電位。
CAN over SPI 和 I2C 的比較
既然我們已經(jīng)學(xué)會了如何使用SPI 和 Arduino和IIC 和 Arduino,讓我們比較一下 SPI 和 I2C 和 CAN 的特性
CAN 協(xié)議應(yīng)用
由于 CAN 協(xié)議的穩(wěn)健性和可靠性,它們被用于汽車、工業(yè)機(jī)械、農(nóng)業(yè)、醫(yī)療設(shè)備等行業(yè)。
由于 CAN 中的布線復(fù)雜性降低,它們主要用于汽車等汽車應(yīng)用。
實施成本低,硬件組件價格也較低。
易于添加和刪除 CAN 總線設(shè)備。
如何在 Arduino 中使用 CAN 協(xié)議
由于 Arduino 不包含任何內(nèi)置 CAN 端口,因此使用了一個名為MCP2515的 CAN 模塊。該 CAN 模塊通過 SPI 通信與 Arduino 連接。讓我們詳細(xì)了解 MCP2515 以及它如何與 Arduino 接口。
MCP2515 CAN 模塊:
MCP2515 模塊有一個 CAN 控制器 MCP2515,它是高速 CAN 收發(fā)器。MCP2515 與 MCU 之間通過 SPI 連接。因此,很容易與任何具有 SPI 接口的微控制器連接。
對于想要學(xué)習(xí) CAN Bus 的初學(xué)者來說,這個模塊將是一個好的開始。此 CAN SPI 板非常適合工業(yè)自動化、家庭自動化和其他汽車嵌入式項目。
MCP2515的特性和規(guī)格:
使用高速CAN收發(fā)器TJA1050
尺寸:40×28mm
用于擴(kuò)展多 CAN 總線接口的 SPI 控制
8MHZ晶振
120Ω終端電阻
支持 1 Mb/s CAN 操作
低電流待機(jī)操作
最多可連接112個節(jié)點
MCP2515 CAN 模塊的引腳排列:
在本教程中,讓我們看看如何通過 CAN總線模塊 MCP2515從 Arduino Nano 向 Arduino Uno 發(fā)送濕度和溫度 (DHT11) 傳感器數(shù)據(jù)。
所需組件
Arduino UNO
阿杜諾納米
DHT11
16x2 液晶顯示器
MCP2515 CAN 模塊 – 2
10k 電位器
面包板
連接電線
MCP2515 Arduino電路圖
CAN Transmitter 端的連接:
CAN接收器側(cè)的電路連接:
兩個 MCP2515 CAN 模塊之間的連接
完成所有連接后,我的硬件如下所示
為 CAN 通信編程 Arduino
首先,我們必須在 Arduino IDE 中安裝 CAN 庫。通過使用以下庫,將 MCP2515 CAN 模塊與 Arduino 連接變得更加容易。
在本教程中,編碼分為兩部分,一是CAN 發(fā)送器代碼(Arduino Nano),另一部分是CAN 接收器代碼(Arduino UNO),兩者均可在本頁底部找到。其說明如下。
在編寫發(fā)送和接收數(shù)據(jù)的程序之前,請確保您已經(jīng)按照上述步驟安裝了庫,并且 CAN 模塊 MCP2515 在您的程序中初始化如下。
初始化 MCP2515 CAN 模塊:
要創(chuàng)建與 MCP2515 的連接,請執(zhí)行以下步驟:
1.設(shè)置SPI CS連接的管腳號(默認(rèn)10)
MCP2515 mcp2515(10);
2.設(shè)置波特率和振蕩器頻率
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. 設(shè)置模式。
mcp2515.setNormalMode(); mcp2515.setLoopbackMode(); mcp2515.setListenOnlyMode();
CAN發(fā)射端代碼說明(Arduino Nano)
在發(fā)射器部分,Arduino Nano 通過 SPI 引腳與 MCP2515 CAN 模塊接口,DHT11 將溫度和濕度數(shù)據(jù)發(fā)送到 CAN 總線。
首先包括所需的庫,用于使用 SPI 通信的 SPI 庫、用于使用 CAN 通信的 MCP2515 庫和用于將 DHT 傳感器與 Arduino 一起使用的 DHT 庫。我們之前將 DHT11 與 Arduino 接口。
#include#include #include
現(xiàn)在定義了與 Arduino Nano 的 A0 相連的 DHT11(OUT 引腳)的引腳名稱
#define DHTPIN A0
而且,DHTTYPE被定義為 DHT11。
#define DHTTYPE DHT11
用于存儲 CAN 消息格式的canMsg結(jié)構(gòu)數(shù)據(jù)類型。
結(jié)構(gòu) can_frame canMsg;
設(shè)置 SPI CS 連接的管腳號(默認(rèn)為 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();
現(xiàn)在 MCP2515 的速度設(shè)置為 500KBPS 和 8MHZ 作為時鐘
mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
并且 MCP2525 設(shè)置為正常模式
mcp2515.setNormalMode();
在無效循環(huán)()中:
以下語句獲取濕度和溫度值并存儲在整數(shù)變量 h 和 t 中。
int h = dht.readHumidity(); int t = dht.readTemperature();
接下來,CAN ID 為 0x036(根據(jù)選擇),DLC 為 8,我們將 h 和 t 數(shù)據(jù)分配給data[0] 和data[1] ,并將所有數(shù)據(jù)保留為 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;
畢竟,要將消息發(fā)送到 CAN BUS,我們使用以下語句。
mcp2515.sendMessage(&canMsg);
所以現(xiàn)在溫度和濕度數(shù)據(jù)作為消息發(fā)送到 CAN 總線。
CAN接收端代碼說明(Arduino UNO)
在接收器部分,Arduino UNO 與 MCP2515 和16x2 LCD 顯示器連接。在這里,Arduino UNO 從 CAN 總線接收溫度和濕度,并在 LCD 中顯示接收到的數(shù)據(jù)。
首先包括所需的庫,用于使用 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);
聲明了一個結(jié)構(gòu)數(shù)據(jù)類型用于存儲CAN 消息格式。
結(jié)構(gòu) can_frame canMsg;
設(shè)置 SPI CS 連接的管腳號(默認(rèn)為 10)
MCP2515 mcp2515(10);
在 void setup() 中:
首先將 LCD 設(shè)置為 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();
現(xiàn)在將 MCP2515 設(shè)置為 500KBPS 的速度和 8MHZ 作為時鐘。
mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
MCP2525 設(shè)置為正常模式。
mcp2515.setNormalMode();
接下來在 void loop() 中:
以下語句用于接收來自 CAN 總線的消息。如果收到消息,則進(jìn)入if條件。
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
在if條件下,數(shù)據(jù)被接收并存儲在 canMsg中,具有濕度值的數(shù)據(jù) [0] 和具有溫度值的數(shù)據(jù) [1]。這兩個值都存儲在整數(shù) x 和 y 中。
int x = canMsg.data[0]; int y = canMsg.data[1];
收到數(shù)值后,溫度和濕度值使用以下語句顯示在 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通信的工作
硬件準(zhǔn)備好后,將 CAN 發(fā)送器和 CAN 接收器的程序(完整程序如下)上傳到各自的 Arduino 板上。通電后,您應(yīng)該注意到 DHT11 讀取的溫度值將通過 CAN 通信發(fā)送到另一個 Arduino,并顯示在第二個Arduino 的 LCD 上,如下圖所示。我還使用交流遙控器檢查液晶顯示屏上顯示的溫度是否接近實際室溫。
CAN 發(fā)射器代碼(Arduino Nano):
#include
#include
#include
#define DHTPIN A0
#define DHTTYPE DHT11
結(jié)構(gòu) 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 設(shè)置為速度 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數(shù)據(jù)長度為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); //發(fā)送CAN報文
delay(1000);
}
CAN接收器代碼(Arduino UNO):
#include
#include
#include
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
結(jié)構(gòu) can_frame canMsg;
MCP2515 mcp2515(10); // SPI CS 引腳 10
void setup() {
lcd.begin(16,2); //設(shè)置 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 設(shè)置為 500KBPS 和 8MHz 時鐘
mcp2515.setNormalMode(); //將CAN設(shè)置為正常模式
}
void loop()
{
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) // 接收數(shù)據(jù)(輪詢讀?。?br />
{
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
+關(guān)注
關(guān)注
57文章
2756瀏覽量
463899 -
MCP2515
+關(guān)注
關(guān)注
0文章
23瀏覽量
15835 -
Arduino
+關(guān)注
關(guān)注
188文章
6472瀏覽量
187317
發(fā)布評論請先 登錄
相關(guān)推薦
評論