Compare commits

..

5 Commits

Author SHA1 Message Date
d2519f4cf7 bootloader 2025-09-19 17:56:03 +08:00
5ac3d5afa7 添加M999命令发送版本号 2025-09-16 16:26:14 +08:00
14fa262d35 注释异常命令回包 2025-09-16 14:58:33 +08:00
70b8e3a602 add data err type 2025-08-25 20:35:54 +08:00
f5cfeb53d2 test 2025-08-25 17:33:32 +08:00
12 changed files with 276 additions and 184 deletions

View File

@@ -29,7 +29,7 @@ set(TARGET_SRC
Src/led.c Src/led.c
Src/uart_ring_buffer.c Src/uart_ring_buffer.c
Src/command.c Src/command.c
Src/i2c.c Src/board_config.c
Src/ultrasonic_analog.c Src/ultrasonic_analog.c
) )

View File

@@ -1,6 +1,10 @@
#ifndef BOARD_CONFIG_H #ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H #define BOARD_CONFIG_H
#define GD32E23XF4 0x10
#define GD32E23XF6 0x20
#define GD32E23XF8 0x40
/* >>>>>>>>>>>>>>>>>>>>[RS485 PHY DEFINE]<<<<<<<<<<<<<<<<<<<< */ /* >>>>>>>>>>>>>>>>>>>>[RS485 PHY DEFINE]<<<<<<<<<<<<<<<<<<<< */
// #define RS485_MAX13487 // RS485 PHY : MAX13487 (AutoDir) // #define RS485_MAX13487 // RS485 PHY : MAX13487 (AutoDir)
@@ -18,6 +22,31 @@
/******************************************************************************/ /******************************************************************************/
/* Dynamic USART Configuration Structure */
typedef struct {
uint32_t rcu_usart;
uint32_t usart_periph;
IRQn_Type irq_type;
void (*irq_handler)(void); // 函数指针:指向中断处理函数
} usart_config_t;
extern usart_config_t g_usart_config;
extern uint8_t g_mcu_flash_size;
/* USART中断处理函数声明 */
void usart0_irq_handler(void);
void usart1_irq_handler(void);
/******************************************************************************/
#define MCU_CODE 23u
#define FW_VERSION_MAJOR 0
#define FW_VERSION_MINOR 0
#define FW_VERSION_PATCH 3
/******************************************************************************/
#define RCU_GPIO_I2C RCU_GPIOF #define RCU_GPIO_I2C RCU_GPIOF
#define RCU_I2C RCU_I2C0 #define RCU_I2C RCU_I2C0
#define I2C_SCL_PORT GPIOF #define I2C_SCL_PORT GPIOF
@@ -36,15 +65,15 @@
/******************************************************************************/ /******************************************************************************/
#define RS485_RCU RCU_USART0 #define RS485_RCU (g_usart_config.rcu_usart)
#define RS485_PHY (g_usart_config.usart_periph)
#define RS485_IRQ (g_usart_config.irq_type)
#define RS485_GPIO_RCU RCU_GPIOA #define RS485_GPIO_RCU RCU_GPIOA
#define RS485_GPIO_PORT GPIOA #define RS485_GPIO_PORT GPIOA
#define RS485_EN_PIN GPIO_PIN_1
#define RS485_TX_PIN GPIO_PIN_2 #define RS485_TX_PIN GPIO_PIN_2
#define RS485_RX_PIN GPIO_PIN_3 #define RS485_RX_PIN GPIO_PIN_3
#define RS485_PHY USART0
#define RS485_BAUDRATE 115200U #define RS485_BAUDRATE 115200U
#define RS485_EN_PIN GPIO_PIN_1
#define RS485_IRQ USART0_IRQn
/******************************************************************************/ /******************************************************************************/
@@ -58,11 +87,6 @@
/******************************************************************************/ /******************************************************************************/
#define US_TX_DELAY_RCU RCU_TIMER15
#define US_TX_DELAY_TIMER TIMER15
/******************************************************************************/
#define US_RX_GPIO_RCU RCU_GPIOB #define US_RX_GPIO_RCU RCU_GPIOB
#define US_RX_EXTI_RCU RCU_CFGCMP #define US_RX_EXTI_RCU RCU_CFGCMP
#define US_RX_GPIO_PORT GPIOA #define US_RX_GPIO_PORT GPIOA
@@ -76,12 +100,11 @@
#define US_ECHO_RCU RCU_TIMER16 #define US_ECHO_RCU RCU_TIMER16
#define US_ECHO_TIMER TIMER16 #define US_ECHO_TIMER TIMER16
#define US_ECHO_CH TIMER_CH_0 #define US_ECHO_CH TIMER_CH_0
#define US_ECHO_TIMER_IRQ TIMER16_IRQn
/******************************************************************************/ /******************************************************************************/
#define TIME_CORRECTION_US 230U void mcu_detect_and_config(void);
#define CAPTURE_VALUE_MAX 550U uint8_t get_flash_size(void);
/******************************************************************************/
#endif //BOARD_CONFIG_H #endif //BOARD_CONFIG_H

