第0x01講 使用Arduino DUE開(kāi)發(fā)板進(jìn)行CAN總線通信

前言

很多計(jì)算機(jī)從業(yè)者對(duì)CAN總線這種通信協(xié)議一知半解甚至一頭霧水典尾,可能是由于其主要應(yīng)用于汽車工業(yè)領(lǐng)域盼砍,讓人覺(jué)得幾分神秘压储。其實(shí),作為計(jì)算機(jī)從業(yè)者徘禁,面對(duì)各種網(wǎng)絡(luò)協(xié)議,其復(fù)雜程度可以吊打CAN總線協(xié)議髓堪。所以本文作為系列課程的第一課送朱,就是要揭開(kāi)CAN總線的神秘面紗,讓讀者在動(dòng)手寫(xiě)代碼并調(diào)試的過(guò)程中體會(huì)CAN總線協(xié)議的工作原理干旁。

愿景是讓您車上實(shí)操驶沼,看看汽車到底在傳輸什么CAN總線消息。對(duì)了争群,首先要有輛車回怜。當(dāng)然,這是玩笑换薄。在沒(méi)有車的情況下玉雾,可以模擬CAN總線消息的傳輸,同樣可以理解CAN總線的運(yùn)行機(jī)制轻要。

接下來(lái)复旬,我們從開(kāi)發(fā)板、CAN模塊冲泥,軟件開(kāi)發(fā)環(huán)境等各方面分別介紹驹碍,目標(biāo)是第一個(gè)CAN總線消息收發(fā)程序能夠運(yùn)行起來(lái)失都!

使用Arduino DUE開(kāi)發(fā)板

Arduino DUE是一個(gè)基于Atmel SAM3X8E ARM Cortex-M3 CPU的微控制器開(kāi)發(fā)板。同時(shí)幸冻,它也是第一款基于32位的ARM核心微控制器粹庞。有54個(gè)數(shù)字輸入輸出針腳(其中12個(gè)可以被用作PWM輸出),12個(gè)模擬信號(hào)輸入洽损,4個(gè)UART(硬件串口)庞溜。

詳細(xì)配置如下表所示,

微處理器 AT91SAM3X8E
運(yùn)行電壓 3.3V
輸入電壓 (推薦) 7-12V
輸入電壓 (極限) 6-16V
數(shù)字I/O針腳 54 (其中12 個(gè)PWM)
模擬信號(hào)輸入 12
模擬信號(hào)輸出 2 (DAC)
全部I/O線輸出直流電流 130 mA
3.3V針腳輸出直流電流 800 mA
5V針腳輸出直流電流 800 mA
閃存 所有可用于用戶程序共512 KB
SRAM 96 KB (兩個(gè)bank: 64KB 和 32KB)
時(shí)鐘速度 84 MHz

注意,不同于其他Arduino家族開(kāi)發(fā)板運(yùn)行電壓是5V碑定,Arduino DUE運(yùn)行電壓是3.3V流码。超過(guò)這個(gè)電壓可能會(huì)損壞開(kāi)發(fā)板。

Arduino DUE開(kāi)發(fā)板實(shí)物圖
圖1 Arduino DUE開(kāi)發(fā)板實(shí)物圖1
圖1 Arduino DUE開(kāi)發(fā)板實(shí)物圖2
Arduino DUE針腳定義

下圖是Arduino DUE針腳定義延刘。注意左下角CANRX0漫试、CANTX0,這引出了本文的重點(diǎn)碘赖,也就是說(shuō)Arduino DUE原生支持CAN總線(關(guān)于CAN總線驾荣,后面會(huì)介紹)控制器模塊。但是貌似只支持一個(gè)(RX和TX分別是CAN模塊的收發(fā)信號(hào)線)CAN控制器模塊普泡?至于為什么需要多于一個(gè)CAN控制器模塊播掷,后面會(huì)揭曉。

