小米电机与STM32——CAN通信

背景介绍:为了利用小米电机,搭建机械臂的关节,需要学习小米电机的使用方法。计划采用STM32驱动小米电机,实现指定运动,为此需要了解他们之间的通信方式,指令写入方法等。花了很多时间学习,但网络上相关资料很少,且对于我这类基础一般的同学,注释不够详细。为此,我认真研读了电机的说明书,参考相关的博文,实现了电机的CAN通信,特作此记录。

更新日期:2024.10.19  

更新内容:补充了电机实验,通过电机实验与反馈对相关内容进行了调整,电机的运控模式、位置模式、速度模式均进行了验证

更新日期:2024.10.31

更新内容:文末附上源码资源链接

一、环回测试接线图

元件:ST-Link  , STM32F103C8T6, 显示屏, 按键开关*2

二、CAN通信实现过程

1.CAN收发

需要设计一个CAN的报文输入与报文接收的函数,以用来进行数据收发,这里前面已经实现了

STM的CAN通信学习_stmcan通讯-CSDN博客

2.小米电机协议转化

需要弄清楚小米电机的CAN通讯协议类型,封装成相应的函数,再结合CAN收发函数进行对应的指令发送以及接收

1)小米电机通信:CAN 2.0通信接口,波特率为1Mbps,采用的扩展帧格式

2)小米电机通信相应的数据格式如下:

结合说明书可以得到具体通信指令对应关系如下:

参照小米电机的说明书内容,29位扩展ID中,Bit28~Bit24用来表示通信类型,说明书关于通信类型包括10种,具体解释与对应关系如下:

//控制命令宏定义,与说明书对应
//获取设备ID(通信类型为0)
#define Communication_Type_GetID 0x00           //获取设备的ID和64位MCU唯一标识符
//运控模式电机控制指令(通信类型为1)
#define Communication_Type_MotionControl 0x01 	//用来向主机发送控制指令
//电机反馈数据(通信类型为2)
#define Communication_Type_MotorRequest 0x02	//用来向主机反馈电机运行状态
//电机使能运行(通信类型为3)
#define Communication_Type_MotorEnable 0x03	    //电机使能运行
//电机停止运行(通信类型为4)
#define Communication_Type_MotorStop 0x04	    //电机停止运行
//电机机械零位(通信类型为6)
#define Communication_Type_SetPosZero 0x06	    //设置电机机械零位
//更改电机的CAN_ID(通信类型为7)
#define Communication_Type_CanID 0x07	        //更改当前电机CAN_ID
//单个参数读取(通信类型为17,即0x11)
#define Communication_Type_GetSingleParameter 0x11	//读取单个参数
//单个参数写入(通信类型为18,即0x12)
#define Communication_Type_Control_Mode 0x12
#define Communication_Type_SetSingleParameter 0x12	//设定单个参数
//故障反馈帧(通信类型为21,即0x15)
#define Communication_Type_ErrorFeedback 0x15	    //故障反馈帧

当要利用STM32发送时,要结合说明书的不同通信类型对应的数据格式,整理获取扩展ID(29位)和对应的数据内容(8Byte)。

例如:下图为获取设备ID的协议使用说明,根据其特点,可以写成扩展ID如下:

//扩展ID由通信类型+主CANID+目标电机ID
txMsg.ExtId = Communication_Type_GetID<<24|Master_CAN_ID<<8|ID;

利用上述方法,参照说明书可以获得所有通讯协议的扩展ID的写法,只要对应的按位填上数据即可。同理也可以写出对应的数据区参数。则可以逐一写出各个函数,实现与小米电机的CAN通信。

三、代码实现与解释说明

1.CAN收发

==》MyCAN.c文件,包括初始化、发送报文、接收报文函数。

1) 初始化函数:MyCAN_Init(),更新于2024.10.19,更新了波特率为1Mb

用来初始化CAN,注意里面的引脚和工作模式,以及相应的波特率设置可以按照控制元件要求修改。这里有一个FIFO0,要与后面接收数据时的FIFO对应。初始化的流程与GPIO口初始化流程类似:开启时钟——定义结构体——调用初始化函数

void MyCAN_Init(void)
{
	/**********************开启GPIOA和CAN1时钟************************************/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//启用GPIOA时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//启用CAN1时钟
	
	/***********************初始化GPIOA的12号引脚,CAN 输出***********************/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//模式为复用推挽输出,注意如果要用作CAN通信,需要选择复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//12号引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//引脚速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);//引脚初始化
	
	/*********************初始化GPIO的11号引脚,CAN输入***************************/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	/*************************初始化CAN1控制器************************************/
	CAN_InitTypeDef CAN_InitStructure;//定义一个CAN的结构体
	/*CAN工作模式选择
     CAN_Mode_Normal             ((uint8_t)0x00)  正常模式
     CAN_Mode_LoopBack           ((uint8_t)0x01)  环回模式
	   CAN_Mode_Silent             ((uint8_t)0x02)  静默模式,只听不发
     CAN_Mode_Silent_LoopBack    ((uint8_t)0x03)  环回静默模式*/
	//CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;//CAN工作模式为环回模式,用于自收自发测试用,实际通信时可以改成正常模式
	CAN_InitStructure.CAN_Mode =  CAN_Mode_Normal ;
	/*波特率计算
	波特率 = 36M(时钟频率) / 48 (预分频器的值)/ (1 + 2(BS1)+ 3(BS2)) = 125K    
	波特率为1Mb,小米电机的波特率就是1Mb36/6/(1+3+2)*
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值