|
通过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) {/ USER CODE BEGIN ADC1_Init 0 / LL_DMA_InitTypeDef DMA_Init_Struct; LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); / 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}; / 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); / ADC1 DMA Init / / 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; LL_DMA_Init(DMA1,LL_DMA_CHANNEL_1,&DMA_Init_Struct); / 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; / 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_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); / Enable ADC internal voltage regulator /
LL_ADC_EnableInternalRegulator(ADC1); 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); } |
STM32G071C8的ADC问题,测量6路交流信号,端口使用PA2-PA7,信号来自电流互感器次级用20欧电阻转为电压信号,并联T4,通过1K,104滤波后到ADC引脚,个别芯片出现PA3结果是固定值,即使直接把引脚对地短短接,结果也是2000多个数,可能是什么原因
STM32G030F6P6TR 48MHz下Flash擦写必HardFault?官方库疑似有坑,求勘误或替代方案
使用STM32H7A3的FMC接口驱动LCD 是否可以用DMA传输数据
STM32G4 ADC 注入通道间断模式异常
STM32F3系列SDADC外部触发 DMA运输的bug
串口DMA收发出现ORE错误
stm32g071的rtc初始化后会直接进入中断怎么办?
STM32G030死机问题
实现最高速率 ADC 数据转 USB 传输
MCU的ADC进行电压采集时,外部输入阻抗最大能到多少?
微信公众号
手机版
对于STM32G0系列来说,这里有两种配置模式,如果所用硬件通道号大于14以后,
就只能配置为not fully configurable模式,这时 转换顺序按默认硬件变化,转换方向
要么从前往后 要么从后往前。
另外一种模式就是fully configruable模式,这时转换顺序可以根据RANK配置。
如果所用硬件通道编号不超过14,两种模式都可以。
我刚才使用cubeMx和HAL库组织代码测试了下,传输符合设计预期。
会不会你代码方面有问题?
现在所用通道都到15了,你这句配置是有问题的:
LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_CONFIGURABLE);
应该是
LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_FIXED);
还没等来大神回复啊,自顶一下。
没看明白楼主的描述,是不是同时开通了多个ADC通道,然后通过DMA连续获得转换结果,然而DMA数组中数据的顺序与通道设置的顺序不一致。
我之前做过双通道示波器的实验,开通了两个转换通道,也是通过DMA来获得转换结果,然后通过DMA数组下标的奇偶来区分通道1或通道2。实验结果大部分时间转换结果是正常的,但是偶尔会两个通道的数据交换,原来偶数下标的数据成为了通道2的,也就是说转换时通道的先后次序改变了。我分析了很久都没有找到原因,多方求助也没有结果,最后实验没能得到预期的结果。
当然,转换结果会有些许偏差,但不影响顺序。
我这边测试,发现这样写校准函数不合适,可以照搬库里面的例程准函数的写法。
[md]谢谢,回头我试试。
谢谢,回头我试试。