圖3 Arduino DUE針腳定義

Arduino DUE對(duì)CAN控制器模塊的支持

打開(kāi)頂部Atmel SAM3X8E ARM Cortex-M3 CPU鏈接撼班,找到如下Block Diagram歧匈,注意CAN0、CAN1砰嘁。


圖4 Atmel SAM3X8E ARM Cortex-M3 CPU支持兩個(gè)CAN控制器

這說(shuō)明件炉,在微控制器級(jí)別,該MCU支持兩個(gè)CAN控制器模塊矮湘,而且暴露出CANRX0和CANTX0斟冕、CANRX1和CANTX1共4個(gè)針腳。當(dāng)然板祝,MCU支持不等于開(kāi)發(fā)板支持宫静,因?yàn)镸CU針腳不一定被開(kāi)發(fā)板暴露。

很慶幸券时,經(jīng)過(guò)查閱相關(guān)資料孤里,確認(rèn)MCU里4個(gè)CAN針腳全部被Arduino DUE暴露,只是Arduino DUE官方文檔沒(méi)有明說(shuō)CANRX1和CANTX1橘洞。實(shí)際CAN0和CAN1如下圖所示捌袜,


圖5 Arduino DUE另外一個(gè)隱藏的CAN控制器

好了,現(xiàn)在從硬件角度來(lái)說(shuō)炸枣,Arduino DUE內(nèi)置了兩個(gè)CAN控制器模塊虏等。注意弄唧,這里說(shuō)的時(shí)控制器模塊,但就像計(jì)算機(jī)理有USB控制器模塊霍衫,不等于有USb外設(shè)候引。要想實(shí)現(xiàn)諸如鍵盤(pán)、鼠標(biāo)等USB外設(shè)的通信敦跌,還需要有USB設(shè)備澄干。類似地,如果想實(shí)現(xiàn)CAN通信還需要有個(gè)CAN總線收發(fā)器模塊柠傍。不過(guò)麸俘,為了不至于制造困惑,接下來(lái)我們來(lái)討論什么是CAN總線惧笛,然后再回來(lái)討論CAN總線收發(fā)器模塊从媚。

CAN總線簡(jiǎn)介

CAN是Controller Area Network的簡(jiǎn)稱,中文翻譯為控制器局域網(wǎng)總線患整。CAN總線是一種用于實(shí)時(shí)串行通信協(xié)議總線拜效,它可以使用兩根交纏在一起的雙絞線來(lái)傳輸信號(hào)。CAN協(xié)議用于汽車中各種不同元件之間通信并级,以取代昂貴笨重的配電線束拂檩。該協(xié)議的健壯性使其用途延伸到其他自動(dòng)化和工業(yè)領(lǐng)域。

簡(jiǎn)單來(lái)說(shuō)嘲碧,

  • 假設(shè)(注意用詞)有兩根線,均長(zhǎng)約40米(和大刀無(wú)關(guān)父阻,為什么40米愈涩,后面課程會(huì)說(shuō)),一根命名為CAN High加矛,一個(gè)命名為CAN Low履婉,對(duì)應(yīng)隱形電平和顯性電平(這個(gè)后面課程會(huì)詳細(xì)介紹)。

  • 這兩根線為了抵消彼此因?yàn)楦哳l電流(電平同時(shí)變化)產(chǎn)生的電磁干擾斟览,即共模消除干擾毁腿,采用雙絞線的形式兩者絞纏(類似于網(wǎng)線里面?zhèn)z倆絞纏)在一起。

  • Arduino DUE的CAN0總線控制器連接到CAN0總線收發(fā)器苛茂,收發(fā)器有兩根線已烤,一根是CAN High,一根是CAN Low妓羊。這兩根線的CAN High和CAN Low分別連接到40米雙絞線的CAN High和CAN Low胯究。

  • CAN Hig電壓介于2.5V ~ 3.5V;CAN Low電壓介于1.5V ~ 2.5V躁绸,從而High和Low形成差分信號(hào)裕循。注意臣嚣,兩根線不可錯(cuò)接。

  • 同樣的剥哑,Arduino DUE的CAN1總線控制器連接到CAN1總線收發(fā)器硅则,收發(fā)器有兩根線,一根是CAN High株婴,一根是CAN Low抢埋。這兩根線的CAN High和CAN Low分別連接到40米雙絞線的CAN High和CAN Low。注意督暂,不可錯(cuò)接揪垄。

  • 這樣,CAN0和CAN1都連接到40米的雙絞線逻翁,兩者通過(guò)這種方式建立了連接饥努。

