完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
通过DMA将采集的ADC->DR的数据向adc_dma_buf[6]这个变量传输(指定的内存地址为adc_dma_buff[0]),CHSELR寄存器的值依次为5,6,7,8,9,10,F,0,实际测试的时候,AIN5的ADC转换结果被传输到了adc_dma_buff[1],AIN6的ADC转换结果被传输到了adc_dma_buff[2],以此类推,AIN10的转换结果被传输到了adc_dma_buff[0],而且数值也都是正确的。网上又说把`ADC_CFGR1.DMACFG置0的,但是这个置0后就不会自动连续传输了,而且成功的转这次转换,也是如上述一样错位。
从现象来看,好像ADC首先开启的是AIN10的转换。有人知道这是啥原因么? 初始化代码如下: void MX_ADC1_Init(void){/[i] USER CODE BEGIN ADC1_Init 0 / LL_DMA_InitTypeDef DMA_Init_Struct;LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);/[i] USER CODE END ADC1_Init 0 / LL_ADC_InitTypeDef ADC_InitStruct = {0};LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /[i] Peripheral clock enable /LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB); GPIO_InitStruct.Pin = LL_GPIO_PIN_5;GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_6;GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_7;GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_0;GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_1;GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_2;GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(GPIOB, &GPIO_InitStruct); /[i] ADC1 DMA Init //[i] USER CODE BEGIN ADC1_DMA_Init 1 / DMA_Init_Struct.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;DMA_Init_Struct.MemoryOrM2MDstAddress = (uint32_t)(adc_dma_data);DMA_Init_Struct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;DMA_Init_Struct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;DMA_Init_Struct.Mode = LL_DMA_MODE_CIRCULAR;DMA_Init_Struct.NbData = 6;DMA_Init_Struct.PeriphOrM2MSrcAddress = (uint32_t)(&ADC1->DR);DMA_Init_Struct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;DMA_Init_Struct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; DMA_Init_Struct.PeriphRequest = LL_DMAMUX_REQ_ADC1;DMA_Init_Struct.Priority = LL_DMA_PRIORITY_LOW; LL_DMA_Init(DMA1,LL_DMA_CHANNEL_1,&DMA_Init_Struct); /[i] USER CODE END ADC1_DMA_Init 1 / ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV2;ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;LL_ADC_Init(ADC1, &ADC_InitStruct);LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_CONFIGURABLE); /[i] Poll for ADC channel configuration ready /while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0){}LL_ADC_ClearFlag_CCRDY(ADC1);ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS;ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;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_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_12CYCLES_5);LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_2, LL_ADC_SAMPLINGTIME_12CYCLES_5);LL_ADC_DisableIT_EOC(ADC1);LL_ADC_DisableIT_EOS(ADC1); /[i] Enable ADC internal voltage regulator /LL_ADC_EnableInternalRegulator(ADC1); uint32_t wait_loop_index;wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US [i](SystemCoreClock / (100000 2))) / 10);while(wait_loop_index != 0){wait_loop_index--;} LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_5);while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0);LL_ADC_ClearFlag_CCRDY(ADC1);LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_5, LL_ADC_SAMPLINGTIME_COMMON_1); LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_6);while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0);LL_ADC_ClearFlag_CCRDY(ADC1);LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_COMMON_1); LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_7);while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0);LL_ADC_ClearFlag_CCRDY(ADC1);LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SAMPLINGTIME_COMMON_1); LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_8);while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0);LL_ADC_ClearFlag_CCRDY(ADC1);LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_8, LL_ADC_SAMPLINGTIME_COMMON_1); LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_9);while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0);LL_ADC_ClearFlag_CCRDY(ADC1);LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SAMPLINGTIME_COMMON_1); LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_6, LL_ADC_CHANNEL_10);while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0);LL_ADC_ClearFlag_CCRDY(ADC1);LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SAMPLINGTIME_COMMON_1); LL_ADC_StartCalibration(ADC1);while(LL_ADC_IsCalibrationOnGoing(ADC1)){} LL_ADC_Enable(ADC1);while(LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0);LL_ADC_REG_StartConversion(ADC1);LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1); } |
|
相关推荐
1个回答
|
|
|
这个错位问题在STM32的ADC+DMA应用中相当常见,尤其在新器件上初试配置时。根本原因在于ADC在启动第一个转换序列时,其内部状态或DMA请求的同步问题。以下是详细分析和解决方案: 问题分析:
解决方案 (选择其一): 下面的方法都是在启动真正连续转换之前,丢弃第一个错误的转换序列。 方法一 (推荐):校准后立即启动一次单次转换并丢弃结果 (G0首选) 方法二:启动DMA传输之前,在初始化序列中手动触发一次扫描并忽略DMA请求/结果 选择哪个方法?
重要检查点:
总结: 问题的核心是ADC在首次转换启动时,其内部通道选择状态机没有准备好从你指定的第一个通道开始。通过在正式启动连续DMA传输之前,执行一次校准和/或启动一次完整的转换序列(并使用单次转换或手动停止序列)并丢弃其结果,可以“重置”ADC的内部状态,确保随后的连续转换序列完美地按照 建议你优先尝试 方法一 (配置好ADC后先Calibration,然后临时设置CHSELR指向一个未用的通道进行单次Polling转换并丢弃结果)。这个方法在实践中成功率高且易于实现。调试时可暂时加大初始化步骤间的延迟或检查相关寄存器配置是否与你预期完全一致。 |
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
4125 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
3216 浏览 1 评论
2742 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
2170 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
14918 浏览 2 评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
3079浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
1888浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
2061浏览 3评论
1973浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
2162浏览 3评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-1 10:38 , Processed in 0.477345 second(s), Total 41, Slave 34 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
644