feat: 完成弹力魔盒初版固件
This commit is contained in:
+25
-13
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
* @file board_pin.h
|
||||
* @brief CBC2 门夹弹力绳板级引脚、电平与时序(换板只改本文件)
|
||||
* @brief CBC1 猫猫捕猎罩板级引脚、电平与时序(换板只改本文件)
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.08.27
|
||||
* @version V1.5.0
|
||||
@@ -27,29 +27,28 @@
|
||||
#define BOARD_LED_ENABLE 1 /**< 1=红绿 LED */
|
||||
#define BOARD_KEY_ENABLE 1 /**< 1=按键 PB1 */
|
||||
#define BOARD_CHG_ENABLE 1 /**< 1=充电检测 PG8 + VPWR */
|
||||
#define BOARD_MOTOR_ENABLE 1 /**< 1=电机 PA6/PC2 */
|
||||
#define BOARD_MOTOR_ENABLE 1 /**< 1=双电机 U13 + U18 */
|
||||
#define BOARD_SHAKE_ENABLE 1 /**< 1=震动输入 PA3 */
|
||||
|
||||
/*============================================================================*/
|
||||
/* GPIO */
|
||||
/*============================================================================*/
|
||||
|
||||
#define BOARD_MOTOR_INA_PIN IO_PORTA_06 /**< 电机 INA */
|
||||
#define BOARD_MOTOR_INB_PIN IO_PORTC_02 /**< 电机 INB */
|
||||
#define BOARD_LEFT_FORWARD_PIN IO_PORTA_06 /**< U13-INA,左轮前进 */
|
||||
#define BOARD_LEFT_BACKWARD_PIN IO_PORTC_02 /**< U13-INB,左轮后退 */
|
||||
#define BOARD_RIGHT_BACKWARD_PIN IO_PORTC_03 /**< U18-INA,右轮后退 */
|
||||
#define BOARD_RIGHT_FORWARD_PIN IO_PORTC_04 /**< U18-INB,右轮前进 */
|
||||
#define BOARD_SHAKE_PIN IO_PORTA_03 /**< 震动开机,常闭开关断开时高脉冲有效 */
|
||||
#define BOARD_LED_RED_PIN IO_PORTA_08 /**< 红灯 LED_PWR,低电平亮 */
|
||||
#define BOARD_LED_GREEN_PIN IO_PORTA_07 /**< 绿灯 LED_CHG,低电平亮 */
|
||||
#define BOARD_KEY_PIN IO_PORTB_01 /**< 按键,低电平按下 */
|
||||
#define BOARD_CHG_PIN IO_PORTG_08 /**< ME4054 CHG,外部 2.2k 上拉 */
|
||||
/* PA3 限位未贴件,空脚不初始化 */
|
||||
|
||||
#define BOARD_LED_ON_LEVEL 0 /**< LED 点亮电平:0=低亮 */
|
||||
#define BOARD_KEY_ACTIVE_LEVEL 0 /**< 按键有效电平:0=按下为低 */
|
||||
#define BOARD_CHG_CHARGING_LEVEL 0 /**< CHG 充电中为低 */
|
||||
|
||||
/**
|
||||
* 收绳方向:1 = INA 高 / INB 低 为收绳(顺时针)
|
||||
* 若实测方向反了,把本宏改为 0
|
||||
*/
|
||||
#define BOARD_MOTOR_IN_INA_HIGH 1
|
||||
#define BOARD_SHAKE_ACTIVE_LEVEL 1 /**< 常闭震动开关:断开时高脉冲有效 */
|
||||
|
||||
/*============================================================================*/
|
||||
/* 电量 / 充电 */
|
||||
@@ -105,8 +104,8 @@
|
||||
/*============================================================================*/
|
||||
|
||||
#define BOARD_MOTOR_REVERSE_MS 1 /**< 换向前先松开,防 H 桥直通 */
|
||||
#define BOARD_HAND_PULSE_MS 1000 /**< 预留;手动 1/2 一直转到写 03 停止 */
|
||||
#define BOARD_MOTOR_PWM_HZ 20000 /**< MCPWM 频率(Hz),20k 避开可听啸叫 */
|
||||
#define BOARD_HAND_PULSE_MS 5000 /**< 手动右转/左转单次最长 5s */
|
||||
#define BOARD_MOTOR_PWM_HZ 200 /**< 猫猫捕猎罩原项目验证过的 MCPWM 频率(Hz) */
|
||||
#define BOARD_MOTOR_PWM_DUTY 8000 /**< 占空比 0~10000=0%~100%,80% */
|
||||
#define BOARD_MOTOR_PWM_IDLE_CLOSE 1 /**< 1=空闲/轻睡关 MCPWM;0=保持开着,方便对比待机电流 */
|
||||
|
||||
@@ -114,6 +113,19 @@
|
||||
/* 自动玩法 */
|
||||
/*============================================================================*/
|
||||
|
||||
#define BOARD_AUTO_MODE_MAX_MS (10u * 60u * 1000u) /**< 自动模式 1~6 单次最长运行时长,到点自动回待机 */
|
||||
#define BOARD_AUTO_MODE_MAX_MS (10u * 60u * 1000u) /**< 自动模式 1~5 单次最长运行时长,到点自动回待机 */
|
||||
|
||||
/*============================================================================*/
|
||||
/* 震动开机 */
|
||||
/*============================================================================*/
|
||||
|
||||
#define BOARD_SHAKE_REARM_MS 50u /**< 高电平稳定后重新武装 */
|
||||
#define BOARD_SHAKE_TRIGGER_EDGE_COUNT 1u /**< 验证阶段:单个高脉冲立即触发 */
|
||||
#define BOARD_SHAKE_TRIGGER_WINDOW_MS 250u /**< 保留窗口参数,便于恢复多脉冲策略 */
|
||||
#define BOARD_SHAKE_POLL_MS 10u /**< 与业务调度器共用的采样节拍 */
|
||||
|
||||
/* PG8/CHG_ON is the only fitted USB-related signal that changes while the
|
||||
* product is in softoff; VPWR is disconnected on boards with R18 not fitted. */
|
||||
#define BOARD_CHG_WAKEUP_INDEX 3u
|
||||
|
||||
#endif /* __BOARD_PIN_H__ */
|
||||
|
||||
+180
-182
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
* @file bsp_hw.c
|
||||
* @brief CBC2 板级 GPIO / ADC:电机 H 桥、LED、按键、充电检测
|
||||
* @brief CBC1 板级 GPIO / ADC:单电机 H 桥、震动、LED、按键、充电检测
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.08.24
|
||||
* @version V1.5.0
|
||||
@@ -28,21 +28,16 @@
|
||||
#include "debug.h"
|
||||
|
||||
static uint8_t s_initialized;
|
||||
|
||||
/** 电机状态,替代原来散落的 7 个 static */
|
||||
typedef struct {
|
||||
BspMotorDir_t dir; /**< 当前实际方向 */
|
||||
BspMotorDir_t pending; /**< 换向死区结束后要切到的方向 */
|
||||
uint16_t duty; /**< 当前实际占空比 */
|
||||
uint16_t pending_duty; /**< 换向死区结束后要用的占空比 */
|
||||
uint16_t switch_ms; /**< 换向死区剩余时长,0=空闲/不在换向中 */
|
||||
u32 switch_t0; /**< 换向死区起始时间戳 */
|
||||
uint8_t pwm_clk_on; /**< 1=MCPWM 时钟已打开 */
|
||||
} BspMotorCtx_t;
|
||||
|
||||
static BspMotorCtx_t s_motor;
|
||||
|
||||
extern u32 timer_get_ms(void);
|
||||
static uint8_t s_motor_active;
|
||||
static uint8_t s_pwm_clk_on;
|
||||
static uint8_t s_motor_switch_pending;
|
||||
static BspMotorDir_t s_left_direction;
|
||||
static BspMotorDir_t s_right_direction;
|
||||
static BspMotorDir_t s_pending_left_direction;
|
||||
static BspMotorDir_t s_pending_right_direction;
|
||||
static uint16_t s_pending_left_duty;
|
||||
static uint16_t s_pending_right_duty;
|
||||
static uint32_t s_motor_switch_started_ms;
|
||||
|
||||
#if (BOARD_LED_ENABLE || BOARD_MOTOR_ENABLE)
|
||||
/**
|
||||
@@ -60,7 +55,7 @@ static void bsp_pin_output(u32 pin, int value)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (BOARD_KEY_ENABLE || BOARD_CHG_ENABLE)
|
||||
#if (BOARD_KEY_ENABLE || BOARD_CHG_ENABLE || BOARD_SHAKE_ENABLE)
|
||||
/**
|
||||
* @brief 配置 GPIO 为数字输入(可内部上拉)
|
||||
* @param pin GPIO 编号
|
||||
@@ -78,40 +73,50 @@ static void bsp_pin_input(u32 pin, int pull_up)
|
||||
#endif
|
||||
|
||||
#if BOARD_MOTOR_ENABLE
|
||||
static void bsp_motor_pwm_channel_init(pwm_ch_num_type channel, u8 pin)
|
||||
{
|
||||
struct pwm_platform_data pwm;
|
||||
|
||||
memset(&pwm, 0, sizeof(pwm));
|
||||
pwm.pwm_aligned_mode = pwm_edge_aligned;
|
||||
pwm.pwm_ch_num = channel;
|
||||
pwm.frequency = BOARD_MOTOR_PWM_HZ;
|
||||
pwm.duty = 0;
|
||||
pwm.h_pin = pin;
|
||||
pwm.l_pin = (u8) - 1;
|
||||
pwm.complementary_en = 0;
|
||||
mcpwm_init(&pwm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化 INA/INB 两路 MCPWM,初始占空比 0(停转)
|
||||
* @return 无
|
||||
*/
|
||||
static void bsp_motor_pwm_init(void)
|
||||
{
|
||||
struct pwm_platform_data pwm;
|
||||
const u32 pins[] = {
|
||||
BOARD_LEFT_FORWARD_PIN, BOARD_LEFT_BACKWARD_PIN,
|
||||
BOARD_RIGHT_BACKWARD_PIN, BOARD_RIGHT_FORWARD_PIN
|
||||
};
|
||||
uint8_t i;
|
||||
|
||||
gpio_set_pull_up(BOARD_MOTOR_INA_PIN, 0);
|
||||
gpio_set_pull_down(BOARD_MOTOR_INA_PIN, 0);
|
||||
gpio_set_die(BOARD_MOTOR_INA_PIN, 1);
|
||||
gpio_set_pull_up(BOARD_MOTOR_INB_PIN, 0);
|
||||
gpio_set_pull_down(BOARD_MOTOR_INB_PIN, 0);
|
||||
gpio_set_die(BOARD_MOTOR_INB_PIN, 1);
|
||||
for (i = 0; i < ARRAY_SIZE(pins); i++) {
|
||||
gpio_set_pull_up(pins[i], 0);
|
||||
gpio_set_pull_down(pins[i], 0);
|
||||
gpio_set_die(pins[i], 1);
|
||||
}
|
||||
|
||||
pwm.pwm_aligned_mode = pwm_edge_aligned;
|
||||
pwm.frequency = BOARD_MOTOR_PWM_HZ;
|
||||
pwm.duty = 0;
|
||||
pwm.l_pin = (u8) - 1;
|
||||
pwm.complementary_en = 0;
|
||||
|
||||
pwm.pwm_ch_num = pwm_ch0;
|
||||
pwm.h_pin = BOARD_MOTOR_INA_PIN;
|
||||
mcpwm_init(&pwm);
|
||||
|
||||
pwm.pwm_ch_num = pwm_ch1;
|
||||
pwm.h_pin = BOARD_MOTOR_INB_PIN;
|
||||
mcpwm_init(&pwm);
|
||||
bsp_motor_pwm_channel_init(pwm_ch0, BOARD_LEFT_FORWARD_PIN);
|
||||
bsp_motor_pwm_channel_init(pwm_ch1, BOARD_LEFT_BACKWARD_PIN);
|
||||
bsp_motor_pwm_channel_init(pwm_ch2, BOARD_RIGHT_BACKWARD_PIN);
|
||||
bsp_motor_pwm_channel_init(pwm_ch3, BOARD_RIGHT_FORWARD_PIN);
|
||||
|
||||
mcpwm_set_duty(pwm_ch0, 0);
|
||||
mcpwm_set_duty(pwm_ch1, 0);
|
||||
s_motor.pwm_clk_on = 1;
|
||||
log_info("motor pwm %uHz duty=%u/10000\n",
|
||||
(unsigned)BOARD_MOTOR_PWM_HZ, (unsigned)BOARD_MOTOR_PWM_DUTY);
|
||||
mcpwm_set_duty(pwm_ch2, 0);
|
||||
mcpwm_set_duty(pwm_ch3, 0);
|
||||
s_pwm_clk_on = 1;
|
||||
log_info("dual motor pwm %uHz\n", (unsigned)BOARD_MOTOR_PWM_HZ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,16 +125,22 @@ static void bsp_motor_pwm_init(void)
|
||||
*/
|
||||
static void bsp_motor_pwm_clock_on(void)
|
||||
{
|
||||
if (s_motor.pwm_clk_on) {
|
||||
if (s_pwm_clk_on) {
|
||||
return;
|
||||
}
|
||||
mcpwm_open(pwm_ch0);
|
||||
mcpwm_open(pwm_ch1);
|
||||
gpio_och_sel_output_signal(BOARD_MOTOR_INA_PIN, OUTPUT_CH_SIGNAL_MC_PWM0_H);
|
||||
gpio_och_sel_output_signal(BOARD_MOTOR_INB_PIN, OUTPUT_CH_SIGNAL_MC_PWM1_H);
|
||||
gpio_set_direction(BOARD_MOTOR_INA_PIN, 0);
|
||||
gpio_set_direction(BOARD_MOTOR_INB_PIN, 0);
|
||||
s_motor.pwm_clk_on = 1;
|
||||
mcpwm_open(pwm_ch2);
|
||||
mcpwm_open(pwm_ch3);
|
||||
gpio_och_sel_output_signal(BOARD_LEFT_FORWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM0_H);
|
||||
gpio_och_sel_output_signal(BOARD_LEFT_BACKWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM1_H);
|
||||
gpio_och_sel_output_signal(BOARD_RIGHT_BACKWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM2_H);
|
||||
gpio_och_sel_output_signal(BOARD_RIGHT_FORWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM3_H);
|
||||
gpio_set_direction(BOARD_LEFT_FORWARD_PIN, 0);
|
||||
gpio_set_direction(BOARD_LEFT_BACKWARD_PIN, 0);
|
||||
gpio_set_direction(BOARD_RIGHT_BACKWARD_PIN, 0);
|
||||
gpio_set_direction(BOARD_RIGHT_FORWARD_PIN, 0);
|
||||
s_pwm_clk_on = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,61 +151,63 @@ static void bsp_motor_pwm_clock_off(void)
|
||||
{
|
||||
mcpwm_set_duty(pwm_ch0, 0);
|
||||
mcpwm_set_duty(pwm_ch1, 0);
|
||||
if (s_motor.pwm_clk_on) {
|
||||
mcpwm_set_duty(pwm_ch2, 0);
|
||||
mcpwm_set_duty(pwm_ch3, 0);
|
||||
if (s_pwm_clk_on) {
|
||||
mcpwm_close(pwm_ch0);
|
||||
mcpwm_close(pwm_ch1);
|
||||
gpio_och_disable_output_signal(BOARD_MOTOR_INA_PIN, OUTPUT_CH_SIGNAL_MC_PWM0_H);
|
||||
gpio_och_disable_output_signal(BOARD_MOTOR_INB_PIN, OUTPUT_CH_SIGNAL_MC_PWM1_H);
|
||||
mcpwm_close(pwm_ch2);
|
||||
mcpwm_close(pwm_ch3);
|
||||
gpio_och_disable_output_signal(BOARD_LEFT_FORWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM0_H);
|
||||
gpio_och_disable_output_signal(BOARD_LEFT_BACKWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM1_H);
|
||||
gpio_och_disable_output_signal(BOARD_RIGHT_BACKWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM2_H);
|
||||
gpio_och_disable_output_signal(BOARD_RIGHT_FORWARD_PIN, OUTPUT_CH_SIGNAL_MC_PWM3_H);
|
||||
JL_MCPWM->MCPWM_CON0 = 0;
|
||||
s_motor.pwm_clk_on = 0;
|
||||
s_pwm_clk_on = 0;
|
||||
}
|
||||
gpio_direction_output(BOARD_MOTOR_INA_PIN, 0);
|
||||
gpio_direction_output(BOARD_MOTOR_INB_PIN, 0);
|
||||
gpio_direction_output(BOARD_LEFT_FORWARD_PIN, 0);
|
||||
gpio_direction_output(BOARD_LEFT_BACKWARD_PIN, 0);
|
||||
gpio_direction_output(BOARD_RIGHT_BACKWARD_PIN, 0);
|
||||
gpio_direction_output(BOARD_RIGHT_FORWARD_PIN, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 立刻改 INA/INB PWM。运转脚输出 duty,另一脚 0%;STOP=两路 0%
|
||||
* @param dir 目标方向
|
||||
* @param duty 占空比 0~10000
|
||||
* @return 无
|
||||
*/
|
||||
static void bsp_motor_gpio(BspMotorDir_t dir, uint16_t duty)
|
||||
static void bsp_drive_gpio(BspMotorDir_t left_dir, uint16_t left_duty,
|
||||
BspMotorDir_t right_dir, uint16_t right_duty)
|
||||
{
|
||||
u16 ina_duty = 0;
|
||||
u16 inb_duty = 0;
|
||||
|
||||
if (duty > 10000) {
|
||||
duty = 10000;
|
||||
if (left_duty > 10000) {
|
||||
left_duty = 10000;
|
||||
}
|
||||
if (right_duty > 10000) {
|
||||
right_duty = 10000;
|
||||
}
|
||||
if (left_dir == BSP_MOTOR_STOP) {
|
||||
left_duty = 0;
|
||||
}
|
||||
if (right_dir == BSP_MOTOR_STOP) {
|
||||
right_duty = 0;
|
||||
}
|
||||
|
||||
if (dir == BSP_MOTOR_IN) {
|
||||
if (BOARD_MOTOR_IN_INA_HIGH) {
|
||||
ina_duty = duty;
|
||||
} else {
|
||||
inb_duty = duty;
|
||||
}
|
||||
} else if (dir == BSP_MOTOR_OUT) {
|
||||
if (BOARD_MOTOR_IN_INA_HIGH) {
|
||||
inb_duty = duty;
|
||||
} else {
|
||||
ina_duty = duty;
|
||||
}
|
||||
}
|
||||
/* Crazy Car's proven driver clears all four channels at every action
|
||||
* boundary, then applies the two wheel outputs as one atomic command. */
|
||||
mcpwm_set_duty(pwm_ch0, 0);
|
||||
mcpwm_set_duty(pwm_ch1, 0);
|
||||
mcpwm_set_duty(pwm_ch2, 0);
|
||||
mcpwm_set_duty(pwm_ch3, 0);
|
||||
|
||||
if ((ina_duty == 0) && (inb_duty == 0)) {
|
||||
/* 换向死区(BOARD_MOTOR_REVERSE_MS)、刹车瞬间也会短暂占空比为 0,
|
||||
* 但马上(1~30ms 内)还要再驱动,不能当成“真空闲”去关时钟:
|
||||
* 频繁 close/open MCPWM 外设比单纯调占空比激进得多,玩法换向越快
|
||||
* 关得越勤,有卡死风险。这里只清占空比(两脚拉低,电气效果一样),
|
||||
* 真正的空闲关时钟统一交给 bsp_hw_sleep_pwm_off()——它在系统真的
|
||||
* 要进轻睡前才调用,并且会先查 bsp_motor_is_busy()。 */
|
||||
mcpwm_set_duty(pwm_ch0, 0);
|
||||
mcpwm_set_duty(pwm_ch1, 0);
|
||||
return;
|
||||
s_motor_active = (uint8_t)(left_duty || right_duty);
|
||||
if (s_motor_active) {
|
||||
bsp_motor_pwm_clock_on();
|
||||
}
|
||||
if (left_dir == BSP_MOTOR_FORWARD) {
|
||||
mcpwm_set_duty(pwm_ch0, left_duty);
|
||||
} else if (left_dir == BSP_MOTOR_BACKWARD) {
|
||||
mcpwm_set_duty(pwm_ch1, left_duty);
|
||||
}
|
||||
if (right_dir == BSP_MOTOR_FORWARD) {
|
||||
mcpwm_set_duty(pwm_ch3, right_duty);
|
||||
} else if (right_dir == BSP_MOTOR_BACKWARD) {
|
||||
mcpwm_set_duty(pwm_ch2, right_duty);
|
||||
}
|
||||
bsp_motor_pwm_clock_on();
|
||||
mcpwm_set_duty(pwm_ch0, ina_duty);
|
||||
mcpwm_set_duty(pwm_ch1, inb_duty);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -231,20 +244,19 @@ BspHw_Ret_t bsp_hw_init(void)
|
||||
|
||||
#if BOARD_MOTOR_ENABLE
|
||||
bsp_motor_pwm_init();
|
||||
s_motor.dir = BSP_MOTOR_STOP;
|
||||
s_motor.pending = BSP_MOTOR_STOP;
|
||||
s_motor.duty = 0;
|
||||
s_motor.pending_duty = 0;
|
||||
s_motor.switch_ms = 0;
|
||||
s_motor_active = 0;
|
||||
s_motor_switch_pending = 0;
|
||||
s_left_direction = BSP_MOTOR_STOP;
|
||||
s_right_direction = BSP_MOTOR_STOP;
|
||||
#if BOARD_MOTOR_PWM_IDLE_CLOSE
|
||||
bsp_motor_pwm_clock_off();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
s_initialized = 1;
|
||||
log_info("hw init led=%d key=%d chg=%d motor=%d\n",
|
||||
log_info("hw init led=%d key=%d chg=%d motor=%d shake=%d\n",
|
||||
BOARD_LED_ENABLE, BOARD_KEY_ENABLE, BOARD_CHG_ENABLE,
|
||||
BOARD_MOTOR_ENABLE);
|
||||
BOARD_MOTOR_ENABLE, BOARD_SHAKE_ENABLE);
|
||||
return BSP_HW_OK;
|
||||
}
|
||||
|
||||
@@ -295,101 +307,93 @@ void bsp_led_all_off(void)
|
||||
bsp_led_green_set(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置电机方向。STOP 时直接切断驱动,自由滑行到停(不做反接刹车)
|
||||
* @param dir 收绳 / 放绳 / 停转
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_motor_set(BspMotorDir_t dir)
|
||||
{
|
||||
bsp_motor_set_pwm(dir, (dir == BSP_MOTOR_STOP) ? 0 : BOARD_MOTOR_PWM_DUTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置电机方向与 PWM 占空比
|
||||
* @param dir 收绳 / 放绳 / 停转
|
||||
* @param duty 占空比 0~10000;STOP 时按 0 处理
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_motor_set_pwm(BspMotorDir_t dir, uint16_t duty)
|
||||
void bsp_drive_set(BspMotorDir_t left_dir, uint16_t left_duty,
|
||||
BspMotorDir_t right_dir, uint16_t right_duty)
|
||||
{
|
||||
#if !BOARD_MOTOR_ENABLE
|
||||
(void)dir;
|
||||
(void)duty;
|
||||
return;
|
||||
(void)left_dir;
|
||||
(void)left_duty;
|
||||
(void)right_dir;
|
||||
(void)right_duty;
|
||||
#else
|
||||
if (duty > 10000) {
|
||||
duty = 10000;
|
||||
uint8_t left_reversing;
|
||||
uint8_t right_reversing;
|
||||
|
||||
if (left_dir < BSP_MOTOR_BACKWARD || left_dir > BSP_MOTOR_FORWARD ||
|
||||
right_dir < BSP_MOTOR_BACKWARD || right_dir > BSP_MOTOR_FORWARD) {
|
||||
return;
|
||||
}
|
||||
if (dir == BSP_MOTOR_STOP) {
|
||||
duty = 0;
|
||||
if (left_dir == BSP_MOTOR_STOP) {
|
||||
left_duty = 0;
|
||||
}
|
||||
if (right_dir == BSP_MOTOR_STOP) {
|
||||
right_duty = 0;
|
||||
}
|
||||
|
||||
/* 同向只改占空比:直接改 PWM,不走换向死区 */
|
||||
if (dir == s_motor.dir && s_motor.switch_ms == 0) {
|
||||
if (duty == s_motor.duty) {
|
||||
return;
|
||||
}
|
||||
s_motor.duty = duty;
|
||||
s_motor.pending = dir;
|
||||
s_motor.pending_duty = duty;
|
||||
bsp_motor_gpio(dir, duty);
|
||||
if (left_duty == 0 && right_duty == 0) {
|
||||
s_motor_switch_pending = 0;
|
||||
/* Keep the last energized directions so an immediate opposite command
|
||||
* still observes the H-bridge dead time. */
|
||||
bsp_drive_gpio(BSP_MOTOR_STOP, 0, BSP_MOTOR_STOP, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 停转:直接切断驱动,让电机自由滑行到停,不做反接刹车——反接刹车电流比
|
||||
* 正常驱动大(电池要同时顶住反向驱动电流和电机反电动势),实测会把供电轨
|
||||
* 拉低触发 LVD 复位。哪怕正在换向死区里,也直接取消死区改成停。 */
|
||||
if (dir == BSP_MOTOR_STOP) {
|
||||
s_motor.switch_ms = 0;
|
||||
s_motor.dir = BSP_MOTOR_STOP;
|
||||
s_motor.pending = BSP_MOTOR_STOP;
|
||||
s_motor.duty = 0;
|
||||
s_motor.pending_duty = 0;
|
||||
bsp_motor_gpio(BSP_MOTOR_STOP, 0);
|
||||
if (s_motor_switch_pending) {
|
||||
s_pending_left_direction = left_dir;
|
||||
s_pending_left_duty = left_duty;
|
||||
s_pending_right_direction = right_dir;
|
||||
s_pending_right_duty = right_duty;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 换向:先松开再输出,避免 H 桥直通 */
|
||||
if (s_motor.dir != BSP_MOTOR_STOP && dir != s_motor.dir) {
|
||||
bsp_motor_gpio(BSP_MOTOR_STOP, 0);
|
||||
s_motor.pending = dir;
|
||||
s_motor.pending_duty = duty;
|
||||
s_motor.switch_ms = BOARD_MOTOR_REVERSE_MS;
|
||||
s_motor.switch_t0 = timer_get_ms();
|
||||
s_motor.dir = BSP_MOTOR_STOP;
|
||||
s_motor.duty = 0;
|
||||
left_reversing = (uint8_t)(s_left_direction != BSP_MOTOR_STOP &&
|
||||
left_dir != BSP_MOTOR_STOP &&
|
||||
left_dir != s_left_direction);
|
||||
right_reversing = (uint8_t)(s_right_direction != BSP_MOTOR_STOP &&
|
||||
right_dir != BSP_MOTOR_STOP &&
|
||||
right_dir != s_right_direction);
|
||||
if (left_reversing || right_reversing) {
|
||||
bsp_drive_gpio(BSP_MOTOR_STOP, 0, BSP_MOTOR_STOP, 0);
|
||||
s_pending_left_direction = left_dir;
|
||||
s_pending_left_duty = left_duty;
|
||||
s_pending_right_direction = right_dir;
|
||||
s_pending_right_duty = right_duty;
|
||||
s_motor_switch_started_ms = timer_get_ms();
|
||||
s_motor_switch_pending = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
s_motor.switch_ms = 0;
|
||||
s_motor.dir = dir;
|
||||
s_motor.pending = dir;
|
||||
s_motor.duty = duty;
|
||||
s_motor.pending_duty = duty;
|
||||
bsp_motor_gpio(dir, duty);
|
||||
bsp_drive_gpio(left_dir, left_duty, right_dir, right_duty);
|
||||
s_left_direction = left_duty ? left_dir : BSP_MOTOR_STOP;
|
||||
s_right_direction = right_duty ? right_dir : BSP_MOTOR_STOP;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bsp_drive_stop(void)
|
||||
{
|
||||
bsp_drive_set(BSP_MOTOR_STOP, 0, BSP_MOTOR_STOP, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 推进换向死区计时,按真实毫秒计时;死区结束后切到目标方向/占空比
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_motor_switch_tick(void)
|
||||
{
|
||||
#if !BOARD_MOTOR_ENABLE
|
||||
return;
|
||||
#else
|
||||
if (s_motor.switch_ms == 0) {
|
||||
#if BOARD_MOTOR_ENABLE
|
||||
if (!s_motor_switch_pending ||
|
||||
(uint32_t)(timer_get_ms() - s_motor_switch_started_ms) <
|
||||
BOARD_MOTOR_REVERSE_MS) {
|
||||
return;
|
||||
}
|
||||
if ((timer_get_ms() - s_motor.switch_t0) < s_motor.switch_ms) {
|
||||
return;
|
||||
}
|
||||
s_motor.switch_ms = 0;
|
||||
s_motor.dir = s_motor.pending;
|
||||
s_motor.duty = s_motor.pending_duty;
|
||||
bsp_motor_gpio(s_motor.dir, s_motor.duty);
|
||||
|
||||
s_motor_switch_pending = 0;
|
||||
bsp_drive_gpio(s_pending_left_direction, s_pending_left_duty,
|
||||
s_pending_right_direction, s_pending_right_duty);
|
||||
s_left_direction = s_pending_left_duty ?
|
||||
s_pending_left_direction : BSP_MOTOR_STOP;
|
||||
s_right_direction = s_pending_right_duty ?
|
||||
s_pending_right_direction : BSP_MOTOR_STOP;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -450,10 +454,15 @@ uint8_t bsp_vpwr_is_online(void)
|
||||
if (mv >= BOARD_VPWR_ONLINE_MV) {
|
||||
return 1;
|
||||
}
|
||||
/* LDO5V_DET is valid immediately after a charge wake, before the ADC has
|
||||
* produced a stable sample. Unlike LVCMP it also drops promptly on pull. */
|
||||
if (get_ldo5v_online_hw()) {
|
||||
return 1;
|
||||
}
|
||||
if (mv <= BOARD_VPWR_OFF_MV) {
|
||||
return 0;
|
||||
}
|
||||
if (get_ldo5v_online_hw() || get_lvcmp_det()) {
|
||||
if (get_lvcmp_det()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -488,16 +497,7 @@ uint8_t bsp_motor_is_busy(void)
|
||||
#if !BOARD_MOTOR_ENABLE
|
||||
return 0;
|
||||
#else
|
||||
if (s_motor.switch_ms) {
|
||||
return 1;
|
||||
}
|
||||
if (s_motor.dir != BSP_MOTOR_STOP) {
|
||||
return 1;
|
||||
}
|
||||
if (s_motor.pending != BSP_MOTOR_STOP) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return (uint8_t)(s_motor_active || s_motor_switch_pending);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -507,13 +507,11 @@ uint8_t bsp_motor_is_busy(void)
|
||||
*/
|
||||
void bsp_hw_enter_sleep_io(void)
|
||||
{
|
||||
bsp_motor_set(BSP_MOTOR_STOP);
|
||||
bsp_drive_stop();
|
||||
#if BOARD_MOTOR_ENABLE
|
||||
s_motor.switch_ms = 0;
|
||||
s_motor.dir = BSP_MOTOR_STOP;
|
||||
s_motor.pending = BSP_MOTOR_STOP;
|
||||
s_motor.duty = 0;
|
||||
s_motor_active = 0;
|
||||
bsp_motor_pwm_clock_off();
|
||||
#endif
|
||||
bsp_led_all_off();
|
||||
|
||||
}
|
||||
|
||||
+11
-15
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
* @file bsp_hw.h
|
||||
* @brief CBC2 板级硬件:电机 / LED / 按键 / 充电 / 电量
|
||||
* @brief CBC1 板级硬件:单电机 / 震动 / LED / 按键 / 充电 / 电量
|
||||
* @author cyWu <1917507415@qq.com>
|
||||
* @date 2026.08.25
|
||||
* @version V1.6.0
|
||||
@@ -27,9 +27,9 @@ typedef enum {
|
||||
} BspHw_Ret_t;
|
||||
|
||||
typedef enum {
|
||||
BSP_MOTOR_STOP = 0, /**< 滑行停(INA/INB 都低) */
|
||||
BSP_MOTOR_IN, /**< 收绳(顺时针,见 BOARD_MOTOR_IN_INA_HIGH) */
|
||||
BSP_MOTOR_OUT /**< 放绳 */
|
||||
BSP_MOTOR_BACKWARD = -1,
|
||||
BSP_MOTOR_STOP = 0,
|
||||
BSP_MOTOR_FORWARD = 1
|
||||
} BspMotorDir_t;
|
||||
|
||||
/**
|
||||
@@ -70,24 +70,20 @@ void bsp_led_all_off(void);
|
||||
* @param dir 收绳 / 放绳 / 停转
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_motor_set(BspMotorDir_t dir);
|
||||
void bsp_drive_set(BspMotorDir_t left_dir, uint16_t left_duty,
|
||||
BspMotorDir_t right_dir, uint16_t right_duty);
|
||||
|
||||
/** 停止左右轮,四路 PWM 全部清零。 */
|
||||
void bsp_drive_stop(void);
|
||||
|
||||
/**
|
||||
* @brief 设置电机方向与 PWM 占空比
|
||||
* @param dir 收绳 / 放绳 / 停转
|
||||
* @param duty 占空比 0~10000(0%~100%);STOP 时忽略
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_motor_set_pwm(BspMotorDir_t dir, uint16_t duty);
|
||||
|
||||
/**
|
||||
* @brief 推进换向死区计时,按真实毫秒计时;死区结束后切到目标方向/占空比
|
||||
* @brief 兼容旧调用;猫猫捕猎罩每个动作更新左轮对应的两路 PWM
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_motor_switch_tick(void);
|
||||
|
||||
/**
|
||||
* @brief 电机是否还在转或处于换向死区
|
||||
* @brief 电机是否还在转
|
||||
* @return 1=忙碌,0=已停且 PWM 已关
|
||||
*/
|
||||
uint8_t bsp_motor_is_busy(void);
|
||||
|
||||
Reference in New Issue
Block a user