#include "adc.h" #include "hlw8032.h" #include "main.h" #include "network.h" #include "led.h" #include "reset_log.h" #include #include ADC_HandleTypeDef hadc1; void adcInit(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) Error_Handler(); sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) Error_Handler(); } uint16_t getAdc(void) { uint16_t adc_value = 0; HAL_ADC_Start(&hadc1); if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) { adc_value = HAL_ADC_GetValue(&hadc1); } HAL_ADC_Stop(&hadc1); return adc_value; } void update_batter(void) { static _Bool powoff = 0; uint16_t adc_value = getAdc(); float batter_valtage = adc_value * (3.3 / 4096.0); batter_valtage = batter_valtage * 11.0; batter_valtage += 0.6; batter_valtage = 100 * (batter_valtage - 10.8) / (12.6 - 10.8); /* 限幅 0~100%:法拉电容放电时 3.3V 基准下跌,ADC 读数失真可能算出负数 */ if (batter_valtage < 0) batter_valtage = 0; if (batter_valtage > 100) batter_valtage = 100; /* 电量 <10% 基本等同外部 12V 断开。法拉电容(5.5F)续航有限, * 首次低于阈值立即 50ms 快速复核 2 次(约 100ms 出结果),仍低马上按断电处理: * 优先把掉电消息发出去,再做本地记录,最后留 500ms 让模组把报文真正发完 */ if (batter_valtage < 10 && powoff == 0) { uint8_t confirm = 1; for (int k = 0; k < 2; k++) { HAL_Delay(50); adc_value = getAdc(); float v = adc_value * (3.3 / 4096.0); v = v * 11.0 + 0.6; v = 100 * (v - 10.8) / (12.6 - 10.8); if (v >= 10) { confirm = 0; break; } } if (!confirm) return; /* 分毫必争:发掉电消息并等模组回 OK(最多 ~1.5s/次,最多试 3 次)。 * 3 次都发不出(通道忙/模组已掉线)也照常记录复位,不能因发送失败就不记录 */ { static uint8_t pub_try = 0; if (NET_publish_power_wait(0) != 0 && ++pub_try < 3) return; pub_try = 0; } powoff = 1; log_info("> 电量低: %d%%", (int)batter_valtage); hlw8032_save(); /* 本地记录:电量、断电原因(都很快) */ reset_log_power_loss(); HAL_Delay(800); /* OK 后再留 800ms 让报文上空口 */ NVIC_SystemReset(); /* BootLoader 会检测主电源,12V 未恢复前不跳 APP,防止外设没上电时程序乱跑 */ } /* LED1: 低电量时常亮 */ if (powoff) LED1_ON; else LED1_OFF; }