重构项目:移除JY901传感器,添加CAN总线支持,集成电机/传感器模块库

This commit is contained in:
CloudPlant Team
2026-04-13 22:49:49 +08:00
parent 116f06ec3c
commit 1c2d945a6d
40 changed files with 8376 additions and 519 deletions

View File

@@ -0,0 +1,101 @@
/**
* @file mf4010v2.c
* @brief MF4010V2 无刷电机驱动程序
* @note 改进版本:
* - 添加错误处理和返回值
* - 添加 CAN 超时机制
* - 使用安全的内联函数替代危险宏
* - 使用 HAL 层解耦硬件依赖
*/
#include "mf4010v2.h"
#include "bsp_can.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/**
* @brief 初始化电机结构体
*/
mf4010_status_t mf4010v2_init(mf4010v2_t* motor, uint16_t id)
{
// 参数验证
if(motor == NULL) {
return MF4010_ERR_INVALID_PARAM;
}
// CAN ID 范围验证 (0x000-0x7FF for standard frame)
if(id > 0x7FF) {
printf("Error: Invalid CAN ID 0x%03X (must be 0x000-0x7FF)\r\n", id);
return MF4010_ERR_INVALID_ID;
}
// 初始化结构体
motor->id = id;
memset(motor->last_response, 0, sizeof(motor->last_response));
motor->last_comm_time = 0;
motor->error_count = 0;
motor->success_count = 0;
motor->flags = MF4010_FLAG_NONE;
motor->ops.init = mf4010v2_init;
motor->ops.send_command = mf4010v2_send_command;
return MF4010_OK;
}
/**
* @brief 发送命令并接收响应(带超时)
*/
mf4010_status_t mf4010v2_send_command(mf4010v2_t* motor, const uint8_t command[8], uint32_t timeout_ms)
{
// 参数验证
if(motor == NULL || command == NULL) {
return MF4010_ERR_INVALID_PARAM;
}
// 验证命令格式(首字节应该是命令字)
if((command[0] & 0x80) == 0 && command[0] < 0x30) {
printf("Warning: Invalid command format 0x%02X\r\n", command[0]);
// 不返回错误,继续执行
}
// 发送 CAN 消息
if (can_send(motor->id, command, 8) != HAL_OK)
{
motor->error_count++;
motor->flags &= ~MF4010_FLAG_CONNECTED;
return MF4010_ERR_TIMEOUT;
}
// 接收响应
uint16_t rx_id;
uint8_t len;
if (MF4010V2_HAL_Receive(&rx_id, motor->last_response, &len, timeout_ms) != HAL_OK)
{
motor->error_count++;
motor->flags &= ~MF4010_FLAG_CONNECTED;
return MF4010_ERR_NO_RESPONSE;
}
// 验证响应 ID
if (rx_id != motor->id)
{
return MF4010_ERR_CRC;
}
motor->last_comm_time = get_system_tick();
motor->success_count++;
motor->flags |= MF4010_FLAG_CONNECTED;
// 解析错误状态
if (motor->last_response[0] & 0x80)
{
uint8_t error_code = motor->last_response[0] & 0x7F;
printf("Motor error from 0x%03X: 0x%02X\r\n", motor->id, error_code);
motor->error_count++;
motor->flags |= MF4010_FLAG_FAULT;
return MF4010_ERR_CRC;
}
motor->flags &= ~MF4010_FLAG_FAULT;
return MF4010_OK;
}

View File

