完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
说明:驱动基于STm32G031K6测试,其他型号需自行做改动。
ADC的初始化: #define ADCIO1_IN_CHANNEL LL_ADC_CHANNEL_5 #define ADCIO2_IN_CHANNEL LL_ADC_CHANNEL_7 uint8_t STM32LLADC1Init(void) { LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; LL_ADC_InitTypeDef ADC_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC); //使能ADC时钟 LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); //谁能响应ADCioGpio时钟 /**ADC1 GPIO Configuration PA5 ------> ADC1_IN5 PA7 ------> ADC1_IN7 */ GPIO_InitStruct.Pin = gpioADCIO1_IN_PIN; //ADC检测IO初始化 GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = gpioADCIO2_IN_PIN; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; //ADC定时转化触发条件来源,可以为软件触发或硬件(外部中断、定时器)触发。 ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS; //ADC顺序采集通道的个数,根据自己需要的通道个数设置 ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; // ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE; //采集方式,单次采集还是连续采集 ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED; //使能DMA,并使用无限传输,如果DMA保存方式为循环覆盖的话才可以使用无限传输。 ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN; //采集的数据循环覆盖模式 LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct); LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE); //失能过采样 LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_CLOCK_FREQ_MODE_HIGH); //采样时钟使用高频模式 LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_CONFIGURABLE); //adc通道和硬件adc in是否强制对应,因为adc的io使用时不是连续的,所以这里使用可自定义配置 LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_160CYCLES_5); //设置通道共用取样时间,根据需要自行选择 LL_ADC_DisableIT_EOC(ADC1); //禁用通道采样结束中断 LL_ADC_DisableIT_EOS(ADC1); //禁用序列采样结束中断,因为使用的是单次软件触发所以这里关闭这些中断 ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV2; //选择采样时钟来源 ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; //采样分辨率 ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; //采样数据对齐方式,右对齐高位补0,左对齐低位补0. ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE; //低功耗模式,使用DMA的话无法使用,这里关闭 LL_ADC_Init(ADC1, &ADC_InitStruct); /** Configure Regular Channel */ //ADC_RegularChannelConfig LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, ADCIO1_IN_CHANNEL); //将硬件通道ADCIO1_IN_CHANNEL映射到ADC通道1 LL_ADC_SetChannelSamplingTime(ADC1, ADCIO1_IN_CHANNEL, LL_ADC_SAMPLINGTIME_COMMON_1); //设置通道采样时间 LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, ADCIO2_IN_CHANNEL); //将硬件通道ADCIO1_IN_CHANNEL映射到ADC通道2 LL_ADC_SetChannelSamplingTime(ADC1, ADCIO2_IN_CHANNEL, LL_ADC_SAMPLINGTIME_COMMON_1); //设置通道采样时间 /*采样数据转换时需要参考电压,参考电压可能是变化的,所以也有可能需要采集*/ //LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_VREFINT); //LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_COMMON_1); return 1; } 激活并校准ADC: uint8_t STM32ActivateADC1(void) { __IO uint32_t wait_loop_index = 0U; __IO uint32_t backup_setting_adc_dma_transfer = 0U; uint32_t Timeout = 0U; /* Variable used for timeout management */ /*## Operation on ADC hierarchical scope: ADC instance #####################*/ /* Note: Hardware constraint (refer to description of the functions */ /* below): */ /* On this STM32 serie, setting of these features is conditioned to */ /* ADC state: */ /* ADC must be disabled. */ /* Note: In this example, all these checks are not necessary but are */ /* implemented anyway to show the best practice usages */ /* corresponding to reference manual procedure. */ /* Software can be optimized by removing some of these checks, if */ /* they are not relevant considering previous settings and actions */ /* in user application. */ if (LL_ADC_IsEnabled(ADC1) == 0) { /* Enable ADC internal voltage regulator */ LL_ADC_EnableInternalRegulator(ADC1); /* Delay for ADC internal voltage regulator stabilization. */ /* Compute number of CPU cycles to wait for, from delay in us. */ /* Note: Variable divided by 2 to compensate partially */ /* CPU processing cycles (depends on compilation optimization). */ /* Note: If system core clock frequency is below 200kHz, wait time */ /* is only a few CPU processing cycles. */ wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10); while(wait_loop_index != 0) { wait_loop_index--; } /* Disable ADC DMA transfer request during calibration */ /* Note: Specificity of this STM32 serie: Calibration factor is */ /* available in data register and also transfered by DMA. */ /* To not insert ADC calibration factor among ADC conversion data */ /* in DMA destination address, DMA transfer must be disabled during */ /* calibration. */ backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(ADC1); LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE); /* Run ADC self calibration */ LL_ADC_StartCalibration(ADC1); /* Poll for ADC effectively calibrated */ Timeout = ADC_CALIBRATION_TIMEOUT_MS; while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0) { /* Check Systick counter flag to decrement the time-out value */ if (LL_SYSTICK_IsActiveCounterFlag()) { if(Timeout-- == 0) { return 0; } } } /* Restore ADC DMA transfer request after calibration */ LL_ADC_REG_SetDMATransfer(ADC1, backup_setting_adc_dma_transfer); /* Delay between ADC end of calibration and ADC enable. */ /* Note: Variable divided by 2 to compensate partially */ /* CPU processing cycles (depends on compilation optimization). */ wait_loop_index = (ADC_DELAY_CALIB_ENABLE_CPU_CYCLES >> 1); while(wait_loop_index != 0) { wait_loop_index--; } /* Enable ADC */ LL_ADC_Enable(ADC1); /* Poll for ADC ready to convert */ Timeout = ADC_ENABLE_TIMEOUT_MS; while (LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0) { /* Check Systick counter flag to decrement the time-out value */ if (LL_SYSTICK_IsActiveCounterFlag()) { if(Timeout-- == 0) { return 0; } } } /* Note: ADC flag ADRDY is not cleared here to be able to check ADC */ /* status afterwards. */ /* This flag should be cleared at ADC Deactivation, before a new */ /* ADC activation, using function "LL_ADC_ClearFlag_ADRDY()". */ } return 1; } 因为ADC配置的是软件触发的单次采样,所以还需要有手动开始和结束采样的函数。 使能ADC采样: uint8_t STM32ADC1SampleEnable(void) { uint32_t Timeout = ADC_ENABLE_TIMEOUT_MS; LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_4); //先使能dma再使能adc,以防采样数据丢失 LL_ADC_Enable(ADC1); Timeout = ADC_ENABLE_TIMEOUT_MS; while(LL_ADC_IsActiveFlag_ADRDY(ADC1) != SET) { if(Timeout-- == 0) { LOG(1,"STM32ADC1SampleEnable ERROR!!!"); return 0; } } LL_ADC_REG_StartConversion(ADC1); return 1; } 失能ADC采样: uint8_t STM32ADC1SampleDisable(void) { uint32_t Timeout = ADC_DISABLE_TIMEOUT_MS; LL_ADC_REG_StopConversion(ADC1); while(LL_ADC_REG_IsConversionOngoing(ADC1) != 0) { if(Timeout-- == 0) { LOG(1,"STM32ADC1SampleDisenable ERROR!!!"); return 0; } } LL_ADC_Disable(ADC1); //先关闭adc再断开dma,以防采样数据丢失 LL_DMA_DisableChannel(DMA1,LL_DMA_CHANNEL_4); return 1; } 进行ADC数据采集流程(采用多次采样求平均值的方式): 1、当需要开始采样前,调用一次STM32ADC1SampleEnable()函数; 2、在一个定时函数内调用LL_ADC_REG_StartConversion(ADC1)进行数据的转换(因为使用的是单次采样,所以每次进入定时函数时都需要调用),取出DMA数据进行累加; 3、达到需要的采样次数之后,对得到的数据进行运算,并调用STM32ADC1SampleDisable()函数关闭ADC通道。 以上方式适用于需要间隔一段时间获取一次ADC数据时使用,例如需要每隔1分钟获取电池电压时,可以进行1分钟倒计时,然后连续进行十次间隔10ms的ADC采样求平均值。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1537 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1490 浏览 1 评论
910 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
654 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1538 浏览 2 评论
1845浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
596浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
499浏览 3评论
499浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
483浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 16:17 , Processed in 0.763955 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号