当前位置: 首页 > news >正文

珠海网站设计公司石家庄网红

珠海网站设计公司,石家庄网红,简单广告设计软件,html语言大型网站开发背景介绍#xff1a;为了利用小米电机#xff0c;搭建机械臂的关节#xff0c;需要学习小米电机的使用方法。计划采用STM32驱动小米电机#xff0c;实现指定运动#xff0c;为此需要了解他们之间的通信方式#xff0c;指令写入方法等。花了很多时间学习#xff0c;但网络…背景介绍为了利用小米电机搭建机械臂的关节需要学习小米电机的使用方法。计划采用STM32驱动小米电机实现指定运动为此需要了解他们之间的通信方式指令写入方法等。花了很多时间学习但网络上相关资料很少且对于我这类基础一般的同学注释不够详细。为此我认真研读了电机的说明书参考相关的博文实现了电机的CAN通信特作此记录。 一、环回测试接线图 元件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发送时要结合说明书的不同通信类型对应的数据格式整理获取扩展ID29位和对应的数据内容8Byte。 例如下图为获取设备ID的协议使用说明根据其特点可以写成扩展ID如下 //扩展ID由通信类型主CANID目标电机ID txMsg.ExtId Communication_Type_GetID24|Master_CAN_ID8|ID; 利用上述方法参照说明书可以获得所有通讯协议的扩展ID的写法只要对应的按位填上数据即可。同理也可以写出对应的数据区参数。则可以逐一写出各个函数实现与小米电机的CAN通信。 三、代码实现与解释说明 1.CAN收发 》MyCAN.c文件包括初始化、发送报文、接收报文函数。 1) 初始化函数MyCAN_Init() 用来初始化CAN注意里面的引脚和工作模式以及相应的波特率设置可以按照控制元件要求修改。这里有一个FIFO0要与后面接收数据时的FIFO对应。初始化的流程与GPIO口初始化流程类似开启时钟——定义结构体——调用初始化函数 /************************************** cMyCAN_Init CAN 初始化函数 ParamNo Init PinGPIOA P11 CAN_RX输入引脚是A11GPIOA P12 CAN_TX输出引脚是A12 **************************************/ 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工作模式为环回模式用于自收自发测试用,实际通信时可以改成正常模式/*波特率计算波特率 36M时钟频率 / 48 预分频器的值/ (1 2BS1 3BS2) 125K */CAN_InitStructure.CAN_Prescaler 48; //预分频器的值为48 CAN_InitStructure.CAN_BS1 CAN_BS1_2tq;//BS1的时间长度1-16tqCAN_InitStructure.CAN_BS2 CAN_BS2_3tq;//BS2的时间长度1-8tqCAN_InitStructure.CAN_SJW CAN_SJW_2tq;//SJW的时间长度1-4tqCAN_InitStructure.CAN_NART DISABLE;//DISABLE表示寄存器置0表示自动重传这个功能叫做不自动重传一般系统默认是自动重传CAN_InitStructure.CAN_TXFP DISABLE;//发送邮箱优先级DISABLE置零ID小的先发送如果是ENABLE置一先进先出CAN_InitStructure.CAN_RFLM DISABLE;//禁用FIOF锁定溢出后新报文覆盖最后一个报文如果是ENABLE则溢出时新报文丢弃CAN_InitStructure.CAN_AWUM DISABLE;//DISABLE 手动唤醒ENABLE 自动唤醒CAN_InitStructure.CAN_TTCM DISABLE;//关闭时间触发通信CAN_InitStructure.CAN_ABOM DISABLE;//DISABLE 手动恢复ENABLE 自动恢复离线自动恢复CAN_Init(CAN1, CAN_InitStructure);//初始化CAN/*****************************初始化CAN过滤器*********************************/CAN_FilterInitTypeDef CAN_FilterInitStructure;//定义CAN过滤器结构体CAN_FilterInitStructure.CAN_FilterNumber 0;//过滤器编号0-13/*几种不同的16位列表模式四个参数分别存入一组ID即可共四个16位ID列表屏蔽模式IDHIGH存入第一组IDMaskIDHIGH存入对应的屏蔽位共两组16位ID和两组屏蔽位32位列表模式IDHIGH和IDLOW组合成一个32位IDMaskIDHIGH和MaskIDLOW组成第二组32位ID32位频闭模式IDHIGH和IDLOW组合成一个32位IDMaskIDHIGH和MaskIDLOW组成第二组32位屏蔽位*/CAN_FilterInitStructure.CAN_FilterIdHigh 0x0000;//高16位CAN_FilterInitStructure.CAN_FilterIdLow 0x0000;//低16位CAN_FilterInitStructure.CAN_FilterMaskIdHigh 0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdLow 0x0000;//选则相应模式为32位屏蔽模式CAN_FilterInitStructure.CAN_FilterScale CAN_FilterScale_32bit;//过滤器位宽32位或者16位这里是32位CAN_FilterInitStructure.CAN_FilterMode CAN_FilterMode_IdMask;//过滤器模式CAN_FilterMode_IdMask 屏蔽模式 CAN_FilterMode_IdList 列表模式CAN_FilterInitStructure.CAN_FilterFIFOAssignment CAN_Filter_FIFO0;//配置过滤器关联这里有两个CAN_Filter_FIFO0CAN_Filter_FIFO1CAN_FilterInitStructure.CAN_FilterActivation ENABLE;//激活过滤器CAN_FilterInit(CAN_FilterInitStructure);//初始化过滤器 }2.发送报文函数MyCAN_Transmit(TxID, TxLength, TxData)   发送报文发送报文的时候先定义一个CanTxMsg结构体说明其ID形式注意小米电机用的是这里如果设计为标准ID后面环回接收时IDtype对应数值位0设计为扩展ID则环回接收时IDtype对应数值为1以便用于区分不同的ID类型。 /************************************* NameMyCAN_Transmit CAN 发送报文 Param ID ID是32位便于后面使用扩展帧Length 数据长度*Data 数据指针 **************************************/ void MyCAN_Transmit(uint32_t ID, uint8_t Length, uint8_t *Data) {CanTxMsg TxMessage; //定义CanTxMsg结构体变量表示待发送的报文TxMessage.StdId ID; //标准IDTxMessage.ExtId ID; //扩展ID//TxMessage.IDE CAN_Id_Standard; //扩展标志位CAN_Id_Standard 标准ID CAN_Id_Extended扩展IDTxMessage.IDE CAN_Id_Extended; //扩展标志位CAN_Id_Standard 标准ID CAN_Id_Extended扩展IDTxMessage.RTR CAN_RTR_Data; //遥控标志位CAN_RTR_Remote 遥控帧 CAN_RTR_Data数据帧TxMessage.DLC Length; //数据段长度传入的参数//把形参DATA传过来的数组赋值给TxMessage.Datafor (uint8_t i 0; i Length; i ){TxMessage.Data[i] Data[i];//将传入的Data数组的值赋值给结构体的Data他们都是8字节的数组}//请求发送报文函数//CAN_Transmit的原理选择空发送邮箱——如果邮箱有空位则将报文写入指定寄存器——TXRQ置1请求发送uint8_t TransmitMailbox CAN_Transmit(CAN1, TxMessage);//请求发送结构体指向的报文返回值是邮箱编号uint32_t Timeout 0;//CAN_TransmitStatus表示返回传输状态函数返回请求发送邮箱的邮箱状态CAN_TxStatus_OK表示发送成功//等待函数返回OK当CAN1的邮箱状态为CAN_TxStatus_Ok表示发送成功如果不成功则进入循环while (CAN_TransmitStatus(CAN1, TransmitMailbox) ! CAN_TxStatus_Ok){Timeout ;//如果大于超时时间则跳出循环if (Timeout 100000){break;}} } 3接收报文函数MyCAN_Receive(RxID, RxLength, RxData, RxIDtype) 函数里面的IDtype参数用于到显示屏幕上验证发送的ID类型是标准ID还是扩展ID。首先定义一个接收报文的结构体判断收到的数据是标准ID还是扩展ID再获取ID值。如果是数据帧则还需要逐个字节获取。 /**************************************** Name:MyCAN_ReceiveFlag Param: 函数用于判断接收FIFO里是否有报文返回值为表示有报文返回值为0表示没有报文 *****************************************/ uint8_t MyCAN_ReceiveFlag(void) {if (CAN_MessagePending(CAN1, CAN_FIFO0) 0)//如果大于零表明FIFO0里面有报文此处的FIFO0与前面的设置一致{return 1;}return 0; }/***************************************** brief: 接收 CAN message param *ID the ID用于做返回值*Length the length of DATA用于做返回值*DATA the Data of CAN massage 注意接收信息是需要输出参数但C语言不支持多个值输出 所以这里用指针表示可以通过函数修改相应的值 *****************************************/ void MyCAN_Receive(uint32_t *ID, uint8_t *Length, uint8_t *Data,uint8_t *IDtype) {CanRxMsg RxMessage;//定义一个CanRxMsg结构体用于存放接收报文CAN_Receive(CAN1, CAN_FIFO0, RxMessage);//接收报文//判断接收的报文是标准ID还是扩展IDif (RxMessage.IDE CAN_Id_Standard){*IDtype0;//表示接受的是标准帧*ID RxMessage.StdId;//标准ID}else{*IDtype1;//表示接收的是扩展帧*ID RxMessage.ExtId; //扩展ID}//判断接收报文是否为数据帧还是遥控帧if (RxMessage.RTR CAN_RTR_Data)//是否为数据帧{//数据帧*Length RxMessage.DLC;//数据长度//数据内容for (uint8_t i 0; i *Length; i ){Data[i] RxMessage.Data[i];}}else{//遥控帧暂时不做处理} } 2.小米电机相应指令函数 0获取设备ID /*—————————————————————————————————————————————————————————————————————————————————*/ /** brief 小米电机ID检查通信类型为0* param[in] id: 控制电机CAN_ID【出厂默认0x7F】**/ void check_cybergear(uint8_t ID) {uint8_t tx_data[8] {0};//没有数据//扩展ID的组合依旧是3个部分txMsg.ExtId Communication_Type_GetID24|Master_CAN_ID8|ID;MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 1运控模式电机控制指令 /*——————————————————————————————————————————————————————————————————————————————————*/ /** brief 小米运控模式指令通信类型1* param[in] Motor: 目标电机结构体* param[in] torque: 力矩设置[-12,12] N*M* param[in] MechPosition: 位置设置[-12.5,12.5] rad* param[in] speed: 速度设置[-30,30] rpm* param[in] kp: 比例参数设置* param[in] kd: 微分参数设置* retval none**/ void motor_controlmode(MI_Motor *Motor,float torque, float MechPosition, float speed, float kp, float kd) { uint8_t tx_data[8]{0};//发送数据初始化//装填发送数据//将目标角度转化为16位2进制数对应字节0~1假设是0x1234tx_data[0]float_to_uint(MechPosition,P_MIN,P_MAX,16)8; //取得是高位的结果即0x12tx_data[1]float_to_uint(MechPosition,P_MIN,P_MAX,16); //取得是低位的结果即0x34//将目标速度转化为16位2进制数对应字节2~3tx_data[2]float_to_uint(speed,V_MIN,V_MAX,16)8; tx_data[3]float_to_uint(speed,V_MIN,V_MAX,16); //目标KPtx_data[4]float_to_uint(kp,KP_MIN,KP_MAX,16)8; tx_data[5]float_to_uint(kp,KP_MIN,KP_MAX,16); //目标KDtx_data[6]float_to_uint(kd,KD_MIN,KD_MAX,16)8; tx_data[7]float_to_uint(kd,KD_MIN,KD_MAX,16); txMsg.ExtId Communication_Type_MotionControl24|float_to_uint(torque,T_MIN,T_MAX,16)8|Motor-CAN_ID;//装填扩展帧数据MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 这里面有一个将浮点数转化为16位二进制数的函数float_to_uint其中对应的参数上下限在.h文件中进行了定义其对应范围是0~65535也就是0~2^16-1 其中的参数范围定义如下这个地方不能修改只能参照说明书定义 /*****************控制参数最值谨慎更改*********************/ #define P_MIN -12.56f #define P_MAX 12.56f #define V_MIN -30.0f #define V_MAX 30.0f #define KP_MIN 0.0f #define KP_MAX 500.0f #define KD_MIN 0.0f #define KD_MAX 5.0f #define T_MIN -12.0f #define T_MAX 12.0f #define MAX_P 720 #define MIN_P -720 2电机反馈数据  电机反馈数据里面我们需要读取的就是这几项电机的ID号电机的角度电机的角速度电机的力矩电机的温度根据下图可以知道接收到的信息的具体位置进而编写出程序如下 /*——————————————————————————————————————————————————————————————————————————————————————*/ /** brief 电机反馈数据通信类型2* param[in] 信息存放的地址* retval none*/ void Rx_Fifo0_Msg(MI_Motor *Motor) {if (MyCAN_ReceiveFlag())//判断是否接收到报文信息{uint32_t RxID;uint8_t RxLength;uint8_t RxData[8];//接收信息放到对应的接收报文之中MyCAN_Receive(RxID, RxLength, RxData);Motor-CAN_ID(RxID0xFFFF)8;//获取接收数据的ID保留低16位其余全变成零再右移8位则获得了bit8~bit15的canidMotor-Angleuint16_to_float(RxData[0]8|RxData[1],MIN_P,MAX_P,16);//将字节0~1转化位浮点数即为当前角度Motor-Speeduint16_to_float(RxData[2]8|RxData[3],V_MIN,V_MAX,16);//将字节2~3转化位浮点数即为当前速度 Motor-Torqueuint16_to_float(RxData[4]8|RxData[5],T_MIN,T_MAX,16);//将字节4~5转化位浮点数即为当前角度 Motor-Temp(RxData[6]8|RxData[7])*Temp_Gain;//将字节4~5转化为当前温度 Motor-error_code(RxID0x1F0000)16; } } 3电机使能运行 /*****************************使能电机通信类型为3******************************** brief 使能小米电机* param[in] Motor:对应控制电机结构体 * retval none*****************************************************/ void start_cybergear(MI_Motor *Motor) {uint8_t tx_data[8] {0}; txMsg.ExtId Communication_Type_MotorEnable24|Master_CAN_ID8|Motor-CAN_ID;MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 4)  电机停止运行 注意当数据区的Byte[0]1时表示清故障 /************************电机停止运行通信类型为4********************************* brief 停止电机* param[in] Motor:对应控制电机结构体 * param[in] clear_error:清除错误位0 不清除 1清除* retval None*******************************************************************************/ void stop_cybergear(MI_Motor *Motor,uint8_t clear_error) {uint8_t tx_data[8]{0};tx_data[0]clear_error;//清除错误位设置txMsg.ExtId Communication_Type_MotorStop24|Master_CAN_ID8|Motor-CAN_ID;MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 }6设置电机机械零位 /**********************设计电机的零点通信类型6**************************** brief 设置电机零点* param[in] Motor: 电机结构体* retval none***********************************************************/ void set_zeropos_cybergear(MI_Motor *Motor) {uint8_t tx_data[8]{0};tx_data[0] 1;//数据区为1//扩展帧格式txMsg.ExtId Communication_Type_SetPosZero24|Master_CAN_ID8|Motor-CAN_ID;MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 7设置电机的CAN_ID /**********************设置电机的CAN_ID,通信类型为7********************* brief 设置电机CANID* param[in] Motor: 电机结构体* param[in] Motor: 设置新ID* retval none**********************************************************************/ void set_CANID_cybergear(MI_Motor *Motor,uint8_t CAN_ID) {uint8_t tx_data[8]{0};txMsg.ExtId Communication_Type_CanID24|CAN_ID16|Master_CAN_ID8|Motor-CAN_ID;Motor-CAN_ID CAN_ID;//将新的ID导入电机结构体MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 17)  单个参数读取 /*************************单个参数读取通信类型17****************** *brief 电机参数读取 *param[in] ID,电机的ID号 */ void check_param_cybergear(MI_Motor *Motor, uint_8 index) {uint8_t tx_data[8]{0}txMsg.ExtId Communication_Type_GetSingleParameter24|Master_CAN_ID8|Motor-CAN_ID;//装填扩展帧数据tx_data[0]index8;//高8位tx_data[1]index;//低8位MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 其中的index为说明书里面的参数列表中的值 /******************参数读取宏定义Index***********************/ #define Run_mode 0x7005 //运动模式 #define Iq_Ref 0x7006 //电流模式指令 #define Spd_Ref 0x700A //转速模式转速 #define Limit_Torque 0x700B //转矩限制 #define Cur_Kp 0x7010 //电流的kp #define Cur_Ki 0x7011 //电流的ki #define Cur_Filt_Gain 0x7014 //电流滤波系数 #define Loc_Ref 0x7016 //位置模式角度指令 #define Limit_Spd 0x7017 //位置模式速度限制 #define Limit_Cur 0x7018 //速度位置模式电流限制 #define mechPos 0x7019 //负载端计圈机械角度 #define iqf 0x701A //iq滤波值 #define mechVel 0x701B //负载端转速 #define VBUS 0x701C //母线电压 #define rotation 0x701D //圈数 #define loc_kp 0x701E //位置的kp #define spd_kp 0x701F //速度的kp #define spd_ki 0x7020 //速度的ki18)  写入单个参数 /******************对应说明书的单个参数写入通信类型为18************** brief 写入电机参数* param[in] Motor:对应控制电机结构体* param[in] Index:写入参数对应地址* param[in] Value:写入参数值* param[in] Value_type:写入参数数据类型可以对照字节数进行区分* retval none*/ static void Set_Motor_Parameter(MI_Motor *Motor,uint16_t Index,float Value,char Value_type){uint8_t tx_data[8]{0};//写入的数据//扩展ID包括三个部分通信类型、主ID、电机IDtxMsg.ExtId Communication_Type_SetSingleParameter24|Master_CAN_ID8|Motor-CAN_ID;//参见说明书的通信类型18里面Index的相关应用方法Index共tx_data[0]Index8; //高8位tx_data[1]Index; //低8位tx_data[2]0x00;tx_data[3]0x00;//如果参数类型为浮点型则对应的数据所占字节数为4对应的数据需要转化为8个字节if(Value_type f){Float_to_Byte(Value);//将数值转化为4个byte 作为返回值tx_data[4]byte[0];//高8位tx_data[5]byte[1];tx_data[6]byte[2];tx_data[7]byte[3];//低8位 }//如果参数类型为uint8只有一个字节else if(Value_type s){tx_data[4](uint8_t)Value;tx_data[5]0x00;tx_data[6]0x00;tx_data[7]0x00; }//can_txd();MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令 } 此外还有几个转化函数 /*———————————————————————————————————————————————————————————————————————————————————————*/ /** brief 小米电机回文16位数据转浮点* param[in] x:16位回文 x_min:对应参数下限 x_max:对应参数上限 bits:参数位数* retval 返回浮点值**/ static float uint16_to_float(uint16_t x,float x_min,float x_max,int bits) {uint32_t span (1 bits) - 1;//二进制数的范围2^bits-1float offset x_max - x_min;//实际范围return offset * x / span x_min;//转换为浮点数 } /*———————————————————————————————————————————————————————————————————————————————————*/ /** brief 小米电机发送浮点转16位数据每个数据都是2个字节也就是16位二进制数* static 表示其作用域仅限于这个文件*/ static int float_to_uint(float x, float x_min, float x_max, int bits) {float span x_max - x_min;//浮点数的范围float offset x_min; //限制X的范围if(x x_max) xx_max;else if(x x_min) x x_min;return (int) ((x-offset)*((float)((1bits)-1))/span);//x-下限/2^bits-1/范围 } /*————————————————————————————————————————————————————————————————————————————————————*/ /** brief 浮点数转4字节函数,这个用于写入参数时使用*/ static uint8_t* Float_to_Byte(float f) {unsigned long longdata 0;//无符号长整型longdata *(unsigned long*)f; //取f的地址将该地址强制转化为无符号长整型指针通过*解引用获得该地址处的值 byte[0] (longdata 0xFF000000) 24;//将最高8位提出来byte[1] (longdata 0x00FF0000) 16;//将第二个高8位提出来byte[2] (longdata 0x0000FF00) 8;//将第三个高8位提出来byte[3] (longdata 0x000000FF);//将第四个高8位提出来return byte;//返回的byte为四个字节的数组 } 3.主函数main.c 对相应的函数进行调用与验证 #include main.h #include cybergear.h /*******************小米电机的控制***************/ /* *v1目前已经把小米电机的库程序建立起来开始进行验证已经验证的程序有初始化和使能函数2024.10.7 */ uint8_t KeyNum;uint32_t RxID; uint8_t RxLength; uint8_t RxData[8]; uint8_t RxIDtype; MI_Motor Cyber; uint8_t Motor_ID0x7F; uint8_t ModeMotion_mode;//控制模式为运动控制 uint32_t id; SM_Param M_set;int main(void) {//初始化OLED_Init();Key_Init();//按键初始化按键对应的引脚分别位B1和B11MyCAN_Init();//CAN初始化CAN对应的引脚位A11和A12A11输入A12输出//以下用于调用程序验证相应的通信数据是否准确init_cybergear(Cyber, Motor_ID, Mode);//初始化电机//*校验用的内容idcheck_cybergear(Cyber.CAN_ID);//小米电机ID检查通信类型为0/*此处验证程序为运控模式的电机控制motor_controlmode*扩展ID显示为01 BFFF 7F其中01为通讯类型BFFF为力矩7F为电机ID号*数据为9001 BFFF 3851 428F 分别表示目标角度、目标角速度、对应KP对应KD*///OLED_ShowHexNum(1, 1, Cyber.CAN_ID,2);M_set.Positionpi/2;//带入程序数据的计算结果为36865映射到16进制为9001M_set.Speed15;//45/60*6553549151转换为16进制是BFFFM_set.Kp110;//110/500*6553514417转换为16进制是3851M_set.Kd1.3;//1.3/5*6553517039转换为16进制是428FM_set.Torque6;//映射到区域为6--12/12--123/43/4*655354915149151转化为16进制为BFFFmotor_controlmode(Cyber,M_set.Torque, M_set.Position, M_set.Speed, M_set.Kp, M_set.Kd);//使能验证//扩展ID为03 0000 7F//数据为0000 0000 0000 0000start_cybergear(Cyber.CAN_ID);//使能小米电机通信类型为3//停止验证//第二个参数为清除错误位0表示不清除1表示清除//扩展ID为04 0000 7F//数据为0000 0000 0000 0000/0100 0000 0000 0000stop_cybergear(Cyber,1);//置零验证//扩展ID为06 0000 7F//数据为0100 0000 0000 0000set_zeropos_cybergear(Cyber);//设置电机的ID号//扩展ID为07 1200 7F//数据0000 0000 0000 0000Motor_ID0x12;set_CANID_cybergear(Cyber,Motor_ID);//读取单个参数//扩展ID11 0000 12其中0x11表示的十进制的17//数据7005 0000 0000 0000Index index;indexRunMode_idx;//0x7005check_param_cybergear(Cyber, index);//设置电机模式//扩展ID12 0000 12//数据70 05 00 00 01 00 00 00set_mode_cybergear(Cyber,Position_mode);//设置电机参数//扩展ID12 0000 12其中0x12 表示十进制的18//数据70 05 00 00 01 00 00 001字节数据在byte4其余数据为byte4~7Value_type value_typ;value_typRunMode_Typ;Set_Motor_Parameter(Cyber,index,Position_mode,value_typ);while (1){} }利用显示器验证相应的发送指令验证代码如下 OLED_ShowString(1, 1, ID:);//第3行第1列显示OLED_ShowHexNum(2, 1, txMsg.ExtId,8 );OLED_ShowString(3, 1, Data:);//第3行第1列显示for (int i1;i8;i){OLED_ShowHexNum(4, i*2-1, tx_data[i-1],2 );} 本文电机函数的验证方法逐个函数调用然后通过屏幕显示指令进行验证得到相应的显示结果与通讯协议的指令格式一致则表明函数无误。 本文参考了博文、视频教程小米电机CyberGear STM32HAL 使用指南_小米电机瞬时电流串口指令-CSDN博客 [3-1] 单个设备环回测试三个设备互相通信_哔哩哔哩_bilibili
http://www.dnsts.com.cn/news/64067.html