@@ -0,0 +1,338 @@
#ifndef __MF4010V2__H__
#define __MF4010V2__H__
/**
* @file mf4010v2.h
* @brief MF4010V2 无刷电机驱动程序
* @note 改进版本:
* - 添加错误处理和返回值
* - 添加 CAN 超时机制
* - 使用安全的内联函数替代危险宏
* - 使用 HAL 层解耦硬件依赖
*
* 电机 CAN ID: 0x141 (默认)
* CAN 波特率1 Mbps
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================
* 状态码和错误定义
* ============================================================================ */
/**
* @brief MF4010V2 状态码
*/
typedef enum {
MF4010_OK = 0, /**< 成功 */
MF4010_ERR_TIMEOUT = -1, /**< CAN 通信超时 */
MF4010_ERR_INVALID_ID = -2, /**< 无效的 CAN ID */
MF4010_ERR_NO_RESPONSE = -3, /**< 无响应 */
MF4010_ERR_INVALID_PARAM = -4, /**< 无效参数 */
MF4010_ERR_BUS_OFF = -5, /**< CAN 总线关闭 */
MF4010_ERR_CRC = -6, /**< CRC 校验错误 */
MF4010_ERR_HARDWARE = -7 /**< 硬件错误 */
} mf4010_status_t;
/**
* @brief 电机状态标志
*/
typedef enum {
MF4010_FLAG_NONE = 0x00, /**< 无标志 */
MF4010_FLAG_RUNNING = 0x01, /**< 电机运行中 */
MF4010_FLAG_ENABLED = 0x02, /**< 电机已使能 */
MF4010_FLAG_FAULT = 0x04, /**< 故障状态 */
MF4010_FLAG_CONNECTED = 0x08 /**< 已连接 */
} mf4010_flag_t;
/* ============================================================================
* 电机结构体定义
* ============================================================================ */
/**
* @brief 电机结构体(优化版)
*/
struct __mf4010v2_ops_t;
typedef struct {
struct __mf4010v2_ops_t ops; /**< 操作函数指针 */
uint16_t id; /**< CAN ID (0x000-0x7FF) */
uint8_t last_response[8]; /**< 最后一次响应数据 */
uint32_t last_comm_time; /**< 最后通信时间戳 (ms) */
uint16_t error_count; /**< 通信错误计数 */
uint16_t success_count; /**< 成功通信计数 */
uint8_t flags; /**< 状态标志 (@ref mf4010_flag_t) */
} mf4010v2_t;
struct __mf4010v2_ops_t {
mf4010_status_t (*init)(mf4010v2_t* self, uint16_t id);
mf4010_status_t (*send_command)(mf4010v2_t* self, const uint8_t command[8], uint32_t timeout_ms);
};
typedef struct __mf4010v2_ops_t mf4010v2_ops_t;
/* ============================================================================
* 核心 API 函数
* ============================================================================ */
/**
* @brief 初始化电机结构体
* @param motor: 电机结构体指针
* @param id: 电机 CAN ID (范围 0x000-0x7FF如 0x141)
* @retval 成功返回 MF4010_OK失败返回错误码
*/
mf4010_status_t mf4010v2_init(mf4010v2_t* motor, uint16_t id);
/**
* @brief 发送命令并接收响应(带超时)
* @param motor: 电机结构体指针
* @param command: 8 字节命令数据
* @param timeout_ms: 超时时间 (ms)0 表示无限等待
* @retval 成功返回 MF4010_OK失败返回错误码
*
* @note 命令格式参考下面的宏定义
* @example
* // 关闭电机
* uint8_t cmd[8] = COMMAND_MOTOR_CLOSE;
* mf4010v2_send_command(&motor, cmd, 1000);
*
* // 速度控制 (100 DPS)
* uint8_t cmd[8];
* cmd_speed_control(cmd, 10000); // 100 * 100 (0.01 DPS/LSB)
* mf4010v2_send_command(&motor, cmd, 1000);
*/
mf4010_status_t mf4010v2_send_command(mf4010v2_t* motor, const uint8_t command[8], uint32_t timeout_ms);
/* ============================================================================
* 命令宏定义8 字节 CAN 命令帧)
* ============================================================================ */
/**
* @brief 电机关闭命令
* @note 命令字0x80
*/
#define COMMAND_MOTOR_CLOSE {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
/**
* @brief 电机运行命令
* @note 命令字0x88
*/
#define COMMAND_MOTOR_RUNNING {0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
/**
* @brief 电机停止命令
* @note 命令字0x81
*/
#define COMMAND_MOTOR_STOP {0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
/**
* @brief 读取 PID 参数命令
* @note 命令字0x30
*/
#define COMMAND_READ_PID_PARAMS {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
/* ============================================================================
* 安全命令生成函数(使用内联函数避免指针问题)
* ============================================================================ */
/**
* @brief 转矩闭环控制命令
* @param buf: 8 字节缓冲区(输出)
* @param iq: 转矩控制量 (-2048 ~ 2048)
* @note 分辨率1 LSB = 1 单位
*/
static inline void cmd_torque_control(uint8_t* buf, int16_t iq)
{
buf[0] = 0xA1;
buf[1] = 0x00;
buf[2] = 0x00;
buf[3] = 0x00;
buf[4] = (uint8_t)(iq & 0xFF);
buf[5] = (uint8_t)((iq >> 8) & 0xFF);
buf[6] = 0x00;
buf[7] = 0x00;
}
/**
* @brief 速度闭环控制命令
* @param buf: 8 字节缓冲区(输出)
* @param speed: 速度控制量
* @note 分辨率0.01 DPS/LSB
* 范围:-204800 ~ +204800 (对应 -2048 ~ +2048 DPS)
* @example
* uint8_t cmd[8];
* cmd_speed_control(cmd, 10000); // 100 DPS
*/
static inline void cmd_speed_control(uint8_t* buf, int32_t speed)
{
buf[0] = 0xA2;
buf[1] = 0x00;
buf[2] = 0x00;
buf[3] = 0x00;
buf[4] = (uint8_t)(speed & 0xFF);
buf[5] = (uint8_t)((speed >> 8) & 0xFF);
buf[6] = (uint8_t)((speed >> 16) & 0xFF);
buf[7] = (uint8_t)((speed >> 24) & 0xFF);
}
/**
* @brief 单圈位置闭环控制命令
* @param buf: 8 字节缓冲区(输出)
* @param direction: 旋转方向 (0x00=顺时针0x01=逆时针)
* @param angle: 目标角度 (单位0.01°, 如 36000=360°)
*/
static inline void cmd_single_ring_pos(uint8_t* buf, uint8_t direction, uint32_t angle)
{
buf[0] = 0xA5;
buf[1] = direction & 0x01;
buf[2] = 0x00;
buf[3] = 0x00;
buf[4] = (uint8_t)(angle & 0xFF);
buf[5] = (uint8_t)((angle >> 8) & 0xFF);
buf[6] = (uint8_t)((angle >> 16) & 0xFF);
buf[7] = (uint8_t)((angle >> 24) & 0xFF);
}
/**
* @brief 增量位置闭环控制命令(带最大速度)
* @param buf: 8 字节缓冲区(输出)
* @param direction: 旋转方向 (0x00=顺时针0x01=逆时针)
* @param max_speed: 最大速度 (单位DPS, 如 360=360 DPS)
* @param angle: 目标角度 (单位0.01°, 如 36000=360°)
*/
static inline void cmd_incr_pos_with_speed(uint8_t* buf, uint8_t direction,
uint16_t max_speed, uint32_t angle)
{
buf[0] = 0xA6;
buf[1] = direction & 0x01;
buf[2] = (uint8_t)(max_speed & 0xFF);
buf[3] = (uint8_t)((max_speed >> 8) & 0xFF);
buf[4] = (uint8_t)(angle & 0xFF);
buf[5] = (uint8_t)((angle >> 8) & 0xFF);
buf[6] = (uint8_t)((angle >> 16) & 0xFF);
buf[7] = (uint8_t)((angle >> 24) & 0xFF);
}
/**
* @brief 增量位置闭环控制命令
* @param buf: 8 字节缓冲区(输出)
* @param angle_increment: 角度增量 (单位0.01°, 如 36000=360°)
* @note 正值 = 逆时针,负值 = 顺时针
*/
static inline void cmd_position_add(uint8_t* buf, int32_t angle_increment)
{
buf[0] = 0xA7;
buf[1] = 0x00;
buf[2] = 0x00;
buf[3] = 0x00;
buf[4] = (uint8_t)(angle_increment & 0xFF);
buf[5] = (uint8_t)((angle_increment >> 8) & 0xFF);
buf[6] = (uint8_t)((angle_increment >> 16) & 0xFF);
buf[7] = (uint8_t)((angle_increment >> 24) & 0xFF);
}
/**
* @brief PID 参数写入命令
* @param buf: 8 字节缓冲区(输出)
* @param location: 写入位置 (0x31=RAM, 0x32=ROM)
* @param angle_kp: 角度环 Kp (0-255)
* @param angle_ki: 角度环 Ki (0-255)
* @param speed_kp: 速度环 Kp (0-255)
* @param speed_ki: 速度环 Ki (0-255)
* @param iq_kp: 电流环 Kp (0-255)
* @param iq_ki: 电流环 Ki (0-255)
*/
static inline void cmd_write_pid_params(uint8_t* buf, uint8_t location,
uint8_t angle_kp, uint8_t angle_ki,
uint8_t speed_kp, uint8_t speed_ki,
uint8_t iq_kp, uint8_t iq_ki)
{
buf[0] = location;
buf[1] = 0x00;
buf[2] = angle_kp;
buf[3] = angle_ki;
buf[4] = speed_kp;
buf[5] = speed_ki;
buf[6] = iq_kp;
buf[7] = iq_ki;
}
/* ============================================================================
* 辅助函数和宏
* ============================================================================ */
/**
* @brief 检查电机是否在线
*/
static inline bool mf4010v2_is_connected(mf4010v2_t* motor)
{
return (motor != NULL) && (motor->flags & MF4010_FLAG_CONNECTED);
}
/**
* @brief 检查电机是否运行
*/
static inline bool mf4010v2_is_running(mf4010v2_t* motor)
{
return (motor != NULL) && (motor->flags & MF4010_FLAG_RUNNING);
}
/**
* @brief 获取电机错误计数
*/
static inline uint16_t mf4010v2_get_error_count(mf4010v2_t* motor)
{
return (motor != NULL) ? motor->error_count : 0;
}
/**
* @brief 重置错误计数
*/
static inline void mf4010v2_reset_errors(mf4010v2_t* motor)
{
if(motor != NULL) {
motor->error_count = 0;
}
}
/**
* @brief 获取响应中的命令字节
*/
#define MF4010_GET_RESPONSE_CMD(motor) ((motor)->last_response[0])
/**
* @brief 获取响应中的数据字节
*/
#define MF4010_GET_RESPONSE_DATA(motor, index) ((motor)->last_response[(index) + 1])
/**
* @brief 检查响应是否包含错误
* @note 如果响应字节 0 的最高位为 1表示有错误
*/
static inline bool mf4010v2_response_has_error(mf4010v2_t* motor)
{
return (motor != NULL) && ((motor->last_response[0] & 0x80) != 0);
}
/**
* @brief 获取错误码(从响应中)
*/
static inline uint8_t mf4010v2_get_error_code(mf4010v2_t* motor)
{
return (motor != NULL) ? (motor->last_response[0] & 0x7F) : 0;
}
#ifdef __cplusplus
}
#endif
#endif /* __MF4010V2__H__ */