/**************************************************************************//** * @file adc.c * @version V1.00 * $Revision: 2$ * $Date: 16/02/25 15:53 $ * @brief Panchip series ADC driver source file * * @note * Copyright (C) 2016 Panchip Technology Corp. All rights reserved. *****************************************************************************/ #include "PanSeries.h" #include "pan_adc.h" #include "pan_sys.h" #include "math.h" /** @addtogroup Panchip_Device_Driver Panchip Device Driver @{ */ /** @addtogroup Panchip_ADC_Driver ADC Driver @{ */ /** @addtogroup Panchip_ADC_EXPORTED_FUNCTIONS ADC Exported Functions @{ */ ADC_OPT_T m_adc_opt; uint32_t global_calc_vbat_mv = 3300; static void bubble_sort_uint16(uint16_t *arr, size_t len) { uint16_t temp; for (size_t i = 0; i < len - 1; i++) { for (size_t j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } static void bubble_sort_float(float *arr, size_t len) { float temp; for (size_t i = 0; i < len - 1; i++) { for (size_t j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } /** * @brief Init ADC config parameters * @param[in] ADCx Base address of ADC module * @param[in] buf_en Enable ADC buffer or not * @return None */ bool ADC_Init(ADC_T *ADCx, bool buf_en) { uint32_t tmpreg; ADCx->BV_CTL |= BIT0; // Enable Bias Voltage Ctrl ADCx->BV_CTL = (ADCx->BV_CTL & ~BIT1) | (buf_en ? BIT1 : 0u); // Enable or disable buffer if (!isFtDataValid) { return false; } if (m_adc_opt.ft_version >= 6) { ADCx->CTL2 = m_adc_opt.adc_ctrl2; ADCx->EXTSMPT = m_adc_opt.adc_extsmpt; } else { // bit13:11 0'b100, bit10:8 0'b101 tmpreg = ADCx->CTL2; tmpreg &= ~(0x7ul << 8); tmpreg |= 5 << 8; tmpreg &= ~(0x7ul << 11); tmpreg |= 4 << 11; tmpreg &= ~(0x7ul << 20); tmpreg |= 7 << 20; tmpreg &= ~(0x7ul << 24); tmpreg |= 7 << 24; ADCx->CTL2 = tmpreg; ADCx->EXTSMPT = 0x00000008; } tmpreg = ADCx->BV_CTL; tmpreg &= ~(0x3Fu << 3); tmpreg |= m_adc_opt.adc_vbg_1v20_trim << 3; ADCx->BV_CTL = tmpreg; return true; } /** * @brief Prepare ADC VBG fitting curve paramters due to SoC VBAT level * @param[in] ADCx Base address of ADC module * @return None */ void ADC_PrepareVbgCalibData(ADC_T *ADCx) { // NOTE1: We assume ADC is already initialized! // NOTE2: We assume ADC input range is already specified! uint32_t chen_bkp = 0; uint32_t sample_code = 0; if (m_adc_opt.ft_version < 3) { // Only use in the SoC which ft_verison >= 3 return; } if (ADCx->CTL2 & ADC_SEL_VREF_Msk) { // Only use when the ADC reference is 1.2v VBG return; } if (ADCx->CHEN) { chen_bkp = ADCx->CHEN; } // Enable channel 10 (internal channel connected to vbat/4) ADC_Open(ADCx, ADC_CHEN_CH10_VDD_4_Msk); // Power on ADC ADC_PowerOn(ADCx); // Delay a while to wait adc stable if (m_adc_opt.chip_info >= 0x20) { SYS_delay_10nop(500); // Delay 100us+ } else { SYS_delay_10nop(10000); // Delay 3ms+ } for (size_t i = 0; i < 8; i++) { /* Start sampling */ ADC_StartConvert(ADC); /* Wait for sampling done */ while (!ADC_IsDataValid(ADC)) {} /* Process sampling result data */ sample_code += ADC_GetConversionData(ADC); // Delay 200us+ to wait adc stable if (m_adc_opt.chip_info < 0x20) { SYS_delay_10nop(1000); } } sample_code /= 8; // Power down ADC ADC_PowerDown(ADC); if (chen_bkp) { ADCx->CHEN = chen_bkp; } global_calc_vbat_mv = ((uint32_t)(m_adc_opt.adc_vbat_k / 10000.0 * sample_code + m_adc_opt.adc_vbat_b / 100.0));; } /** * @brief Convert adc code to voltage in uV * @param[in] ADCx Base address of ADC module * @param[in] adc_code Code sampled by ADC module * @return ADC sample voltage output in mV */ float ADC_OutputVoltage(ADC_T *ADCx, uint32_t adc_code) { float voltage_mv = 0; if (ADCx->CTL2 & ADC_SEL_VREF_Msk) // Ref src is Vbat { voltage_mv = m_adc_opt.adc_vdd_k / 10000.0 * adc_code + m_adc_opt.adc_vdd_b; // code to code voltage_mv = voltage_mv * global_calc_vbat_mv / 4096; } else // Ref src is ADC VBG (1.2v) { if (m_adc_opt.ft_version >= 3) { uint32_t calc_vbat_mv = global_calc_vbat_mv; uint32_t vol_list[] = {1800, 2100, 2400, 2700, 3000, 3300, 3600}; float V1, V2; float A; uint8_t vol_index = 0; for (uint8_t i = 0; i < 7; i++) { if (calc_vbat_mv <= vol_list[0]) { voltage_mv = (float)m_adc_opt.adc_vbg_kb[0].adc_vbg_k / 100000.0 * adc_code + m_adc_opt.adc_vbg_kb[0].adc_vbg_b / 100.0; break; } else if (calc_vbat_mv >= vol_list[6]) { voltage_mv = (float)m_adc_opt.adc_vbg_kb[6].adc_vbg_k / 100000.0 * adc_code + m_adc_opt.adc_vbg_kb[6].adc_vbg_b / 100.0; break; } if (calc_vbat_mv < vol_list[i]) { vol_index = i; V1 = (float)m_adc_opt.adc_vbg_kb[vol_index - 1].adc_vbg_k / 100000.0 * adc_code + m_adc_opt.adc_vbg_kb[vol_index - 1].adc_vbg_b / 100.0; V2 = (float)m_adc_opt.adc_vbg_kb[vol_index].adc_vbg_k / 100000.0 * adc_code + m_adc_opt.adc_vbg_kb[vol_index].adc_vbg_b / 100.0; A = (float)(calc_vbat_mv - vol_list[vol_index - 1]) / 300; voltage_mv = A * V2 + (1 - A) * V1; break; } } } else { voltage_mv = m_adc_opt.adc_vbg_k / 100000.0 * adc_code + m_adc_opt.adc_vbg_b / 100.0; } } return voltage_mv; } /** * @brief get caliration params relatd adc ft process * @param[in] ADC_OPT_T hold adc ft parameters * @return NULL */ void ADC_SetCalirationParams(OTP_STRUCT_T *opt) { m_adc_opt.chip_info = opt->m.chip_info; m_adc_opt.ft_version = opt->m.ft_version; m_adc_opt.adc_temp_volt = opt->m.adc_temp_volt; m_adc_opt.adc_vbg_1v20_trim = opt->m.adc_vbg_1v20_trim; m_adc_opt.adc_vbg_b = opt->m.adc_vbg_b; m_adc_opt.adc_vbg_k = opt->m.adc_vbg_k; m_adc_opt.adc_vdd_b = opt->m.adc_vdd_b; m_adc_opt.adc_vdd_k = opt->m.adc_vdd_k; m_adc_opt.current_temp_value = opt->m.current_temp_value; m_adc_opt.adc_vbat_k = opt->m_v2.adc_vbat_k; m_adc_opt.adc_vbat_b = opt->m_v2.adc_vbat_b; m_adc_opt.adc_vbat_dtemp_k = opt->m_v2.adc_vbat_dtemp_k; m_adc_opt.adc_vbat_dtemp_b = opt->m_v2.adc_vbat_dtemp_b; memcpy(m_adc_opt.adc_vbg_kb, opt->m_v2.adc_vbg_kb, sizeof(ADC_VBG_KB_T) * 7); m_adc_opt.adc_temp_k = opt->m_v2.adc_temp_k; m_adc_opt.adc_ctrl2 = opt->m_v2.adc_ctrl2; m_adc_opt.adc_extsmpt = opt->m_v2.adc_extsmpt; } /** * @brief Start sampling many data codes, trim several largest and smallest codes and calculate average valu * @param[in] ADCx Base address of ADC module * @param[in] sample_buf Buffer to temporarily store ADC sample code * @param[in] sample_cnt Total sampling count * @param[in] trim_cnt Total trim count, that means throw away the smallest trim_cnt/2 and largest trim_cnt/2 sample codes * @return ADC calculated sample code */ uint32_t ADC_SamplingCodeTrimMean(ADC_T *ADCx, uint16_t *sample_buf, uint32_t sample_cnt, uint32_t trim_cnt) { uint32_t sample_code = 0; // Handle exception if (sample_cnt <= trim_cnt) { return UINT32_MAX; // Error occurred } // Start sampling for (int i = 0; i < sample_cnt; i++) { ADC_StartConvert(ADCx); // Wait for sampling done while (!ADC_IsDataValid(ADCx)) { } // Process sampling result data sample_buf[i] = ADC_GetConversionData(ADCx); // Delay 200us+ to wait adc stable if (m_adc_opt.chip_info < 0x20) { SYS_delay_10nop(1000); } } // Filter out several largest and smallest data and calculate average value bubble_sort_uint16(sample_buf, sample_cnt); for (int i = trim_cnt / 2; i < (sample_cnt - trim_cnt / 2); i++) { sample_code += sample_buf[i]; } sample_code /= sample_cnt - trim_cnt; return sample_code; } /** * @brief Measure SoC Temperature using the ADC internal Channel 9 * @param[in] ADCx Base address of ADC module * @return ADC measured temperature in Celsius */ float ADC_MeasureSocTemperature(ADC_T *ADCx) { uint32_t u32TempReg = 0; float temp_param_k = (m_adc_opt.chip_info >= 0x20) ? (m_adc_opt.ft_version >= 6 ? m_adc_opt.adc_temp_k : 0.35) : -0.69; // t = k * (v - vFT) + tFT float voltage = 0; float temp_voltage_arr[128]; // Enable ADC channel 9 ADC_Open(ADCx, ADC_CHEN_CH9_TMP_Msk); // Change ADC Ref to ADC-VBG (1.2v) if is not if (ADCx->CTL2 & ADC_SEL_VREF_Msk) { ADC_SelInputRange(ADCx, ADC_INPUTRANGE_LOW); } // Prepare ADC vbg calib paramter due to currnet soc vbat after setting input range to the 0~1.2v ref ADC_PrepareVbgCalibData(ADCx); // Power on ADC ADC_PowerOn(ADCx); // Delay a while to wait adc stable if (m_adc_opt.chip_info >= 0x20) { SYS_delay_10nop(500); // Delay 100us+ } else { SYS_delay_10nop(50000); // Delay 15ms+ } // Start sampling for (int i = 0; i < 128; i++) { ADC_StartConvert(ADCx); // Wait for sampling done while (!ADC_IsDataValid(ADCx)) { } // Process sampling result data u32TempReg = ADC_GetConversionData(ADCx); temp_voltage_arr[i] = ADC_OutputVoltage(ADCx, u32TempReg); } // Power down ADC ADC_PowerDown(ADCx); // Filter out largest 8 and smallest 8 data and calculate average value bubble_sort_float(temp_voltage_arr, 128); for (int i = 8; i < 120; i++) { voltage += temp_voltage_arr[i]; } voltage /= 112; // Calculate and return current temp by formula: t = k * (v - vFT) + tFT - tDelta return temp_param_k * (voltage - (double)m_adc_opt.adc_temp_volt / 10.0) + (double)m_adc_opt.current_temp_value / 100.0 - (m_adc_opt.ft_version >= 5 ? ((double)m_adc_opt.adc_vbat_dtemp_k / 10000000.0 * global_calc_vbat_mv + (double)m_adc_opt.adc_vbat_dtemp_b / 1000.0) : 0); } /** * @brief Measure SoC Temperature More Fast using the ADC internal Channel 9 * @param[in] ADCx Base address of ADC module * @return ADC measured temperature in Celsius */ float ADC_MeasureSocTemperatureFast(ADC_T *ADCx) { uint32_t temp_code = 0; float temp_param_k = (m_adc_opt.chip_info >= 0x20) ? (m_adc_opt.ft_version >= 6 ? m_adc_opt.adc_temp_k : 0.35) : -0.69; // t = k * (v - vFT) + tFT float voltage = 0; uint16_t temp_code_arr[128]; // Check if current chip support this API if (m_adc_opt.chip_info < 0x20) { return -1.0f; } // Enable ADC channel 9 ADC_Open(ADCx, ADC_CHEN_CH9_TMP_Msk); // Change ADC Ref to ADC-VBG (1.2v) if is not if (ADCx->CTL2 & ADC_SEL_VREF_Msk) { ADC_SelInputRange(ADCx, ADC_INPUTRANGE_LOW); } // Prepare ADC vbg calib paramter due to currnet soc vbat after setting input range to the 0~1.2v ref ADC_PrepareVbgCalibData(ADCx); // Power on ADC ADC_PowerOn(ADCx); // Delay a while to wait adc stable SYS_delay_10nop(500); // Delay 100us+ // Start sampling for (int i = 0; i < 128; i++) { ADC_StartConvert(ADCx); // Wait for sampling done while (!ADC_IsDataValid(ADCx)) { } // Process sampling result data temp_code_arr[i] = ADC_GetConversionData(ADCx); } // Power down ADC ADC_PowerDown(ADCx); // Filter out largest 8 and smallest 8 data and calculate average value bubble_sort_uint16(temp_code_arr, 128); for (int i = 8; i < 120; i++) { temp_code += temp_code_arr[i]; } temp_code /= 112; // Calculate voltage of temp sensor voltage = ADC_OutputVoltage(ADCx, temp_code); // Calculate and return current temp by formula: t = k * (v - vFT) + tFT - tDelta return temp_param_k * (voltage - (double)m_adc_opt.adc_temp_volt / 10.0) + (double)m_adc_opt.current_temp_value / 100.0 - (m_adc_opt.ft_version >= 5 ? ((double)m_adc_opt.adc_vbat_dtemp_k / 10000000.0 * global_calc_vbat_mv + (double)m_adc_opt.adc_vbat_dtemp_b / 1000.0) : 0); } /** * @brief Measure SoC VBAT using the ADC internal Channel 10 * @param[in] ADCx Base address of ADC module * @return ADC measured VBAT voltage in mV */ uint16_t ADC_MeasureSocVbat(ADC_T *ADCx) { uint32_t u32TempReg = 0; float voltage = 0; float temp_voltage_arr[32]; // Enable channel 10 (internal channel connected to vbat/4) ADC_Open(ADCx, ADC_CHEN_CH10_VDD_4_Msk); // Change ADC Ref to ADC-VBG (1.2v) if is not if (ADCx->CTL2 & ADC_SEL_VREF_Msk) { ADC_SelInputRange(ADCx, ADC_INPUTRANGE_LOW); } // if (m_adc_opt.chip_info < 0x20) { // // Prepare ADC vbg calib paramter due to currnet soc vbat after setting input range to the 0~1.2v ref // ADC_PrepareVbgCalibData(ADCx); // } // Power on ADC ADC_PowerOn(ADCx); // Delay a while to wait adc stable if (m_adc_opt.chip_info >= 0x20) { SYS_delay_10nop(500); // Delay 100us+ } else { SYS_delay_10nop(50000); // Delay 15ms+ } // Start sampling for (int i = 0; i < 32; i++) { ADC_StartConvert(ADCx); // Wait for sampling done while (!ADC_IsDataValid(ADCx)) { } // Process sampling result data u32TempReg = ADC_GetConversionData(ADCx); if (m_adc_opt.ft_version >= 3) { temp_voltage_arr[i] = ((float)(m_adc_opt.adc_vbat_k / 10000.0 * u32TempReg + m_adc_opt.adc_vbat_b / 100.0)); } else { temp_voltage_arr[i] = ADC_OutputVoltage(ADCx, u32TempReg); } } // Power down ADC ADC_PowerDown(ADCx); // Filter out largest 8 and smallest 8 data and calculate average value bubble_sort_float(temp_voltage_arr, 32); for (int i = 8; i < 24; i++) { voltage += temp_voltage_arr[i]; } voltage /= 16; if (m_adc_opt.ft_version < 3) { voltage = (uint16_t)(4 * voltage + 0.5); // Rounding off } return voltage; } /** * @brief Disable ADC Power * @param[in] adc Base address of ADC module * @return None */ void ADC_Disable(ADC_T *ADCx) { // SYS->IPRST1 |= SYS_IPRST1_ADCRST_Msk; // SYS->IPRST1 &= ~SYS_IPRST1_ADCRST_Msk; ADCx->CTL &= ~ADC_CTL_ADCEN_Msk; return; } /** * @brief Disable ADC module * @param[in] adc Base address of ADC module * @return None */ void ADC_Close(void) { // SYS->IPRST1 |= SYS_IPRST1_ADCRST_Msk; // SYS->IPRST1 &= ~SYS_IPRST1_ADCRST_Msk; // return; } /** * @brief Configure the hardware trigger condition and enable hardware trigger * @param[in] adc Base address of ADC module * @param[in] u32Source Decides the hardware trigger source. Valid values are: * - \ref ADC_TRIGGER_BY_EXT_PIN * - \ref ADC_TRIGGER_BY_PWM * @param[in] u32Param While ADC trigger by PWM, this parameter is used to set the delay between PWM * trigger and ADC conversion. Valid values are from 0 ~ 0xFF, and actual delay * time is (4 * u32Param * HCLK). While ADC trigger by external pin, this parameter * is used to set trigger condition. Valid values are: * - \ref ADC_FALLING_EDGE_TRIGGER * - \ref ADC_RISING_EDGE_TRIGGER * @return None */ void ADC_EnableHWTrigger(ADC_T *ADCx,uint32_t Source,uint32_t TrgCondition) { ADCx->CTL &= ~(ADC_TRIGGER_BY_PWM | ADC_RISING_EDGE_TRIGGER | ADC_CTL_HWTRGEN_Msk); if(Source == ADC_TRIGGER_BY_EXT_PIN) { ADCx->CTL &= ~(ADC_CTL_HWTRGSEL_Msk | ADC_CTL_HWTRGCOND_Msk); ADCx->CTL |= (Source | TrgCondition); } else { ADCx->CTL |= Source; } ADCx->CTL |= ADC_CTL_HWTRGEN_Msk; return; } /** * @brief Disable hardware trigger ADC function. * @param[in] adc Base address of ADC module * @return None */ void ADC_DisableHWTrigger(ADC_T *ADCx) { ADCx->CTL &= ~(ADC_TRIGGER_BY_PWM | ADC_RISING_EDGE_TRIGGER | ADC_CTL_HWTRGEN_Msk); } /** * @brief Enable the interrupt(s) selected by u32Mask parameter. * @param[in] adc Base address of ADC module * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit * corresponds to a interrupt status. This parameter decides which * interrupts will be enabled. * - \ref ADC_ADIF_INT * - \ref ADC_CMP0_INT * - \ref ADC_CMP1_INT * @return None */ void ADC_EnableInt(ADC_T *ADCx, uint32_t Mask) { if(Mask & ADC_ADIF_INT) ADCx->CTL |= ADC_CTL_ADCIEN_Msk; if(Mask & ADC_CMP0_INT) ADCx->CMP0 |= ADC_CMP0_ADCMPIE_Msk; if(Mask & ADC_CMP1_INT) ADCx->CMP1 |= ADC_CMP1_ADCMPIE_Msk; return; } /** * @brief Disable the interrupt(s) selected by u32Mask parameter. * @param[in] adc Base address of ADC module * @param[in] u32Mask The combination of interrupt status bits listed below. Each bit * corresponds to a interrupt status. This parameter decides which * interrupts will be disabled. * - \ref ADC_ADIF_INT * - \ref ADC_CMP0_INT * - \ref ADC_CMP1_INT * @return None */ void ADC_DisableInt(ADC_T *ADCx, uint32_t Mask) { if(Mask & ADC_ADIF_INT) ADCx->CTL &= ~ADC_CTL_ADCIEN_Msk; if(Mask & ADC_CMP0_INT) ADCx->CMP0 &= ~ADC_CMP0_ADCMPIE_Msk; if(Mask & ADC_CMP1_INT) ADCx->CMP1 &= ~ADC_CMP1_ADCMPIE_Msk; return; } /** * @brief ADC PWM Sequential Mode Control. * @param[in] adc Base address of ADC module * @param[in] u32SeqTYPE This parameter decides which type will be selected. * - \ref ADC_SEQMODE_TYPE_23SHUNT * - \ref ADC_SEQMODE_TYPE_1SHUNT * @param[in] u32ModeSel This parameter decides which mode will be selected. * - \ref ADC_SEQMODE_MODESELECT_CH01 * - \ref ADC_SEQMODE_MODESELECT_CH12 * - \ref ADC_SEQMODE_MODESELECT_CH02 * - \ref ADC_SEQMODE_MODESELECT_ONE * @return None */ void ADC_SeqModeEnable(ADC_T *ADCx, uint32_t SeqType, uint32_t ModeSel) { // Enable ADC Sequential Mode ADCx->SEQCTL = ADCx->SEQCTL | ADC_SEQCTL_SEQEN_Msk; // Select ADC Sequential Mode Type ADCx->SEQCTL = (ADCx->SEQCTL & ~(ADC_SEQCTL_SEQTYPE_Msk)) | (SeqType << ADC_SEQCTL_SEQTYPE_Pos); // Select ADC Sequential Mode Type ADCx->SEQCTL = (ADCx->SEQCTL & ~(ADC_SEQCTL_MODESEL_Msk)) | (ModeSel << ADC_SEQCTL_MODESEL_Pos); return; } /** * @brief ADC PWM Sequential Mode PWM Trigger Source and type. * @param[in] adc Base address of ADC module * @param[in] u32SeqModeTriSrc1 This parameter decides first PWM trigger source and type. * * * @return None */ void ADC_SeqModeTriggerSrc(ADC_T *ADCx, uint32_t SeqModeTriSrc) { // Select PWM Trigger Source Selection for TRG1CTL or TRG2CTL if(ADCx->SEQCTL & ADC_SEQCTL_TRG_SEL_Msk) ADCx->SEQCTL = (ADCx->SEQCTL & ~(ADC_SEQCTL_TRG2CTL_Msk)) | (SeqModeTriSrc << ADC_SEQCTL_TRG2CTL_Pos); else ADCx->SEQCTL = (ADCx->SEQCTL & ~(ADC_SEQCTL_TRG1CTL_Msk)) | (SeqModeTriSrc << ADC_SEQCTL_TRG1CTL_Pos); return; } /** * @brief Configure the comparator 0 and enable it * @param[in] adc Base address of ADC module * @param[in] ChNum Specifies the source channel, valid value are from 0 to 7 * @param[in] CmpCondition Specifies the compare condition * - \ref ADC_CMP0_LESS_THAN * - \ref ADC_CMP0_GREATER_OR_EQUAL_TO * @param[in] CmpData Specifies the compare value. Valid value are between 0 ~ 0x3FF * @param[in] MatchCnt Specifies the match count setting, valid values are between 1~16 * @param[in] CmpSelect comparator select,0 or 1 * @return None * @details For example, ADC_CompareEnable(ADC, 5, ADC_CMP_GREATER_OR_EQUAL_TO, 0x800, 10,ADC_COMPARATOR_0); * Means ADC will assert comparator 0 flag if channel 5 conversion result is * greater or equal to 0x800 for 10 times continuously. * \hideinitializer */ void ADC_CompareEnable(ADC_T *ADCx, uint32_t ChNum, uint32_t CmpCondition, uint32_t CmpData, uint32_t MatchCnt, uint32_t CmpSelect) { uint32_t TmpRegister; if(ADC_COMPARATOR_1 == CmpSelect) TmpRegister = ADC->CMP1; else TmpRegister = ADC->CMP0; TmpRegister |= (ChNum << ADC_CMP0_CMPCH_Pos); //select compare channel TmpRegister |= CmpCondition; //select compare condition(less than or greater than ) TmpRegister |= (CmpData << ADC_CMP0_CMPDAT_Pos); //set expect compare data TmpRegister |= ((MatchCnt - 1) << ADC_CMP0_CMPMCNT_Pos); //set compare match count if(ADC_COMPARATOR_1 == CmpSelect){ TmpRegister |= ADC_CMP1_ADCMPEN_Msk; //comparator enable ADC->CMP1 = TmpRegister; } else{ TmpRegister |= ADC_CMP0_ADCMPEN_Msk; //comparator enable ADC->CMP0 = TmpRegister; } } /** * @brief set ADC PWM one channel Sequential Mode configuration. * @param[in] adc Base address of ADC module * @param[in] Trig This parameter decides first PWM trigger source and type. * @param[in] Level This parameter decides fifo threshold value. * @param[in] DmaEn This parameter decides dma is used or not. * @param[in] HwClrEN This parameter decides PWM trigger flag cleared by hardware or software. * @param[in] AdcCh This parameter decides which adc channel selected. * @return None */ void ADC_SeqOneChModeConfig(ADC_T *ADCx, uint32_t Trig, uint8_t Level, uint8_t DmaEn, uint8_t HwClrEN) { // ADC Hardware External trigger Enabled by PMW ADC_EnableHWTrigger(ADCx, ADC_TRIGGER_BY_PWM, Trig); ADC_SetFifoTrigLevel(ADCx,Level); if(DmaEn) ADC_DmaModeEnable(ADCx,ENABLE); else ADC_DmaModeEnable(ADCx,DISABLE); // ADC Sequential mode & type Enable ADC_SeqModeEnable(ADCx,ADC_SEQMODE_TYPE_23SHUNT,ADC_SEQMODE_MODESELECT_ONE); ADC_SeqModeOneChEn(ADCx,ENABLE); if(HwClrEN) ADC_ClearByHw(ADCx,ENABLE); else ADC_ClearByHw(ADCx,DISABLE); } /*@}*/ /* end of group Panchip_ADC_EXPORTED_FUNCTIONS */ /*@}*/ /* end of group Panchip_ADC_Driver */ /*@}*/ /* end of group Panchip_Device_Driver */ /*** (C) COPYRIGHT 2016 Panchip Technology Corp. ***/