View File

@@ -81,6 +81,8 @@ void command_process(void);
*/ */
void handle_command(const uint8_t *cmd, uint8_t len); void handle_command(const uint8_t *cmd, uint8_t len);
void ultrasonic_distance_raw_value_report(void);
/** @} */ // end of Command group /** @} */ // end of Command group
#endif // COMMAND_H #endif // COMMAND_H

View File

@@ -9,23 +9,13 @@ extern volatile bool g_ultrasonic_measure_done;
/**************************************************************************************************/ /**************************************************************************************************/
#define ULTRASONIC_TX_CYCLES 5U /* 发送5个PWM周期驱动换能器 */ #define ULTRASONIC_TX_CYCLES 5U /* 发送5个PWM周期驱动换能器 */
#define ULTRASONIC_TX_TIME 498U // ms #define ULTRASONIC_TX_RINGDOWN_RELOAD 240U // 240us
#define ULTRASONIC_MAX_TOF_RELOAD 1000U //us #define ULTRASONIC_MAX_TOF_RELOAD 2000U // 1000us
/**************************************************************************************************/ /**************************************************************************************************/
void ultrasonic_tx_init(void);
void ultrasonic_pwm_out_cycles(void); void ultrasonic_pwm_out_cycles(void);
// void ultrasonic_transmit_delay(const uint16_t micro_second);
// void ultrasonic_rece_exti_config(void);
void ultrasonic_echo_timer_config(void);
void ultrasonic_config(void); void ultrasonic_config(void);
// uint16_t ultrasonic_calc_distance(void); #endif // ULTRASONIC_ANALOG_H
#endif // UART_H

52
Src/board_config.c Normal file
View File

@@ -0,0 +1,52 @@
#include "gd32e23x.h"
#include "board_config.h"
#include "systick.h"
/******************************************************************************/
#define FLASH_SIZE_ADDR (*(const uint8_t *)0x1FFFF7E0) // Flash base address
/******************************************************************************/
/* 前向声明中断处理函数 */
void usart0_irq_handler(void);
void usart1_irq_handler(void);
usart_config_t g_usart_config = {
.rcu_usart = RCU_USART1,
.usart_periph = USART1,
.irq_type = USART1_IRQn,
.irq_handler = usart1_irq_handler // 初始化函数指针
};
uint8_t g_mcu_flash_size = 0;
void mcu_detect_and_config(void) {
g_mcu_flash_size = FLASH_SIZE_ADDR;
switch (g_mcu_flash_size) {
case GD32E23XF4:
g_usart_config.rcu_usart = RCU_USART0;
g_usart_config.usart_periph = USART0;
g_usart_config.irq_type = USART0_IRQn;
g_usart_config.irq_handler = usart0_irq_handler; // 指向USART0处理函数
break;
case GD32E23XF6:
g_usart_config.rcu_usart = RCU_USART1;
g_usart_config.usart_periph = USART1;
g_usart_config.irq_type = USART1_IRQn;
g_usart_config.irq_handler = usart1_irq_handler; // 指向USART1处理函数
break;
default: // Default to GD32E23XF8
g_usart_config.rcu_usart = RCU_USART1;
g_usart_config.usart_periph = USART1;
g_usart_config.irq_type = USART1_IRQn;
g_usart_config.irq_handler = usart1_irq_handler; // 指向USART1处理函数
break;
}
}
uint8_t get_flash_size(void) {
return g_mcu_flash_size;
}

View File

