623 lines
16 KiB
C
623 lines
16 KiB
C
/*!
|
|
* \file xc_drv_adc.c
|
|
*
|
|
* \brief Target xc adc driver implementation
|
|
*
|
|
* \copyright Revised BSD License, see section \ref LICENSE.
|
|
*
|
|
* \code
|
|
*
|
|
* _ __ _ ________ _
|
|
* | |/ /(_)___ / ____/ /_ (_)___
|
|
* | // / __ \/ / / __ \/ / __ \
|
|
* / |/ / / / / /___/ / / / / /_/ /
|
|
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
|
|
* /_/
|
|
* (C) 2022-2025 XinChip
|
|
*
|
|
* \endcode
|
|
*
|
|
* \author ( XinChip ) Alex-J
|
|
*
|
|
* \author ( XinChip )
|
|
*/
|
|
|
|
/*-----------------------------------------------------------------------------------
|
|
INCLUDE HEADE FILES
|
|
------------------------------------------------------------------------------------*/
|
|
#include "xc6xxx.h"
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
Local Variables
|
|
-------------------------------------------------------------------------------------*/
|
|
static uint16_t adc_value[2 * ADC_FIFO_DOUT_LEN] = {0};
|
|
static uint16_t adc_it_val;
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
Global Variables
|
|
-------------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
Func Prototype
|
|
-------------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
Functions
|
|
-------------------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_init
|
|
* @details ADC initialization
|
|
* @param[in] adc_cfg £ºThis is the structure parameter that the ADC initializes
|
|
* @param[out] void
|
|
* @retval void
|
|
* @other
|
|
adc_cfg.Freq = ADC_FREQ_2M;
|
|
adc_cfg.RefVol = ADC_REF_VOL_3_3V;
|
|
adc_cfg.SampEdge = ADC_SAMPEDGE_RISE;
|
|
adc_cfg.ExtDataMode = ADC_EXT_DATA_MODE_32BIT;
|
|
adc_cfg.ExtEdgeSel = ADC_EXT_EDGE_SEL_INTER;
|
|
adc_cfg.ExtSampleNum = ADC_EXT_SAMPLE_NUM_8;
|
|
adc_cfg.ExtTriggerSel = ADC_EXT_TRIGGER_SEL_PWM0;
|
|
|
|
adc_init(&adc_cfg);
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_init(ADC_InitCfg_t *adc_cfg)
|
|
{
|
|
cpr_rstctl_ctlapb_sw__gpadc_rstn__setf(RSTCTL_ENABLE);
|
|
cpr_rstctl_ctlapb_sw__gpadc_rstn__setf(RSTCTL_DISABLE);
|
|
cpr_ctlapbclken_grctl__gpadc_pclk_en__setf(ENABLE);
|
|
|
|
cpr_opa_ctrl_reg__bg_5v_ctrl__setf(ENABLE);
|
|
|
|
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE);
|
|
|
|
xc_adc_fifo_flush();
|
|
|
|
adc_timer0_set(ADC_TIMER);
|
|
|
|
adc_main_ctl__edge_sel__setf(adc_cfg->SampEdge);
|
|
|
|
xc_adc_freq_set(adc_cfg->Freq);
|
|
|
|
xc_adc_refvol_set(adc_cfg->RefVol);
|
|
|
|
adc_main_ctl__ext_edge_sel__setf(adc_cfg->ExtEdgeSel);
|
|
|
|
adc_main_ctl__ext_sample_num__setf(adc_cfg->ExtSampleNum);
|
|
|
|
adc_main_ctl__ext_trigger_sel__setf(adc_cfg->ExtTriggerSel);
|
|
|
|
adc_main_ctl__ext_data_mode__setf(adc_cfg->ExtDataMode);
|
|
}
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_data_average
|
|
* @details Calculate the average of a set of data
|
|
* @param[in] data : The data to be averaged len : Take the number of averages
|
|
* @param[out] void
|
|
* @retval average
|
|
***************************************************************************************
|
|
*/
|
|
uint16_t xc_adc_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 / 4;
|
|
|
|
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 = filter_cnt; i < len - filter_cnt; i++)
|
|
{
|
|
sum_data += data[i];
|
|
add_cnt++;
|
|
}
|
|
|
|
if(0 == add_cnt)
|
|
{
|
|
return 0xffff;
|
|
}
|
|
else
|
|
{
|
|
return sum_data / add_cnt;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_data_average
|
|
* @details Select and initialize the GPIO port based on the channel
|
|
* @param[in] Channel : adc Channel
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_channel_gpio_config(ADC_ChannelTypeDef_t Channel)
|
|
{
|
|
GPIO_InitCfg_t GPIO_InitCfg;
|
|
|
|
GPIO_InitCfg.Mux = GPIO_Mux0;
|
|
GPIO_InitCfg.FunSel = GPIO_Dx;
|
|
GPIO_InitCfg.Dir = GPIO_DIR_INPUT;
|
|
GPIO_InitCfg.Pull = GPIO_NOPULL;
|
|
GPIO_InitCfg.Int = NOT_INT;
|
|
|
|
switch(Channel)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_21 - Channel;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_0;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_1;
|
|
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_4;
|
|
}
|
|
break;
|
|
|
|
case 7:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_5;
|
|
}
|
|
break;
|
|
|
|
case 10:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_2;
|
|
}
|
|
break;
|
|
|
|
case 11:
|
|
{
|
|
GPIO_InitCfg.Pin = GPIO_3;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
xc_gpio_init(&GPIO_InitCfg);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_startgetvalue
|
|
* @details The corresponding ADC sampling value is obtained according to the channel
|
|
|
|
* @param[in] Channel : The ADC sampling channel to be obtained
|
|
* @param[in] *adc_val: ADC sample storage area
|
|
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_start_get_value(ADC_ChannelTypeDef_t Channel, uint16_t *adc_val)
|
|
{
|
|
uint32_t val;
|
|
ADC_FIFO_TypeDef_t *fifo_val = NULL;
|
|
uint32_t time_out = 100000;
|
|
uint8_t adc_count = 0;
|
|
uint16_t vvol;
|
|
*adc_val = 0;
|
|
|
|
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE);
|
|
|
|
adc_chan_ctl__select_chan__setf(Channel);
|
|
|
|
adc_fifo_ctl__read_req_thresh__setf(ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8);
|
|
|
|
xc_adc_fifo_flush();
|
|
|
|
adc_int_set(adc_int_get());
|
|
|
|
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_ENABLE);
|
|
|
|
val = adc_int_raw_get();
|
|
|
|
while(((val & ADC_INT_READ_REQ_INT_SET) != ADC_INT_READ_REQ_INT_SET) &&
|
|
time_out)
|
|
{
|
|
__nop();
|
|
|
|
val = adc_int_raw_get();
|
|
time_out--;
|
|
}
|
|
|
|
if(time_out == 0)
|
|
{
|
|
DEBUG("adc time_out\n");
|
|
return;
|
|
}
|
|
|
|
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE);
|
|
|
|
fifo_val = (ADC_FIFO_TypeDef_t *)&val;
|
|
|
|
for(int t = 0; t < ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8; t++)
|
|
{
|
|
val = adc_fifo_get();
|
|
|
|
if(fifo_val->chanel_1 != fifo_val->chanel_2)
|
|
{
|
|
//DEBUG("channel error :%d\n", t);
|
|
return;
|
|
}
|
|
|
|
if(fifo_val->chanel_1 != Channel)
|
|
{
|
|
//DEBUG("channel error :%d\n", t);
|
|
return;
|
|
}
|
|
|
|
adc_value[adc_count++] = fifo_val->value_1;
|
|
adc_value[adc_count++] = fifo_val->value_2;
|
|
// DEBUG("adc_value :%d\n", fifo_val->value_1);
|
|
// DEBUG("adc_value :%d\n", fifo_val->value_2);
|
|
}
|
|
|
|
vvol = xc_adc_data_average(adc_value, adc_count);
|
|
*adc_val = vvol;
|
|
|
|
if(vvol == 0)
|
|
{
|
|
*adc_val = vvol + 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_enable
|
|
* @details Start adc sampling
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_enable(void)
|
|
{
|
|
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_ENABLE) ;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_disable
|
|
* @details Stop adc sampling
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_disable(void)
|
|
{
|
|
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_enable_it
|
|
* @details Enable adc interrupt
|
|
* @param[in] it
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_enable_it(uint8_t it)
|
|
{
|
|
adc_int_en_set(it) ;
|
|
}
|
|
|
|
void xc_adc_disable_it(uint8_t it)
|
|
{
|
|
adc_int_en_set(it) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_fifo_req_len_set
|
|
* @details fifo receive length Settings for adc
|
|
* @param[in] len : fifo length
|
|
(ADC_FIFO_CTL_READ_REQ_THRESH_LEN_1 ~ ADC_FIFO_CTL_READ_REQ_THRESH_LEN_15)
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_fifo_req_len_set(uint8_t len)
|
|
{
|
|
adc_fifo_ctl__read_req_thresh__setf(len);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_wait_time_set
|
|
* @details ADC sampling wait time and interval Settings
|
|
|
|
* @param[in] timer0: Sampling wait time
|
|
* @param[in] timer1: Sampling interval time
|
|
ADC switches automatically when activated:
|
|
sampling time(sampling frequency) = timer0 + timer1;
|
|
(1M sampling(1US) = 0X1 + 31)
|
|
timer0 < timer1
|
|
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_wait_time_set(uint8_t timer0, uint16_t timer1)
|
|
{
|
|
adc_timer1_set(timer1);
|
|
adc_timer0_set(timer0);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_ch_auto_enable
|
|
* @details The ADC automatic switchover was enabled
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_ch_auto_enable(void)
|
|
{
|
|
adc_main_ctl__auto_sw__setf(ADC_MAIN_CTL_AUTO_SW_ENABLE);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_ch_auto_enable
|
|
* @details Disable the ADC automatic switching function
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_ch_auto_disable(void)
|
|
{
|
|
adc_main_ctl__auto_sw__setf(ADC_MAIN_CTL_AUTO_SW_DISABLE);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_ch_auto_set
|
|
* @details Set the channel to be switched automatically
|
|
* @param[in] ch : Automatic switching channel ( 1-->4 channel ¡ê?A bit represents a channel )
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_ch_auto_set(uint8_t ch)
|
|
{
|
|
adc_chan_ctl__chan_auto__setf(ch);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_ch_auto_set
|
|
* @details ADC channel selection for non-automatic switching channels
|
|
* @param[in] ch : 0 - 13(ADC_CH0_PIN21 - ADC_CH13_PIN6)
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_ch_not_auto_set(uint8_t ch)
|
|
{
|
|
adc_chan_ctl__select_chan__setf(ch);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_it_set
|
|
* @details ADC Interrupt setting
|
|
* @param[in] it :
|
|
* Bits Field Name Reset Value
|
|
* ----- ------------------ -----------
|
|
* 1 FIFO_ERROR_INT 0
|
|
* 0 READ_REQ_INT 0
|
|
*
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_it_set(uint8_t it)
|
|
{
|
|
adc_int_set(it);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_it_get
|
|
* @details Gets the ADC interrupt enable
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval nterrupt enable register
|
|
***************************************************************************************
|
|
*/
|
|
uint8_t xc_adc_it_get(void)
|
|
{
|
|
return adc_int_get();
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_data_get
|
|
* @details Get ADC sampling data
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval adc fifo data
|
|
***************************************************************************************
|
|
*/
|
|
uint32_t xc_adc_data_get(void)
|
|
{
|
|
return adc_fifo__fifo_dout__getf();
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_it_collectval_set
|
|
* @details ADC interrupts to save data
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void xc_adc_it_collectval_set(uint16_t val)
|
|
{
|
|
adc_it_val = val;
|
|
}
|
|
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief xc_adc_it_collectval_get
|
|
* @details Gets the data saved by the ADC interrupt
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval adc_it_val
|
|
***************************************************************************************
|
|
*/
|
|
uint16_t xc_adc_it_collectval_get(void)
|
|
{
|
|
return adc_it_val;
|
|
}
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief GADC_Handler
|
|
* @details ADC interrupts the callback function
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
void GADC_Handler(void)
|
|
{
|
|
adc_intr_callback();
|
|
adc_int_set(adc_int_get());
|
|
}
|
|
|
|
/**
|
|
**************************************************************************************
|
|
* @brief adc_intr_callback
|
|
* @details ADC interrupts the callback function that gets ADC sampled data
|
|
* @param[in] void
|
|
* @param[out] void
|
|
* @retval void
|
|
***************************************************************************************
|
|
*/
|
|
__WEAK void adc_intr_callback(void)
|
|
{
|
|
uint32_t adc_int;
|
|
uint32_t val;
|
|
|
|
uint8_t adc_count = 0;
|
|
ADC_FIFO_TypeDef_t *fifo_val = NULL;
|
|
uint8_t channel = adc_chan_ctl__select_chan__getf();
|
|
|
|
adc_int = adc_int_get();
|
|
|
|
if(!(adc_int & (ADC_INT_READ_REQ_INT_SET | ADC_INT_FIFO_ERROR_INT_SET)))
|
|
{
|
|
// DEBUG("adc error\n");
|
|
return;
|
|
}
|
|
|
|
fifo_val = (ADC_FIFO_TypeDef_t *)&val;
|
|
|
|
for(int t = 0; t < adc_fifo_ctl__read_req_thresh__getf(); t++)
|
|
{
|
|
val = adc_fifo_get();
|
|
|
|
if(fifo_val->chanel_1 != fifo_val->chanel_2)
|
|
{
|
|
DEBUG("channel error :%d\n", t);
|
|
break;
|
|
}
|
|
|
|
if(fifo_val->chanel_1 != channel)
|
|
{
|
|
DEBUG("channel error :%d\n", t);
|
|
break;
|
|
}
|
|
|
|
adc_value[adc_count++] = fifo_val->value_1;
|
|
adc_value[adc_count++] = fifo_val->value_2;
|
|
}
|
|
|
|
val = xc_adc_data_average(adc_value, adc_count);
|
|
xc_adc_it_collectval_set(val);
|
|
|
|
adc_chan_ctl__select_chan__setf(channel);
|
|
}
|
|
|
|
|