2020-10-25

项目场景:

使用GD32E230替换STM32F030过程中,发现ADC功能在flash擦除操作时,出现异常。


问题描述:

将ADC进行DMA配置,把3路ADC与内存进行映射,启动ADC和DMA,ADC软件触发,自动循环模式。启动后DMA用ADC采集到的数值不停的刷新内存,程序负责对这段内存分路取平均值即可。.在使用过程中,需要对操作参数进行保存(保存到Flash里),保存一执行,发现采集的ADC发生了突变,调试发现,导致突变的直接原因是DMA映射的通道数据发生了错乱。比如原来的第一路会跑到第二路,第二路会跑到第三路,第三路则变成了第一路。

ADC的配置如下:注意采用了ADC_CTL1_SWRCST|ADC_CONTINUOUS_MODE,软触发和连续模式。

adc_config(void)
{
dma_parameter_struct dma_init_struct;
    RCU_REG_VAL(RCU_ADC) |= BIT(RCU_BIT_POS(RCU_ADC));
    RCU_REG_VAL(RCU_GPIOA) |= BIT(RCU_BIT_POS(RCU_GPIOA));
    RCU_REG_VAL(RCU_GPIOB) |= BIT(RCU_BIT_POS(RCU_GPIOB));
    RCU_REG_VAL(RCU_DMA) |= BIT(RCU_BIT_POS(RCU_DMA));
    RCU_CFG0 &= ~RCU_CFG0_ADCPSC;
    RCU_CFG2 &= ~(RCU_CFG2_ADCSEL | RCU_CFG2_IRC28MDIV | RCU_CFG2_ADCPSC2);
    /* set the ADC clock according to ck_adc */
     RCU_CFG0 |= RCU_ADC_CKAPB2_DIV8;
   RCU_CFG2 |= RCU_CFG2_ADCSEL;
    
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE,  GPIO_PIN_1 | GPIO_PIN_5);//GPIO_PIN_0 |
    gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
    
    
    /* ADC channel length config */   
        // adc_channel_length_config(ADC_REGULAR_CHANNEL, 3);
        ADC_RSQ0 &= ~((uint32_t)ADC_RSQ0_RL);
    ADC_RSQ0 |= RSQ0_RL((uint32_t)2);
    /* ADC regular channel config */
    adc_regular_channel6_10_config(0U, ADC_CHANNEL_1, ADC_SAMPLETIME_239POINT5);
    adc_regular_channel6_10_config(1U, ADC_CHANNEL_5, ADC_SAMPLETIME_239POINT5);
    adc_regular_channel6_10_config(2U, ADC_CHANNEL_9, ADC_SAMPLETIME_239POINT5);
      ADC_CTL1 &= ~((uint32_t)ADC_CTL1_ETSRC|ADC_CTL1_DAL);;
     ADC_CTL0 |= (ADC_SCAN_MODE);
    ADC_CTL1 |= (ADC_EXTTRIG_REGULAR_NONE|ADC_CTL1_ETERC|ADC_CTL1_ADCON|ADC_CTL1_RSTCLB|ADC_CTL1_DMA|ADC_CTL1_SWRCST|ADC_CONTINUOUS_MODE);
   

    /* initialize DMA channel0 */
    //dma_deinit(DMA_CH0);
    dma_init_struct.direction    = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr  = (uint32_t)aDC;
    dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
    dma_init_struct.number       = 24;
    dma_init_struct.periph_addr  = (uint32_t)&(ADC_RDATA);
    dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
    dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA_CH0, &dma_init_struct);
    
   
         DMA_CHCTL(DMA_CH0) &= ~DMA_CHXCTL_M2M;
   DMA_CHCTL(DMA_CH0) |= (DMA_CHXCTL_CMEN|DMA_CHXCTL_CHEN);
    }

原因分析:

具体原因未知,用STM32F030时并没有此问题。这里只讲如何规避,如果有小伙伴知道原因的话,可以让大家一起学习一下。


解决方案:

把自动连续触发模式ADC_CONTINUOUS_MODE去掉,在主程序中没10ms设置软件触发一次ADC_CTRL1寄存器改为:

ADC_CTL1 |= (ADC_EXTTRIG_REGULAR_NONE|ADC_CTL1_ETERC|ADC_CTL1_ADCON|ADC_CTL1_RSTCLB|ADC_CTL1_DMA);

 并在每10ms置位一次软触发:

if(RESET == (ADC_CTL1 & ADC_CTL1_SWRCST))
    {
        ADC_CTL1 |= ADC_CTL1_SWRCST;
    }

这样规避了ADC的DMA映射与flash擦除操作导致的问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值