From e9a96aec6a30e6f7b9619031ca9c5cb0f755d9b5 Mon Sep 17 00:00:00 2001 From: yelvlab Date: Wed, 13 Aug 2025 00:56:55 +0800 Subject: [PATCH] add delay ms safe & add led heart beat --- Inc/led.h | 1 + Inc/systick.h | 3 +++ Src/gd32e23x_it.c | 2 ++ Src/led.c | 37 +++++++++++++++++++++++++++++++++++++ Src/main.c | 5 +++-- Src/systick.c | 22 ++++++++++++++++++++++ 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/Inc/led.h b/Inc/led.h index 6177e10..7376a5e 100644 --- a/Inc/led.h +++ b/Inc/led.h @@ -8,5 +8,6 @@ void led_init(void); void led_on(void); void led_off(void); void led_toggle(void); +void led_heart_beat(void); #endif // LED_H diff --git a/Inc/systick.h b/Inc/systick.h index 1944b07..83d892f 100644 --- a/Inc/systick.h +++ b/Inc/systick.h @@ -24,4 +24,7 @@ void delay_ms(uint32_t count); /* delay a time in microseconds */ void delay_us(uint32_t count); +/* delay function that doesn't interfere with SysTick interrupt */ +void delay_ms_safe(uint32_t count); + #endif /* SYS_TICK_H */ \ No newline at end of file diff --git a/Src/gd32e23x_it.c b/Src/gd32e23x_it.c index d3a29d1..3512280 100644 --- a/Src/gd32e23x_it.c +++ b/Src/gd32e23x_it.c @@ -36,6 +36,7 @@ OF SUCH DAMAGE. #include "systick.h" #include "uart.h" #include "uart_ring_buffer.h" +#include "led.h" /*! \brief this function handles NMI exception @@ -96,6 +97,7 @@ void PendSV_Handler(void) \retval none */ void SysTick_Handler(void) { + led_heart_beat(); // LED心跳指示灯 } void USART0_IRQHandler(void) { diff --git a/Src/led.c b/Src/led.c index b39ec12..1661867 100644 --- a/Src/led.c +++ b/Src/led.c @@ -1,5 +1,42 @@ #include "led.h" +/** + * @brief LED心跳指示灯功能 + * @details 实现类似心跳的LED闪烁模式:快闪两次然后暂停 + * 适合在SysTick中断中调用,通过计数器控制闪烁节拍 + * @note 假设SysTick中断频率为1ms,心跳周期约为2秒 + * 心跳模式:亮200ms->灭200ms->亮200ms->灭1400ms(循环) + */ +void led_heart_beat(void) +{ + static uint16_t heart_beat_counter = 0; + + // 心跳周期:2000ms (假设SysTick为1ms中断) + // 模式:亮200ms -> 灭200ms -> 亮200ms -> 灭1400ms + heart_beat_counter++; + + if (heart_beat_counter <= 200) { + // 第一次亮:0-200ms + led_on(); + } + else if (heart_beat_counter <= 400) { + // 第一次灭:200-400ms + led_off(); + } + else if (heart_beat_counter <= 600) { + // 第二次亮:400-600ms + led_on(); + } + else if (heart_beat_counter <= 2000) { + // 长时间灭:600-2000ms + led_off(); + } + else { + // 重置计数器,开始新的心跳周期 + heart_beat_counter = 0; + } +} + void led_init(void) { rcu_periph_clock_enable(LED_RCU); gpio_mode_set(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); diff --git a/Src/main.c b/Src/main.c index cc932ba..fced534 100644 --- a/Src/main.c +++ b/Src/main.c @@ -57,9 +57,10 @@ int main(void) led_init(); printf("Hello USART0!"); - led_off(); + // 移除led_off()调用,让心跳函数控制LED while(1){ - delay_ms(100); + // 使用不会干扰SysTick中断的安全延时函数 + delay_ms_safe(100); command_process(); } } diff --git a/Src/systick.c b/Src/systick.c index dc4b213..8478805 100644 --- a/Src/systick.c +++ b/Src/systick.c @@ -30,6 +30,10 @@ void systick_config(void) count_1us = (float)SystemCoreClock/8000000; //计算了每毫秒所需的 SysTick 计数值 count_1ms = (float)count_1us * 1000; + + // 配置SysTick为1ms周期中断 + // 注意:SysTick_Config会自动设置时钟源为HCLK,所以需要使用SystemCoreClock/1000 + SysTick_Config(SystemCoreClock / 1000); // 1ms中断 } /** @@ -88,4 +92,22 @@ void delay_ms(uint32_t count) SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //将 SysTick 计数器的当前值清零,以便下次使用 SysTick->VAL = 0x0000U; +} + +/** + * ************************************************************************ + * @brief delay_ms_safe 毫秒延时函数(不干扰SysTick中断) + * @details 使用简单循环实现延时,不会重新配置SysTick + * @param[in] count 毫秒值 + * ************************************************************************ + */ +void delay_ms_safe(uint32_t count) +{ + // 基于系统时钟的简单循环延时 + // 这是一个粗略的估计,实际延时可能有偏差 + uint32_t loops_per_ms = SystemCoreClock / 8000; // 粗略估计 + + for(uint32_t i = 0; i < count; i++) { + for(volatile uint32_t j = 0; j < loops_per_ms; j++); + } } \ No newline at end of file