STM32L476 ADC多通道采集DMA传输的数据不正确
用STM32L476的ADC1采集6个通道,使用TIM4+DMA的方式,现在测试结果是DMA传输完成中断能正常响应但是传输的数据不符合预期,是错的,不知道哪里的问题。经测试用DMA传输一个通道数据时,数据是正确的,说明DMA的配置和ADC的配置没问题才对。相关代码:void Adc1_CH_Init(void)
{
uint32_t wait_loop_index;
LL_GPIO_InitTypeDef GPIO_InitStruct={0};
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
/* 使能相应时钟 */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK); /* 选择ADC的时钟源为sysclk->80M */
/* 配置ADC1采样通道 */
GPIO_InitStruct.Pin = LL_GPIO_PIN_4|LL_GPIO_PIN_5|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_4|LL_GPIO_PIN_5;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
LL_GPIO_EnablePinAnalogControl(GPIOA, LL_GPIO_PIN_4|LL_GPIO_PIN_5|LL_GPIO_PIN_7);
LL_GPIO_EnablePinAnalogControl(GPIOC, LL_GPIO_PIN_4|LL_GPIO_PIN_5);
/* ADC1初始化 */
/* 退出掉电模式 */
LL_ADC_DisableDeepPowerDown(ADC1);
/* 启动内部稳压器 */
LL_ADC_EnableInternalRegulator(ADC1);
/* 等待内部稳压器启动 */
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
/* 设置ADC分频系数 */
ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;
ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV6; /* 将ADC内核时钟频率设置为20M */
LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
/* 采样率设置 */
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_StartCalibration(ADC1, LL_ADC_SINGLE_ENDED);
/* 等待校准完成 */
while(LL_ADC_IsCalibrationOnGoing(ADC1) != 0UL);
wait_loop_index = ((LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES * 32) >> 1);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
/* 规则采样参数配置 */
ADC_REG_InitStruct.TriggerSource=LL_ADC_REG_TRIG_EXT_TIM4_TRGO;
// ADC_REG_InitStruct.DMATransfer=LL_ADC_REG_DMA_TRANSFER_LIMITED;
ADC_REG_InitStruct.DMATransfer=LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
ADC_REG_InitStruct.ContinuousMode=LL_ADC_REG_CONV_SINGLE;
ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
LL_ADC_REG_SetTriggerEdge(ADC1, LL_ADC_REG_TRIG_EXT_RISING);
/* 配置规则通道 */
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_9);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SAMPLINGTIME_92CYCLES_5);
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_10);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SAMPLINGTIME_92CYCLES_5);
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_12);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_92CYCLES_5);
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_13);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_13, LL_ADC_SAMPLINGTIME_92CYCLES_5);
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_13, LL_ADC_SINGLE_ENDED);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_14);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_14, LL_ADC_SAMPLINGTIME_92CYCLES_5);
LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_14, LL_ADC_SINGLE_ENDED);
/* 初始化采样定时器 */
Samp_TIM_Init();
DMA_Channel1_Init((uint32_t)&ADC1->DR, (uint32_t)Device.buff, SAMPLE_NUM);
}
void DMA_Channel1_Init(uint32_t srcaddr, uint32_t destaddr, uint16_t count)
{
LL_DMA_InitTypeDef LL_DMA_Struct;
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1);
LL_DMA_Struct.PeriphRequest=LL_DMA_REQUEST_0;
LL_DMA_Struct.Direction=LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
//LL_DMA_Struct.Mode=LL_DMA_MODE_NORMAL;
LL_DMA_Struct.Mode=LL_DMA_MODE_CIRCULAR;
LL_DMA_Struct.Priority=LL_DMA_PRIORITY_HIGH;
LL_DMA_Struct.NbData=count;
LL_DMA_Struct.PeriphOrM2MSrcAddress=(uint32_t)srcaddr;
LL_DMA_Struct.MemoryOrM2MDstAddress=(uint32_t)destaddr;
LL_DMA_Struct.PeriphOrM2MSrcDataSize=LL_DMA_PDATAALIGN_HALFWORD;
LL_DMA_Struct.MemoryOrM2MDstDataSize=LL_DMA_MDATAALIGN_HALFWORD;
LL_DMA_Struct.PeriphOrM2MSrcIncMode=LL_DMA_PERIPH_NOINCREMENT;
LL_DMA_Struct.MemoryOrM2MDstIncMode=LL_DMA_MEMORY_INCREMENT;
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &LL_DMA_Struct);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), SAMPLE_PRIORITY, 0));
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
}
void Samp_TIM_Init(void)
{
LL_TIM_InitTypeDef LL_TIM_Struct={0};
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
LL_TIM_Struct.Prescaler=79;
LL_TIM_Struct.Autoreload=999;/* 1000 */
LL_TIM_Struct.CounterMode=LL_TIM_COUNTERDIRECTION_UP;
LL_TIM_Struct.ClockDivision=LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM4, &LL_TIM_Struct);
LL_TIM_EnableARRPreload(TIM4);
LL_TIM_SetClockSource(TIM4, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM4, LL_TIM_TRGO_UPDATE);
LL_TIM_DisableCounter(TIM4);
}
<blockquote><blockquote>void Adc1_CH_Init(void)
找到问题了,我有个ADC通道输入电压为4V,这个4V我猜会导致ADC工作异常,因为我把这个4V的问题解决后,整个ADC部分程序都正常了。 这么说是这个通道采样电压过高影响到其它通道正常采集了。 谢谢分享!
页:
[1]