暂存 更新bsp_adc代码

This commit is contained in:
常正强 2025-06-11 10:07:00 +08:00
parent 3ff537e147
commit a0e034e69f
6 changed files with 167 additions and 150 deletions

View File

@ -107,7 +107,7 @@ int main(void)
BSP_LED_Init();
BSP_VBAT_Init();
BSP_ADC_Init();
logDebug("VBAT init ok\n");
BSP_Ml307r_Init();

View File

@ -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__ */

View File

@ -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前缀

View File

@ -118,7 +118,7 @@ typedef struct __attribute__((packed))
uint32_t out_pressure; // 4B 阀门出口压力 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=解锁 1=锁定

View File

@ -1,154 +1,163 @@
/*
* bsp_adc.c
*
* Created on: 20241129
* 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 <string.h>
#include "bsp_led.h"
#undef LOG_ENABLE
#define LOG_ENABLE 1
#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粗调偏差值
static tmosTaskID vbat_task_id = INVALID_TASK_ID;
tmosTaskID adc_task_id = INVALID_TASK_ID;
static uint8_t vbat_low_flag = 0; // 电压过低标志
void VBAT_ADC_Init(void)
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 0V2.1V 0V2V
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 0V0.26V 0V0.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);
}
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;
BSP_VBAT_IoInit();
// BSP_COIL_IoInit();
BSP_VBAT_AdcInit();
// 0dB(1倍) (ADC/2048)*Vref 2*Vref 0V2.1V 0V2V
// 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));
}

View File

@ -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