当前位置:AIGC资讯 > 数据采集 > 正文

BLE芯片PHY6222---ADC采集精度

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. 根据自身产品情况分压电路自行调试相关阻值,容值

更新时间 2023-11-08