大疆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收发器是使用电机的必备硬件条件,一定要先确定自己有这个东西。至于原因,咱们接下来说明。
0x01 硬件层面分析
为什么需要CAN收发器
通过分析硬件层面我们能知道为什么需要额外的CAN收发器。请看下图:

从图中我们能看出,STM32拥有的外设叫做:CAN控制器,它负责CAN通信的筛选、优先级、仲裁等问题。相当于咱们的邮局,帮忙盖个邮戳,分分类。通过复用GPIO以后,它延伸出两个引脚:CAN_RX和CAN_TX,类比串口我们知道一个负责收一个负责发。
实际上,这两个引脚上传输的数据已经是CAN报文了,该有的格式它都有,STM32的CAN回环模式就相当于直接把CAN_RX和CAN_TX相连,就可以收到自己发的消息。
问题是,CAN在设计的时候为了消除共模干扰,特地选用了差分信号(也叫差模信号)传输。咱们的C610、C620电调,接收发送的就是差分信号。这才是CAN收发器的作用:
把来自STM32的信号转换成差分信号让电调听得懂,把来自电调的差分信号转换成STM32听得懂的信号。
请注意:
连接CAN_RX和CAN_TX引脚与CAN收发器的引脚时,并不需要像串口一样交叉。直接将RX连接到标有RX的引脚,TX类似。
120Ω的终端电阻呢?
不知道朋友们有没有注意到C610、C620电调上都有一个开关,C620的在侧面,旁边写着CAN RESISTOR,这也是CAN总线的设计要求。
根据咱们学的《电路理论》这门课,当信号波长小于电路尺寸的时候,我们就不能把电路当成集中电路来分析。对于can总线是一样的,由于电调采用1MHz的通信频率,为了防止一些不必要的干扰,我们需要在CAN总线的两端分别用120Ω电阻跨接起来。比如之前图中的两端可以认为是咱们的CAN收发器是一端,下面的电调是另一端。
对于只有一个电调的情况下,可以打开电调上的电阻,然后直接和CAN收发器连接,这样虽然少了一端的终端电阻,但实际上可以运行。如果同时控制两个及以上的电调,那就可以打开其中两个的终端电阻,构成总线的两端。当然也可以手动组成如下图的总线结构并且关闭电调上的终端电阻,图中还加入了电容进行滤波。

0x02 软件配置简析
其实,看完硬件部分就已经可以正常使用电调电机了,因为大疆官方例程中已经把CAN通信配置好了,直接可以使用。
但是如果涉及非常多的设备同时控制,比如超过四个电机的情况下,或者还有其他的外设要通过CAN总线相连,简单了解软件配置也是很有好处。
而且,我发现很多朋友是在做RoboMaster比赛,全面的了解软硬件还是十分必要的,如果出现问题也有利于排查,不至于浪费大量时间。
接下来我们还是使用咱们的老朋友:大疆官方M2006例程、M3508例程来作为样本。主要探究以下问题:
- 通信频率如何设定为1MHz
 - CAN过滤器的配置
 - 报文的接收与发送
 
两个文件:bsp_can.c和can.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
大疆M3508、M2006必备CAN总线知识与配置方法的更多相关文章
- 小白学PID-以大疆M3508、M2006为例
		
前言: 最近用到了大疆的直流无刷(BLDC)减速电机M3508和M2006.做RoboMaster比赛的同学应该对它们很熟悉,这两款电机质量都不错,配套电调C620.C610功能强大,应用场景广泛.当 ...
 - 双非本科进大疆(SP)!
		
哈喽,大家好,我是仲一.今天和大家分享的是一位优秀双非本科生上岸大疆的经历(羡慕哭了...). 今年4月底的时候,这位学弟和我分享了他拿下oppo,京东,联发科实习offer的经历,当时我还发了朋友圈 ...
 - 前端开发者必备的Nginx知识
		
摘要: 最常用的Web服务器 -- Nginx 原文:前端开发者必备的Nginx知识 作者:ConardLi Fundebug经授权转载,版权归原作者所有. Nginx在应用程序中的作用 解决跨域 请 ...
 - [转帖]java必备的开发知识和技能
		
