You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
11 KiB
379 lines
11 KiB
|
2 weeks ago
|
/******************************************************************************
|
||
|
|
|
||
|
|
版权所有 (C), 2018-2099, Radkil
|
||
|
|
|
||
|
|
******************************************************************************
|
||
|
|
文 件 名 : msg_example.c
|
||
|
|
版 本 号 : 初稿
|
||
|
|
作 者 : radkil
|
||
|
|
生成日期 : 2026年7月13日
|
||
|
|
最近修改 :
|
||
|
|
功能描述 : 消息中心使用示例
|
||
|
|
|
||
|
|
修改历史 :
|
||
|
|
1.日 期 : 2026年7月13日
|
||
|
|
作 者 : radkil
|
||
|
|
修改内容 : 创建文件
|
||
|
|
|
||
|
|
******************************************************************************/
|
||
|
|
|
||
|
|
#include "BHBF_robot.h"
|
||
|
|
#include "msg_center.h"
|
||
|
|
#include "motor_manager.h"
|
||
|
|
#include "msp_motor_leisai.h"
|
||
|
|
#include "cmsis_os.h"
|
||
|
|
#include "FreeRTOS.h"
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 模块定义 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
// 模块名称定义
|
||
|
|
#define MODULE_NAME_MOTOR "motor"
|
||
|
|
#define MODULE_NAME_CHASSIS "chassis"
|
||
|
|
#define MODULE_NAME_UI "ui"
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 电机模块命令字定义 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
typedef enum {
|
||
|
|
MOTOR_CMD_SET_SPEED = 0x01, // 设置速度
|
||
|
|
MOTOR_CMD_SET_POSITION = 0x02, // 设置位置
|
||
|
|
MOTOR_CMD_STOP = 0x03, // 停止
|
||
|
|
MOTOR_CMD_GET_STATUS = 0x04, // 获取状态
|
||
|
|
MOTOR_CMD_SET_HOME = 0x05, // 设置零点
|
||
|
|
MOTOR_CMD_SPEED_MODE = 0x06, // 速度模式
|
||
|
|
MOTOR_CMD_POSITION_MODE = 0x07, // 位置模式
|
||
|
|
} Motor_Cmd_e;
|
||
|
|
|
||
|
|
// 电机命令数据结构
|
||
|
|
typedef struct {
|
||
|
|
uint8_t m_ucMotorIndex; // 电机索引(0=左轮,1=右轮)
|
||
|
|
int32_t m_iValue; // 值(速度/位置等)
|
||
|
|
} Motor_CmdData_t;
|
||
|
|
|
||
|
|
// 电机状态数据结构
|
||
|
|
typedef struct {
|
||
|
|
uint8_t m_ucMotorIndex;
|
||
|
|
int32_t m_iPosition;
|
||
|
|
int32_t m_iVelocity;
|
||
|
|
uint32_t m_uiFaultCode;
|
||
|
|
} Motor_StatusData_t;
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 底盘模块命令字定义 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
typedef enum {
|
||
|
|
CHASSIS_CMD_MOVE = 0x01, // 移动
|
||
|
|
CHASSIS_CMD_STOP = 0x02, // 停止
|
||
|
|
CHASSIS_CMD_SET_SPEED = 0x03, // 设置速度
|
||
|
|
} Chassis_Cmd_e;
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
int32_t m_iSpeedX; // X方向速度
|
||
|
|
int32_t m_iSpeedY; // Y方向速度
|
||
|
|
int32_t m_iSpeedW; // 旋转速度
|
||
|
|
} Chassis_MoveData_t;
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 模块级变量 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
static uint32_t g_uiMotorModuleID = 0;
|
||
|
|
static uint32_t g_uiChassisModuleID = 0;
|
||
|
|
static uint32_t g_uiUIModuleID = 0;
|
||
|
|
|
||
|
|
static Motor_Instance_t *g_apstMotors[2] = {NULL, NULL};
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 电机模块消息处理 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
static void Motor_ModuleHandler(const Msg_t *pstMsg)
|
||
|
|
{
|
||
|
|
if (NULL == pstMsg)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (pstMsg->m_uiMsgID)
|
||
|
|
{
|
||
|
|
case MOTOR_CMD_SET_SPEED:
|
||
|
|
{
|
||
|
|
if (pstMsg->m_uiDataLen >= sizeof(Motor_CmdData_t))
|
||
|
|
{
|
||
|
|
Motor_CmdData_t *pstData = (Motor_CmdData_t *)pstMsg->m_aucData;
|
||
|
|
if (pstData->m_ucMotorIndex < 2 && g_apstMotors[pstData->m_ucMotorIndex] != NULL)
|
||
|
|
{
|
||
|
|
MotorMgr_SetTargetSpeed(g_apstMotors[pstData->m_ucMotorIndex], pstData->m_iValue);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case MOTOR_CMD_STOP:
|
||
|
|
{
|
||
|
|
for (int i = 0; i < 2; i++)
|
||
|
|
{
|
||
|
|
if (g_apstMotors[i] != NULL)
|
||
|
|
{
|
||
|
|
MotorMgr_SetTargetSpeed(g_apstMotors[i], 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case MOTOR_CMD_SET_HOME:
|
||
|
|
{
|
||
|
|
if (pstMsg->m_uiDataLen >= sizeof(Motor_CmdData_t))
|
||
|
|
{
|
||
|
|
Motor_CmdData_t *pstData = (Motor_CmdData_t *)pstMsg->m_aucData;
|
||
|
|
if (pstData->m_ucMotorIndex < 2 && g_apstMotors[pstData->m_ucMotorIndex] != NULL)
|
||
|
|
{
|
||
|
|
MotorMgr_SetHome(g_apstMotors[pstData->m_ucMotorIndex]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case MOTOR_CMD_GET_STATUS:
|
||
|
|
{
|
||
|
|
// 回复状态给请求者
|
||
|
|
Motor_StatusData_t stStatus;
|
||
|
|
for (int i = 0; i < 2; i++)
|
||
|
|
{
|
||
|
|
if (g_apstMotors[i] != NULL)
|
||
|
|
{
|
||
|
|
const Motor_Data_t *pstData = MotorMgr_GetData(g_apstMotors[i]);
|
||
|
|
if (pstData != NULL)
|
||
|
|
{
|
||
|
|
stStatus.m_ucMotorIndex = i;
|
||
|
|
stStatus.m_iPosition = pstData->m_iRealPosition;
|
||
|
|
stStatus.m_iVelocity = pstData->m_iRealVelocity;
|
||
|
|
stStatus.m_uiFaultCode = pstData->m_uiFaultCode;
|
||
|
|
|
||
|
|
// 回复给请求者
|
||
|
|
MsgCenter_SendTo("ui", 0x10, &stStatus, sizeof(stStatus));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 底盘模块消息处理 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
static void Chassis_ModuleHandler(const Msg_t *pstMsg)
|
||
|
|
{
|
||
|
|
if (NULL == pstMsg)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (pstMsg->m_uiMsgID)
|
||
|
|
{
|
||
|
|
case CHASSIS_CMD_MOVE:
|
||
|
|
{
|
||
|
|
if (pstMsg->m_uiDataLen >= sizeof(Chassis_MoveData_t))
|
||
|
|
{
|
||
|
|
Chassis_MoveData_t *pstData = (Chassis_MoveData_t *)pstMsg->m_aucData;
|
||
|
|
|
||
|
|
// 转换为左右轮速度(差速模型)
|
||
|
|
int32_t iLeftSpeed = pstData->m_iSpeedX - pstData->m_iSpeedW;
|
||
|
|
int32_t iRightSpeed = pstData->m_iSpeedX + pstData->m_iSpeedW;
|
||
|
|
|
||
|
|
// 发送给电机模块
|
||
|
|
Motor_CmdData_t stMotorCmd;
|
||
|
|
stMotorCmd.m_ucMotorIndex = 0;
|
||
|
|
stMotorCmd.m_iValue = iLeftSpeed;
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_MOTOR, MOTOR_CMD_SET_SPEED, &stMotorCmd, sizeof(stMotorCmd));
|
||
|
|
|
||
|
|
stMotorCmd.m_ucMotorIndex = 1;
|
||
|
|
stMotorCmd.m_iValue = iRightSpeed;
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_MOTOR, MOTOR_CMD_SET_SPEED, &stMotorCmd, sizeof(stMotorCmd));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case CHASSIS_CMD_STOP:
|
||
|
|
{
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_MOTOR, MOTOR_CMD_STOP, NULL, 0);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* UI模块消息处理 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
static void UI_ModuleHandler(const Msg_t *pstMsg)
|
||
|
|
{
|
||
|
|
if (NULL == pstMsg)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 处理来自其他模块的回复
|
||
|
|
switch (pstMsg->m_uiMsgID)
|
||
|
|
{
|
||
|
|
case 0x10: // 电机状态回复
|
||
|
|
{
|
||
|
|
if (pstMsg->m_uiDataLen >= sizeof(Motor_StatusData_t))
|
||
|
|
{
|
||
|
|
Motor_StatusData_t *pstStatus = (Motor_StatusData_t *)pstMsg->m_aucData;
|
||
|
|
RD_PRINTF("Motor[%d] Status: Pos=%ld, Vel=%ld, Fault=%ld\n",
|
||
|
|
pstStatus->m_ucMotorIndex,
|
||
|
|
pstStatus->m_iPosition,
|
||
|
|
pstStatus->m_iVelocity,
|
||
|
|
pstStatus->m_uiFaultCode);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 模块任务函数 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
// 电机模块任务
|
||
|
|
void Motor_ModuleTask(void *argument)
|
||
|
|
{
|
||
|
|
// 初始化电机
|
||
|
|
MotorMgr_Init();
|
||
|
|
|
||
|
|
Motor_Config_t stConfig = {
|
||
|
|
.m_ucMotorID = 1,
|
||
|
|
.m_uiPulsePerRound = 10000,
|
||
|
|
.m_uiReductionRatio = 70,
|
||
|
|
.m_fWheelDiameter = 0.26f
|
||
|
|
};
|
||
|
|
g_apstMotors[0] = MotorMgr_Create(&stConfig, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
|
||
|
|
|
||
|
|
stConfig.m_ucMotorID = 2;
|
||
|
|
g_apstMotors[1] = MotorMgr_Create(&stConfig, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
|
||
|
|
|
||
|
|
// 初始化电机
|
||
|
|
for (int i = 0; i < 2; i++)
|
||
|
|
{
|
||
|
|
if (g_apstMotors[i] != NULL)
|
||
|
|
{
|
||
|
|
MotorMgr_ResetAll(g_apstMotors[i]);
|
||
|
|
MotorMgr_ActivateAll(g_apstMotors[i]);
|
||
|
|
MotorMgr_SpeedModeInit(g_apstMotors[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
// 处理消息
|
||
|
|
MsgCenter_ProcessWait(g_uiMotorModuleID, 2);
|
||
|
|
|
||
|
|
// 周期性读取电机状态
|
||
|
|
for (int i = 0; i < 2; i++)
|
||
|
|
{
|
||
|
|
if (g_apstMotors[i] != NULL)
|
||
|
|
{
|
||
|
|
MotorMgr_RequestPosition(g_apstMotors[i]);
|
||
|
|
MotorMgr_RequestVelocity(g_apstMotors[i]);
|
||
|
|
MotorMgr_RequestFault(g_apstMotors[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 底盘模块任务
|
||
|
|
void Chassis_ModuleTask(void *argument)
|
||
|
|
{
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
// 处理消息
|
||
|
|
MsgCenter_ProcessWait(g_uiChassisModuleID, 10);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// UI模块任务
|
||
|
|
void UI_ModuleTask(void *argument)
|
||
|
|
{
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
// 处理消息
|
||
|
|
MsgCenter_ProcessWait(g_uiUIModuleID, 100);
|
||
|
|
|
||
|
|
// 定期请求电机状态
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_MOTOR, MOTOR_CMD_GET_STATUS, NULL, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 初始化示例 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
void MsgExample_Init(void)
|
||
|
|
{
|
||
|
|
// 初始化消息中心
|
||
|
|
MsgCenter_Init();
|
||
|
|
|
||
|
|
// 注册模块
|
||
|
|
g_uiMotorModuleID = MsgCenter_Register(MODULE_NAME_MOTOR, Motor_ModuleHandler);
|
||
|
|
g_uiChassisModuleID = MsgCenter_Register(MODULE_NAME_CHASSIS, Chassis_ModuleHandler);
|
||
|
|
g_uiUIModuleID = MsgCenter_Register(MODULE_NAME_UI, UI_ModuleHandler);
|
||
|
|
|
||
|
|
// 创建模块任务
|
||
|
|
const osThreadAttr_t motor_task_attr = {
|
||
|
|
.name = "motor_task",
|
||
|
|
.stack_size = 1024,
|
||
|
|
.priority = (osPriority_t) osPriorityHigh5,
|
||
|
|
};
|
||
|
|
(void)osThreadNew(Motor_ModuleTask, NULL, &motor_task_attr);
|
||
|
|
|
||
|
|
const osThreadAttr_t chassis_task_attr = {
|
||
|
|
.name = "chassis_task",
|
||
|
|
.stack_size = 512,
|
||
|
|
.priority = (osPriority_t) osPriorityHigh4,
|
||
|
|
};
|
||
|
|
(void)osThreadNew(Chassis_ModuleTask, NULL, &chassis_task_attr);
|
||
|
|
|
||
|
|
const osThreadAttr_t ui_task_attr = {
|
||
|
|
.name = "ui_task",
|
||
|
|
.stack_size = 512,
|
||
|
|
.priority = (osPriority_t) osPriorityNormal3,
|
||
|
|
};
|
||
|
|
(void)osThreadNew(UI_ModuleTask, NULL, &ui_task_attr);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*==============================================*
|
||
|
|
* 外部调用示例 *
|
||
|
|
*==============================================*/
|
||
|
|
|
||
|
|
// 从任何线程调用这些函数即可跨线程控制电机
|
||
|
|
void Example_SetMotorSpeed(uint8_t ucMotorIndex, int32_t iSpeed)
|
||
|
|
{
|
||
|
|
Motor_CmdData_t stData;
|
||
|
|
stData.m_ucMotorIndex = ucMotorIndex;
|
||
|
|
stData.m_iValue = iSpeed;
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_MOTOR, MOTOR_CMD_SET_SPEED, &stData, sizeof(stData));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Example_StopAllMotors(void)
|
||
|
|
{
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_MOTOR, MOTOR_CMD_STOP, NULL, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Example_ChassisMove(int32_t iSpeedX, int32_t iSpeedW)
|
||
|
|
{
|
||
|
|
Chassis_MoveData_t stData;
|
||
|
|
stData.m_iSpeedX = iSpeedX;
|
||
|
|
stData.m_iSpeedY = 0;
|
||
|
|
stData.m_iSpeedW = iSpeedW;
|
||
|
|
MsgCenter_SendTo(MODULE_NAME_CHASSIS, CHASSIS_CMD_MOVE, &stData, sizeof(stData));
|
||
|
|
}
|