更新项目结构,修改自述文件

This commit is contained in:
2026-05-17 21:16:52 +08:00
parent bc5bd0c72e
commit a4ccd91c75
28 changed files with 129 additions and 50 deletions

122
01-Device/BMI088.c Normal file
View File

@@ -0,0 +1,122 @@
#include "BMI088.h"
#include "can.h"
#include "BMI088driver.h"
#include <math.h>
#include "Parameter.h"
BMI088_Init_typedef BMI088_Data;
//简介:获取欧拉角数据(单位:°)
BMI088_Init_typedef BMI088_GetData(BMI088_Init_typedef *data)
{
//上次读取时刻、本次读取时刻、读取时间间隔
static uint32_t last_read_time = 0;
static uint32_t current_time = 0;
static uint32_t delta_time = 0;
static double yaw_g,pitch_g,roll_g;//角速度计算三轴数据
static double yaw_a,pitch_a,roll_a;//加速度计算三轴数据
float alpha = 0.95238;//0.95238
BMI088_read(data->Gyro, data->Accel, &data->Temp);
if(data->Accel[0]>2 || data->Accel[1]>2 || data->Accel[2]>2){
//计算时间变化
last_read_time = current_time;
current_time = HAL_GetTick();
delta_time = current_time - last_read_time;
//计算欧拉角
yaw_g += (0.001f * delta_time) * data->Gyro[2]/ PI * 180; // 角度增量 = 角速度 * 时间
pitch_g += (0.001f * delta_time) * data->Gyro[1]/ PI * 180;
roll_g += (0.001f * delta_time) * data->Gyro[0]/ PI * 180;
yaw_a = 0; // 角度增量 = 角速度 * 时间
pitch_a = atan2(data->Accel[0],data->Accel[2]) / PI * 180;
roll_a = atan2(data->Accel[1],data->Accel[2]) / PI * 180;
data->Yaw = alpha*yaw_g + (1-alpha)*yaw_a;
data->Pitch = alpha*pitch_g + (1-alpha)*pitch_a;
data->Roll = alpha*roll_g + (1-alpha)*roll_a;
}
if(data->Yaw > 180) data->Yaw -=360;
else if(data->Yaw < -180) data->Yaw +=360;
if(data->Pitch > 180) data->Pitch -=360;
else if(data->Pitch < -180) data->Pitch +=360;
if(data->Roll > 180) data->Roll -=360;
else if(data->Roll < -180) data->Roll +=360;
return *data;
}
void BMI088_Can_Angle(int16_t data1, int16_t data2,
int16_t data3, int16_t data4,
CAN_HandleTypeDef *hcan)//CANID:0x200 电机ID:1-4 (-10000,10000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x146;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = data1 >> 8;
Can_Send_Data[1] = data1;
Can_Send_Data[2] = data2 >> 8;
Can_Send_Data[3] = data2;
Can_Send_Data[4] = data3 >> 8;
Can_Send_Data[5] = data3;
Can_Send_Data[6] = data4 >> 8;
Can_Send_Data[7] = data4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void BMI088_Can_Gyro(int16_t data1, int16_t data2,
int16_t data3, int16_t data4,
CAN_HandleTypeDef *hcan)//CANID:0x200 电机ID:1-4 (-10000,10000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x147;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = data1 >> 8;
Can_Send_Data[1] = data1;
Can_Send_Data[2] = data2 >> 8;
Can_Send_Data[3] = data2;
Can_Send_Data[4] = data3 >> 8;
Can_Send_Data[5] = data3;
Can_Send_Data[6] = data4 >> 8;
Can_Send_Data[7] = data4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void BMI088_Can_Accel(int16_t data1, int16_t data2,
int16_t data3, int16_t data4,
CAN_HandleTypeDef *hcan)//CANID:0x200 电机ID:1-4 (-10000,10000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x148;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = data1 >> 8;
Can_Send_Data[1] = data1;
Can_Send_Data[2] = data2 >> 8;
Can_Send_Data[3] = data2;
Can_Send_Data[4] = data3 >> 8;
Can_Send_Data[5] = data3;
Can_Send_Data[6] = data4 >> 8;
Can_Send_Data[7] = data4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}

27
01-Device/BMI088.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef BMI088_H
#define BMI088_H
#include "stdint.h"
#include "can.h"
typedef struct
{
float Accel[3];
float Gyro[3];
float Yaw,Pitch,Roll;
float Mag[3];
float Temp;
}BMI088_Init_typedef;
BMI088_Init_typedef BMI088_GetData(BMI088_Init_typedef *data);
void BMI088_Can_Angle(int16_t data1, int16_t data2,
int16_t data3, int16_t data4,
CAN_HandleTypeDef *hcan);
void BMI088_Can_Gyro( int16_t data1, int16_t data2,
int16_t data3, int16_t data4,
CAN_HandleTypeDef *hcan);
void BMI088_Can_Accel(int16_t data1, int16_t data2,
int16_t data3, int16_t data4,
CAN_HandleTypeDef *hcan);
#endif // BMI088_H

319
01-Device/Motor.c Normal file
View File

