大疆M3508、M2006必備CAN總線知識與配置方法


使用大疆M3508、M2006的CAN總線知識與配置方法


電機

前言:

兩個月前的一篇文章:PID與三環控制發布以后,有不少朋友在微信上交流大疆M3508、M2006的使用問題,其中有一個方面值得單獨拿出來聊一聊:CAN通信

對於很多朋友,包括我自己,使用大疆的M3508、M2006無刷直流電機和C610、C620電調是第一次接觸到CAN通信。大疆的這幾款產品原本設計的非常容易上手,應該幾天就能熟練使用。但是由於C610、C620電調選用了CAN總線通信,給不少人帶來了困擾。然而使用這幾個電機並不需要把CAN通信了解的有多么深

困擾往往來自:

  • CAN總線之前用的比較少
  • 現有CAN通信資料少而且復雜

這篇文章旨在快速掃盲,給出使用M3508、M2006電機的必備CAN通信知識,希望能降低使用門檻,給各位朋友節約時間。內容均使用M3508與M2006實測過,演示視頻在文章末尾。

本文僅涉及必備知識,甚至盡量避開復雜的通信原理,力求淺顯易懂。

0x00 需要額外的CAN收發器!!!

這件事要放到前面去說,因為已經有幾位朋友的經歷指出了其必要性。

如果我們有一塊STM32開發板,也有電調電機和電源。那么我們的STM32引腳與電調的CAN_H和CAN_L之間是不能直接相連的。

需要購買如下圖所示的CAN收發器,作為兩者連接的橋梁。一般我用的是TJA1050芯片的模塊。

CAN收發器

CAN收發器是使用電機的必備硬件條件,一定要先確定自己有這個東西。至於原因,咱們接下來說明。

0x01 硬件層面分析

為什么需要CAN收發器

通過分析硬件層面我們能知道為什么需要額外的CAN收發器。請看下圖:

硬件結構

從圖中我們能看出,STM32擁有的外設叫做:CAN控制器,它負責CAN通信的篩選、優先級、仲裁等問題。相當於咱們的郵局,幫忙蓋個郵戳,分分類。通過復用GPIO以后,它延伸出兩個引腳:CAN_RXCAN_TX,類比串口我們知道一個負責收一個負責發。

實際上,這兩個引腳上傳輸的數據已經是CAN報文了,該有的格式它都有,STM32的CAN回環模式就相當於直接把CAN_RXCAN_TX相連,就可以收到自己發的消息。

問題是,CAN在設計的時候為了消除共模干擾,特地選用了差分信號(也叫差模信號)傳輸。咱們的C610、C620電調,接收發送的就是差分信號。這才是CAN收發器的作用:

把來自STM32的信號轉換成差分信號讓電調聽得懂,把來自電調的差分信號轉換成STM32聽得懂的信號。


請注意:

連接CAN_RXCAN_TX引腳與CAN收發器的引腳時,並不需要像串口一樣交叉。直接將RX連接到標有RX的引腳,TX類似。


120Ω的終端電阻呢?

不知道朋友們有沒有注意到C610、C620電調上都有一個開關,C620的在側面,旁邊寫着CAN RESISTOR,這也是CAN總線的設計要求。

根據咱們學的《電路理論》這門課,當信號波長小於電路尺寸的時候,我們就不能把電路當成集中電路來分析。對於can總線是一樣的,由於電調采用1MHz的通信頻率,為了防止一些不必要的干擾,我們需要在CAN總線的兩端分別用120Ω電阻跨接起來。比如之前圖中的兩端可以認為是咱們的CAN收發器是一端,下面的電調是另一端。

對於只有一個電調的情況下,可以打開電調上的電阻,然后直接和CAN收發器連接,這樣雖然少了一端的終端電阻,但實際上可以運行。如果同時控制兩個及以上的電調,那就可以打開其中兩個的終端電阻,構成總線的兩端。當然也可以手動組成如下圖的總線結構並且關閉電調上的終端電阻,圖中還加入了電容進行濾波。

CAN總線圖

0x02 軟件配置簡析

其實,看完硬件部分就已經可以正常使用電調電機了,因為大疆官方例程中已經把CAN通信配置好了,直接可以使用。

但是如果涉及非常多的設備同時控制,比如超過四個電機的情況下,或者還有其他的外設要通過CAN總線相連,簡單了解軟件配置也是很有好處。

而且,我發現很多朋友是在做RoboMaster比賽,全面的了解軟硬件還是十分必要的,如果出現問題也有利於排查,不至於浪費大量時間。

接下來我們還是使用咱們的老朋友:大疆官方M2006例程M3508例程來作為樣本。主要探究以下問題:

  • 通信頻率如何設定為1MHz
  • CAN過濾器的配置
  • 報文的接收與發送

兩個文件:bsp_can.ccan.c

如何把通信頻率設定為1MHz?

以下是文件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過濾器得配置,因為官方例程也沒怎么配置,大可直接套用。

過濾器是針對接收信息進行篩選得部件,因為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。

后面依照手冊填充數據然后發送,過程比較簡單。

0x03 總結

又是一篇有關大疆電機的文章,也是結合我自己的經歷和上一篇文章的反饋才有了這篇。現在還記得我剛開始接觸CAN通信時候的疑惑感,感覺資料都太復雜看不下去。水平確實有限,也就只能力求個淺顯易懂,希望能幫助朋友們節約一些時間吧。相關例程可以在公眾號上向我索要。

這里放上前一篇文章鏈接:PID和三環控制-以大疆M3508、M2006為例 https://blog.csdn.net/qq_28039135/article/details/116379392

更多嵌入式,電機控制相關文章請移步公眾號,來找我聊聊天吧:

公眾號

技術新人,水平有限,還請各位朋友多多指教。如果對文章有任何的疑問或者發現錯誤請一定指出!

演示視頻:

同時控制M3505、M2006雙電機的演示視頻在公眾號原文底部:

文章二維碼


歡迎轉載,請注明作者與原文地址:

作者:胡小安

原文鏈接:https://www.cnblogs.com/huxiaoan/p/15046967.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM