你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32L476 ADC多通道采集DMA传输的数据不正确

[复制链接]
mvvm 提问时间:2020-5-3 16:29 /
悬赏5ST金币未解决
用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);
}

  1. <blockquote><blockquote>void Adc1_CH_Init(void)
复制代码


收藏 评论3 发布时间:2020-5-3 16:29

举报

3个回答
mvvm 最优答案 回答时间:2020-5-3 17:48:44
找到问题了,我有个ADC通道输入电压为4V,这个4V我猜会导致ADC工作异常,因为我把这个4V的问题解决后,整个ADC部分程序都正常了。
hujjj 回答时间:2020-5-3 18:04:10
这么说是这个通道采样电压过高影响到其它通道正常采集了。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

likang1202 回答时间:2020-5-4 19:13:51
谢谢分享!
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版