@@ -0,0 +1,319 @@
#include "Motor.h"
M3508_Motor Can1_M3508_MotorStatus[8];//M3508电机状态数组
M3508_Motor Can2_M3508_MotorStatus[8];//M3508电机状态数组
M6020_Motor Can1_M6020_MotorStatus[7];//GM6020电机状态数组
M6020_Motor Can2_M6020_MotorStatus[7];//GM6020电机状态数组
M2006_Motor Can1_M2006_MotorStatus[8];//M2006电机状态数组
M2006_Motor Can2_M2006_MotorStatus[8];//M2006电机状态数组
#define MOTOR_ENCODER_ECD_MAX 8192.0f
#define MOTOR_ENCODER_HALF_ECD_MAX 4096.0f
void Motor_3508_Current1( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan)//CANID:0x200 电机ID:1-4 (-16384,16384)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x200;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = device1 >> 8;
Can_Send_Data[1] = device1;
Can_Send_Data[2] = device2 >> 8;
Can_Send_Data[3] = device2;
Can_Send_Data[4] = device3 >> 8;
Can_Send_Data[5] = device3;
Can_Send_Data[6] = device4 >> 8;
Can_Send_Data[7] = device4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void Motor_3508_Current2( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan)//CANID:0x1FF 电机ID:5-8 (-16384,16384)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x1FF;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = device1 >> 8;
Can_Send_Data[1] = device1;
Can_Send_Data[2] = device2 >> 8;
Can_Send_Data[3] = device2;
Can_Send_Data[4] = device3 >> 8;
Can_Send_Data[5] = device3;
Can_Send_Data[6] = device4 >> 8;
Can_Send_Data[7] = device4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void CAN1_M3508_DataProcess(M3508_ID ID,uint8_t *Data)
{
uint16_t M3508_RotorNowAngle=(uint16_t)((((uint16_t)Data[0])<<8)|Data[1]);//本次转子机械角度原始数据
if(M3508_RotorNowAngle-Can1_M3508_MotorStatus[ID-0x201].RawRotorAngle>4000 && Can1_M3508_MotorStatus[ID-0x201].First_Flag==1) Can1_M3508_MotorStatus[ID-0x201].Rotor_r--;//本次转子机械角度原始数据和上次转子机械角度原始数据出现跃变
else if(Can1_M3508_MotorStatus[ID-0x201].RawRotorAngle-M3508_RotorNowAngle>4000 && Can1_M3508_MotorStatus[ID-0x201].First_Flag==1) Can1_M3508_MotorStatus[ID-0x201].Rotor_r++;
else if(Can1_M3508_MotorStatus[ID-0x201].First_Flag!=1) Can1_M3508_MotorStatus[ID-0x201].First_Flag=1;
Can1_M3508_MotorStatus[ID-0x201].RawRotorAngle =M3508_RotorNowAngle;//转子机械角度原始数据
Can1_M3508_MotorStatus[ID-0x201].RotorAngle =M3508_RotorNowAngle*0.0439453125f;//=M3508_RotorNowAngle/8192.0f*360.0f;//转子机械角度
Can1_M3508_MotorStatus[ID-0x201].RawRotorPosition =8192*Can1_M3508_MotorStatus[ID-0x201].Rotor_r+M3508_RotorNowAngle;//转子角度位置原始数据
Can1_M3508_MotorStatus[ID-0x201].RotorPosition =360.0f*Can1_M3508_MotorStatus[ID-0x201].Rotor_r+Can1_M3508_MotorStatus[ID-0x201].RotorAngle;//转子角度位置
Can1_M3508_MotorStatus[ID-0x201].RotorSpeed =(int16_t)((((uint16_t)Data[2])<<8)|Data[3]);//转子转速原始数据
Can1_M3508_MotorStatus[ID-0x201].ShaftPosition =Can1_M3508_MotorStatus[ID-0x201].RotorPosition*0.0520746310219994f;//=Can1_M3508_MotorStatus[ID-0x201].RotorPosition/M3508_ReductionRatio;//转轴角度位置
Can1_M3508_MotorStatus[ID-0x201].Shaft_r =(int64_t)(Can1_M3508_MotorStatus[ID-0x201].ShaftPosition)/360;
if(Can1_M3508_MotorStatus[ID-0x201].ShaftPosition<0 && Can1_M3508_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can1_M3508_MotorStatus[ID-0x201].Shaft_r<0)Can1_M3508_MotorStatus[ID-0x201].Shaft_r--;//获取转轴圈数
Can1_M3508_MotorStatus[ID-0x201].ShaftAngle=Can1_M3508_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can1_M3508_MotorStatus[ID-0x201].Shaft_r;//转轴机械角度
Can1_M3508_MotorStatus[ID-0x201].ShaftSpeed=Can1_M3508_MotorStatus[ID-0x201].RotorSpeed*0.0520746310219994f;//=Can1_M3508_MotorStatus[ID-0x201].RotorSpeed/M3508_ReductionRatio;//转轴转速
Can1_M3508_MotorStatus[ID-0x201].RawCurrent=(int16_t)((((uint16_t)Data[4])<<8)|Data[5]);//转矩电流原始数据
Can1_M3508_MotorStatus[ID-0x201].Current=Can1_M3508_MotorStatus[ID-0x201].RawCurrent*0.001220703125f;//=Can1_M3508_MotorStatus[ID-0x201].RawCurrent/16384.0f*20.0f;//转矩电流
Can1_M3508_MotorStatus[ID-0x201].Power=Can1_M3508_MotorStatus[ID-0x201].ShaftSpeed*Can1_M3508_MotorStatus[ID-0x201].Current*0.031413612565445f;//=Can1_M3508_MotorStatus[ID-0x201].ShaftSpeed*Can1_M3508_MotorStatus[ID-0x201].Current*M3508_TorqueConstant/9.55f;//电机功率(功率P(kW)=转轴转速v(RPM)*转矩T(N·m)/9550,转矩T=转矩电流*转矩常数)
if(Can1_M3508_MotorStatus[ID-0x201].Power<0)Can1_M3508_MotorStatus[ID-0x201].Power*=-1;//功率去负数化
Can1_M3508_MotorStatus[ID-0x201].Temperature=Data[6];//电机温度
}
void CAN2_M3508_DataProcess(M3508_ID ID,uint8_t *Data)
{
uint16_t M3508_RotorNowAngle=(uint16_t)((((uint16_t)Data[0])<<8)|Data[1]);//本次转子机械角度原始数据
if(M3508_RotorNowAngle-Can2_M3508_MotorStatus[ID-0x201].RawRotorAngle>4000 && Can2_M3508_MotorStatus[ID-0x201].First_Flag==1) Can2_M3508_MotorStatus[ID-0x201].Rotor_r--;//本次转子机械角度原始数据和上次转子机械角度原始数据出现跃变
else if(Can2_M3508_MotorStatus[ID-0x201].RawRotorAngle-M3508_RotorNowAngle>4000 && Can2_M3508_MotorStatus[ID-0x201].First_Flag==1) Can2_M3508_MotorStatus[ID-0x201].Rotor_r++;
else if(Can2_M3508_MotorStatus[ID-0x201].First_Flag!=1) Can2_M3508_MotorStatus[ID-0x201].First_Flag=1;
Can2_M3508_MotorStatus[ID-0x201].RawRotorAngle =M3508_RotorNowAngle;//转子机械角度原始数据
Can2_M3508_MotorStatus[ID-0x201].RotorAngle =M3508_RotorNowAngle*0.0439453125f;//=M3508_RotorNowAngle/8192.0f*360.0f;//转子机械角度
Can2_M3508_MotorStatus[ID-0x201].RawRotorPosition =8192*Can2_M3508_MotorStatus[ID-0x201].Rotor_r+M3508_RotorNowAngle;//转子角度位置原始数据
Can2_M3508_MotorStatus[ID-0x201].RotorPosition =360.0f*Can2_M3508_MotorStatus[ID-0x201].Rotor_r+Can2_M3508_MotorStatus[ID-0x201].RotorAngle;//转子角度位置
Can2_M3508_MotorStatus[ID-0x201].RotorSpeed =(int16_t)((((uint16_t)Data[2])<<8)|Data[3]);//转子转速原始数据
Can2_M3508_MotorStatus[ID-0x201].ShaftPosition =Can2_M3508_MotorStatus[ID-0x201].RotorPosition*0.0520746310219994f;//=Can2_M3508_MotorStatus[ID-0x201].RotorPosition/M3508_ReductionRatio;//转轴角度位置
Can2_M3508_MotorStatus[ID-0x201].Shaft_r =(int64_t)(Can2_M3508_MotorStatus[ID-0x201].ShaftPosition)/360;
if(Can2_M3508_MotorStatus[ID-0x201].ShaftPosition<0 && Can2_M3508_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can2_M3508_MotorStatus[ID-0x201].Shaft_r<0)Can2_M3508_MotorStatus[ID-0x201].Shaft_r--;//获取转轴圈数
Can2_M3508_MotorStatus[ID-0x201].ShaftAngle=Can2_M3508_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can2_M3508_MotorStatus[ID-0x201].Shaft_r;//转轴机械角度
Can2_M3508_MotorStatus[ID-0x201].ShaftSpeed=Can2_M3508_MotorStatus[ID-0x201].RotorSpeed*0.0520746310219994f;//=Can2_M3508_MotorStatus[ID-0x201].RotorSpeed/M3508_ReductionRatio;//转轴转速
Can2_M3508_MotorStatus[ID-0x201].RawCurrent=(int16_t)((((uint16_t)Data[4])<<8)|Data[5]);//转矩电流原始数据
Can2_M3508_MotorStatus[ID-0x201].Current=Can2_M3508_MotorStatus[ID-0x201].RawCurrent*0.001220703125f;//=Can2_M3508_MotorStatus[ID-0x201].RawCurrent/16384.0f*20.0f;//转矩电流
Can2_M3508_MotorStatus[ID-0x201].Power=Can2_M3508_MotorStatus[ID-0x201].ShaftSpeed*Can2_M3508_MotorStatus[ID-0x201].Current*0.031413612565445f;//=Can2_M3508_MotorStatus[ID-0x201].ShaftSpeed*Can2_M3508_MotorStatus[ID-0x201].Current*M3508_TorqueConstant/9.55f;//电机功率(功率P(kW)=转轴转速v(RPM)*转矩T(N·m)/9550,转矩T=转矩电流*转矩常数)
if(Can2_M3508_MotorStatus[ID-0x201].Power<0)Can2_M3508_MotorStatus[ID-0x201].Power*=-1;//功率去负数化
Can2_M3508_MotorStatus[ID-0x201].Temperature=Data[6];//电机温度
}
void Motor_6020_Voltage1( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan)//CANID:0x1FF 电机ID:1-4 (-25000,25000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x1FF;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = device1 >> 8;
Can_Send_Data[1] = device1;
Can_Send_Data[2] = device2 >> 8;
Can_Send_Data[3] = device2;
Can_Send_Data[4] = device3 >> 8;
Can_Send_Data[5] = device3;
Can_Send_Data[6] = device4 >> 8;
Can_Send_Data[7] = device4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void Motor_6020_Voltage2( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan)//CANID:0x2FF 电机ID:5-8 (-25000,25000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x2FF;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = device1 >> 8;
Can_Send_Data[1] = device1;
Can_Send_Data[2] = device2 >> 8;
Can_Send_Data[3] = device2;
Can_Send_Data[4] = device3 >> 8;
Can_Send_Data[5] = device3;
Can_Send_Data[6] = device4 >> 8;
Can_Send_Data[7] = device4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void CAN1_M6020_DataProcess(M6020_ID ID,uint8_t *Data)
{
uint16_t GM6020_NowAngle=(uint16_t)((((uint16_t)Data[0])<<8)|Data[1]);//本次机械角度原始数据
if(GM6020_NowAngle-Can1_M6020_MotorStatus[ID-0x205].Angle>4000 && Can1_M6020_MotorStatus[ID-0x205].First_Flag==1 && Can1_M6020_MotorStatus[ID-0x205].r>0)
Can1_M6020_MotorStatus[ID-0x205].r--;//本次机械角度原始数据和上次机械角度原始数据出现跃变
else if(Can1_M6020_MotorStatus[ID-0x205].Angle-GM6020_NowAngle>4000 && Can1_M6020_MotorStatus[ID-0x205].First_Flag==1 && Can1_M6020_MotorStatus[ID-0x205].r<1)
Can1_M6020_MotorStatus[ID-0x205].r++;
else if(Can1_M6020_MotorStatus[ID-0x205].First_Flag!=1)
Can1_M6020_MotorStatus[ID-0x205].First_Flag++;
Can1_M6020_MotorStatus[ID-0x205].Angle =GM6020_NowAngle;//机械角度
Can1_M6020_MotorStatus[ID-0x205].ANgle =GM6020_NowAngle/8192.0f*360.0f;//机械角度
if(Can1_M6020_MotorStatus[ID-0x205].ANgle > 180) Can1_M6020_MotorStatus[ID-0x205].ANgle -= 360.0f;
else if(Can1_M6020_MotorStatus[ID-0x205].ANgle < -180) Can1_M6020_MotorStatus[ID-0x205].ANgle += 360.0f;
Can1_M6020_MotorStatus[ID-0x205].Position =8192*Can1_M6020_MotorStatus[ID-0x205].r+GM6020_NowAngle;//角度位置
Can1_M6020_MotorStatus[ID-0x205].Speed =(int16_t)((((uint16_t)Data[2])<<8)|Data[3]);//转速
Can1_M6020_MotorStatus[ID-0x205].Current =(int16_t)((((uint16_t)Data[4])<<8)|Data[5]);//实际转矩电流
Can1_M6020_MotorStatus[ID-0x205].Temperature=Data[6];//电机温度
}
void CAN2_M6020_DataProcess(M6020_ID ID,uint8_t *Data)
{
uint16_t GM6020_NowAngle=(uint16_t)((((uint16_t)Data[0])<<8)|Data[1]);//本次机械角度原始数据
if(GM6020_NowAngle-Can2_M6020_MotorStatus[ID-0x205].Angle>4000 && Can2_M6020_MotorStatus[ID-0x205].First_Flag==1 && Can2_M6020_MotorStatus[ID-0x205].r>0)
Can2_M6020_MotorStatus[ID-0x205].r--;//本次机械角度原始数据和上次机械角度原始数据出现跃变
else if(Can2_M6020_MotorStatus[ID-0x205].Angle-GM6020_NowAngle>4000 && Can2_M6020_MotorStatus[ID-0x205].First_Flag==1 && Can2_M6020_MotorStatus[ID-0x205].r<1)
Can2_M6020_MotorStatus[ID-0x205].r++;
else if(Can2_M6020_MotorStatus[ID-0x205].First_Flag!=1)
Can2_M6020_MotorStatus[ID-0x205].First_Flag++;
Can2_M6020_MotorStatus[ID-0x205].Angle =GM6020_NowAngle;//机械角度
Can2_M6020_MotorStatus[ID-0x205].ANgle =GM6020_NowAngle/8192.0f*360.0f;//机械角度
if(Can2_M6020_MotorStatus[ID-0x205].ANgle > 180) Can2_M6020_MotorStatus[ID-0x205].ANgle -= 360.0f;
else if(Can2_M6020_MotorStatus[ID-0x205].ANgle < -180) Can2_M6020_MotorStatus[ID-0x205].ANgle += 360.0f;
Can2_M6020_MotorStatus[ID-0x205].Position =8192*Can2_M6020_MotorStatus[ID-0x205].r+GM6020_NowAngle;//角度位置
Can2_M6020_MotorStatus[ID-0x205].Speed =(int16_t)((((uint16_t)Data[2])<<8)|Data[3]);//转速
Can2_M6020_MotorStatus[ID-0x205].Current =(int16_t)((((uint16_t)Data[4])<<8)|Data[5]);//实际转矩电流
Can2_M6020_MotorStatus[ID-0x205].Temperature=Data[6];//电机温度
}
void Motor_2006_Current1( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan)//CANID:0x200 电机ID:1-4 (-10000,10000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x200;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = device1 >> 8;
Can_Send_Data[1] = device1;
Can_Send_Data[2] = device2 >> 8;
Can_Send_Data[3] = device2;
Can_Send_Data[4] = device3 >> 8;
Can_Send_Data[5] = device3;
Can_Send_Data[6] = device4 >> 8;
Can_Send_Data[7] = device4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void Motor_2006_Current2( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan)//CANID:0x1FF 电机ID:5-8 (-10000,10000)
{
CAN_TxHeaderTypeDef Tx_Message;
uint8_t Can_Send_Data[8];
uint32_t send_mail_box;
Tx_Message.StdId = 0x1FF;
Tx_Message.IDE = CAN_ID_STD;
Tx_Message.RTR = CAN_RTR_DATA;
Tx_Message.DLC = 0x08;
Can_Send_Data[0] = device1 >> 8;
Can_Send_Data[1] = device1;
Can_Send_Data[2] = device2 >> 8;
Can_Send_Data[3] = device2;
Can_Send_Data[4] = device3 >> 8;
Can_Send_Data[5] = device3;
Can_Send_Data[6] = device4 >> 8;
Can_Send_Data[7] = device4;
HAL_CAN_AddTxMessage(hcan, &Tx_Message, Can_Send_Data, &send_mail_box);
}
void CAN1_M2006_DataProcess(M2006_ID ID,uint8_t *Data)
{
uint16_t M2006_RotorNowAngle=(uint16_t)((((uint16_t)Data[0])<<8)|Data[1]);//本次转子机械角度原始数据
if(M2006_RotorNowAngle-Can1_M2006_MotorStatus[ID-0x201].RawRotorAngle>4000 && Can1_M2006_MotorStatus[ID-0x201].First_Flag==1)Can1_M2006_MotorStatus[ID-0x201].Rotor_r--;//本次转子机械角度原始数据和上次转子机械角度原始数据出现跃变
else if(Can1_M2006_MotorStatus[ID-0x201].RawRotorAngle-M2006_RotorNowAngle>4000 && Can1_M2006_MotorStatus[ID-0x201].First_Flag==1)Can1_M2006_MotorStatus[ID-0x201].Rotor_r++;
else if(Can1_M2006_MotorStatus[ID-0x201].First_Flag!=1)Can1_M2006_MotorStatus[ID-0x201].First_Flag=1;
Can1_M2006_MotorStatus[ID-0x201].RawRotorAngle=M2006_RotorNowAngle;//转子机械角度原始数据
Can1_M2006_MotorStatus[ID-0x201].RotorAngle=M2006_RotorNowAngle*0.0439453125f;//=M2006_RotorNowAngle/8192.0f*360.0f;//转子机械角度
Can1_M2006_MotorStatus[ID-0x201].RawRotorPosition=8192*Can1_M2006_MotorStatus[ID-0x201].Rotor_r+M2006_RotorNowAngle;//转子角度位置原始数据
Can1_M2006_MotorStatus[ID-0x201].RotorPosition=360.0f*Can1_M2006_MotorStatus[ID-0x201].Rotor_r+Can1_M2006_MotorStatus[ID-0x201].RotorAngle;//转子角度位置
Can1_M2006_MotorStatus[ID-0x201].RotorSpeed=(int16_t)((((uint16_t)Data[2])<<8)|Data[3]);//转子转速原始数据
Can1_M2006_MotorStatus[ID-0x201].ShaftPosition=Can1_M2006_MotorStatus[ID-0x201].RotorPosition*0.0277777777777778f;//=Can1_M2006_MotorStatus[ID-0x201].RotorPosition/M2006_ReductionRatio;//转轴角度位置
Can1_M2006_MotorStatus[ID-0x201].Shaft_r=(int64_t)(Can1_M2006_MotorStatus[ID-0x201].ShaftPosition)/360;
if(Can1_M2006_MotorStatus[ID-0x201].ShaftPosition<0 && Can1_M2006_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can1_M2006_MotorStatus[ID-0x201].Shaft_r<0)Can1_M2006_MotorStatus[ID-0x201].Shaft_r--;//获取转轴圈数
Can1_M2006_MotorStatus[ID-0x201].ShaftAngle=Can1_M2006_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can1_M2006_MotorStatus[ID-0x201].Shaft_r;//转轴机械角度
Can1_M2006_MotorStatus[ID-0x201].ShaftSpeed=Can1_M2006_MotorStatus[ID-0x201].RotorSpeed*0.0277777777777778f;//=Can1_M2006_MotorStatus[ID-0x201].RotorSpeed/M2006_ReductionRatio;//转轴转速
Can1_M2006_MotorStatus[ID-0x201].RawCurrent=(int16_t)((((uint16_t)Data[4])<<8)|Data[5]);//转矩电流原始数据
Can1_M2006_MotorStatus[ID-0x201].Current=Can1_M2006_MotorStatus[ID-0x201].RawCurrent*0.001f;//=Can1_M2006_MotorStatus[ID-0x201].RawCurrent/10000.0f*10.0f;//转矩电流
Can1_M2006_MotorStatus[ID-0x201].Power=Can1_M2006_MotorStatus[ID-0x201].ShaftSpeed*Can1_M2006_MotorStatus[ID-0x201].Current*0.018848167539267f;//=Can1_M2006_MotorStatus[ID-0x201].ShaftSpeed*Can1_M2006_MotorStatus[ID-0x201].Current*M2006_TorqueConstant/9.55f;//电机功率(功率P(kW)=转轴转速v(RPM)*转矩T(N·m)/9550,转矩T=转矩电流*转矩常数)
if(Can1_M2006_MotorStatus[ID-0x201].Power<0)Can1_M2006_MotorStatus[ID-0x201].Power*=-1;//功率去负数化
}
void CAN2_M2006_DataProcess(M2006_ID ID,uint8_t *Data)
{
uint16_t M2006_RotorNowAngle=(uint16_t)((((uint16_t)Data[0])<<8)|Data[1]);//本次转子机械角度原始数据
if(M2006_RotorNowAngle-Can2_M2006_MotorStatus[ID-0x201].RawRotorAngle>4000 && Can2_M2006_MotorStatus[ID-0x201].First_Flag==1)Can2_M2006_MotorStatus[ID-0x201].Rotor_r--;//本次转子机械角度原始数据和上次转子机械角度原始数据出现跃变
else if(Can2_M2006_MotorStatus[ID-0x201].RawRotorAngle-M2006_RotorNowAngle>4000 && Can2_M2006_MotorStatus[ID-0x201].First_Flag==1)Can2_M2006_MotorStatus[ID-0x201].Rotor_r++;
else if(Can2_M2006_MotorStatus[ID-0x201].First_Flag!=1)Can2_M2006_MotorStatus[ID-0x201].First_Flag=1;
Can2_M2006_MotorStatus[ID-0x201].RawRotorAngle=M2006_RotorNowAngle;//转子机械角度原始数据
Can2_M2006_MotorStatus[ID-0x201].RotorAngle=M2006_RotorNowAngle*0.0439453125f;//=M2006_RotorNowAngle/8192.0f*360.0f;//转子机械角度
Can2_M2006_MotorStatus[ID-0x201].RawRotorPosition=8192*Can2_M2006_MotorStatus[ID-0x201].Rotor_r+M2006_RotorNowAngle;//转子角度位置原始数据
Can2_M2006_MotorStatus[ID-0x201].RotorPosition=360.0f*Can2_M2006_MotorStatus[ID-0x201].Rotor_r+Can2_M2006_MotorStatus[ID-0x201].RotorAngle;//转子角度位置
Can2_M2006_MotorStatus[ID-0x201].RotorSpeed=(int16_t)((((uint16_t)Data[2])<<8)|Data[3]);//转子转速原始数据
Can2_M2006_MotorStatus[ID-0x201].ShaftPosition=Can2_M2006_MotorStatus[ID-0x201].RotorPosition*0.0277777777777778f;//=Can2_M2006_MotorStatus[ID-0x201].RotorPosition/M2006_ReductionRatio;//转轴角度位置
Can2_M2006_MotorStatus[ID-0x201].Shaft_r=(int64_t)(Can2_M2006_MotorStatus[ID-0x201].ShaftPosition)/360;
if(Can2_M2006_MotorStatus[ID-0x201].ShaftPosition<0 && Can2_M2006_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can2_M2006_MotorStatus[ID-0x201].Shaft_r<0)Can2_M2006_MotorStatus[ID-0x201].Shaft_r--;//获取转轴圈数
Can2_M2006_MotorStatus[ID-0x201].ShaftAngle=Can2_M2006_MotorStatus[ID-0x201].ShaftPosition-360.0f*Can2_M2006_MotorStatus[ID-0x201].Shaft_r;//转轴机械角度
Can2_M2006_MotorStatus[ID-0x201].ShaftSpeed=Can2_M2006_MotorStatus[ID-0x201].RotorSpeed*0.0277777777777778f;//=Can2_M2006_MotorStatus[ID-0x201].RotorSpeed/M2006_ReductionRatio;//转轴转速
Can2_M2006_MotorStatus[ID-0x201].RawCurrent=(int16_t)((((uint16_t)Data[4])<<8)|Data[5]);//转矩电流原始数据
Can2_M2006_MotorStatus[ID-0x201].Current=Can2_M2006_MotorStatus[ID-0x201].RawCurrent*0.001f;//=Can2_M2006_MotorStatus[ID-0x201].RawCurrent/10000.0f*10.0f;//转矩电流
Can2_M2006_MotorStatus[ID-0x201].Power=Can2_M2006_MotorStatus[ID-0x201].ShaftSpeed*Can2_M2006_MotorStatus[ID-0x201].Current*0.018848167539267f;//=Can2_M2006_MotorStatus[ID-0x201].ShaftSpeed*Can2_M2006_MotorStatus[ID-0x201].Current*M2006_TorqueConstant/9.55f;//电机功率(功率P(kW)=转轴转速v(RPM)*转矩T(N·m)/9550,转矩T=转矩电流*转矩常数)
if(Can2_M2006_MotorStatus[ID-0x201].Power<0)Can2_M2006_MotorStatus[ID-0x201].Power*=-1;//功率去负数化
}
float Motor_Encoder_Circle(float target_angle, float current_encoder_angle)
{
float err = target_angle - current_encoder_angle;
if (err > MOTOR_ENCODER_HALF_ECD_MAX) {
// 当前值落后一圈或多圈,加一个最大值使其追上
current_encoder_angle += MOTOR_ENCODER_ECD_MAX;
} else if (err < -MOTOR_ENCODER_HALF_ECD_MAX) {
// 当前值超前一圈或多圈,减一个最大值使其退回
current_encoder_angle -= MOTOR_ENCODER_ECD_MAX;
}
// 如果误差在范围内,则 current_encoder_angle 不变
return current_encoder_angle;
}

