BLE芯片PHY6222的ADC采集精度
目录
BLE芯片PHY6222的ADC采集精度 目的 前提 内容 结论 异常情况(采集值过大或者过小,采集时间过长)目的
PHY6222在0~4.2V电压下的ADC采集精度(默认320k的采样率)
前提
1. PHY6222EVB板V1.1
2. SDK路径:SDK\release_bbb_sdk-PHY62XX_SDK_3.0.9\example\peripheral\adc
内容
与引脚的对应关系,1往左移7位,那P20对应就是最高位,所以使用外部分压,那ADC配置上应该是.is_high_resolution = 0xff(by pass 6路ADC全开的话,应该是.is_high_resolution = 0xfc
)
typedef enum
{
ADC_CH0DIFF = 1,/*p18(positive),p25(negative),only works in diff*/
ADC_CH0 = 2,ADC_CH1N_P11 = 2,
ADC_CH1 = 3,ADC_CH1P_P23 = 3,ADC_CH1DIFF = 3,/*P23 and P11*/
ADC_CH2 = 4,ADC_CH2N_P24 = 4,
ADC_CH3 = 5,ADC_CH2P_P14 = 5,ADC_CH2DIFF = 5,/*P14 and P24*/
ADC_CH4 = 6,ADC_CH3N_P15 = 6,
ADC_CH9 = 7,ADC_CH3P_P20 = 7,ADC_CH3DIFF = 7,/*P20 and P15*/
ADC_CH_VOICE = 8,
ADC_CH_NUM =9,
} adc_CH_t;
#define ADC_BIT(ch) (1<<ch)
adc_cfg 配置
adc_Cfg_t adc_cfg =
{
.channel = ADC_BIT(ADC_CH1P_P23),//通道1对应P23采集
.is_continue_mode = FALSE, //单次采集(后面我是软件定时连续采集)
.is_differential_mode = 0x00, //单端模式
.is_high_resolution = 0xff, //bypass模式,测试电压量程为0~0.8V
};
选择bypass模式,为使用外部分压电路
分压系数:9.1/1.8
9.1/1.8+1.8+1.8=10.9/1.8约等于6.055555555555556
结论
交流Q:715827731
12bit的PHY6222在无负载情况下,bypass模式且外部分压下,PHY6222外部电压越高,误差也就越大,大概的正常误差会在25mV左右,但芯片引脚出来的ADC精度没有乘以分压系数时可以控制在10mV之内的误差,采集64次产生一次采集中断,每输出一次ADC值大概花费284us。
异常情况(采集值过大或者过小,采集时间过长)
出现采集值不准的 情况,可以先打印芯片出厂时ADC的校准值是正常,
LOG(“AD_CAL[%x %x]\n”,adc_cal_negtive,adc_cal_postive);,正常打印的值是:0x0800081a(0800,081a左右,只要偏差不要过大)
如果指令读取的校准值过大或者过小,可以把adc.c的 hal_adc_value_cal函数替换成以下校准驱动:
float hal_adc_value_cal(adc_CH_t ch,uint16_t* buf, uint32_t size, uint8_t high_resol, uint8_t diff_mode)
{
uint32_t i;
int adc_sum = 0;
volatile float result = 0.0;
for (i = 0; i < size; i++)
{
adc_sum += (buf[i]&0xfff);
}
hal_adc_load_calibration_value();
result = ((float)adc_sum)/size;
//LOG("adc_sum:%10d %10d ",adc_sum,adc_sum/(MAX_ADC_SAMPLE_SIZE-3));
// if((adc_cal_postive!=0xfff)&&(adc_cal_negtive!=0xfff)&&(adc_cal_negtive>0xfff))
if((ABS(adc_cal_postive - 0x0800) < 0x0cc)&&(ABS(adc_cal_negtive - 0x0800) < 0x0cc))
{
float delta = ((int)(adc_cal_postive-adc_cal_negtive))/2.0;
if(ch&0x01)
{
result = (diff_mode) ? ((result-2048-delta)*2/(adc_cal_postive+adc_cal_negtive))
: ((result-delta) /(adc_cal_postive+adc_cal_negtive));
}
else
{
result = (diff_mode) ? ((result-2048-delta)*2/(adc_cal_postive+adc_cal_negtive))
: ((result+delta) /(adc_cal_postive+adc_cal_negtive));
}
}
else
{
result = (diff_mode) ? (float)(result / 2048 -1) : (float)(result /4096);
}
if(high_resol == TRUE)
{
result *= 0.8;
}
else
{
result = (float)result *(float)adc_Lambda[ch]*0.8/1000000;
}
return result;
}
如果指令读取的值正常,但输出的ADC值还是不准,可以根据自身情况做如下尝试的改善
1. 去掉所有LOG和无关的延迟
2. 蓝牙广播和连接时,瞬间发射功率会影响到ADC基准电压,如此时ADc正在采集,那么采集到的值是一个受干扰的值,不是预期的值.
一种规避方法,在蓝牙广播和蓝牙连接后,延时几毫秒(建议10ms,根据自身情况慢慢调),待ADC基准电压稳定后再采集。
3. 根据自身产品情况分压电路自行调试相关阻值,容值