From 6c1a5eb1a9891898552bb9320ba973349ca4bffa Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Wed, 08 Jul 2026 20:51:59 +0800
Subject: [PATCH] Update mdelay and gpio function

---
 ex1.buzzer-music/Board/miscdev.c |  115 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/ex1.buzzer-music/Board/miscdev.c b/ex1.buzzer-music/Board/miscdev.c
index 73c7a4a..986afbc 100644
--- a/ex1.buzzer-music/Board/miscdev.c
+++ b/ex1.buzzer-music/Board/miscdev.c
@@ -12,6 +12,33 @@
 
 /*
  *+----------------------+
+ *|    STM32 GPIO API    |
+ *+----------------------+
+ */
+
+void gpio_clk_enable(GPIO_TypeDef *port)
+{
+    if      (port == GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE();
+    else if (port == GPIOB) __HAL_RCC_GPIOB_CLK_ENABLE();
+    else if (port == GPIOC) __HAL_RCC_GPIOC_CLK_ENABLE();
+    else if (port == GPIOD) __HAL_RCC_GPIOD_CLK_ENABLE();
+#ifdef GPIOE
+    else if (port == GPIOE) __HAL_RCC_GPIOE_CLK_ENABLE();
+#endif
+#ifdef GPIOF
+    else if (port == GPIOF) __HAL_RCC_GPIOF_CLK_ENABLE();
+#endif
+#ifdef GPIOG
+    else if (port == GPIOG) __HAL_RCC_GPIOG_CLK_ENABLE();
+#endif
+#ifdef GPIOH
+    else if (port == GPIOH) __HAL_RCC_GPIOH_CLK_ENABLE();
+#endif
+}
+
+
+/*
+ *+----------------------+
  *|  GPIO Led/Relay API  |
  *+----------------------+
  */
@@ -79,7 +106,7 @@
     if( which >= LedMax )
         return ;
 
-    level = status==OFF ? GPIO_PIN_SET : GPIO_PIN_RESET;
+    level = status==ON ? leds[which].active : !leds[which].active;
     HAL_GPIO_WritePin(leds[which].group, leds[which].pin, level);
 }
 
@@ -103,10 +130,10 @@
 void blink_led(int which, uint32_t interval)
 {
     turn_led(which, ON);
-    HAL_Delay(interval);
+    mdelay(interval);
 
     turn_led(which, OFF);
-    HAL_Delay(interval);
+    mdelay(interval);
 }
 
 /**
@@ -174,13 +201,15 @@
  *+----------------------+
  */
 
-/* gcc 编译器中的 printf 函数将会调用 __io_putchar() 函数,实现最终的字符打印
- * keil编译器中的 printf 函数将会调用 fputc() 函数,实现最终的字符打印
- * 这里我们定义一个宏 PUTCHAR_PROTOTYPE 来兼容这两个编译器所需要的函数原型;
+/* gcc 编译器的 printf 将会调用 __io_putchar() 函数,实现最终的字符打印
+ * keil编译器的 printf 将会调用 fputc() 函数,实现最终的字符打印
+ * 这里我们定义一个宏 PUTCHAR_PROTOTYPE 来兼容两个编译器所需要的函数原型
+ *
+ * 注意:
+ *  1. Keil5 工程需要勾选:Options for Target -> Target -> Use MicroLIB
+ *  2. Keil5 的编译器 armclang(AC6) 会定义 __GNUC__ 宏,而旧版 armcc(AC5) 则不会
  */
-#if defined(__ARMCC_VERSION) /* MDK ARM Compiler */
-FILE __stdout;
-FILE __stdin;
+#if defined(__ARMCC_VERSION) /*  */
 #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
 #elif defined(__GNUC__) /* GCC */
 #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
@@ -268,6 +297,70 @@
     return 0;
 }
 
+/* ------------------- Lux 滤波相关参数 ------------------- */
+#define LUX_SAMPLE_COUNT   10   /* 每次采集的原始样本数 */
+#define LUX_TRIM_COUNT      2   /* 排序后,头尾各丢弃的样本数 */
+
+/**
+ * @brief  简单冒泡排序(数据量很小,不追求性能)
+ */
+static void sort_u32(uint32_t *arr, int n)
+{
+    for (int i = 0; i < n - 1; i++)
+    {
+        for (int j = 0; j < n - 1 - i; j++)
+        {
+            if (arr[j] > arr[j + 1])
+            {
+                uint32_t tmp = arr[j];
+                arr[j] = arr[j + 1];
+                arr[j + 1] = tmp;
+            }
+        }
+    }
+}
+
+/**
+ * @brief  多次采样光照度ADC值,排序后去掉两端的离群样本,再取平均
+ * @param  lux: 输出参数,滤波后的光照度值
+ * @retval 0 成功, -1 失败
+ */
+static int adc_read_lux_filtered(uint32_t *lux)
+{
+    uint32_t samples[LUX_SAMPLE_COUNT];
+    uint32_t sum = 0;
+    int valid_count;
+
+    /* 多次采样光照度ADC值 */
+    for (int i = 0; i < LUX_SAMPLE_COUNT; i++)
+    {
+        if (adc_read_channel(ADC_CHANNEL_15, &samples[i]) != 0)
+            return -1;
+    }
+
+    /* 将多次采样的数据排序 */
+    sort_u32(samples, LUX_SAMPLE_COUNT);
+
+    /* 丢弃排序后头尾各 LUX_TRIM_COUNT 个可能的离群值 */
+    valid_count = LUX_SAMPLE_COUNT - 2 * LUX_TRIM_COUNT;
+    if (valid_count <= 0)
+    {
+        /* 参数配置不合理时兜底,避免除0 */
+        valid_count = LUX_SAMPLE_COUNT;
+        for (int i = 0; i < LUX_SAMPLE_COUNT; i++)
+            sum += samples[i];
+    }
+    else
+    {
+        for (int i = LUX_TRIM_COUNT; i < LUX_SAMPLE_COUNT - LUX_TRIM_COUNT; i++)
+            sum += samples[i];
+    }
+
+    *lux = sum / valid_count;
+
+    return 0;
+}
+
  /**
  * @brief  采集光照度与噪声值
  * @param  lux:   输出参数,采集到的光照度值
@@ -276,11 +369,11 @@
  */
 int adc_sample_lux_noisy(uint32_t *lux, uint32_t *noisy)
 {
-    if (adc_read_channel(ADC_CHANNEL_15, lux) != 0)
+    if (adc_read_lux_filtered(lux) != 0)
         return -1;
 
     if (adc_read_noisy_peak(noisy, 50) != 0)
-        return -1;
+        return -2;
 
     return 0;
 }

--
Gitblit v1.10.0