124
01-Device/Motor.h Normal file
View File

@@ -0,0 +1,124 @@
#ifndef MOTOR_H
#define MOTOR_H
#include <stdint.h>
#include "can.h"
typedef enum//3508
{
M3508_1=0x201,//ID1
M3508_2=0x202,//ID2
M3508_3=0x203,//ID3
M3508_4=0x204,//ID4
M3508_5=0x205,//ID5
M3508_6=0x206,//ID6
M3508_7=0x207,//ID7
M3508_8=0x208,//ID8
}M3508_ID;//M3508电机ID号枚举
typedef enum//6020
{
GM6020_1=0x205,//ID1
GM6020_2=0x206,//ID2
GM6020_3=0x207,//ID3
GM6020_4=0x208,//ID4
GM6020_5=0x209,//ID5
GM6020_6=0x20A,//ID6
GM6020_7=0x20B,//ID7
}M6020_ID;//GM6020电机ID号枚举
typedef enum//2006
{
M2006_1=0x201,//ID1
M2006_2=0x202,//ID2
M2006_3=0x203,//ID3
M2006_4=0x204,//ID4
M2006_5=0x205,//ID5
M2006_6=0x206,//ID6
M2006_7=0x207,//ID7
M2006_8=0x208,//ID8
}M2006_ID;//M2006电机ID号枚举
typedef struct//3508
{
uint8_t First_Flag;//M3508电机首次接收标志位
int64_t Rotor_r;//M3508电机转子转过圈数
uint16_t RawRotorAngle; //编码器原始数据(范围0~8191,对应0~360°,注意:8192对应360°)
float RotorAngle; //编码器所映射的角度(0~360°)
int64_t RawRotorPosition;//M3508电机转子角度位置原始数据
float RotorPosition;//M3508电机转子角度位置(单位°)
int16_t RotorSpeed;//M3508电机转子转速(单位RPM)
int64_t Shaft_r;//M3508电机转轴转过圈数
float ShaftAngle;//M3508电机转轴机械角度(单位°)
float ShaftPosition;//M3508电机转轴角度位置(单位°)
float ShaftSpeed;//M3508电机转轴转速(单位RPM)
int16_t RawCurrent;//M3508电机转矩电流原始数据(范围-16384~16384,对应-20A~20A,注意:16384对应20A)
float Current;//M3508电机转矩电流(单位A)
float Power;//M3508电机功率(单位W)
uint8_t Temperature;//M3508电机电机温度(单位℃)
}M3508_Motor;//M3508电机状态结构体(减速比3591:187(≈19:1),转矩系数0.3N·m/A)
typedef struct//6020
{
int16_t Current; //GM6020电机实际转矩电流
uint8_t Temperature;//GM6020电机电机温度
uint16_t Angle; //GM6020电机机械角度
int16_t Speed; //GM6020电机转速
float ANgle;
uint8_t First_Flag; //GM6020电机首次接收标志位
int64_t r; //GM6020电机转过圈数(默认圈数只会出现0,1)
int64_t Position; //GM6020电机角度位置原始数据
}M6020_Motor;//GM6020电机状态结构体
typedef struct//2006
{
uint8_t First_Flag;//M2006电机首次接收标志位
int64_t Rotor_r;//M2006电机转子转过圈数
uint16_t RawRotorAngle;//M2006电机转子机械角度原始数据(范围0~8191,对应0~360°,注意:8192对应360°)
float RotorAngle;//M2006电机转子机械角度(单位°)
int64_t RawRotorPosition;//M2006电机转子角度位置原始数据
float RotorPosition;//M2006电机转子角度位置(单位°)
int16_t RotorSpeed;//M2006电机转子转速(单位RPM)
int64_t Shaft_r;//M2006电机转轴转过圈数
float ShaftAngle;//M2006电机转轴机械角度(单位°)
float ShaftPosition;//M2006电机转轴角度位置(单位°)
float ShaftSpeed;//M2006电机转轴转速(单位RPM)
int16_t RawCurrent;//M2006电机转矩电流原始数据(范围-10000~10000,对应-10A~10A,注意:10000对应10A)
float Current;//M2006电机转矩电流(单位A)
float Power;//M2006电机功率(单位W)
}M2006_Motor;//M2006电机状态结构体(减速比36:1,转矩系数0.18N·m/A)
void Motor_3508_Current1( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan);//CANID:0x200 电机ID:1-4 (-16384,16384)
void Motor_3508_Current2( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan);//CANID:0x1FF 电机ID:5-8 (-16384,16384)
void CAN1_M3508_DataProcess(M3508_ID ID,uint8_t *Data);
void CAN2_M3508_DataProcess(M3508_ID ID,uint8_t *Data);
void Motor_6020_Voltage1( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan);//CANID:0x1FF 电机ID:1-4 (-25000,25000)
void Motor_6020_Voltage2( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan);//CANID:0x2FF 电机ID:5-8 (-25000,25000)
void CAN1_M6020_DataProcess(M6020_ID ID,uint8_t *Data);
void CAN2_M6020_DataProcess(M6020_ID ID,uint8_t *Data);
void Motor_2006_Current1( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan);//CANID:0x200 电机ID:1-4 (-10000,10000)
void Motor_2006_Current2( int16_t device1, int16_t device2,
int16_t device3, int16_t device4,
CAN_HandleTypeDef *hcan);//CANID:0x1FF 电机ID:5-8 (-10000,10000)
void CAN1_M2006_DataProcess(M2006_ID ID,uint8_t *Data);
void CAN2_M2006_DataProcess(M2006_ID ID,uint8_t *Data);
float Motor_Encoder_Circle(float target_angle, float current_encoder_angle);
#endif //MOTOR_H

