diff --git a/APP/peripheral_main.c b/APP/peripheral_main.c index 6145475..1ade295 100644 --- a/APP/peripheral_main.c +++ b/APP/peripheral_main.c @@ -107,7 +107,7 @@ int main(void) BSP_LED_Init(); - BSP_VBAT_Init(); + BSP_ADC_Init(); logDebug("VBAT init ok\n"); BSP_Ml307r_Init(); diff --git a/bsp/inc/bsp_adc.h b/bsp/inc/bsp_adc.h index 2d35bd1..34d2f6b 100644 --- a/bsp/inc/bsp_adc.h +++ b/bsp/inc/bsp_adc.h @@ -5,20 +5,27 @@ * Author: 123 */ -#ifndef INCLUDE_BSP_ADC_H_ -#define INCLUDE_BSP_ADC_H_ +#ifndef __BSP_ADC_H__ +#define __BSP_ADC_H__ -#include "CH58x_common.h" -#define VBAT_EVT_START (0x0001 << 2) +#include "CONFIG.h" -#define VBAT_LOW_THRESHOLD 2.0f // 电池电压低阈值,单位V +// PA 2,3 +#define ADC_VBAT_PIN GPIO_Pin_5 +#define ADC_COIL_PIN GPIO_Pin_4 -void VBAT_ADC_Init(void); -void BSP_VBAT_Init(void); +// channel +#define ADC_VBAT_CHANNEL 1 +#define ADC_COIL_CHANNEL 0 +#define VBAT_CHECK_EVT (0x0001 << 0) -void Send_Low_Battery_Message(float vbat); -void Handle_Low_Battery(float vbat); +extern tmosTaskID adc_task_id; -uint8_t BSP_ReadVbat(void); -#endif /* INCLUDE_BSP_ADC_H_ */ +#define VBAT_LOW_MV 3000 // 电池电压低阈值,单位mV + +void BSP_ADC_Init(void); + +uint16_t BSP_ReadVbat(void); + +#endif /* __BSP_ADC_H__ */ diff --git a/bsp/inc/bsp_ml307r.h b/bsp/inc/bsp_ml307r.h index 14952e0..8335905 100644 --- a/bsp/inc/bsp_ml307r.h +++ b/bsp/inc/bsp_ml307r.h @@ -19,7 +19,7 @@ // #define MQTT_HOST "120.25.151.173" // MQTT服务器地址 #define MQTT_HOST "8.135.10.183" // MQTT服务器地址 // #define MQTT_PORT 1883 // MQTT服务器端口 -#define MQTT_PORT 27440 // MQTT服务器端口 +#define MQTT_PORT 24539 // MQTT服务器端口 #define MQTT_USER "guest" // MQTT用户名 #define MQTT_PASS "guest" // MQTT密码 #define CLIENT_ID "ZBF" // 客户端ID前缀 diff --git a/bsp/inc/bsp_valve.h b/bsp/inc/bsp_valve.h index 244d657..186e26e 100644 --- a/bsp/inc/bsp_valve.h +++ b/bsp/inc/bsp_valve.h @@ -118,7 +118,7 @@ typedef struct __attribute__((packed)) uint32_t out_pressure; // 4B 闃闂ㄥ嚭鍙e帇鍔 Pa uint32_t atm_pressure; // 4B 闃闂ㄥぇ姘斿帇鍔 Pa uint8_t type; // 闃闂ㄧ被鍨 - uint8_t bat; // 1B 鐢垫睜鐢靛帇 30=3V,18=1.8V + uint16_t bat; // 2B 鐢垫睜鐢靛帇 30=3V,18=1.8V uint8_t humi; // 1B 闃闂ㄦ箍搴 %RH int8_t rssi; uint8_t Lock; // 1B 闃闂ㄩ攣鐘舵 0=瑙i攣 1=閿佸畾 diff --git a/bsp/src/bsp_adc.c b/bsp/src/bsp_adc.c index 8b853ce..c5c9af7 100644 --- a/bsp/src/bsp_adc.c +++ b/bsp/src/bsp_adc.c @@ -1,154 +1,163 @@ -/* - * bsp_adc.c - * - * Created on: 2024年11月29日 - * Author: 123 - */ #include "bsp_adc.h" -#include "CONFIG.h" + +#include "bsp_uart.h" #include "log.h" -#include "bsp_motor.h" -#include "bsp_led.h" #include "bsp_ml307r.h" -#include +#include "bsp_led.h" -signed short RoughCalib_Value = 0; // ADC粗调偏差值 -static tmosTaskID vbat_task_id = INVALID_TASK_ID; -static uint8_t vbat_low_flag = 0; // 电压过低标志 +#undef LOG_ENABLE +#define LOG_ENABLE 1 -void VBAT_ADC_Init(void) +#define LOG_LVL LOG_DEBUG + +#undef LOG_TAG +#define LOG_TAG "adc" + +uint16_t adcBuff[40]; + +// 当前的供电电压 mv +uint16_t vbat_mv; +// 当前的电机电流产生的电压 mv +uint16_t coil_mv; + +signed short RoughCalib_Value = 0; // ADC粗调偏差值 + +tmosTaskID adc_task_id = INVALID_TASK_ID; +static uint8_t vbat_low_flag = 0; // 电压过低标志 + +void BSP_VBAT_IoInit(void) { - // 功能引脚数字输入禁用寄存器 - R32_PIN_IN_DIS |= (1U << 4); // 禁用数字功能 - //ADC初始化 - /* 单通道采样:选择adc通道0做采样,对应 PA4引脚, 带数据校准功能 */ - GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating); - // 采样率最高8M - ADC_ExtSingleChSampInit(SampleFreq_8_or_4, ADC_PGA_1_2); - - RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中 - logDebug("RoughCalib_Value =%d \n", RoughCalib_Value); - - ADC_ChannelCfg(0); - ADC_ExcutSingleConver();//时间足够时建议再次转换并丢弃首次ADC数据 - DelayMs(10); + // 默认情况下,ADC 引脚和所在 GPIO 引脚的数字功能是同时存在的 + // ,在进行 ADC 测量时候,需要吧 GPIO 设置为高阻输入 + // ,当 ADC 的电平处于中间态的时候,这时候往往会导致数字部分漏电 + // ,这时候我们可以通过寄存器 R16_PIN_ANALOG_IE 来禁用相关的 AIN 通道所在的数字功能: + R32_PIN_IN_DIS |= ADC_VBAT_PIN; // 禁用数字功能 + GPIOA_ModeCfg(ADC_VBAT_PIN, GPIO_ModeIN_Floating); } -void ADC_GPIO_Init(void) +void BSP_COIL_IoInit(void) { - GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating); - // 确保ADC电源已启用 - R8_ADC_CFG |= RB_ADC_POWER_ON; + R32_PIN_IN_DIS |= ADC_COIL_PIN; // 禁用数字功能 + GPIOA_ModeCfg(ADC_COIL_PIN, GPIO_ModeIN_Floating); +} + +void BSP_VBAT_AdcInit(void) +{ + // 0dB(1倍) (ADC/2048)*Vref 2*Vref 0V~2.1V 0V~2V + ADC_ExtSingleChSampInit(SampleFreq_4_or_2, ADC_PGA_0); + + ADC_ChannelCfg(ADC_VBAT_CHANNEL); +} + +// TODO:使能差分,选择0#通道:实际是对A0(正端)和A2(负端)的电压进行差分转换; +void BSP_COIL_AdcInit(void) +{ + // 12dB(4倍) 0V (ADC/8192-0.25)*Vref 0.25*Vref 0V~0.26V 0V~0.23V + ADC_ExtDiffChSampInit(SampleFreq_4_or_2, ADC_PGA_4); + ADC_ChannelCfg(ADC_COIL_CHANNEL); + + // ADC_VoltConverDiffPGA_12dB(ADC_COIL_CHANNEL); +} + +// https://www.cnblogs.com/iot-fan/p/14304854.html +uint16_t BSP_ReadVbat(void) +{ + uint8_t i = 0; + uint32_t countadc = 0; + uint16_t min_number = 0; + uint16_t max_number = 0; + + BSP_VBAT_AdcInit(); + ADC_ExcutSingleConver(); // 时间足够时建议再次转换并丢弃首次ADC数据 + for (i = 0; i < 20; i++) + { + adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次 + // DelayMs(1); + } + for (i = 0; i < 20; i++) + { + countadc += ADC_VoltConverSignalPGA_0dB(adcBuff[i]); + if (i == 0) + { + min_number = ADC_VoltConverSignalPGA_0dB(adcBuff[i]); + max_number = ADC_VoltConverSignalPGA_0dB(adcBuff[i]); + } + min_number = ((min_number > ADC_VoltConverSignalPGA_0dB(adcBuff[i])) ? ADC_VoltConverSignalPGA_0dB(adcBuff[i]) : min_number); // 软件滤波 + max_number = ((max_number < ADC_VoltConverSignalPGA_0dB(adcBuff[i])) ? ADC_VoltConverSignalPGA_0dB(adcBuff[i]) : max_number); + } + logDebug("min=%d, max=%d, diff=%d", min_number, max_number, (max_number - min_number)); + countadc = (countadc - min_number - max_number) / 18; // 删除最小与最大值 + logDebug("countaveradc = %d", countadc); + vbat_mv = countadc * 3; + logDebug("VBAT = %d mV", vbat_mv); + + return vbat_mv; +} + +// https://www.cnblogs.com/iot-fan/p/14304854.html +uint16_t BSP_ReadCoil(void) +{ + uint8_t i = 0; + uint32_t countadc = 0; + uint16_t min_number = 0; + uint16_t max_number = 0; + + BSP_COIL_AdcInit(); + ADC_ExcutSingleConver(); // 时间足够时建议再次转换并丢弃首次ADC数据 + for (i = 0; i < 20; i++) + { + adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次 + // DelayMs(1); + } + for (i = 0; i < 20; i++) + { + countadc += ADC_VoltConverSignalPGA_0dB(adcBuff[i]); + if (i == 0) + { + min_number = ADC_VoltConverSignalPGA_0dB(adcBuff[i]); + max_number = ADC_VoltConverSignalPGA_0dB(adcBuff[i]); + } + min_number = ((min_number > ADC_VoltConverSignalPGA_0dB(adcBuff[i])) ? ADC_VoltConverSignalPGA_0dB(adcBuff[i]) : min_number); // 软件滤波 + max_number = ((max_number < ADC_VoltConverSignalPGA_0dB(adcBuff[i])) ? ADC_VoltConverSignalPGA_0dB(adcBuff[i]) : max_number); + } + logDebug("min=%d, max=%d, diff=%d", min_number, max_number, (max_number - min_number)); + countadc = (countadc - min_number - max_number) / 18; // 删除最小与最大值 + logDebug("countaveradc = %d", countadc); + vbat_mv = countadc * 3; + logDebug("VBAT = %d mV", vbat_mv); + + return vbat_mv; } uint16_t VBAT_ProcessEvent(uint8_t task_id, uint16_t events) { - if (events & VBAT_EVT_START) + if (events & VBAT_CHECK_EVT) { - uint16_t adc_vbat = 0; - float vbat = 0; - float IN_VBAT = 0; - // ADC_GPIO_Init(); - // ADC_ChannelCfg(0); - // adc_vbat = ADC_ExcutSingleConver() + RoughCalib_Value; - // logDebug("adc_vbat =%d \n", adc_vbat); - // vbat = (adc_vbat/1024.0-1)*1.05; - // logDebug("vbat =%f \n", vbat); - // tmos_start_task(vbat_task_id, VBAT_EVT_START, MS1_TO_SYSTEM_TIME(1000*60)); //1000*60 - uint8_t retry_count = 0; - uint8_t success = 0; - int32_t vbat_mV = 0; - int32_t IN_VBAT_mV = 0; - - while (retry_count < 3 && !success) { - ADC_GPIO_Init(); - ADC_ChannelCfg(0); - adc_vbat = ADC_ExcutSingleConver() + RoughCalib_Value; - if (adc_vbat > 100 && adc_vbat < 6000) { - // vbat = (adc_vbat/1024.0-1)*1.05; - // IN_VBAT = vbat * 2; - // logDebug("adc_vbat = %d, IN_VBAT = %.2f V\n", adc_vbat, IN_VBAT); - // 使用整数计算代替浮点计算 (adc_vbat/1024.0-1)*1.05 转换为定点运算 - // 公式: ((adc_vbat * 1000) / 1024 - 1000) * 105 / 100 - vbat_mV = ((adc_vbat * 1000) / 1024 - 1000) * 105 / 100; - IN_VBAT_mV = vbat_mV * 2; - logDebug("adc_vbat = %d, IN_VBAT = %d.%02d V\n", adc_vbat, IN_VBAT_mV/1000, (IN_VBAT_mV%1000)/10); - success = 1; - } else { - retry_count++; - DelayMs(10); - logDebug("ADC error %d/3\n", retry_count); - } - } - - if (success) { - if (IN_VBAT < VBAT_LOW_THRESHOLD) { - // Handle_Low_Battery(IN_VBAT); - IotFlag_t.Low_Voltage_flag = 1; - } else if (vbat_low_flag) { - vbat_low_flag = 0; - LED_VBAT_CLOSE; - logDebug("Voltage is normal (%.2fV)\n", IN_VBAT); - } - } else { - logDebug("Voltage measurement failed\n"); - if (!vbat_low_flag) { - IN_VBAT = 1.0f; - // Handle_Low_Battery(IN_VBAT); - IotFlag_t.Low_Voltage_flag = 1; - } - } - - uint32_t next_check_time = vbat_low_flag ? - MS1_TO_SYSTEM_TIME(1000*1) : //1000*30 电压低时30秒检测一次 - MS1_TO_SYSTEM_TIME(1000*6); //1000*60 正常时1分钟检测一次 - - tmos_start_task(vbat_task_id, VBAT_EVT_START, next_check_time); - return (events ^ VBAT_EVT_START); + BSP_ReadVbat(); + return (events ^ VBAT_CHECK_EVT); } return 0; } -void BSP_VBAT_Init(void) + +void BSP_ADC_Init(void) { - VBAT_ADC_Init(); - vbat_task_id = TMOS_ProcessEventRegister(VBAT_ProcessEvent); - tmos_set_event(vbat_task_id, VBAT_EVT_START); + BSP_VBAT_IoInit(); + // BSP_COIL_IoInit(); + + BSP_VBAT_AdcInit(); + // 0dB(1倍) (ADC/2048)*Vref 2*Vref 0V~2.1V 0V~2V + // ADC_ExtSingleChSampInit(SampleFreq_4_or_2, ADC_PGA_0); + + // 采样数据粗调,获取偏差值,必须先配置ADC后调用此函数获取校准值 + RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差,记录到全局变量 RoughCalib_Value中 + logDebug("RoughCalib_Value =%d", RoughCalib_Value); + + adc_task_id = TMOS_ProcessEventRegister(VBAT_ProcessEvent); + logDebug("adc_task_id = %d", adc_task_id); + tmos_start_task(adc_task_id, VBAT_CHECK_EVT, MS1_TO_SYSTEM_TIME(1000)); } -uint8_t BSP_ReadVbat(void) -{ -uint16_t adcBuff[40]; -uint16_t min_number = 0; -uint16_t max_number = 0; - uint8_t i; - uint32_t CountBat = 0; - // ADC_InterBATSampInit(); - ADC_GPIO_Init(); - ADC_ChannelCfg(0); - DelayUs(1); - ADC_ExcutSingleConver(); - DelayUs(1); - for (i = 0; i < 20; i++) - { - adcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次 - } - for (i = 0; i < 20; i++) - { - CountBat += adcBuff[i]; - if (i == 0) - { - min_number = adcBuff[i]; - max_number = adcBuff[i]; - } - min_number = ((min_number > adcBuff[i]) ? adcBuff[i] : min_number); // 软件滤波 - max_number = ((max_number < adcBuff[i]) ? adcBuff[i] : max_number); - } - logDebug("min_number = %d, max_number = %d", min_number, max_number); - CountBat = (CountBat - min_number - max_number) / 18; // 删除最小与最大值 - // CountBat = CountBat * 2.05078125 - 3150; - // uint8_t vbat = (uint8_t)(CountBat / 100); - uint32_t vbat_mV = ((CountBat * 1000) / 1024 - 1000) * 105 / 100; - uint8_t vbat = (vbat_mV * 2) / 100; - logDebug("AverageCountBat = %dmV, vbat = %d(100mV)", CountBat, vbat); - return vbat; -} \ No newline at end of file + + + + diff --git a/bsp/src/bsp_bmp390.c b/bsp/src/bsp_bmp390.c index 8ad71f7..2cd1da8 100644 --- a/bsp/src/bsp_bmp390.c +++ b/bsp/src/bsp_bmp390.c @@ -2,6 +2,7 @@ #include "bsp_motor.h" #include "bsp_led.h" #include "bsp_key.h" +#include "bsp_adc.h" #include "CONFIG.h" #include "log.h" #include "bsp_ml307r.h" @@ -383,8 +384,8 @@ void Lower_IO_Deinit(void) // GPIOB_ModeCfg(GPIO_Pin_23 | GPIO_Pin_22, GPIO_ModeIN_PD); // ADC - GPIOA_ResetBits(GPIO_Pin_4); - GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating); + GPIOA_ResetBits(ADC_VBAT_PIN); + GPIOA_ModeCfg(ADC_VBAT_PIN, GPIO_ModeIN_Floating); ADC_DisablePower(); // BMP390