@@ -18,6 +18,7 @@
#include "board_config.h" #include "board_config.h"
#include "gd32e23x_usart.h" #include "gd32e23x_usart.h"
#include "ultrasonic_analog.h" #include "ultrasonic_analog.h"
#include "systick.h"
/* ============================================================================ /* ============================================================================
* 协议格式说明 * 协议格式说明
@@ -29,7 +30,7 @@
* @details * @details
* Host -> Device 命令帧格式: * Host -> Device 命令帧格式:
* [0] HEADER = 0xD5 // 包头标识 * [0] HEADER = 0xD5 // 包头标识
* [1] BOARD_TYPE = 0x03 // 板卡类型标识 * [1] BOARD_TYPE = 0x04 // 板卡类型标识
* [2] LEN = 数据区字节数 // 有效载荷长度 * [2] LEN = 数据区字节数 // 有效载荷长度
* [3..(3+LEN-1)] 数据 // 命令数据,如 "M1", "M2S123" * [3..(3+LEN-1)] 数据 // 命令数据,如 "M1", "M2S123"
* [last] CRC = 校验码 // 从索引1到(last-1)的累加和低8位 * [last] CRC = 校验码 // 从索引1到(last-1)的累加和低8位
@@ -71,6 +72,7 @@
#define RESP_TYPE_HEADER_ERR 0xF2 /**< 包头错误 */ #define RESP_TYPE_HEADER_ERR 0xF2 /**< 包头错误 */
#define RESP_TYPE_TYPE_ERR 0xF3 /**< 类型错误 */ #define RESP_TYPE_TYPE_ERR 0xF3 /**< 类型错误 */
#define RESP_TYPE_LEN_ERR 0xF4 /**< 长度错误 */ #define RESP_TYPE_LEN_ERR 0xF4 /**< 长度错误 */
#define RESP_TYPE_DATA_ERR 0xF5 /**< 数据错误 */
/** @} */ /** @} */
/* ============================================================================ /* ============================================================================
@@ -154,13 +156,6 @@ static void send_response(uint8_t type, const uint8_t *payload, uint8_t len)
// 等待发送完成 // 等待发送完成
while (usart_flag_get(RS485_PHY, USART_FLAG_TC) == RESET) {} while (usart_flag_get(RS485_PHY, USART_FLAG_TC) == RESET) {}
// // 使用printf发送通过重定向到串口
// for (uint8_t i = 0; i < buf_len; i++) {
// printf("%c", buf[i]);
// }
// // 刷新缓冲区
// fflush(stdout);
} }
/** /**
@@ -231,7 +226,7 @@ void handle_command(const uint8_t *frame, uint8_t len) {
// 命令必须以 'M' 开头 // 命令必须以 'M' 开头
if (cmd[0] != 'M'){ if (cmd[0] != 'M'){
send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err));
return; return;
} }
@@ -243,7 +238,7 @@ void handle_command(const uint8_t *frame, uint8_t len) {
if (used_base_cmd == 0) if (used_base_cmd == 0)
{ {
// 'M' 后没有数字,格式错误 // 'M' 后没有数字,格式错误
send_response(RESP_TYPE_LEN_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_LEN_ERR, s_report_status_err, sizeof(s_report_status_err));
return; return;
} }
@@ -253,20 +248,25 @@ void handle_command(const uint8_t *frame, uint8_t len) {
if (cmd_index == cmd_len) { if (cmd_index == cmd_len) {
// 仅基础命令,如 M1, M2, M3 // 仅基础命令,如 M1, M2, M3
switch (base_cmd) { switch (base_cmd) {
case 1u: // M1: enable sensor report case 1u: // M1: send ultrasonic driver single and respon raw data
// g_ultrasonic_measure_done = false; // 启动超声波PWM发送
ultrasonic_pwm_out_cycles(); ultrasonic_pwm_out_cycles();
gpio_bit_toggle(GPIOA, GPIO_PIN_0); uint16_t timeout_count = 0;
const uint16_t max_timeout = 250;
while (g_ultrasonic_measure_done)
{ while (!g_ultrasonic_measure_done && timeout_count < max_timeout) {
g_ultrasonic_measure_done = false; delay_10us(1); // 延时 10us
send_response(RESP_TYPE_OK, s_report_status_err, sizeof(s_report_status_err)); timeout_count++;
return;
} }
// 根据等待结果发送不同的响应
if (g_ultrasonic_measure_done) {
ultrasonic_distance_raw_value_report();
} else {
static const uint8_t timeout_error_data[] = {0xFF, 0xFF };
send_response(RESP_TYPE_DATA_ERR, timeout_error_data, sizeof(timeout_error_data));
}
return;
case 2u: // M2: disable sensor report case 2u: // M2: disable sensor report
send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok)); send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
@@ -284,6 +284,13 @@ void handle_command(const uint8_t *frame, uint8_t len) {
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok)); // send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
// return; // return;
case 999u: //M999: 输出固件版本号vMCU_CODE.FW_VERSION_MAJOR.FW_VERSION_MINOR.FW_VERSION_PATCH
char version_str[16];
int n = snprintf(version_str, sizeof(version_str), "v%u.%u.%u.%u", MCU_CODE, FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_PATCH);
send_response(RESP_TYPE_OK, (uint8_t *)version_str, (uint8_t)n);
// send_response(RESP_TYPE_OK, (uint8_t *)"v23.0.0.3", 9);
return;
default: default:
// 其它无参数命令在此扩展示例M100处理逻辑该如何待定 // 其它无参数命令在此扩展示例M100处理逻辑该如何待定
// send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok)); // send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
@@ -291,7 +298,7 @@ void handle_command(const uint8_t *frame, uint8_t len) {
break; break;
} }
// 未在处理列表的无参数基础命令,回复错误 // 未在处理列表的无参数基础命令,回复错误
send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err));
return; return;
} }
@@ -302,7 +309,7 @@ void handle_command(const uint8_t *frame, uint8_t len) {
const uint8_t used_param_cmd = parse_uint_dec(&cmd[cmd_index], (uint8_t)(cmd_len - cmd_index), &param_value); const uint8_t used_param_cmd = parse_uint_dec(&cmd[cmd_index], (uint8_t)(cmd_len - cmd_index), &param_value);
if (used_param_cmd == 0) { if (used_param_cmd == 0) {
// 'S' 后没有数字,格式错误 // 'S' 后没有数字,格式错误
send_response(RESP_TYPE_LEN_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_LEN_ERR, s_report_status_err, sizeof(s_report_status_err));
return; return;
} }
@@ -310,13 +317,12 @@ void handle_command(const uint8_t *frame, uint8_t len) {
{ {
// case 100u: // case 100u:
// // set_pwm(param_value); // // set_pwm(param_value);
// printf("Set PWM to %u\n", param_value);
// return; // return;
default: default:
break; break;
} }
send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err));
} }
} }
@@ -396,14 +402,14 @@ void command_process(void) {
#endif #endif
if (verification_status && cmd_buf[1] != PROTOCOL_BOARD_TYPE) { if (verification_status && cmd_buf[1] != PROTOCOL_BOARD_TYPE) {
send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_TYPE_ERR, s_report_status_err, sizeof(s_report_status_err));
verification_status = false; verification_status = false;
} }
if (verification_status) { if (verification_status) {
uint8_t crc_calc = command_sum_crc_calc(cmd_buf, expected_cmd_len); uint8_t crc_calc = command_sum_crc_calc(cmd_buf, expected_cmd_len);
uint8_t crc_recv = cmd_buf[expected_cmd_len - 1]; uint8_t crc_recv = cmd_buf[expected_cmd_len - 1];
if (crc_calc != crc_recv) { if (crc_calc != crc_recv) {
send_response(RESP_TYPE_CRC_ERR, s_report_status_err, sizeof(s_report_status_err)); // send_response(RESP_TYPE_CRC_ERR, s_report_status_err, sizeof(s_report_status_err));
verification_status = false; verification_status = false;
} }
} }
@@ -418,3 +424,39 @@ void command_process(void) {
} }
} }
} }
/**
* @brief 超声波测距原始值上报函数
* @details 读取超声波测距的定时器计数值,计算距离并按协议格式发送响应包
* 距离计算公式:距离(0.1mm) = 定时器计数值(us) * 17
* 响应数据格式4字节32位无符号整数单位为0.1mm
* @note 定时器配置为1us计数最大计时2000us对应距离340mm
* @ingroup Command
*/
void ultrasonic_distance_raw_value_report(void) {
uint8_t raw_result[2];
uint16_t raw_distance = 0;
// 读取定时器计数值(微秒)
uint16_t timer_count_us = timer_counter_read(US_ECHO_TIMER);
if (timer_count_us < ULTRASONIC_TX_RINGDOWN_RELOAD) {
// 超出最大计时范围,返回错误
send_response(RESP_TYPE_DATA_ERR, s_report_status_err, sizeof(s_report_status_err));
return;
}
// 计算距离:定时器计数值 * 17 = 距离(0.1mm)
// 声速340m/s往返距离时间单位us
// 距离(mm) = (timer_count_us * 340) / (2 * 1000) = timer_count_us * 0.17
// 距离(0.1mm) = timer_count_us * 1.7 ≈ timer_count_us * 17 / 10
raw_distance = (uint16_t)timer_count_us * 17;
// 将16位距离值分解为2个字节大端序
raw_result[0] = (uint8_t)(raw_distance >> 8);
raw_result[1] = (uint8_t)(raw_distance & 0xFF);
// 发送响应包
send_response(RESP_TYPE_OK, raw_result, sizeof(raw_result));
return;
}

