Simplify the use of timers, timer13 sends ultrasonic waves, timer16 counts (debounce time and flight time)

The ultrasonic transducer is driven only after each command is issued.
This commit is contained in:
2025-08-25 17:05:47 +08:00
parent 16c5a31a63
commit 2d752eed5e
8 changed files with 98 additions and 136 deletions

View File

@@ -36,15 +36,15 @@
/******************************************************************************/
#define RS485_RCU RCU_USART1
#define RS485_RCU RCU_USART0
#define RS485_GPIO_RCU RCU_GPIOA
#define RS485_GPIO_PORT GPIOA
#define RS485_TX_PIN GPIO_PIN_2
#define RS485_RX_PIN GPIO_PIN_3
#define RS485_PHY USART1
#define RS485_PHY USART0
#define RS485_BAUDRATE 115200U
#define RS485_EN_PIN GPIO_PIN_1
#define RS485_IRQ USART1_IRQn
#define RS485_IRQ USART0_IRQn
/******************************************************************************/
@@ -58,6 +58,11 @@
/******************************************************************************/
#define US_TX_DELAY_RCU RCU_TIMER15
#define US_TX_DELAY_TIMER TIMER15
/******************************************************************************/
#define US_RX_GPIO_RCU RCU_GPIOB
#define US_RX_EXTI_RCU RCU_CFGCMP
#define US_RX_GPIO_PORT GPIOA
@@ -68,6 +73,7 @@
/******************************************************************************/
// 修改为TIMER15相关定义
#define US_ECHO_RCU RCU_TIMER16
#define US_ECHO_TIMER TIMER16
#define US_ECHO_CH TIMER_CH_0
@@ -75,9 +81,4 @@
/******************************************************************************/
#define TIME_CORRECTION_US 230U
#define CAPTURE_VALUE_MAX 550U
/******************************************************************************/
#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 ultrasonic_distance_raw_value_report(void);
/** @} */ // end of Command group
#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_TIME 498U // ms
#define ULTRASONIC_MAX_TOF_RELOAD 1000U //us
#define ULTRASONIC_TX_RINGDOWN_RELOAD 240U // 240us
#define ULTRASONIC_MAX_TOF_RELOAD 1000U // 1000us
/**************************************************************************************************/
void ultrasonic_tx_init(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);
// uint16_t ultrasonic_calc_distance(void);
#endif // UART_H
#endif // ULTRASONIC_ANALOG_H

View File

@@ -12,8 +12,8 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
/* Memories definition */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K
}
/* Sections */

View File