圖6 CAN總線CAN High和CAN Low電壓

這就像居民樓里入戶的220V交流電電纜,每戶都是2根線八回,零線和火線酷愧,各種用電設(shè)備都接在這連根線上。理論上缠诅,所有變電站下方的220V用電設(shè)備溶浴,其兩根火線或兩根零線其電位一致。

把居民入戶220V交流電纜和CAN總線相比不同之處在于管引,CAN總線任意兩個(gè)節(jié)點(diǎn)直接都可以發(fā)送消息士败。

另外,有些人可能疑惑褥伴,為什么一直在糾結(jié)是不是兩個(gè)CAN模塊呢谅将?難道一個(gè)模塊不行嗎?CAN總線協(xié)議規(guī)定重慢,一個(gè)CAN幀必須得到至少一個(gè)除了本節(jié)點(diǎn)的其他節(jié)點(diǎn)的確認(rèn)(Acknowledgement)饥臂,否則視為出錯(cuò)。所以似踱,如果有兩個(gè)或者兩個(gè)以上的CAN控制器即收發(fā)器模塊便于測(cè)試隅熙,尤其繼集成在個(gè)開(kāi)發(fā)板上。這也是為什么我們?nèi)腴T(mén)的第一課選擇了Arduino DUE核芽。

關(guān)于CAN總線線介紹到這里囚戚,詳細(xì)介紹請(qǐng)關(guān)注后續(xù)課程。

CAN收發(fā)器和控制器

CAN收發(fā)器和控制器分別對(duì)應(yīng)CAN總線的物理層和數(shù)據(jù)鏈路層狞洋。


圖7 CAN收發(fā)器和控制器
CAN收發(fā)器

CAN收發(fā)器是將差分信號(hào)轉(zhuǎn)換成TTL (Transistor Transistor Logic)電平信號(hào)弯淘,或者將TTL電平信號(hào)轉(zhuǎn)成差分信號(hào)。

  • CAH High - CAN Low = 2.5V - 2.5V = 0.0V吉懊,顯性電平庐橙。
  • CAH High - CAN Low = 3.5V - 1.5V = 2.0V假勿,隱形電平。
圖8 CAN收發(fā)器顯性電平和隱形電平

圖9 某款CAN收發(fā)器
CAN控制器

CAN控制器實(shí)現(xiàn)CAN總線的協(xié)議棧以及數(shù)據(jù)鏈路層态鳖,

  • 用于生成CAN數(shù)據(jù)幀并以二進(jìn)制的方式發(fā)送转培。并在此過(guò)程中進(jìn)行位填充、添加CRC校驗(yàn)浆竭、應(yīng)答檢測(cè)等浸须。
  • 用于將接收到的二進(jìn)制進(jìn)行解析,并在此過(guò)程中進(jìn)行收發(fā)比對(duì)邦泄、去位填充删窒、執(zhí)行CRC校驗(yàn)等操作。


    圖10 CAN控制器工作原理

連接CAN收發(fā)器到Arduino DUE開(kāi)發(fā)板

準(zhǔn)備好了知識(shí)顺囊,現(xiàn)在可以開(kāi)始上手了肌索。首先硬件準(zhǔn)備。