View File

@@ -38,8 +38,7 @@ OF SUCH DAMAGE.
#include "uart_ring_buffer.h" #include "uart_ring_buffer.h"
#include "led.h" #include "led.h"
#include "ultrasonic_analog.h" #include "ultrasonic_analog.h"
#include "board_config.h"
extern uint16_t g_capture_value;
/*! /*!
\brief this function handles NMI exception \brief this function handles NMI exception
@@ -104,39 +103,21 @@ void SysTick_Handler(void) {
delay_decrement(); delay_decrement();
} }
// /** void TIMER16_IRQHandler(void)
// * @brief This function handles TIMER15 interrupt request. {
// * @param[in] none // CH0比较中断 (ULTRASONIC_TX_RINGDOWN_RELOAD)
// * @param[out] none if(timer_interrupt_flag_get(TIMER16, TIMER_INT_FLAG_CH0) != RESET) {
// * @retval None timer_interrupt_flag_clear(TIMER16, TIMER_INT_FLAG_CH0);
// */ exti_interrupt_enable(US_RX_GPIO_EXTI);
// void TIMER15_IRQHandler(void) {
// if (timer_interrupt_flag_get(US_TX_DELAY_TIMER, TIMER_INT_FLAG_UP) == SET)
// {
// timer_interrupt_flag_clear(US_TX_DELAY_TIMER, TIMER_INT_FLAG_UP);
// exti_interrupt_enable(US_RX_GPIO_EXTI); // turn on hardware external input interrupt
// timer_counter_value_config(US_ECHO_TIMER, 0);
// timer_enable(US_ECHO_TIMER); // turn on timer to calculate the first ultrasonic echo time
// timer_disable(US_TX_DELAY_TIMER);
// }
// }
void TIMER15_IRQHandler(void) {
if (timer_interrupt_flag_get(TIMER15, TIMER_INT_FLAG_CH1)) {
timer_interrupt_flag_clear(TIMER15, TIMER_INT_FLAG_CH1);
// g_ultrasonic_measure_done = true; // TODO 测距命令发送回报标识位,最终不应在这里
gpio_bit_set(GPIOA, GPIO_PIN_0); // TODO waiting for delete
}
if (timer_interrupt_flag_get(TIMER15, TIMER_INT_FLAG_UP)) {
timer_interrupt_flag_clear(TIMER15, TIMER_INT_FLAG_UP);
timer_disable(TIMER15);
} }
// UP更新中断 (ULTRASONIC_MAX_TOF_RELOAD)
if(timer_interrupt_flag_get(TIMER16, TIMER_INT_FLAG_UP) != RESET) {
timer_interrupt_flag_clear(TIMER16, TIMER_INT_FLAG_UP);
timer_disable(US_ECHO_TIMER);
}
} }
/** /**
* @brief This function handles external lines 0 to 1 interrupt request * @brief This function handles external lines 0 to 1 interrupt request
* @param[in] none * @param[in] none
@@ -147,14 +128,12 @@ void EXTI0_1_IRQHandler(void) {
if (exti_interrupt_flag_get(US_RX_GPIO_EXTI) == SET) if (exti_interrupt_flag_get(US_RX_GPIO_EXTI) == SET)
{ {
exti_interrupt_flag_clear(US_RX_GPIO_EXTI); exti_interrupt_flag_clear(US_RX_GPIO_EXTI);
g_capture_value = timer_channel_capture_value_register_read(US_ECHO_TIMER, US_ECHO_CH);
timer_disable(US_ECHO_TIMER); timer_disable(US_ECHO_TIMER);
g_ultrasonic_measure_done = true; // 超声转换完成,置位flag后有命令处理部分回包
exti_interrupt_disable(US_RX_GPIO_EXTI); exti_interrupt_disable(US_RX_GPIO_EXTI);
} }
} }
/* PWM周期计数器 - 使用ULTRASONIC_TX_CYCLES宏 */ /* PWM周期计数器 - 使用ULTRASONIC_TX_CYCLES宏 */
volatile uint8_t pwm_cycle_count = 0; volatile uint8_t pwm_cycle_count = 0;
@@ -167,15 +146,21 @@ void TIMER13_IRQHandler(void)
if(pwm_cycle_count >= (ULTRASONIC_TX_CYCLES)) { if(pwm_cycle_count >= (ULTRASONIC_TX_CYCLES)) {
timer_disable(TIMER13); timer_disable(TIMER13);
pwm_cycle_count = 0; pwm_cycle_count = 0;
g_ultrasonic_measure_done = true; // TODO 测距命令发送回报标识位,最终不应在这里
} }
} }
} }
void USART0_IRQHandler(void) { void USART0_IRQHandler(void) {
if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { // 检查当前配置是否使用USART0并且函数指针不为空
uint8_t data = usart_data_receive(USART0); if(g_usart_config.usart_periph == USART0 && g_usart_config.irq_handler != 0) {
(void)uart_ring_buffer_put(data); // 缓冲满时丢弃,返回值可用于统计 g_usart_config.irq_handler(); // 通过函数指针调用对应的处理函数
}
}
void USART1_IRQHandler(void) {
// 检查当前配置是否使用USART1并且函数指针不为空
if(g_usart_config.usart_periph == USART1 && g_usart_config.irq_handler != 0) {
g_usart_config.irq_handler(); // 通过函数指针调用对应的处理函数
} }
} }

