Files
hpw421/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_adc.c
T
2026-06-06 16:49:48 +08:00

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);
}