@@ -30,7 +30,7 @@
* @details
* Host -> Device 命令帧格式:
* [0] HEADER = 0xD5 // 包头标识
* [1] BOARD_TYPE = 0x03 // 板卡类型标识
* [1] BOARD_TYPE = 0x04 // 板卡类型标识
* [2] LEN = 数据区字节数 // 有效载荷长度
* [3..(3+LEN-1)] 数据 // 命令数据,如 "M1", "M2S123"
* [last] CRC = 校验码 // 从索引1到(last-1)的累加和低8位
@@ -155,13 +155,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) {}
// // 使用printf发送通过重定向到串口
// for (uint8_t i = 0; i < buf_len; i++) {
// printf("%c", buf[i]);
// }
// // 刷新缓冲区
// fflush(stdout);
}
/**
@@ -254,18 +247,9 @@ void handle_command(const uint8_t *frame, uint8_t len) {
if (cmd_index == cmd_len) {
// 仅基础命令,如 M1, M2, M3
switch (base_cmd) {
case 1u: // M1: enable sensor report
gpio_bit_toggle(GPIOA, GPIO_PIN_0);
case 1u: // M1: send ultrasonic driver single and respon raw data
// 启动超声波PWM发送
ultrasonic_pwm_out_cycles();
// 启动TIMER16用于240us精确计时
timer_counter_value_config(TIMER16, 0); // 复位计数器
timer_enable(TIMER16); // 启动定时器
// 等待超声测量完成最多等待1ms (100次 * 10us)
// TIMER16将在240us时设置g_ultrasonic_measure_done = true
uint16_t timeout_count = 0;
const uint16_t max_timeout = 150;
@@ -274,15 +258,11 @@ void handle_command(const uint8_t *frame, uint8_t len) {
timeout_count++;
}
gpio_bit_toggle(GPIOA, GPIO_PIN_0);
// 根据等待结果发送不同的响应
if (g_ultrasonic_measure_done) {
// 测量完成,发送正常响应
send_response(RESP_TYPE_OK, s_report_status_ok, sizeof(s_report_status_ok));
ultrasonic_distance_raw_value_report();
} else {
// 超时发送读取错误包理论上不应该发生因为TIMER16会在240us时触发
static const uint8_t timeout_error_data[] = { 0xFF, 0xFF, 0xFF, 0xFF };
static const uint8_t timeout_error_data[] = {0xFF, 0xFF };
send_response(RESP_TYPE_OK, timeout_error_data, sizeof(timeout_error_data));
}
return;
@@ -329,7 +309,6 @@ void handle_command(const uint8_t *frame, uint8_t len) {
{
// case 100u:
// // set_pwm(param_value);
// printf("Set PWM to %u\n", param_value);
// return;
default:
@@ -437,3 +416,32 @@ 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);
// 计算距离:定时器计数值 * 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));
}

View File

@@ -102,27 +102,18 @@ void SysTick_Handler(void) {
delay_decrement();
}
void TIMER16_IRQHandler(void) {
// 处理通道0比较中断240us时触发
if (timer_interrupt_flag_get(TIMER16, TIMER_INT_FLAG_CH0)) {
void TIMER16_IRQHandler(void)
{
// CH0比较中断 (ULTRASONIC_TX_RINGDOWN_RELOAD)
if(timer_interrupt_flag_get(TIMER16, TIMER_INT_FLAG_CH0) != RESET) {
timer_interrupt_flag_clear(TIMER16, TIMER_INT_FLAG_CH0);
// 在240us时执行的操作
g_ultrasonic_measure_done = true; // 设置测量完成标志
// TODO: 在这里可以执行其他240us时需要的操作
// 例如启动其他定时器、设置GPIO、记录时间戳等
exti_interrupt_enable(US_RX_GPIO_EXTI);
}
// 处理重装载中断1000us时触发即超时
if (timer_interrupt_flag_get(TIMER16, TIMER_INT_FLAG_UP)) {
// 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);
// 达到最大时间1ms自动关闭定时器
timer_disable(TIMER16);
// TODO: 超时处理逻辑
// 如果需要,可以在这里设置超时标志或执行其他清理操作
timer_disable(US_ECHO_TIMER);
}
}
@@ -136,14 +127,12 @@ void EXTI0_1_IRQHandler(void) {
if (exti_interrupt_flag_get(US_RX_GPIO_EXTI) == SET)
{
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);
g_ultrasonic_measure_done = true; // 超声转换完成,置位flag后有命令处理部分回包
exti_interrupt_disable(US_RX_GPIO_EXTI);
}
}
/* PWM周期计数器 - 使用ULTRASONIC_TX_CYCLES宏 */
volatile uint8_t pwm_cycle_count = 0;
@@ -156,7 +145,6 @@ void TIMER13_IRQHandler(void)
if(pwm_cycle_count >= (ULTRASONIC_TX_CYCLES)) {
timer_disable(TIMER13);
pwm_cycle_count = 0;
// g_ultrasonic_measure_done = true; // 注释掉现在由TIMER16在240us时设置
}
}

View File

