Files
stair56e_uart/component/boot2/bsp/bsp_gpadc.c
T
2026-08-05 19:07:52 +08:00

332 lines
9.2 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 "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();
}