View File

@@ -38,11 +38,10 @@ OF SUCH DAMAGE.
#include "led.h" #include "led.h"
#include "command.h" #include "command.h"
#include <stdio.h> #include <stdio.h>
#include "i2c.h"
#include "board_config.h" #include "board_config.h"
#include "ultrasonic_analog.h" #include "ultrasonic_analog.h"
volatile uint16_t g_capture_value; // #define FLASH_SIZE_ADDR (*(const uint16_t *)0x1FFFF7E0)
/*! /*!
\brief main function \brief main function
@@ -52,14 +51,21 @@ volatile uint16_t g_capture_value;
*/ */
int main(void) int main(void)
{ {
nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x2000); // 设置向量表偏移地址为0x2000
led_init();
mcu_detect_and_config();
setbuf(stdout, NULL); setbuf(stdout, NULL);
systick_config(); systick_config();
rs485_init(); rs485_init();
led_init();
ultrasonic_config(); ultrasonic_config();
ultrasonic_pwm_out_cycles();
// printf("Flash size: %d Kbytes\n", get_flash_size());
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
char hello_world[] = {"Hello World!\r\n"}; char hello_world[] = {"Hello World!\r\n"};
@@ -75,14 +81,7 @@ int main(void)
while(1){ while(1){
// ultrasonic_pwm_out_cycles();
// delay_ms(10);
command_process(); command_process();
delay_ms(10); delay_ms(10);
// uint16_t ultrasonic_value = ultrasonic_calc_distance();
// printf("ultrasonic value: %d", ultrasonic_value);
// delay_ms(10);
} }
} }