設(shè)備準(zhǔn)備

按照下表來(lái)準(zhǔn)備設(shè)備特碳。

設(shè)備 型號(hào) 數(shù)量 是否必選
開(kāi)發(fā)板 Arduino DUE 1
CAN收發(fā)器 任何集成SN65HVD230芯片收發(fā)器诚亚。比如微雪、丟石頭等品牌午乓。 2
面包板 任何5排以上的面包板 1
跳線 任何公-公(使用面包板)站宗、或者公-母(不使用面包板)針跳線。 若干
設(shè)備連線

按照下表來(lái)連接設(shè)備益愈。

開(kāi)發(fā)板 CAN收發(fā)器0 CAN收發(fā)器1
CAN High CAN High
CAN Low CAN Low
3.3V 3.3V 3.3V
GND GND GND
CANRX RX
CANTX TX
DAC0 RX
53 TX

參考圖片如下梢灭,

圖11 Arduino DUE與CAN收發(fā)器連線1

圖12 Arduino DUE與CAN收發(fā)器連線2

圖13 Arduino DUE與CAN收發(fā)器連線3

檢查無(wú)誤后,插上MicroUSB腕唧,建議使用Native USB Port(離電源插口遠(yuǎn)的插口)上電或辖。


圖14 Arduino DUE插上MicroUSB到Native USB Port

留一個(gè)疑問(wèn)?雙絞線在哪枣接?

使用Arduino IDE開(kāi)發(fā)

請(qǐng)自行安裝Arduino IDE。安裝完成后缺谴,運(yùn)行Arduino IDE但惶,打開(kāi)BOARDS MANAGER,搜關(guān)鍵字“Due”湿蛔,然后點(diǎn)“INSTALL”安裝膀曾。


圖15 Arduino IDE安裝DUE開(kāi)發(fā)板支持

安裝完開(kāi)發(fā)板,在安裝Library阳啥。打開(kāi)LIBRARY MANAGER添谊,搜索“can_due”,滾動(dòng)到最下方察迟,點(diǎn)“INSTALL”安裝斩狱,


圖16 Arduino IDE安裝can_due驅(qū)動(dòng)

打開(kāi)”File“耳高,然后選擇‘Save“,可以命名為“CANTransceiver”所踊,此時(shí)泌枪,項(xiàng)目如下所示,


圖17 創(chuàng)建CANTransceiver項(xiàng)目

接下來(lái)我們通過(guò)代碼在兩個(gè)收發(fā)器之間傳送消息秕岛。


#include <due_can.h>

// Leave the macro defined in the case you use the Native USB Port.
// Comment out if you use then Programming Port.
#define Serial SerialUSB

#define MAXIMUM_CAN_FRAME_DATA_LENGTH   8
#define MAXIMUM_FRAMES_NUMBER           5000

void setup()
{
    Serial.begin(115200);

    while (!Serial);
    
    if (Can0.begin(CAN_BPS_1000K) && Can1.begin(CAN_BPS_1000K))
        Serial.println("CAN0 and CAN1 initialized.");
    else
        Serial.println("Failed to initialize the CAN devices.");

    echo();
}

void loop()
{
  // put your main code here, to run repeatedly:

}