95
01-Device/Remote.c Normal file
View File

@@ -0,0 +1,95 @@
#include "Remote.h"
#include "main.h"
#include "BSP_USART.h"
//===============变量区
extern UART_HandleTypeDef huart3; //usart.c
extern DMA_HandleTypeDef hdma_usart3_rx; //usart.c
const RC_ctrl_t *local_rc_ctrl;
static uint8_t sbus_rx_buf[2][SBUS_RX_BUF_NUM]; //双缓冲区
RC_ctrl_t rc_ctrl;
//===============内部函数
const RC_ctrl_t *remote_GetControlPoint(void)
{
return &rc_ctrl;
}
static void remote_SbusToRC(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
{
if (sbus_buf == NULL || rc_ctrl == NULL)
{
return;
}
rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff; //!< Channel 0
rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff; //!< Channel 1
rc_ctrl->rc.ch[2] = ((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) | //!< Channel 2
(sbus_buf[4] << 10)) &0x07ff;
rc_ctrl->rc.ch[3] = ((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff; //!< Channel 3
rc_ctrl->rc.s[0] = ((sbus_buf[5] >> 4) & 0x0003); //!< Switch left
rc_ctrl->rc.s[1] = ((sbus_buf[5] >> 4) & 0x000C) >> 2; //!< Switch right
rc_ctrl->mouse.x = sbus_buf[6] | (sbus_buf[7] << 8); //!< Mouse X axis
rc_ctrl->mouse.y = sbus_buf[8] | (sbus_buf[9] << 8); //!< Mouse Y axis
rc_ctrl->mouse.z = sbus_buf[10] | (sbus_buf[11] << 8); //!< Mouse Z axis
rc_ctrl->mouse.press_l = sbus_buf[12]; //!< Mouse Left Is Press ?
rc_ctrl->mouse.press_r = sbus_buf[13]; //!< Mouse Right Is Press ?
rc_ctrl->key.v = sbus_buf[14] | (sbus_buf[15] << 8); //!< KeyBoard value
rc_ctrl->rc.ch[4] = sbus_buf[16] | (sbus_buf[17] << 8); //NULL
rc_ctrl->rc.ch[0] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[1] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[2] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[3] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[4] -= RC_CH_VALUE_OFFSET;
}
//===============公共函数
void Remote_Init(void)//遥控器初始化
{
local_rc_ctrl = remote_GetControlPoint();
DBUS_DMA_Init(sbus_rx_buf[0], sbus_rx_buf[1], SBUS_RX_BUF_NUM);
}
void Remote_UART_IDLE_Callback(void)
{
static uint16_t this_time_rx_len = 0;
// 清除 IDLE 标志(注意:原代码误清 PEFLAG应清 IDLE
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
if ((hdma_usart3_rx.Instance->CR & DMA_SxCR_CT) == RESET)
{
/* 当前使用的是 Memory 0 */
__HAL_DMA_DISABLE(&hdma_usart3_rx);
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
hdma_usart3_rx.Instance->CR |= DMA_SxCR_CT; // 切换到 Memory 1
__HAL_DMA_ENABLE(&hdma_usart3_rx);
if (this_time_rx_len == RC_FRAME_LENGTH)
{
remote_SbusToRC(sbus_rx_buf[0], &rc_ctrl);
}
}
else
{
/* 当前使用的是 Memory 1 */
__HAL_DMA_DISABLE(&hdma_usart3_rx);
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
hdma_usart3_rx.Instance->CR &= ~DMA_SxCR_CT; // 切换回 Memory 0
__HAL_DMA_ENABLE(&hdma_usart3_rx);
if (this_time_rx_len == RC_FRAME_LENGTH)
{
remote_SbusToRC(sbus_rx_buf[1], &rc_ctrl);
}
}
}

69
01-Device/Remote.h Normal file
View File

@@ -0,0 +1,69 @@
#ifndef REMOTE_H
#define REMOTE_H
#include <stdint.h>
#define SBUS_RX_BUF_NUM 36u
#define RC_FRAME_LENGTH 18u
#define RC_CH_VALUE_MIN ((uint16_t)364)
#define RC_CH_VALUE_OFFSET ((uint16_t)1024)
#define RC_CH_VALUE_MAX ((uint16_t)1684)
/* ----------------------- RC Switch Definition----------------------------- */
#define RC_SW_UP ((uint16_t)1)
#define RC_SW_MID ((uint16_t)3)
#define RC_SW_DOWN ((uint16_t)2)
#define switch_is_down(s) (s == RC_SW_DOWN)
#define switch_is_mid(s) (s == RC_SW_MID)
#define switch_is_up(s) (s == RC_SW_UP)
/* ----------------------- PC Key Definition-------------------------------- */
#define KEY_PRESSED_OFFSET_W ((uint16_t)1 << 0)
#define KEY_PRESSED_OFFSET_S ((uint16_t)1 << 1)
#define KEY_PRESSED_OFFSET_A ((uint16_t)1 << 2)
#define KEY_PRESSED_OFFSET_D ((uint16_t)1 << 3)
#define KEY_PRESSED_OFFSET_SHIFT ((uint16_t)1 << 4)
#define KEY_PRESSED_OFFSET_CTRL ((uint16_t)1 << 5)
#define KEY_PRESSED_OFFSET_Q ((uint16_t)1 << 6)
#define KEY_PRESSED_OFFSET_E ((uint16_t)1 << 7)
#define KEY_PRESSED_OFFSET_R ((uint16_t)1 << 8)
#define KEY_PRESSED_OFFSET_F ((uint16_t)1 << 9)
#define KEY_PRESSED_OFFSET_G ((uint16_t)1 << 10)
#define KEY_PRESSED_OFFSET_Z ((uint16_t)1 << 11)
#define KEY_PRESSED_OFFSET_X ((uint16_t)1 << 12)
#define KEY_PRESSED_OFFSET_C ((uint16_t)1 << 13)
#define KEY_PRESSED_OFFSET_V ((uint16_t)1 << 14)
#define KEY_PRESSED_OFFSET_B ((uint16_t)1 << 15)
/* ----------------------- Data Struct ------------------------------------- */
typedef __packed struct
{
__packed struct
{
int16_t ch[5];
char s[2];
} rc;
__packed struct
{
int16_t x;
int16_t y;
int16_t z;
uint8_t press_l;
uint8_t press_r;
} mouse;
__packed struct
{
uint16_t v;
} key;
} RC_ctrl_t;
/* ----------------------- Internal Data ----------------------------------- */
//extern const RC_ctrl_t *local_rc_ctrl;
extern const RC_ctrl_t *remote_GetControlPoint(void);
void Remote_Init(void);//遥控器初始化
void Remote_UART_IDLE_Callback(void);
#endif