View File

@@ -16,6 +16,7 @@
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include "gd32e23x_usart.h" #include "gd32e23x_usart.h"
#include "board_config.h"
#undef errno #undef errno
extern int errno; extern int errno;
@@ -164,7 +165,7 @@ int _execve(char *name, char **argv, char **env)
// USART0 printf重定向实现 // USART0 printf重定向实现
int __io_putchar(int ch) { int __io_putchar(int ch) {
// 等待发送缓冲区空 // 等待发送缓冲区空
while (usart_flag_get(USART0, USART_FLAG_TBE) == RESET) {} while (usart_flag_get(RS485_PHY, USART_FLAG_TBE) == RESET) {}
usart_data_transmit(USART0, (uint8_t)ch); usart_data_transmit(RS485_PHY, (uint8_t)ch);
return ch; return ch;
} }

View File

@@ -3,7 +3,7 @@
#include "gd32e23x_rcu.h" #include "gd32e23x_rcu.h"
#include "gd32e23x_gpio.h" #include "gd32e23x_gpio.h"
#include "board_config.h" #include "board_config.h"
#include "uart_ring_buffer.h"
void rs485_init(void) { void rs485_init(void) {
@@ -37,7 +37,7 @@ void rs485_init(void) {
usart_enable(RS485_PHY); usart_enable(RS485_PHY);
nvic_irq_enable(USART0_IRQn, 0); nvic_irq_enable(RS485_IRQ, 0);
usart_interrupt_enable(RS485_PHY, USART_INT_RBNE); usart_interrupt_enable(RS485_PHY, USART_INT_RBNE);
// usart_interrupt_enable(RS485_PHY, USART_INT_IDLE); // usart_interrupt_enable(RS485_PHY, USART_INT_IDLE);
@@ -70,3 +70,37 @@ void rs485_init(void) {
#endif // RS485_MAX13487 #endif // RS485_MAX13487
} }
/******************************************************************************/
/* 具体的中断处理函数实现 */
/******************************************************************************/
void usart0_irq_handler(void) {
// 处理USART0的接收中断
if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) {
uint8_t data = usart_data_receive(USART0);
// 使用原有的环形缓冲区处理逻辑
(void)uart_ring_buffer_put(data); // 缓冲满时丢弃,返回值可用于统计
}
// 处理USART0的空闲中断
if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) {
usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);
// 在这里添加空闲中断处理逻辑
}
}
void usart1_irq_handler(void) {
// 处理USART1的接收中断
if(usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE)) {
uint8_t data = usart_data_receive(USART1);
// 使用原有的环形缓冲区处理逻辑
(void)uart_ring_buffer_put(data); // 缓冲满时丢弃,返回值可用于统计
}
// 处理USART1的空闲中断
if(usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE)) {
usart_interrupt_flag_clear(USART1, USART_INT_FLAG_IDLE);
// 在这里添加空闲中断处理逻辑
}
}

View File

