BLE_TYQ_CH584M/BSP/src/bsp_adc.c

134 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "bsp_adc.h"
#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;
void BSP_ADC_Init(void)
{
uint8_t i;
#if 0
// ±10C没啥参考价值
/* 温度采样并输出 */
logDebug("\n1.Temperature sampling...\n");
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));
logDebug("%d %d %d \n", adc_to_temperature_celsius(adcBuff[i]), adcBuff[i], C25);
}
#endif
#if 1
// 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);
}
logDebug("min_number = %d, max_number = %d", min_number, max_number);
CountBat = (CountBat - min_number - max_number) / 18; // 删除最小与最大值
logDebug("AverageCountBat = %d", CountBat);
#endif
// 默认情况下ADC 引脚和所在 GPIO 引脚的数字功能是同时存在的
// ,在进行 ADC 测量时候,需要吧 GPIO 设置为高阻输入
// ,当 ADC 的电平处于中间态的时候,这时候往往会导致数字部分漏电
// ,这时候我们可以通过寄存器 R16_PIN_ANALOG_IE 来禁用相关的 AIN 通道所在的数字功能:
R32_PIN_CONFIG2 |= (1U << 13);
/* 单通道采样选择adc通道3做采样对应 PA13引脚 带数据校准功能 */
GPIOA_ModeCfg(GPIO_Pin_13, GPIO_ModeIN_Floating);
// -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
ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0);
RoughCalib_Value = ADC_DataCalib_Rough(); // 用于计算ADC内部偏差记录到全局变量 RoughCalib_Value中
logDebug("RoughCalib_Value =%d", RoughCalib_Value);
// 刚上电,要给电容充电
DelayMs(300);
logDebug("PA13:::::");
ADC_ChannelCfg(3);
for (i = 0; i < 20; i++)
{
adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; // 连续采样20次
// DelayMs(5);
}
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);
}
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);
/*
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;
logDebug("voltage=%1.3lf V", voltage);
logDebug("VIN: %1.3lf V", voltage * 2);
}