| | |
| | | |
| | | /* |
| | | *+----------------------+ |
| | | *| 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 | |
| | | *+----------------------+ |
| | | */ |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | *+----------------------+ |
| | | */ |
| | | |
| | | /* 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) |
| | |
| | | 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: 输出参数,采集到的光照度值 |
| | |
| | | */ |
| | | 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; |
| | | } |