/****************************************************************************** * @file bsp_hw.c * @brief CBR3 板级 GPIO / MCPWM:LED、按键、风扇 * @author cyWu <1917507415@qq.com> * @date 2026.08.29 * @version V1.0.0,首次发布(移植门夹:删电机/充电/电量,改单 LED + 风扇 PWM) * * @note CT1642 在 PG0/PG1、AHT20 在 PC4/PC5,各自独立驱动, * bsp_hw 只管 LED/KEY/FAN,不碰这两组脚。 ******************************************************************************/ #include "system/includes.h" #include "asm/gpio.h" #include "asm/mcpwm.h" #include "bsp_hw.h" #define LOG_TAG_CONST APP #define LOG_TAG "[BSP_HW]" #define LOG_ERROR_ENABLE #define LOG_INFO_ENABLE #include "debug.h" static uint8_t s_initialized; /** 风扇 PWM 状态 */ typedef struct { uint8_t pwm_clk_on; /**< 1=MCPWM 时钟已打开 */ uint16_t duty; /**< 当前占空比 */ } BspFanCtx_t; static BspFanCtx_t s_fan; #if (BOARD_LED_ENABLE || BOARD_KEY_ENABLE) /** * @brief 配置 GPIO 为推挽输出 * @param pin GPIO 编号 * @param value 输出初值 * @return 无 */ static void bsp_pin_output(u32 pin, int value) { gpio_set_pull_up(pin, 0); gpio_set_pull_down(pin, 0); gpio_set_die(pin, 1); gpio_direction_output(pin, value); } #endif #if BOARD_KEY_ENABLE /** * @brief 配置 GPIO 为数字输入(可内部上拉) * @param pin GPIO 编号 * @param pull_up 1=内部上拉,0=不上拉 * @return 无 */ static void bsp_pin_input(u32 pin, int pull_up) { gpio_direction_output(pin, 1); gpio_set_direction(pin, 1); gpio_set_pull_down(pin, 0); gpio_set_pull_up(pin, pull_up ? 1 : 0); gpio_set_die(pin, 1); } #endif #if BOARD_FAN_ENABLE /** * @brief 初始化风扇 MCPWM ch0,初始占空比 0(关) * @return 无 */ static void bsp_fan_pwm_init(void) { struct pwm_platform_data pwm; gpio_set_pull_up(BOARD_FAN_PIN, 0); gpio_set_pull_down(BOARD_FAN_PIN, 0); gpio_set_die(BOARD_FAN_PIN, 1); pwm.pwm_aligned_mode = pwm_edge_aligned; pwm.frequency = BOARD_FAN_PWM_HZ; pwm.duty = 0; pwm.l_pin = (u8) - 1; pwm.complementary_en = 0; pwm.pwm_ch_num = pwm_ch0; pwm.h_pin = BOARD_FAN_PIN; mcpwm_init(&pwm); mcpwm_set_duty(pwm_ch0, 0); s_fan.pwm_clk_on = 1; s_fan.duty = 0; log_info("fan pwm %uHz duty=0\n", (unsigned)BOARD_FAN_PWM_HZ); } /** * @brief 打开 MCPWM 并绑回 PC3 * @return 无 */ static void bsp_fan_pwm_clock_on(void) { if (s_fan.pwm_clk_on) { return; } mcpwm_open(pwm_ch0); gpio_och_sel_output_signal(BOARD_FAN_PIN, OUTPUT_CH_SIGNAL_MC_PWM0_H); gpio_set_direction(BOARD_FAN_PIN, 0); s_fan.pwm_clk_on = 1; } /** * @brief 关闭 MCPWM 时钟并拉低(待机/关机必关) * @return 无 */ static void bsp_fan_pwm_clock_off(void) { mcpwm_set_duty(pwm_ch0, 0); if (s_fan.pwm_clk_on) { mcpwm_close(pwm_ch0); gpio_och_disable_output_signal(BOARD_FAN_PIN, OUTPUT_CH_SIGNAL_MC_PWM0_H); JL_MCPWM->MCPWM_CON0 = 0; s_fan.pwm_clk_on = 0; } gpio_direction_output(BOARD_FAN_PIN, 0); /* 关 = 拉低(风扇高导通) */ } #endif /** * @brief 初始化 GPIO / 风扇 MCPWM * @return BSP_HW_OK=成功 */ BspHw_Ret_t bsp_hw_init(void) { if (s_initialized) { return BSP_HW_OK; } #if BOARD_LED_ENABLE bsp_pin_output(BOARD_LED_PIN, !BOARD_LED_ON_LEVEL); /* 初始灭 */ #endif #if BOARD_KEY_ENABLE bsp_pin_input(BOARD_KEY_PIN, 1); #endif #if BOARD_FAN_ENABLE bsp_fan_pwm_init(); bsp_fan_pwm_clock_off(); /* 初始关,待机不耗电 */ #endif s_initialized = 1; log_info("hw init led=%d key=%d fan=%d\n", BOARD_LED_ENABLE, BOARD_KEY_ENABLE, BOARD_FAN_ENABLE); return BSP_HW_OK; } /** * @brief 查询板级硬件是否已初始化 * @return BSP_HW_OK=已初始化,BSP_HW_ERR_NOT_INIT=未初始化 */ BspHw_Ret_t bsp_hw_get_status(void) { return s_initialized ? BSP_HW_OK : BSP_HW_ERR_NOT_INIT; } /** * @brief 状态 LED 开关(PC2,低电平亮) * @param on 1=亮,0=灭 * @return 无 */ void bsp_led_set(uint8_t on) { #if BOARD_LED_ENABLE gpio_direction_output(BOARD_LED_PIN, on ? BOARD_LED_ON_LEVEL : !BOARD_LED_ON_LEVEL); #else (void)on; #endif } /** * @brief 风扇 PWM 占空比(PC3,高有效,20kHz) * @param duty 0~10000(0%=关 MCPWM 并拉低;>0 打开时钟输出) * @return 无 */ void bsp_fan_set_duty(uint16_t duty) { #if BOARD_FAN_ENABLE if (duty > 10000) { duty = 10000; } if (duty == 0) { bsp_fan_pwm_clock_off(); s_fan.duty = 0; return; } bsp_fan_pwm_clock_on(); mcpwm_set_duty(pwm_ch0, duty); s_fan.duty = duty; #else (void)duty; #endif } /** * @brief 读取按键 * @return 1=按下,0=未按下 */ uint8_t bsp_key_is_pressed(void) { #if BOARD_KEY_ENABLE return (uint8_t)(gpio_read(BOARD_KEY_PIN) == BOARD_KEY_ACTIVE_LEVEL); #else return 0; #endif } /** * @brief 进深睡前:风扇 PWM 关掉并拉低,灯全灭 * @return 无 */ void bsp_hw_enter_sleep_io(void) { bsp_fan_set_duty(0); bsp_led_set(0); }