/*! * \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); }