332 lines
8.8 KiB
C
332 lines
8.8 KiB
C
|
||
#include "Includes.h"
|
||
|
||
|
||
/*
|
||
2021/09/17
|
||
1、在芯片FT测试过程中,将ADC工艺误差校正。
|
||
|
||
2、ADC 校准值(数据)存储于FLASH 第240K 位置,占用8Byte.(4+4Byte 校准数据和取反校验)
|
||
|
||
3、校准中心值CALI_CENTER_VL=10000 ,ADC计算时,将ADC原始值乘以校准值再除以中心值(10000)
|
||
value_calibrated = value * calibration_param / CALI_CENTER_VL ;
|
||
|
||
4、读取校准值接口:int gadc_calibration_get(uint32_t *value)
|
||
具体用法请参考adc-demo,调用接口返回值大于0表示正确获取到校准值。
|
||
|
||
2022/02/11
|
||
1、增加3.3V参考电压时的校准参数。
|
||
*/
|
||
|
||
|
||
#define PROG_SECTOR_NUM 60 // = 4*60 = 240k
|
||
#define CALI_CENTER_VL 10000
|
||
#define CALI_OFFSET_VL 1000
|
||
|
||
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
void adc_gpio_config(uint8_t io_gpadc_channel)
|
||
{
|
||
if(io_gpadc_channel==0xff) return;
|
||
gpio_mux_ctl(io_gpadc_channel,0);
|
||
gpio_fun_sel(io_gpadc_channel,0);
|
||
gpio_fun_inter(io_gpadc_channel,0);
|
||
gpio_direction_input(io_gpadc_channel, 3);/*FLOATING*/
|
||
}
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
void gpadc_config_channel(uint16_t channel)
|
||
{
|
||
__write_hw_reg32(GPADC_CHAN_CTL ,channel);
|
||
__write_hw_reg32(GPADC_FIFO_CTL , 0x10);
|
||
__write_hw_reg32(GPADC_FIFO_CTL , 0x00);
|
||
}
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
extern void init_adc(uint8_t freq,uint8_t gadc_ref)
|
||
{
|
||
uint32_t adc_reg = 0;
|
||
__write_hw_reg32(CPR_RSTCTL_CTLAPB_SW , 0x10000000);/*先使GPADC_RSTN=0,再使 GPADC_RSTN=1软复位 GPADC 模块*/
|
||
__write_hw_reg32(CPR_RSTCTL_CTLAPB_SW , 0x10001000);
|
||
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL , 0x20002000);/*使能GPADC_PCLK_EN 的GPADC_PCLK时钟*/
|
||
__write_hw_reg32(GPADC_FIFO_CTL , 0x10);/*对FIFO进行一次清空操作*/
|
||
__write_hw_reg32(GPADC_FIFO_CTL , 0x00);
|
||
if((freq>GADC_FREQ_500K)||(freq<GADC_FREQ_8M)) freq = GADC_FREQ_1M;
|
||
if(GADC_REF_2_47V == gadc_ref)
|
||
adc_reg = (freq<<8)|0x10 ;
|
||
else
|
||
adc_reg = (freq<<8)|0x12 ;
|
||
__write_hw_reg32(GPADC_RF_CTL ,adc_reg);/*GPADC_RF_CTL GPADC_PCLK/(gpadc_clkdiv*2)=16M/16=1M ,select 2.4V vref*/
|
||
__write_hw_reg32(GPADC_TIMER0 ,4); /*通道切换等待时间 4us*/
|
||
__write_hw_reg32(GPADC_MAIN_CTL , 0x09);/*GPADC_MAIN_CTL 打开GPADC模块,数据采集上升沿.*/
|
||
|
||
//NVIC_EnableIRQ(GADC_IRQn);
|
||
|
||
}
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
|
||
int gadc_calibration_get(uint32_t *value)
|
||
{
|
||
uint32_t vl[2] = {0};
|
||
uint32_t neg[2] = {0};
|
||
uint8_t get_buf[16] = {0};
|
||
#if 0 /*SPI0*/
|
||
Init_spi_master(0, SPIM_CLK_16MHZ);
|
||
spi_flash_Release_powerdown();
|
||
spi_flash_Read(PROG_SECTOR_NUM*FLASH_SECTOR_SIZE,get_buf,12);
|
||
spi_flash_Enter_powerdown();
|
||
#else /*XIP*/
|
||
|
||
|
||
#endif
|
||
vl[0] = get_buf[0]*0x1000000 + get_buf[1]*0x10000 + get_buf[2]*0x100 + get_buf[3] ;
|
||
neg[0] = get_buf[4]*0x1000000 + get_buf[5]*0x10000 + get_buf[6]*0x100 + get_buf[7] ;
|
||
|
||
vl[1] = get_buf[8]*0x1000000 + get_buf[9]*0x10000 + get_buf[10]*0x100 + get_buf[11] ;
|
||
neg[1] = get_buf[12]*0x1000000 + get_buf[13]*0x10000 + get_buf[14]*0x100 + get_buf[15] ;
|
||
|
||
printf("calibration 2.47v=[%d],3.3v=[%d],neg=[%d]\n", vl[0], vl[1], neg[0]);
|
||
if( (neg[0] == ~vl[0]) && ( (vl[0] > CALI_CENTER_VL-CALI_OFFSET_VL)&&(vl[0] < CALI_CENTER_VL+CALI_OFFSET_VL) ))
|
||
{
|
||
value[0] = vl[0];
|
||
value[1] = vl[1];
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
}
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
uint16_t data_average(uint16_t *data,uint16_t len)
|
||
{
|
||
uint16_t add_cnt = 0;
|
||
uint32_t sum_data = 0;
|
||
uint8_t filter_cnt = 0;
|
||
|
||
filter_cnt = len/10;
|
||
|
||
for(int i=0; i<len-1; i++)
|
||
{
|
||
for(int j=0; j<len-i-1; j++)
|
||
{
|
||
if(data[j]>data[j+1])
|
||
{
|
||
uint16_t temp = data[j];
|
||
data[j] = data[j+1];
|
||
data[j+1] = temp;
|
||
}
|
||
}
|
||
}
|
||
|
||
for(int i=6*filter_cnt; i<len-3*filter_cnt; i++)
|
||
{
|
||
sum_data += data[i];
|
||
add_cnt++;
|
||
}
|
||
|
||
if(0 == add_cnt) return -1;
|
||
else return sum_data/add_cnt;
|
||
}
|
||
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
uint16_t gpadc_val_update(uint8_t update_ch)
|
||
{
|
||
gadc_cache_t *temp_gadc_cache = NULL;
|
||
uint16_t gadc_value[2*FIFO_DEEP] = {0};
|
||
uint16_t gadc_count = 0;
|
||
uint32_t val;
|
||
temp_gadc_cache = (gadc_cache_t*)&val;
|
||
|
||
for(int t=0; t<FIFO_DEEP; t++)
|
||
{
|
||
__read_hw_reg32(GPADC_FIFO,val);
|
||
if(update_ch == temp_gadc_cache->chanel_1) gadc_value[gadc_count++] = temp_gadc_cache->value_1;
|
||
if(update_ch == temp_gadc_cache->chanel_2) gadc_value[gadc_count++] = temp_gadc_cache->value_2;
|
||
|
||
if((update_ch != 0)&&(0 == temp_gadc_cache->chanel_1)) break; //empty
|
||
}
|
||
|
||
if(gadc_count<=2) return -1;
|
||
else return data_average(gadc_value+2,gadc_count-2); //Remove the first FIFO data
|
||
}
|
||
|
||
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
|
||
void test_gpadc_3_3V(void)
|
||
{
|
||
|
||
uint16_t count = 0;
|
||
char state=4;
|
||
uint16_t value = 0;
|
||
uint16_t value_calibrated = 0;
|
||
uint32_t calibration_param[2] = {0};
|
||
if(gadc_calibration_get(calibration_param)>0)
|
||
{
|
||
printf("[3.3v] gadc_calibration_get success!,cali param=%d\n",calibration_param[1]);
|
||
}
|
||
else
|
||
{
|
||
calibration_param[1] = 10000;
|
||
printf("[3.3v] gadc_calibration_get error!\n");
|
||
}
|
||
adc_gpio_config(IO_GPADC_CHANNEL4);
|
||
adc_gpio_config(IO_GPADC_CHANNEL5);
|
||
adc_gpio_config(IO_GPADC_CHANNEL6);
|
||
adc_gpio_config(IO_GPADC_CHANNEL7);
|
||
|
||
init_adc(GADC_FREQ_1M,GADC_REF_AVDD);
|
||
gpadc_config_channel(state);
|
||
while(1)
|
||
{
|
||
//If the delay is less, you have to test it well !
|
||
for(int i=0; i<0x1000; i++); //delay
|
||
|
||
value = gpadc_val_update(state);
|
||
value_calibrated = value * calibration_param[1] / CALI_CENTER_VL ;
|
||
int old_state = state;
|
||
|
||
switch(state)
|
||
{
|
||
|
||
case 4:
|
||
gpadc_config_channel(5);
|
||
state=5;
|
||
break;
|
||
case 5:
|
||
gpadc_config_channel(6);
|
||
state=6;
|
||
break;
|
||
case 6:
|
||
gpadc_config_channel(7);
|
||
state=7;
|
||
break;
|
||
case 7:
|
||
gpadc_config_channel(4);
|
||
state=4;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if(count++>=1000)
|
||
{
|
||
count =0;
|
||
//printf("%1d-%3d ",old_state,value);
|
||
printf("[3.3v] channel:%d:0x%04X===cali=%d===before cali Voltage:%f V,after cali Voltage:%f V \r\n",\
|
||
old_state,value,calibration_param[1],((value)*3.3)/(1.0*1024),((value_calibrated)*3.3)/(1.0*1024));
|
||
//printf("channel:%d======Voltage:%f V\r\n",old_state,((value_calibrated)*3.3)/(1.0*1024));
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
void test_gpadc_2_47V(void)
|
||
{
|
||
uint16_t count = 0;
|
||
char state=4;
|
||
uint16_t value = 0;
|
||
uint16_t value_calibrated = 0;
|
||
uint32_t calibration_param[2] = {0};
|
||
if(gadc_calibration_get(calibration_param)>0)
|
||
{
|
||
printf("[2.47v] gadc_calibration_get success!,cali param=%d\n",calibration_param[0]);
|
||
}
|
||
else
|
||
{
|
||
calibration_param[0] = 10000;
|
||
printf("[2.47v] gadc_calibration_get error!\n");
|
||
}
|
||
|
||
adc_gpio_config(IO_GPADC_CHANNEL4);
|
||
adc_gpio_config(IO_GPADC_CHANNEL5);
|
||
adc_gpio_config(IO_GPADC_CHANNEL6);
|
||
adc_gpio_config(IO_GPADC_CHANNEL7);
|
||
init_adc(GADC_FREQ_1M,GADC_REF_2_47V);
|
||
gpadc_config_channel(state);
|
||
while(1)
|
||
{
|
||
//If the delay is less, you have to test it well !
|
||
for(int i=0; i<0x1000; i++); //delay
|
||
|
||
value = gpadc_val_update(state);
|
||
value_calibrated = value * calibration_param[0] / CALI_CENTER_VL ;
|
||
int old_state = state;
|
||
|
||
switch(state)
|
||
{
|
||
|
||
case 4:
|
||
gpadc_config_channel(5);
|
||
state=5;
|
||
break;
|
||
case 5:
|
||
gpadc_config_channel(6);
|
||
state=6;
|
||
break;
|
||
case 6:
|
||
gpadc_config_channel(7);
|
||
state=7;
|
||
break;
|
||
case 7:
|
||
gpadc_config_channel(4);
|
||
state=4;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if(count++>=1000)
|
||
{
|
||
count =0;
|
||
//printf("%1d-%3d ",old_state,value);
|
||
printf("[2.47v] channel:%d:0x%04X===cali=%d===before cali Voltage:%f V,after cali Voltage:%f V \r\n",\
|
||
old_state,value,calibration_param[0],((value)*2.47)/(1.0*1024),((value_calibrated)*2.47)/(1.0*1024));
|
||
//printf("channel:%d======Voltage:%f V\r\n",old_state,((value_calibrated)*3.3)/(1.0*1024));
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Copyright (c) 2022 - 2025, XinChip
|
||
* All rights reserved.
|
||
* Author : D
|
||
*/
|
||
void test_gpadc(void)
|
||
{
|
||
test_gpadc_3_3V();
|
||
// test_gpadc_2_47V();
|
||
}
|