static void echo(void)
{
    CAN_FRAME frame1, frame2, incoming;

    uint32_t id         = random(0x00000001, 0x00FFFDFF);

    Serial.println(id, HEX);

    frame1.id           = id;
    frame1.length       = MAXIMUM_CAN_FRAME_DATA_LENGTH;
    frame1.data.low     = 0x0001;
    frame1.data.high    = 0x1000;
    frame1.extended     = 1;

    uint16_t addition   = 0x0200;

    frame2.id           = id + addition;
    frame2.length       = MAXIMUM_CAN_FRAME_DATA_LENGTH;
    frame2.data.low     = 0x00000002;
    frame2.data.high    = 0x20000000;
    frame2.extended     = 1;

    Can0.watchFor(id);
    Can1.watchFor(id + addition);

    uint32_t sentFrames, receivedFrames;
    uint16_t counter = 0;

    Can0.sendFrame(frame2);

    sentFrames ++;

    while (1)
    {
        if (Can0.available() > 0)
        {
            Can0.read(incoming);
            Can0.sendFrame(frame2);

            delayMicroseconds(100);

            receivedFrames ++;
            sentFrames ++;
            counter++;
        }

        if (Can1.available() > 0)
        {
            Can1.read(incoming);
            Can1.sendFrame(frame1);

            delayMicroseconds(100);

            receivedFrames ++;
            sentFrames ++;
            counter++;
        }

        if (counter > MAXIMUM_FRAMES_NUMBER)
        {
            counter = 0;

            Serial.print("Sent: ");
            Serial.print(sentFrames);
            Serial.print(", Received: ");
            Serial.print(receivedFrames);
            Serial.println(".");
        }
    }
}

代碼簡(jiǎn)單解釋如下碌燕,

  • 首先在void setup()方法里初始化Can0和Can1。
  • 在echo()方法里继薛,首先定義了三個(gè)數(shù)據(jù)幀變量修壕,frame1、frame2以及傳入的incoming幀遏考。查看CAN_FRAME慈鸠,發(fā)現(xiàn)這是一個(gè)結(jié)構(gòu)體,容易轉(zhuǎn)換成字節(jié)流诈皿。
  • 接著對(duì)frame1和frame2進(jìn)行賦值林束,分別是id、數(shù)據(jù)字段稽亏、長(zhǎng)度以及是否是擴(kuò)展幀壶冒,這些都是必選字段。
  • watchFor是通過(guò)id過(guò)濾截歉,器用過(guò)濾會(huì)忽然那些非符合條件的幀胖腾,畢竟像汽車這種適合CAN總線使用的場(chǎng)景,可能有多達(dá)數(shù)百個(gè)CAN設(shè)備瘪松,而且一個(gè)設(shè)備一秒鐘發(fā)送很多幀都有可能咸作。

所以,一個(gè)過(guò)濾功能非常有必要宵睦。

上傳燒錄程序

上傳燒錄记罚,運(yùn)行程序,打開(kāi)Serial Monitor可以看到數(shù)據(jù)幀在兩個(gè)CAN收發(fā)器之間傳送壳嚎。

圖18 程序運(yùn)行結(jié)果

小結(jié)

本文作為CAN總線第一課桐智,弱化了概念,簡(jiǎn)化了程序代碼烟馅,目的就是為讓您上手说庭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市郑趁,隨后出現(xiàn)的幾起案子刊驴,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捆憎,死亡現(xiàn)場(chǎng)離奇詭異舅柜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)攻礼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)业踢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人礁扮,你說(shuō)我怎么就攤上這事知举。” “怎么了太伊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵雇锡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我僚焦,道長(zhǎng)锰提,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任芳悲,我火速辦了婚禮立肘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘名扛。我一直安慰自己谅年,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布肮韧。 她就那樣靜靜地躺著融蹂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弄企。 梳的紋絲不亂的頭發(fā)上超燃,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音拘领,去河邊找鬼意乓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛约素,可吹牛的內(nèi)容都是我干的洽瞬。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼业汰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了菩颖?” 一聲冷哼從身側(cè)響起样漆,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晦闰,沒(méi)想到半個(gè)月后放祟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鳍怨,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年跪妥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鞋喇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡眉撵,死狀恐怖侦香,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纽疟,我是刑警寧澤罐韩,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站污朽,受9級(jí)特大地震影響散吵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蟆肆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一矾睦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧炎功,春花似錦枚冗、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至州藕,卻和暖如春束世,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背床玻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工毁涉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锈死。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓贫堰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親待牵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子其屏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容