java必备的开发知识和技能 https://blog.csdn.net/qq_34405062/article/details/89389646 学习一下java 其实上学那会儿学的 早就过时加落伍 ...
 - 如何学习FPGA?FPGA学习必备的基础知识
		
如何学习FPGA?FPGA学习必备的基础知识 时间:2013-08-12 来源:eepw 作者: 关键字:FPGA 基础知识 FPGA已成为现今的技术热点之一,无论学生还是工程师都希望 ...
 - 【阿里聚安全·安全周刊】双十一背后的“霸下-七层流量清洗”系统| 大疆 VS “白帽子”,到底谁威胁了谁?
		
关键词:霸下-七层流量清洗系统丨大疆 VS "白帽子"丨抢购软件 "第一案"丨企业安全建设丨Aadhaar 数据泄漏丨朝鲜APT组织Lazarus丨31款违规A ...
 - CAN总线知识总结
		
CAN总线知识整理 一.特点 二.CAN物理层 隐性(逻辑1),显性(逻辑0). 三.CAN数据链路层 3.1通信机制 3.2数据帧 3.3错误帧 3.4其它帧格式 3.5位定时与同步
 - Android开发学习必备的java知识
		
Android开发学习必备的java知识本讲内容:对象.标识符.关键字.变量.常量.字面值.基本数据类型.整数.浮点数.布尔型.字符型.赋值.注释 Java作为一门语言,必然有他的语法规则.学习编程语 ...
 - 企业私有源代码上传github致入侵之大疆案判决了
		
事件简单回顾: 1.2017年8月28日,大疆宣布“大疆威胁识别奖励计划”,最高3万美元: 2.然而在此之前,大疆农业事业部某员工将企业私有源代码上传到了github: 3.就职于大疆竞对公司Depa ...
 
随机推荐
- jmeter--文件上传和下载
			
文件下载 文件下载的method一般是get.本例中导出excel文件. 下载文件如果要求下载到本地,需要另写脚本.采用jsr223或者beashell PostProcessor都可以. 代码如下: ...
 - 练习(time.tick定时器监控数据库)
			
设立个定时器,监控数据库里fb_state(发布状态),并将数据库中一条记录的开始时间与截止时间和当前时间进行比对.若当前时间在开始时间与结束时间之间,则将发布状态设为1,否则为0. 同时,将此段代码 ...
 - 08:'my_tag' is not a registered tag library. Must be one of
			
确保每次修改模板标签时都重新启动 Django 开发服务器(或确保它自己重新启动).如果服务器没有重新启动,Django 将不会注册标签. 从 django 1.9 开始,您可以在如下设置中加载这些新 ...
 - Django基础之视图层
			
内容概要 小白必会三板斧 request对象方法初识 form表单上传文件 Jsonresponse FBV与CBV 内容详细 1 小白必会三板斧 HttpResponse render redire ...
 - 使用 Hexo 搭建静态博客
			
目录 Hexo 简介 什么是 Hexo? Hexo 安装 Hexo 建站 Hexo 配置 Hexo 自定义主题 Hexo 写作 Hexo 服务器 Hexo 生成与发布 一键部署 Hexo 站点到 gi ...
 - Netty 面试题 (史上最全、持续更新)
			
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
 - Redis不是只有get set那么简单
			
我以前还没接触Redis的时候,听到大数据组的小伙伴在讨论Redis,觉得这东西好高端,要是哪天我们组也可以使用下Redis就好了,好长一段时间后,我们项目中终于引入了Redis这个技术,我用了几下, ...
 - 合宙模块LUA相关资料汇总
			
1. 目录 1. 目录 [2. LUA二次开发](#2. LUA二次开发) 2.1 [新手教程](#2.1 新手教程) 2.2 [进阶教程](#2.2 进阶教程) 2.3 [LUA开发环境](#2.3 ...
 - springboot+kurento+coturn+contos的视频通讯服务搭建
			
springboot+kurento+coturn+contos的视频通讯服务搭建 服务器CentOS Linux release 7.9.2009 (Core) 本案例成功于20210628 1.默 ...
 - 铂金07:整齐划一-CountDownLatch如何协调多线程的开始和结束
			
欢迎来到<并发王者课>,本文是该系列文章中的第20篇. 在上一篇文章中,我们介绍了Condition的用法.在本文中,将为你介绍CountDownLatch的用法.CountDownLat ...