前言:
兩個月前的一篇文章:PID與三環控制發佈之後,有很多朋友在微信上交流大疆M350八、M2006的使用問題,其中有一個方面值得單獨拿出來聊一聊:CAN通訊html
對於不少朋友,包括我本身,使用大疆的M350八、M2006無刷直流電機和C6十、C620電調是第一次接觸到CAN通訊。大疆的這幾款產品本來設計的很是容易上手,應該幾天就能熟練使用。可是因爲C6十、C620電調選用了CAN總線通訊,給很多人帶來了困擾。然而使用這幾個電機並不須要把CAN通訊瞭解的有多麼深。微信
困擾每每來自:函數
- CAN總線以前用的比較少
- 現有CAN通訊資料少並且複雜
這篇文章旨在快速掃盲,給出使用M350八、M2006電機的必備CAN通訊知識,但願能下降使用門檻,給各位朋友節約時間。內容均使用M3508與M2006實測過,演示視頻在文章末尾。.net
本文僅涉及必備知識,甚至儘可能避開復雜的通訊原理,力求淺顯易懂。設計
這件事要放到前面去說,由於已經有幾位朋友的經歷指出了其必要性。code
若是咱們有一塊STM32開發板,也有電調電機和電源。那麼咱們的STM32引腳與電調的CAN_H和CAN_L之間是不能直接相連的。component
須要購買以下圖所示的CAN收發器,做爲二者鏈接的橋樑。通常我用的是TJA1050芯片的模塊。視頻
CAN收發器是使用電機的必備硬件條件,必定要先肯定本身有這個東西。至於緣由,我們接下來講明。htm
經過分析硬件層面咱們能知道爲何須要額外的CAN收發器。請看下圖:blog
從圖中咱們能看出,STM32擁有的外設叫作:CAN控制器,它負責CAN通訊的篩選、優先級、仲裁等問題。至關於我們的郵局,幫忙蓋個郵戳,分分類。經過複用GPIO之後,它延伸出兩個引腳:CAN_RX
和CAN_TX
,類比串口咱們知道一個負責收一個負責發。
實際上,這兩個引腳上傳輸的數據已是CAN報文了,該有的格式它都有,STM32的CAN迴環模式就至關於直接把CAN_RX
和CAN_TX
相連,就能夠收到本身發的消息。
問題是,CAN在設計的時候爲了消除共模干擾,特意選用了差分信號(也叫差模信號)傳輸。我們的C6十、C620電調,接收發送的就是差分信號。這纔是CAN收發器的做用:
把來自STM32的信號轉換成差分信號讓電調聽得懂,把來自電調的差分信號轉換成STM32聽得懂的信號。
鏈接CAN_RX
和CAN_TX
引腳與CAN收發器的引腳時,並不須要像串口同樣交叉。直接將RX鏈接到標有RX的引腳,TX相似。
不知道朋友們有沒有注意到C6十、C620電調上都有一個開關,C620的在側面,旁邊寫着CAN RESISTOR
,這也是CAN總線的設計要求。
根據我們學的《電路理論》這門課,當信號波長小於電路尺寸的時候,咱們就不能把電路當成集中電路來分析。對於can總線是同樣的,因爲電調採用1MHz的通訊頻率,爲了防止一些沒必要要的干擾,咱們須要在CAN總線的兩端分別用120Ω電阻跨接起來。好比以前圖中的兩端能夠認爲是我們的CAN收發器是一端,下面的電調是另外一端。
對於只有一個電調的狀況下,能夠打開電調上的電阻,而後直接和CAN收發器鏈接,這樣雖然少了一端的終端電阻,但實際上能夠運行。若是同時控制兩個及以上的電調,那就能夠打開其中兩個的終端電阻,構成總線的兩端。固然也能夠手動組成以下圖的總線結構而且關閉電調上的終端電阻,圖中還加入了電容進行濾波。
其實,看完硬件部分就已經能夠正常使用電調電機了,由於大疆官方例程中已經把CAN通訊配置好了,直接可使用。
可是若是涉及很是多的設備同時控制,好比超過四個電機的狀況下,或者還有其餘的外設要經過CAN總線相連,簡單瞭解軟件配置也是頗有好處。
並且,我發現不少朋友是在作RoboMaster比賽,全面的瞭解軟硬件仍是十分必要的,若是出現問題也有利於排查,不至於浪費大量時間。
接下來咱們仍是使用我們的老朋友:大疆官方M2006例程、M3508例程來做爲樣本。主要探究如下問題:
- 通訊頻率如何設定爲1MHz
- CAN過濾器的配置
- 報文的接收與發送
兩個文件:bsp_can.c
和can.c
如下是文件can.c
中截取的代碼(有刪改):
CAN_HandleTypeDef hcan1; /* CAN1 init function */ void MX_CAN1_Init(void) { hcan1.Instance = CAN1; hcan1.Init.Prescaler = 3;//分頻係數設置爲3 hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SJW = CAN_SJW_1TQ; // =================請看這裏👇 hcan1.Init.BS1 = CAN_BS1_9TQ; hcan1.Init.BS2 = CAN_BS2_4TQ; // =====================這裏👆 //省略一些。。。。。 HAL_CAN_Init(&hcan1); }
注意,大疆的例程是爲大疆的開發板所編寫,其主控芯片是STM32F429,在這裏F4與F1的時鐘頻率差異會影響到配置的具體參數。
我們重點來看分頻係數的肯定以及標出的兩行。
STM32F4通常來講主頻率會配置到168MHz,通過4分頻以後獲得了42MHz的APB1時鐘,CAN控制器正是從APB1上獲取時鐘。代碼中hcan1.Init.Prescaler = 3;
正是將42MHz的時鐘進行3分頻,獲得了14MHz的時鐘。這就是真正被使用的頻率。接着咱們看傳輸一個bit須要哪幾部分:
因此,傳輸一位的時間能夠看做T=(1+BS1+BS2)*tq,tq(time quantum)。因此在例程裏就是1+9+4=14個tq。而tq恰好是CAN時鐘頻率14MHz的倒數,tq=(1/14MHz),T=14*tq,得T=(1/1MHz),一樣f=1/T=1MHz。由此得到了咱們須要的頻率。
同理,若是是F1,APB1時鐘通常是36MHz,那麼咱們設置分頻係數爲4,BS1=5,BS2=3,也能獲得1MHz。
其實通常來講並不須要注意CAN過濾器得配置,由於官方例程也沒怎麼配置,大可直接套用。
過濾器是針對接收信息進行篩選得部件,由於CAN總線上得消息每每比較複雜,經過過濾器能夠選出想要接受的消息。大體過程是過濾器會對全部收到的報文按照我們設定的規則進行篩選,若是符合要求就會放入FIFO緩衝區保存下來。而這個規則就是報文的id信息。爲了實現複雜的id篩選,引入了id寄存器和id掩碼寄存器,其配合過程很是的。。精彩👍。有興趣能夠了解一下。
下面得代碼摘自文件bsp_can.c
(有刪改):
void my_can_filter_init_recv_all(CAN_HandleTypeDef* _hcan) { CAN_FilterConfTypeDef CAN_FilterConfigStructure; static CanTxMsgTypeDef Tx1Message; static CanRxMsgTypeDef Rx1Message; CAN_FilterConfigStructure.FilterNumber = 0; CAN_FilterConfigStructure.FilterMode = CAN_FILTERMODE_IDMASK; CAN_FilterConfigStructure.FilterScale = CAN_FILTERSCALE_32BIT; CAN_FilterConfigStructure.FilterIdHigh = 0x0000; CAN_FilterConfigStructure.FilterIdLow = 0x0000; CAN_FilterConfigStructure.FilterMaskIdHigh = 0x0000; CAN_FilterConfigStructure.FilterMaskIdLow = 0x0000; CAN_FilterConfigStructure.FilterFIFOAssignment = CAN_FilterFIFO0; CAN_FilterConfigStructure.BankNumber = 14; CAN_FilterConfigStructure.FilterActivation = ENABLE; HAL_CAN_ConfigFilter(_hcan, &CAN_FilterConfigStructure) ; }
這裏咱們發現不管是id仍是掩碼都是0,也就是接收總線上的全部報文。那麼在多電機的狀況下如何區分消息的發出者呢?
咱們先看看接收,如下選自bsp_can.c
(有刪改):
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* _hcan) { switch(_hcan->pRxMsg->StdId){ case CAN_2006Moto1_ID://0x201 case CAN_2006Moto2_ID://0x202 case CAN_2006Moto3_ID://0x203 case CAN_2006Moto4_ID://0x204 { static u8 i; i = _hcan->pRxMsg->StdId - CAN_2006Moto1_ID; get_moto_measure(&moto_chassis[i], _hcan); } break; }
這是CAN的接收中斷回調函數,在來到這個函數以前,得到的報文已經被儲存在pRxMsg
指向的結構體當中。switch語句經過判別StdId
來肯定是否是電機發來的報文,而且判斷是哪一個電機。而這個StdId
我們並不陌生,它是前面所說的FilterId
的一部分。
官方手冊中提到在同一個CAN總線上,最多能夠接入8個電調,經過電調的自動分配他們分別是地址0x201~0x208。
再看發送:
void set_moto_current(CAN_HandleTypeDef* hcan, s16 iq1, s16 iq2, s16 iq3, s16 iq4){ hcan->pTxMsg->StdId = 0x200; hcan->pTxMsg->IDE = CAN_ID_STD; hcan->pTxMsg->RTR = CAN_RTR_DATA; hcan->pTxMsg->DLC = 0x08; hcan->pTxMsg->Data[0] = (iq1 >> 8); hcan->pTxMsg->Data[1] = iq1; hcan->pTxMsg->Data[2] = (iq2 >> 8); hcan->pTxMsg->Data[3] = iq2; hcan->pTxMsg->Data[4] = iq3 >> 8; hcan->pTxMsg->Data[5] = iq3; hcan->pTxMsg->Data[6] = iq4 >> 8; hcan->pTxMsg->Data[7] = iq4; HAL_CAN_Transmit(hcan, 100); }
按照手冊,咱們能看出,若是要給編號爲0x2010x204的電調發信息,要把發送中的`StdId`設置爲0x200,如果要給0x2050x208的四個電調發信息,則要設置爲0x1FF。
後面依照手冊填充數據而後發送,過程比較簡單。
又是一篇有關大疆電機的文章,也是結合我本身的經歷和上一篇文章的反饋纔有了這篇。如今還記得我剛開始接觸CAN通訊時候的疑惑感,感受資料都太複雜看不下去。水平確實有限,也就只能力求個淺顯易懂,但願能幫助朋友們節約一些時間吧。相關例程能夠在公衆號上向我索要。
這裏放上前一篇文章連接:PID和三環控制-以大疆M350八、M2006爲例 https://blog.csdn.net/qq_28039135/article/details/116379392
更多嵌入式,電機控制相關文章請移步公衆號,來找我聊聊天吧:
技術新人,水平有限,還請各位朋友多多指教。若是對文章有任何的疑問或者發現錯誤請必定指出!
同時控制M350五、M2006雙電機的演示視頻在公衆號原文底部:
歡迎轉載,請註明做者與原文地址:
做者:胡小安