#include "app_adc_dma.h" #include "py32f0xx_ll_gpio.h" #include "py32f0xx_ll_adc.h" #include "py32f0xx_ll_utils.h" #include "py32f0xx_ll_bus.h" #include "py32f0xx_ll_dma.h" /* Private define ------------------------------------------------------------*/ #define ADC_CALIBRATION_TIMEOUT_MS ((uint32_t) 1) #define VDDA_APPLI ((uint32_t)3300) #define VAR_CONVERTED_DATA_INIT_VALUE (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B) + 1) /* Private variables ---------------------------------------------------------*/ __IO uint32_t ADCxConvertedDatas[6]; uint8_t ADC_CONV = 0; uint16_t Current_mA[6]; /** * @brief ADC配置函数 * @param 无 * @retval 无 */ void APP_AdcConfig(void) { /* 配置ADC通道和管脚 */ /* 使能GPIOA时钟 */ LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); /* 配置管脚PA0/1/2/3为模拟输入 */ LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_0| LL_GPIO_PIN_1| LL_GPIO_PIN_2 \ | LL_GPIO_PIN_3, LL_GPIO_MODE_ANALOG); /* ADC通道和时钟源需在ADEN=0时配置,其余的需在ADSTART=0时配置 */ /* 配置内部转换通道,使能VREFINT 和 temperature Sensor */ LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT | \ LL_ADC_PATH_INTERNAL_TEMPSENSOR); /* 设置ADC时钟 */ LL_ADC_SetClock(ADC1, LL_ADC_CLOCK_SYNC_PCLK_DIV32);//LL_ADC_CLOCK_SYNC_PCLK_DIV2); /* 设置12位分辨率 */ LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B); /* 设置数据右对齐 */ LL_ADC_SetResolution(ADC1, LL_ADC_DATA_ALIGN_RIGHT); /* 设置低功耗模式无 */ LL_ADC_SetLowPowerMode(ADC1, LL_ADC_LP_MODE_NONE); /* 设置通道转换时间 */ LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_239CYCLES_5); /* 设置触发源为Software */ LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_SOFTWARE); /* 设置转换模式为单次转换 */ LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_SINGLE); /* 设置DMA模式为循环 */ LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_UNLIMITED); /* 设置过载管理模式为覆盖上一个值 */ LL_ADC_REG_SetOverrun(ADC1, LL_ADC_REG_OVR_DATA_OVERWRITTEN); /* 扫描方向为向上 */ LL_ADC_REG_SetSequencerScanDirection(ADC1,LL_ADC_REG_SEQ_SCAN_DIR_FORWARD); /* 设置非连续模式为不使能 */ LL_ADC_REG_SetSequencerDiscont(ADC1, LL_ADC_REG_SEQ_DISCONT_DISABLE); /* 设置通道0-3, vrefint为转换通道 */ LL_ADC_REG_SetSequencerChannels(ADC1,LL_ADC_CHANNEL_0 | LL_ADC_CHANNEL_1 \ | LL_ADC_CHANNEL_2 | LL_ADC_CHANNEL_3 \ | LL_ADC_CHANNEL_VREFINT \ | LL_ADC_CHANNEL_TEMPSENSOR); } /** * @brief ADC校准函数 * @param 无 * @retval 无 */ void APP_AdcCalibrate(void) { __IO uint32_t wait_loop_index = 0; __IO uint32_t backup_setting_adc_dma_transfer = 0; #if (USE_TIMEOUT == 1) uint32_t Timeout = 0; #endif if (LL_ADC_IsEnabled(ADC1) == 0) { /* 校准时关闭ADC的DMA配置 */ backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(ADC1); LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE); /* 使能校准 */ LL_ADC_StartCalibration(ADC1); #if (USE_TIMEOUT == 1) Timeout = ADC_CALIBRATION_TIMEOUT_MS; #endif while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0) { #if (USE_TIMEOUT == 1) /* 检测校准是否超时 */ if (LL_SYSTICK_IsActiveCounterFlag()) { if(Timeout-- == 0) { } } #endif } /* ADC校准结束和使能ADC之间的延时最低4个ADC Clock */ LL_mDelay(1); /* 还原ADC的DMA配置 */ LL_ADC_REG_SetDMATransfer(ADC1, backup_setting_adc_dma_transfer); } } /** * @brief ADC使能函数 * @param 无 * @retval 无 */ void APP_AdcEnable(void) { /* 使能ADC */ LL_ADC_Enable(ADC1); /* 使能ADC 稳定时间,最低8个ADC Clock */ LL_mDelay(1); } /** * @brief DMA配置函数 * @param 无 * @retval 无 */ void APP_DmaConfig() { /* 使能DMA1 时钟 */ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); /* 使能syscfg 时钟 */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG); /* ADC对应通道LL_DMA_CHANNEL_1 */ SET_BIT(SYSCFG->CFGR3, 0x0); /* 配置DMA传输方向为外设到存储器 */ LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); /* 配置DMA优先级为高 */ LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_HIGH); /* 配置DMA循环模式 */ LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR); /* 配置DMA外设地址不变模式 */ LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT); /* 配置DMA存储地址自增模式 */ LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT); /* 配置DMA外设传输方式为字 */ LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_WORD); /* 配置DMA存储器传输方式为字 */ LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_WORD); /* 配置DMA传输长度为4 */ LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, 6); /* 配置DMA外设和存储器的地址 */ LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&ADC1->DR,\ (uint32_t)ADCxConvertedDatas, LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1)); /* 使能DMA传输完成中断 */ LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); /* DMA中断配置 */ NVIC_SetPriority(DMA1_Channel1_IRQn, 0); NVIC_EnableIRQ(DMA1_Channel1_IRQn); /* 使能DMA */ LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); } /** * @brief DMA传输完成回调函数 * @param 无 * @retval 无 */ void APP_DMATransferCompleteCallback() { for(int i = 0; i< 5; i++) { Current_mA[i] = __LL_ADC_CALC_DATA_TO_VOLTAGE(VDDA_APPLI, \ ADCxConvertedDatas[i], LL_ADC_RESOLUTION_12B); } Current_mA[5] = __LL_ADC_CALC_TEMPERATURE(VDDA_APPLI, ADCxConvertedDatas[5], LL_ADC_RESOLUTION_12B); ADC_CONV = 1; } /************************ (C) COPYRIGHT Puya *****END OF FILE******************/