@@ -38,10 +38,11 @@ OF SUCH DAMAGE.
#include "led.h"
#include "command.h"
#include <stdio.h>
#include "i2c.h"
#include "board_config.h"
#include "ultrasonic_analog.h"
// #define FLASH_SIZE_ADDR (*(const uint16_t *)0x1FFFF7E0)
/*!
\brief main function
\param[in] none
@@ -58,6 +59,7 @@ int main(void)
led_init();
ultrasonic_config();
ultrasonic_pwm_out_cycles();
#ifdef DEBUG_VERBOSE
char hello_world[] = {"Hello World!\r\n"};
@@ -73,14 +75,7 @@ int main(void)
while(1){
// ultrasonic_pwm_out_cycles();
// delay_ms(10);
command_process();
delay_ms(10);
// uint16_t ultrasonic_value = ultrasonic_calc_distance();
// printf("ultrasonic value: %d", ultrasonic_value);
// delay_ms(10);
}
}

View File

@@ -9,13 +9,6 @@ volatile bool g_ultrasonic_measure_done = false;
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);
gpio_mode_set(US_TX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, US_TX_GPIO_PIN);
@@ -59,23 +52,32 @@ void ultrasonic_tx_init(void) {
timer_counter_value_config(US_TX_TIMER, 0);
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) {
g_ultrasonic_measure_done = false;
// 停止发射定时器
timer_disable(TIMER13);
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);
// TODO 启动后续回波计时器
// timer_enable(US_ECHO_TIMER);
// 启动回波计时器
timer_enable(US_ECHO_TIMER);
}
void ultrasonic_receive_exti_config(void) {
@@ -88,75 +90,51 @@ void ultrasonic_receive_exti_config(void) {
exti_init(US_RX_GPIO_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_flag_clear(US_RX_GPIO_EXTI);
// exti_interrupt_enable(EXTI_0);
}
void ultrasonic_echo_timer_config(void) {
// 使能TIMER16时钟
rcu_periph_clock_enable(US_ECHO_RCU);
// 复位定时器到默认状态
timer_deinit(US_ECHO_TIMER);
// 配置基本定时器参数
timer_parameter_struct timer_initpara;
timer_struct_para_init(&timer_initpara);
// 设置分频器72MHz ÷ 72 = 1MHz每个计数 = 1us
timer_initpara.prescaler = 71; // (72-1)实际分频比为72
timer_initpara.prescaler = 71; // 72MHz/72 = 1MHz (1us per count)
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
// 设置周期999 (0-999共1000个计数) = 1000us = 1ms最大计时
timer_initpara.period = 999; // 1000us重装载周期
timer_initpara.period = (ULTRASONIC_MAX_TOF_RELOAD - 1);
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
// 初始化定时器基本参数
timer_init(US_ECHO_TIMER, &timer_initpara);
// 配置通道0用于240us比较中断不是PWM输出仅用于比较
timer_auto_reload_shadow_disable(US_ECHO_TIMER);
// 配置输出比较通道0
timer_oc_parameter_struct timer_oc_initpara;
timer_channel_output_struct_para_init(&timer_oc_initpara);
// 禁用输出,仅用于内部比较中断
timer_oc_initpara.outputstate = TIMER_CCX_DISABLE;
timer_oc_initpara.outputstate = TIMER_CCX_ENABLE;
timer_oc_initpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(US_ECHO_TIMER, US_ECHO_CH, &timer_oc_initpara);
timer_channel_output_config(US_ECHO_TIMER, TIMER_CH_0, &timer_oc_initpara);
// 设置比较模式为时间比较不是PWM模式
timer_channel_output_mode_config(US_ECHO_TIMER, US_ECHO_CH, TIMER_OC_MODE_TIMING);
// 配置输出比较模式
timer_channel_output_mode_config(US_ECHO_TIMER, TIMER_CH_0, TIMER_OC_MODE_TIMING);
// 设置240us时触发比较中断计数值239因为从0开始计数
timer_channel_output_pulse_value_config(US_ECHO_TIMER, US_ECHO_CH, 239);
// 设置比较值
timer_channel_output_pulse_value_config(US_ECHO_TIMER, TIMER_CH_0, (ULTRASONIC_TX_RINGDOWN_RELOAD - 1));
// 启用比较中断CH0和重装载中断UP
timer_interrupt_enable(US_ECHO_TIMER, TIMER_INT_CH0); // 240us比较中断
timer_interrupt_enable(US_ECHO_TIMER, TIMER_INT_UP); // 1000us重装载中断
// 清除中断标志
timer_interrupt_flag_clear(US_ECHO_TIMER, TIMER_INT_FLAG_CH0);
timer_interrupt_flag_clear(US_ECHO_TIMER, TIMER_INT_FLAG_UP);
// 使能中断
timer_interrupt_enable(US_ECHO_TIMER, TIMER_INT_UP); // UP中断
timer_interrupt_enable(US_ECHO_TIMER, TIMER_INT_CH0); // CH0中断
// 配置NVIC中断优先级设置为较高优先级1确保及时响应
nvic_irq_enable(TIMER16_IRQn, 1);
nvic_irq_enable(US_ECHO_TIMER_IRQ, 1U);
// 注意定时器配置完成但不启动需要在其他地方调用timer_enable()启动
// timer_single_pulse_mode_config(US_ECHO_TIMER, TIMER_SP_MODE_SINGLE);
}
void ultrasonic_config(void) {
ultrasonic_tx_init();
// ultrasonic_transmit_debounce_delay(TIME_CORRECTION_US);
// ultrasonic_receive_exti_config();
ultrasonic_receive_exti_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;
// }