@@ -6,17 +6,9 @@
#include "systick.h" #include "systick.h"
volatile bool g_ultrasonic_measure_done = false; volatile bool g_ultrasonic_measure_done = false;
extern uint32_t g_capture_value;
void ultrasonic_tx_init(void) { void ultrasonic_tx_init(void) {
// TODO
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
gpio_bit_reset(GPIOA, GPIO_PIN_0);
rcu_periph_clock_enable(US_TX_GPIO_RCU); rcu_periph_clock_enable(US_TX_GPIO_RCU);
gpio_mode_set(US_TX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, US_TX_GPIO_PIN); gpio_mode_set(US_TX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, US_TX_GPIO_PIN);
@@ -60,42 +52,34 @@ void ultrasonic_tx_init(void) {
timer_counter_value_config(US_TX_TIMER, 0); timer_counter_value_config(US_TX_TIMER, 0);
timer_interrupt_enable(US_TX_TIMER, TIMER_INT_UP); timer_interrupt_enable(US_TX_TIMER, TIMER_INT_UP);
nvic_irq_enable(TIMER13_IRQn, 2); nvic_irq_enable(TIMER13_IRQn, 2U);
} }
void ultrasonic_pwm_out_cycles(void) { void ultrasonic_pwm_out_cycles(void) {
g_ultrasonic_measure_done = false; g_ultrasonic_measure_done = false;
// 停止发射定时器
timer_disable(TIMER13); timer_disable(TIMER13);
timer_channel_output_state_config(TIMER13, TIMER_CH_0, TIMER_CCX_ENABLE); timer_channel_output_state_config(TIMER13, TIMER_CH_0, TIMER_CCX_ENABLE);
// 重置并启动回波计时器
timer_disable(US_ECHO_TIMER);
// 重要:清除所有中断标志
// timer_interrupt_flag_clear(US_ECHO_TIMER, TIMER_INT_FLAG_CH0);
// timer_interrupt_flag_clear(US_ECHO_TIMER, TIMER_INT_FLAG_UP);
// 重置计数器
timer_counter_value_config(US_ECHO_TIMER, 0);
// 启动发射PWM
timer_enable(US_TX_TIMER); timer_enable(US_TX_TIMER);
timer_enable(TIMER15);
// 启动回波计时器
timer_enable(US_ECHO_TIMER);
} }
// void ultrasonic_transmit_debounce_delay(const uint16_t micro_second) {
// rcu_periph_clock_enable(US_TX_DELAY_RCU);
// timer_deinit(US_TX_DELAY_TIMER);
// timer_parameter_struct timer_initpara;
// timer_struct_para_init(&timer_initpara);
// timer_initpara.prescaler = 71;
// timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
// timer_initpara.counterdirection = TIMER_COUNTER_UP;
// timer_initpara.period = micro_second - 1;
// timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
// timer_initpara.repetitioncounter = 0;
// timer_init(US_TX_DELAY_TIMER, &timer_initpara);
// timer_auto_reload_shadow_enable(US_TX_DELAY_TIMER);
// timer_interrupt_enable(US_TX_DELAY_TIMER, TIMER_INT_UP);
// nvic_irq_enable(TIMER15_IRQn, 1U);
// }
void ultrasonic_receive_exti_config(void) { void ultrasonic_receive_exti_config(void) {
rcu_periph_clock_enable(US_RX_GPIO_RCU); rcu_periph_clock_enable(US_RX_GPIO_RCU);
rcu_periph_clock_enable(US_RX_EXTI_RCU); rcu_periph_clock_enable(US_RX_EXTI_RCU);
@@ -106,8 +90,6 @@ void ultrasonic_receive_exti_config(void) {
exti_init(US_RX_GPIO_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING); exti_init(US_RX_GPIO_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_flag_clear(US_RX_GPIO_EXTI); exti_flag_clear(US_RX_GPIO_EXTI);
// exti_interrupt_enable(EXTI_0);
} }
void ultrasonic_echo_timer_config(void) { void ultrasonic_echo_timer_config(void) {
@@ -116,61 +98,43 @@ void ultrasonic_echo_timer_config(void) {
timer_parameter_struct timer_initpara; timer_parameter_struct timer_initpara;
timer_struct_para_init(&timer_initpara); timer_struct_para_init(&timer_initpara);
timer_initpara.prescaler = 71; timer_initpara.prescaler = 71; // 72MHz/72 = 1MHz (1us per count)
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = ULTRASONIC_MAX_TOF_RELOAD - 1; timer_initpara.period = (ULTRASONIC_MAX_TOF_RELOAD - 1);
timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER15, &timer_initpara); timer_init(US_ECHO_TIMER, &timer_initpara);
timer_auto_reload_shadow_disable(US_ECHO_TIMER);
// 配置输出比较通道0
timer_oc_parameter_struct timer_oc_initpara; timer_oc_parameter_struct timer_oc_initpara;
timer_channel_output_struct_para_init(&timer_oc_initpara); timer_channel_output_struct_para_init(&timer_oc_initpara);
timer_oc_initpara.outputstate = TIMER_CCX_ENABLE; timer_oc_initpara.outputstate = TIMER_CCX_ENABLE;
timer_oc_initpara.ocpolarity = TIMER_OC_POLARITY_HIGH; timer_oc_initpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(TIMER15, TIMER_CH_1,&timer_oc_initpara); timer_channel_output_config(US_ECHO_TIMER, TIMER_CH_0, &timer_oc_initpara);
timer_interrupt_enable(TIMER15, TIMER_INT_CH1 | TIMER_INT_UP); // 配置输出比较模式
nvic_irq_enable(TIMER15_IRQn, 0); timer_channel_output_mode_config(US_ECHO_TIMER, TIMER_CH_0, TIMER_OC_MODE_TIMING);
// 设置比较值
timer_channel_output_pulse_value_config(US_ECHO_TIMER, TIMER_CH_0, (ULTRASONIC_TX_RINGDOWN_RELOAD - 1));
// 清除中断标志
timer_interrupt_flag_clear(US_ECHO_TIMER, TIMER_INT_FLAG_CH0);
timer_interrupt_flag_clear(US_ECHO_TIMER, TIMER_INT_FLAG_UP);
// timer_parameter_struct timer_initpara; // 使能中断
// timer_struct_para_init(&timer_initpara); timer_interrupt_enable(US_ECHO_TIMER, TIMER_INT_UP); // UP中断
// timer_initpara.prescaler = 71; timer_interrupt_enable(US_ECHO_TIMER, TIMER_INT_CH0); // CH0中断
// timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
// timer_initpara.counterdirection = TIMER_COUNTER_UP; nvic_irq_enable(US_ECHO_TIMER_IRQ, 1U);
// timer_initpara.period = ULTRASONIC_MAX_TOF_RELOAD;
// timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
// timer_initpara.repetitioncounter = 0;
// timer_init(US_ECHO_TIMER, &timer_initpara);
// timer_ic_parameter_struct timer_icinitpara;
// timer_channel_input_struct_para_init(&timer_icinitpara);
// timer_icinitpara.icpolarity = TIMER_IC_POLARITY_BOTH_EDGE;
// timer_icinitpara.icselection = TIMER_IC_SELECTION_INDIRECTTI;
// timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
// timer_icinitpara.icfilter = 0x03;
// timer_input_capture_config(US_ECHO_TIMER, US_ECHO_CH, &timer_icinitpara);
// timer_single_pulse_mode_config(US_ECHO_TIMER, TIMER_SP_MODE_SINGLE);
} }
void ultrasonic_config(void) { void ultrasonic_config(void) {
ultrasonic_tx_init(); ultrasonic_tx_init();
// ultrasonic_transmit_debounce_delay(TIME_CORRECTION_US); ultrasonic_receive_exti_config();
// ultrasonic_receive_exti_config();
ultrasonic_echo_timer_config(); ultrasonic_echo_timer_config();
} }
// uint16_t ultrasonic_calc_distance(void) {
// // while (!ultrasonicMeasurementDone);
// // uint32_t us_value = timer_channel_capture_value_register_read(US_ECHO_TIMER, US_ECHO_CH);
// uint16_t distance = (TIME_CORRECTION_US + g_capture_value) * 17;
// /*
// * (TIME_CORRECTION_US + us_value) * 340 m/s
// * -----------------------------------------
// * 1000 000
// * ----------------------------------------------
// * 2
// */
// return distance;
// }

View File

@@ -1,14 +1,14 @@
# Project basic info # Project basic info
set(PROJECT_NAME "gd32e23x") set(PROJECT_NAME "ultrasonic-analog")
set(VERSION_MAJOR 1) set(VERSION_MAJOR 0)
set(VERSION_MINOR 0) set(VERSION_MINOR 0)
set(VERSION_PATCH 0) set(VERSION_PATCH 3)
set(VERSION "V${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") set(VERSION "V${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
string(TIMESTAMP BUILD_DATE "%Y-%m-%d") string(TIMESTAMP BUILD_DATE "%Y-%m-%d")
# 编译条件如IIC类型等 # 编译条件如IIC类型等
# set(IIC_TYPE "AutoDetectDriveCurrent") # set(IIC_TYPE "AutoDetectDriveCurrent")
set(IIC_TYPE "HW-IIC") set(IIC_TYPE "24V")
# 其它自定义宏 # 其它自定义宏
add_definitions(-DIIC_TYPE=${IIC_TYPE}) add_definitions(-DIIC_TYPE=${IIC_TYPE})