From 6e3290c70ea83e90abcfd26208bf31f79507db77 Mon Sep 17 00:00:00 2001 From: yelvlab Date: Tue, 28 Jul 2026 15:28:30 +0800 Subject: [PATCH] =?UTF-8?q?add(actuator):=E6=B7=BB=E5=8A=A0=E6=8E=A8?= =?UTF-8?q?=E6=9D=86=E7=9A=84=E9=A9=B1=E5=8A=A8=E5=87=BD=E6=95=B0=E5=B7=B2?= =?UTF-8?q?=E7=BB=8F=E9=AA=8C=E8=AF=81OK=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 +- Inc/actuator.h | 12 +++++ Inc/board_config.h | 71 ++++++++++++++++++++++-------- Src/actuator.c | 106 +++++++++++++++++++++++++++++++++++++++++++++ Src/command.c | 23 +++++----- Src/main.c | 17 +++++--- 6 files changed, 197 insertions(+), 35 deletions(-) create mode 100644 Inc/actuator.h create mode 100644 Src/actuator.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 21fcbf3..e9fcee3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,9 @@ set(TARGET_SRC Src/led.c Src/uart_ring_buffer.c Src/command.c - Src/i2c.c + # Src/i2c.c Src/board_config.c + Src/actuator.c ) # 设置输出目录 diff --git a/Inc/actuator.h b/Inc/actuator.h new file mode 100644 index 0000000..5e40922 --- /dev/null +++ b/Inc/actuator.h @@ -0,0 +1,12 @@ +#ifndef ACTUATOR_H +#define ACTUATOR_H + +#include "board_config.h" +#include "gd32e23x.h" +#include "stdbool.h" + +void actuator_init(void); + +void actuator_output(actuator_channel_t channel, uint16_t duty, actuator_direction_t direction); + +#endif // ACTUATOR_H \ No newline at end of file diff --git a/Inc/board_config.h b/Inc/board_config.h index 415a9cf..3246d4f 100644 --- a/Inc/board_config.h +++ b/Inc/board_config.h @@ -1,12 +1,15 @@ #ifndef BOARD_CONFIG_H #define BOARD_CONFIG_H -#ifndef DISABLE -#define DISABLE 0 +#include "gd32e23x.h" +#include "stdbool.h" + +#ifndef CFG_DISABLE +#define CFG_DISABLE 0 #endif -#ifndef ENABLE -#define ENABLE 1 +#ifndef CFG_ENABLE +#define CFG_ENABLE 1 #endif #define GD32E23XF4 0x10 @@ -19,25 +22,25 @@ /* >>>>>>>>>>>>>>>>>>>>[IIC TYPE DEFINE]<<<<<<<<<<<<<<<<<<<< */ -#define SOFTWARE_IIC DISABLE // DISABLE: Hardware IIC; ENABLE: Software IIC +#define SOFTWARE_IIC CFG_DISABLE // CFG_DISABLE: Hardware IIC; CFG_ENABLE: Software IIC /* >>>>>>>>>>>>>>>>>>>>[DEBUG MODE]<<<<<<<<<<<<<<<<<<<< */ -#define DEBUG_MODE DISABLE // DISABLE: Release Mode; ENABLE: Debug Mode +#define DEBUG_MODE CFG_DISABLE // CFG_DISABLE: Release Mode; CFG_ENABLE: Debug Mode /* >>>>>>>>>>>>>>>>>>>>[COMMAND DEBUG]<<<<<<<<<<<<<<<<<<<< */ -#define COM_DEBUG DISABLE // DISABLE: Command debug off; ENABLE: Command debug on +#define COM_DEBUG CFG_DISABLE // CFG_DISABLE: Command debug off; CFG_ENABLE: Command debug on /* >>>>>>>>>>>>>>>>>>>>[DEBUG ASSERTIONS DEFINE]<<<<<<<<<<<<<<<<<<<< */ -#define DEBUG_VERBOSE DISABLE // DISABLE: Verbose debug off; ENABLE: Verbose debug on +#define DEBUG_VERBOSE CFG_DISABLE // CFG_DISABLE: Verbose debug off; CFG_ENABLE: Verbose debug on /* >>>>>>>>>>>>>>>>>>>>[SEGGER RTT DETECTION]<<<<<<<<<<<<<<<<<<<< */ -#define SEGGER_RTT_DETECTION ENABLE // DISABLE: SEGGER RTT off; ENABLE: SEGGER RTT on +#define SEGGER_RTT_DETECTION CFG_ENABLE // CFG_DISABLE: SEGGER RTT off; CFG_ENABLE: SEGGER RTT on -#if SEGGER_RTT_DETECTION == ENABLE +#if SEGGER_RTT_DETECTION == CFG_ENABLE #include "SEGGER_RTT.h" #define RTT_printf(ch, ...) SEGGER_RTT_printf(ch, __VA_ARGS__) #define RTT_WriteString(ch, s) SEGGER_RTT_WriteString(ch, s) @@ -67,13 +70,13 @@ void usart1_irq_handler(void); /******************************************************************************/ -#define RCU_GPIO_I2C RCU_GPIOF -#define RCU_I2C RCU_I2C0 -#define I2C_SCL_PORT GPIOF -#define I2C_SCL_PIN GPIO_PIN_1 -#define I2C_SDA_PORT GPIOF -#define I2C_SDA_PIN GPIO_PIN_0 -#define I2C_GPIO_AF GPIO_AF_1 +// #define RCU_GPIO_I2C RCU_GPIOF +// #define RCU_I2C RCU_I2C0 +// #define I2C_SCL_PORT GPIOF +// #define I2C_SCL_PIN GPIO_PIN_1 +// #define I2C_SDA_PORT GPIOF +// #define I2C_SDA_PIN GPIO_PIN_0 +// #define I2C_GPIO_AF GPIO_AF_1 /******************************************************************************/ @@ -83,6 +86,40 @@ void usart1_irq_handler(void); /******************************************************************************/ +typedef enum { + ACTUATOR_CH1 = 0, + ACTUATOR_CH2 +} actuator_channel_t; + +typedef enum { + DIRECTION_PUSH = 0, // 推动方向 + DIRECTION_PULL // 拉动方向 +} actuator_direction_t; + +/******************************************************************************/ + +#define ACTUATOR_CH1_PWM_RCU RCU_GPIOA +#define ACTUATOR_CH1_PWM_PORT GPIOA +#define ACTUATOR_CH1_PWM_PIN GPIO_PIN_10 +#define ACTUATOR_CH1_GPIO_RCU RCU_GPIOF +#define ACTUATOR_CH1_GPIO_PORT GPIOF +#define ACTUATOR_CH1_GPIO_PIN GPIO_PIN_0 + +#define ACTUATOR_CH2_PWM_RCU RCU_GPIOA +#define ACTUATOR_CH2_PWM_PORT GPIOA +#define ACTUATOR_CH2_PWM_PIN GPIO_PIN_9 +#define ACTUATOR_CH2_GPIO_RCU RCU_GPIOF +#define ACTUATOR_CH2_GPIO_PORT GPIOF +#define ACTUATOR_CH2_GPIO_PIN GPIO_PIN_1 + +#define ACTUATOR_PWM_TIMER_RCU RCU_TIMER0 +#define ACTUATOR_PWM_TIMER TIMER0 + +#define ACTUATOR_CH1_PWM_TIMER_CH TIMER_CH_2 +#define ACTUATOR_CH2_PWM_TIMER_CH TIMER_CH_1 + +/******************************************************************************/ + #define UART_RCU (g_usart_config.rcu_usart) #define UART_PHY (g_usart_config.usart_periph) #define UART_IRQ (g_usart_config.irq_type) diff --git a/Src/actuator.c b/Src/actuator.c new file mode 100644 index 0000000..3621baa --- /dev/null +++ b/Src/actuator.c @@ -0,0 +1,106 @@ +#include "actuator.h" + +void actuator_init(void) { + // Initialize PWM pins for actuators + rcu_periph_clock_enable(ACTUATOR_CH1_PWM_RCU); + rcu_periph_clock_enable(ACTUATOR_CH2_PWM_RCU); + rcu_periph_clock_enable(ACTUATOR_CH1_GPIO_RCU); + rcu_periph_clock_enable(ACTUATOR_CH2_GPIO_RCU); + // rcu_periph_clock_enable(PWM3_RCU); + // rcu_periph_clock_enable(PWM4_RCU); + + rcu_periph_clock_enable(ACTUATOR_PWM_TIMER_RCU); // Enable clock for TIMER0 + + gpio_mode_set(ACTUATOR_CH1_PWM_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, ACTUATOR_CH1_PWM_PIN); + gpio_output_options_set(ACTUATOR_CH1_PWM_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, ACTUATOR_CH1_PWM_PIN); + gpio_af_set(ACTUATOR_CH1_PWM_PORT, GPIO_AF_2, ACTUATOR_CH1_PWM_PIN); + + gpio_mode_set(ACTUATOR_CH2_PWM_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, ACTUATOR_CH2_PWM_PIN); + gpio_output_options_set(ACTUATOR_CH2_PWM_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, ACTUATOR_CH2_PWM_PIN); + gpio_af_set(ACTUATOR_CH2_PWM_PORT, GPIO_AF_2, ACTUATOR_CH2_PWM_PIN); + + gpio_mode_set(ACTUATOR_CH1_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, ACTUATOR_CH1_GPIO_PIN); + gpio_output_options_set(ACTUATOR_CH1_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, ACTUATOR_CH1_GPIO_PIN); + gpio_bit_reset(ACTUATOR_CH1_GPIO_PORT, ACTUATOR_CH1_GPIO_PIN); // Set initial state to LOW + + gpio_mode_set(ACTUATOR_CH2_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, ACTUATOR_CH2_GPIO_PIN); + gpio_output_options_set(ACTUATOR_CH2_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, ACTUATOR_CH2_GPIO_PIN); + gpio_bit_reset(ACTUATOR_CH2_GPIO_PORT, ACTUATOR_CH2_GPIO_PIN); // Set initial state to LOW + + // Additional actuator initialization code can be added here + + // HSI = 72MHz , Freq Timer = 72MHz / (Prescaler + 1) / (Period + 1) + timer_deinit(ACTUATOR_PWM_TIMER); + timer_parameter_struct timer_initpara; + timer_initpara.prescaler = 2; // 72MHz / (2+1) = 24MHz + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 999; // 24MHz / (999 + 1) = 24kHz + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(ACTUATOR_PWM_TIMER, &timer_initpara); + + timer_oc_parameter_struct timer_ocinitpara; + timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocinitpara.outputstate = TIMER_CCX_ENABLE; + timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + + // CH0 + timer_channel_output_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, &timer_ocinitpara); + timer_channel_output_mode_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, TIMER_OC_SHADOW_ENABLE); + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, 0); + + // CH1 + timer_channel_output_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, &timer_ocinitpara); + timer_channel_output_mode_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, TIMER_OC_SHADOW_ENABLE); + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, 0); + + timer_auto_reload_shadow_enable(ACTUATOR_PWM_TIMER); + timer_primary_output_config(ACTUATOR_PWM_TIMER, ENABLE); + timer_enable(ACTUATOR_PWM_TIMER); +} + +void actuator_output(actuator_channel_t channel, uint16_t duty, actuator_direction_t direction) { + + if (duty > 999) duty = 999; // Limit duty cycle to max value + + if (direction != DIRECTION_PUSH && direction != DIRECTION_PULL) { + // Invalid direction, handle error if necessary + return; + } + + // Set PWM output for the specified actuator channel + // This is a placeholder; actual implementation will depend on the PWM configuration + // For example, setting the duty cycle to a specific value to activate the actuator + if (channel == ACTUATOR_CH1) { + if (direction == DIRECTION_PUSH) { + SEGGER_RTT_printf(0, "Actuator CH1 PUSH with duty %d\n", duty); + gpio_bit_reset(ACTUATOR_CH1_GPIO_PORT, ACTUATOR_CH1_GPIO_PIN); // Set direction LOW + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, duty); + } else if (direction == DIRECTION_PULL) { + SEGGER_RTT_printf(0, "Actuator CH1 PULL with duty %d\n", duty); + gpio_bit_set(ACTUATOR_CH1_GPIO_PORT, ACTUATOR_CH1_GPIO_PIN); // Set direction HIGH + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, (999 - duty)); + } + } else if (channel == ACTUATOR_CH2) { + if (direction == DIRECTION_PUSH) { + gpio_bit_reset(ACTUATOR_CH2_GPIO_PORT, ACTUATOR_CH2_GPIO_PIN); // Set direction LOW + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, duty); + } else if (direction == DIRECTION_PULL) { + gpio_bit_set(ACTUATOR_CH2_GPIO_PORT, ACTUATOR_CH2_GPIO_PIN); // Set direction HIGH + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, (999 - duty)); + } + } else { + // Invalid channel, handle error if necessary + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH1_PWM_TIMER_CH, 0); // Ensure CH1 is off + timer_channel_output_pulse_value_config(ACTUATOR_PWM_TIMER, ACTUATOR_CH2_PWM_TIMER_CH, 0); // Ensure CH2 is off + gpio_bit_reset(ACTUATOR_CH1_GPIO_PORT, ACTUATOR_CH1_GPIO_PIN); // Set CH1 direction LOW + gpio_bit_reset(ACTUATOR_CH2_GPIO_PORT, ACTUATOR_CH2_GPIO_PIN); // Set CH2 direction LOW + } +} \ No newline at end of file diff --git a/Src/command.c b/Src/command.c index ab423cf..bdfeb46 100644 --- a/Src/command.c +++ b/Src/command.c @@ -21,6 +21,7 @@ #include "gd32e23x_usart.h" #include "i2c.h" #include "core_cm23.h" +#include "actuator.h" /* ============================================================================ * 协议格式说明 @@ -67,15 +68,15 @@ /** @name 响应帧标识符 * @{ */ -#define RESP_HEADER 0xB5 /**< 响应帧包头标识 >**/ -#define RESP_TYPE_OK 0xF0 /**< 成功响应类型 >**/ -#define RESP_TYPE_CRC_ERR 0xF1 /**< CRC校验错误 >**/ -#define RESP_TYPE_HEADER_ERR 0xF2 /**< 包头错误 >**/ -#define RESP_TYPE_TYPE_ERR 0xF3 /**< 板类型错误 >**/ -#define RESP_TYPE_LEN_ERR 0xF4 /**< 长度错误 >**/ -#define RESP_TYPE_PARAM_ERR 0xFD /**< 参数错误 >**/ -#define RESP_TYPE_CMD_ERR 0xFE /**< 命令错误 >**/ -#define RESP_TYPE_ERR 0xFF /**< 通用错误 >**/ +#define RESP_HEADER 0xB5 /**< 响应帧包头标识 */ +#define RESP_TYPE_OK 0xF0 /**< 成功响应类型 */ +#define RESP_TYPE_CRC_ERR 0xF1 /**< CRC校验错误 */ +#define RESP_TYPE_HEADER_ERR 0xF2 /**< 包头错误 */ +#define RESP_TYPE_TYPE_ERR 0xF3 /**< 板类型错误 */ +#define RESP_TYPE_LEN_ERR 0xF4 /**< 长度错误 */ +#define RESP_TYPE_PARAM_ERR 0xFD /**< 参数错误 */ +#define RESP_TYPE_CMD_ERR 0xFE /**< 命令错误 */ +#define RESP_TYPE_ERR 0xFF /**< 通用错误 */ /** @} */ /* ============================================================================ @@ -101,7 +102,7 @@ void system_software_reset(void) } /* Debug output control */ -#if COM_DEBUG == ENABLE +#if COM_DEBUG == CFG_ENABLE #include #define COMMAND_DEBUG(fmt, ...) printf("[COMMAND] " fmt "\n", ##__VA_ARGS__) #else @@ -565,7 +566,7 @@ void command_process(void) { // 到帧尾,进行各项校验 bool verification_status = true; - #if DEBUG_VERBOSE == ENABLE + #if DEBUG_VERBOSE == CFG_ENABLE if (cmd_buf[0] != PROTOCOL_PACKAGE_HEADER) { send_response(RESP_TYPE_HEADER_ERR, s_report_status_err, sizeof(s_report_status_err)); verification_status = false; diff --git a/Src/main.c b/Src/main.c index 9bc9432..cd94610 100644 --- a/Src/main.c +++ b/Src/main.c @@ -41,6 +41,7 @@ OF SUCH DAMAGE. #include #include "i2c.h" #include "board_config.h" +#include "actuator.h" /*! \brief main function @@ -60,20 +61,24 @@ int main(void) uart_ring_buffer_init(); uart_init(); - i2c_config(); + actuator_init(); -#if DEBUG_MODE == ENABLE + // actuator_output(ACTUATOR_CH1, 800, DIRECTION_PULL); // Set actuator channel 1 to high, channel 2 to low + + // i2c_config(); + +#if DEBUG_MODE == CFG_ENABLE printf("Hello World!\r\n"); #endif -#if SEGGER_RTT_DETECTION == ENABLE +#if SEGGER_RTT_DETECTION == CFG_ENABLE RTT_printf(0, "Hello World!\r\n"); #endif -#if DEBUG_VERBOSE == ENABLE - i2c_scan(); +#if DEBUG_VERBOSE == CFG_ENABLE + // i2c_scan(); - i2c_bus_reset(); + // i2c_bus_reset(); #endif /* ========== Command Testing ========== */