相关文章:

  • 网站备案单位的联系方式做个网站成本
  • 长治网站建设龙采科技技术支持建立网站需要什么条件
  • 芜湖网站开发广东高端网站建设报价
  • 类似猪八戒的网站建设网站建设的公司业务
  • 智能网站建设模板售后电子商务类网站建设实训报告
  • 济宁市住房和城乡建设局网站做外贸一般做什么
  • 寻找网站建设 网站外包wordpress 中文图片无法显示
  • 彩票创建网站广州新塘做网站
  • m版网站开发做百度网站如何收费
  • 郑州建设企业网站找哪个公司重庆建站多少钱一年
  • 为什么多个网站域名有同个网站备案网络工程师是什么专业
  • 桂林有哪些做网站的电话秦皇岛建设网站官网
  • 没网站做哪个广告联盟百度网络小说排行榜
  • php企业网站后台管理系统如何简单快速的制作网站
  • 网站管理员容易做吗苏州三笑网络科技有限公司
  • 南阳做网站的手机 wordpress html5
  • 做阿里巴巴还是做网站好做楼盘网站
  • 做音乐网站用什么程序网络营销策略有哪些
  • 重庆建设网站的公司国外小型网站
  • 怎么免费建立公司网站河源网站搭建费用
  • 网站里做任务网站建设蛋蛋28
  • 网站设计方案策划网站广告费怎么做分录
  • 车子网站手机网站大全1
  • 个人网站设计论文范文成品视频直播软件推荐哪个好一点的
  • 西部建设网站0000网站建设
  • 网站开发流程详细介绍wordpress主题贝宝
  • 湘潭网站建设的公司网站部署到服务器
  • 网站建设的功能都需要有哪些深圳建筑人才网为什么电脑打不开
  • 做个什么网站做响应式网站代码
  • 福州长乐网站建设小学生抄写新闻20字