BLE_DCF_TYQ_CH592F/BSP/src/bsp_adc.c

156 lines
5.2 KiB
C
Raw Normal View History

#include "bsp_adc.h"
2024-12-13 13:22:31 +08:00
#include "bsp_uart.h"
#include "log.h"
#undef LOG_ENABLE
#define LOG_ENABLE 1
#undef LOG_TAG
#define LOG_TAG "adc"
// https://www.cnblogs.com/gscw/p/17682385.html
// 计算公式参考手册,建议使用 “建议实际可用测量电压范围” 作为 ADC 采集的增益选择判断标准。计算公式参考手册。
// 仅使用 ADC 功能,同时降低功耗,可以将引脚的数字输入功能关闭,配置 R16_PIN_ANALOG_IE。 注如果引脚用于模拟功能ADC/TouchKey建议将该引脚的数字输入功能关闭即设置数字输入禁用从而可以降低功耗并有利于减少干扰。
// PA9 引脚进行 ADC 采集,在置为浮空后,过 300ms 左右再进行 ADC 的采集。因为初次烧录的时候 boot 是串口功能开启的PA9 是输出高电平。切换到浮空会需要等待时间。
uint16_t adcBuff[40];
volatile uint8_t adclen;
volatile uint8_t DMA_end = 0;
signed short RoughCalib_Value = 0; // ADC粗调偏差值
uint32_t countadc = 0;
uint16_t min_number = 0;
uint16_t max_number = 0;
double voltage = 0;
2024-12-16 21:26:43 +08:00
uint8_t BSP_ReadVbat(void)
{
uint8_t i;
// VBAT
uint32_t CountBat = 0;
ADC_InterBATSampInit();
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);
}
2024-12-13 13:22:31 +08:00
logDebug("min_number = %d, max_number = %d", min_number, max_number);
CountBat = (CountBat - min_number - max_number) / 18; // 删除最小与最大值
2024-12-16 21:26:43 +08:00
uint8_t vbat = (uint8_t)(CountBat / 100);
logDebug("AverageCountBat = %dmV, vbat = %d(100mV)", CountBat, vbat);
//缩小到100mV
return vbat;
}
void BSP_ADC_Init(void)
{
2025-02-21 14:38:41 +08:00
uint8_t i;
2024-12-16 21:26:43 +08:00
#if 1
// logDebug();
#endif
logDebug("ADC init");
2025-02-22 17:22:49 +08:00
#if 0
2024-12-16 21:26:43 +08:00
// ±10C没啥参考价值
/* 温度采样并输出 */
2025-02-21 14:38:41 +08:00
logDebug("\n1.Temperature sampling...");
2024-12-16 21:26:43 +08:00
ADC_InterTSSampInit();
for (i = 0; i < 20; i++)
{
adcBuff[i] = ADC_ExcutSingleConver(); // 连续采样20次
}
for (i = 0; i < 20; i++)
{
uint32_t C25 = 0;
C25 = (*((PUINT32)ROM_CFG_TMP_25C));
2025-02-21 14:38:41 +08:00
logDebug("%d %d %d", adc_to_temperature_celsius(adcBuff[i]), adcBuff[i], C25);
2024-12-16 21:26:43 +08:00
}
#endif
2025-02-22 17:22:49 +08:00
#if 0
2025-02-21 14:38:41 +08:00
// PA1
2024-12-16 21:26:43 +08:00
2024-12-11 14:31:10 +08:00
// 默认情况下ADC 引脚和所在 GPIO 引脚的数字功能是同时存在的
// ,在进行 ADC 测量时候,需要吧 GPIO 设置为高阻输入
// ,当 ADC 的电平处于中间态的时候,这时候往往会导致数字部分漏电
// ,这时候我们可以通过寄存器 R16_PIN_ANALOG_IE 来禁用相关的 AIN 通道所在的数字功能:
2025-02-21 14:38:41 +08:00
// 功能引脚数字输入禁用寄存器
R32_PIN_IN_DIS |= (1U << 1); // 禁用数字功能
/* 单通道采样选择adc通道8做采样对应 PA1引脚 带数据校准功能 */
GPIOA_ModeCfg(GPIO_Pin_1, GPIO_ModeIN_Floating);
2024-12-11 14:31:10 +08:00
// -6dB (1/2 倍) (ADC/1024-1)*Vref 3*Vref -0.2V 3.15V 1.9V 3V
// 0db (1 倍) (ADC/2048)*Vref 2*Vref 0V 2.1V 0V 2V
// 6db (2 倍) (ADC/4096+0.5)*Vref 1.5*Vref 0.525V 1.575V 0.6V 1.5V
2025-02-21 14:38:41 +08:00
// 采样率最高8M
ADC_ExtSingleChSampInit(SampleFreq_8_or_4, ADC_PGA_0);
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差记录到全局变量 RoughCalib_Value中
2024-12-13 13:22:31 +08:00
logDebug("RoughCalib_Value =%d", RoughCalib_Value);
// 刚上电,要给电容充电
DelayMs(300);
2025-02-21 14:38:41 +08:00
logDebug("PA1 channel 8");
ADC_ChannelCfg(8);
for (i = 0; i < 20; i++)
{
adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
// DelayMs(5);
}
2024-12-13 13:22:31 +08:00
logDebug("original: ");
logHexDumpAll(adcBuff, 20);
// 注意由于ADC内部偏差的存在当采样电压在所选增益范围极限附近的时候可能会出现数据溢出的现象
for (i = 0; i < 20; i++)
{
countadc += 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);
}
2024-12-13 13:22:31 +08:00
logDebug("min=%d, max=%d, diff=%d", min_number, max_number, (max_number - min_number));
countadc = (countadc - min_number - max_number) / 18; // 删除最小与最大值
2024-12-13 13:22:31 +08:00
logDebug("countaveradc = %d", countadc);
2024-12-11 14:31:10 +08:00
/*
int16_t adc_raw;
adc_raw = ADC_ExcutSingleConver() + RoughCalib_Value;
//PGA=-12db
voltage_mv = adc_raw*1050/512 - (3*1050);
//PGA=-6db
voltage_mv = adc_raw*1050/1024 - (1*1050);
//PGA=0db
voltage_mv = adc_raw*1050/2048;
//PGA=6db
voltage_mv = adc_raw*1050/4096 + (1050/2);
*/
voltage = (double)(countadc) / 2048 * 1.05;
2024-12-13 13:22:31 +08:00
logDebug("voltage=%1.3lf V", voltage);
logDebug("VIN: %1.3lf V", voltage * 2);
2024-12-14 13:31:23 +08:00
#endif
}
2024-12-14 13:31:23 +08:00