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

STM32L053 低功耗采集时,ADC打开与关闭有时出现问题

[复制链接]
wgcrdg 提问时间:2018-2-9 08:23 /
STM32L053 隔几秒钟采集一次数据。STM32L053 低功耗时,进入停止模式,通过RTC中断唤醒,唤醒后,打开EnableADC()采集数据,采集完成后,关闭DisableADC(),以节省电池电量。但是有时候出现死循环,不知道是怎么回事,也是按参数手册上面做的,还是不行。

void EnableADC(void)
{
  ADC1->ISR |= ADC_ISR_ADRDY;
  ADC->CCR |= (ADC_CCR_VREFEN|ADC_CCR_TSEN);
  ADC1->CR |= ADC_CR_ADEN; //使能ADC
  if ((ADC1->CFGR1 &  ADC_CFGR1_AUTOFF) == 0)
  {
    while ((ADC1->ISR & ADC_ISR_ADRDY) == 0)
    {
      //这里可以添加超时管理
      /*打开时,这个地方有时候出现死循环*/
    }
  }
  ADC1->CR |= ADC_CR_ADSTART; //启动ADC转换
}


void DisableADC(void)
{
  //确保没有转换
  if ((ADC1->CR & ADC_CR_ADSTART) != 0)
  {
    //停止任何正在进行的转换
    ADC1->CR |= ADC_CR_ADSTP;
  }
  //等到ADSTP由硬件复位即停止转换
  while ((ADC1->CR & ADC_CR_ADSTP) != 0)
  {
    //这里可以添加超时管理
  }
  ADC1->CR |= ADC_CR_ADDIS; //禁用ADC
  //等到ADC是完全禁用
  while ((ADC1->CR & ADC_CR_ADEN) != 0)
  {
    //这里可以添加超时管理
    /*关闭时,这个地方有时候出现死循环*/
  }
  ADC1->ISR |= ADC_ISR_ADRDY;
  ADC->CCR &= ~(ADC_CCR_VREFEN|ADC_CCR_TSEN);
}
555.JPG
222.png

点评

帮你把第二张图改了,留了一大块空白看着多难受  发表于 2018-2-9 09:17

评分

参与人数 1 ST金币 -2 收起 理由
Tcreat -2 建议楼主把前提条件叙述清楚

查看全部评分

收藏 评论17 发布时间:2018-2-9 08:23

举报

17个回答
wgcrdg 回答时间:2018-2-9 09:25:58
本帖最后由 wgcrdg 于 2018-2-9 09:51 编辑

下面是开始程序时的ADC与DMA的初始化部分。

uint16_t ADC_array[6];
//这个函数配置ADC的DMA来存储结果序列,转换的结果存储在n个元素数组
void ConfigureDMA(void)
{
  //使外围时钟DMA
  RCC->AHBENR |= RCC_AHBENR_DMA1EN;
  //启用DMA传输ADC
  ADC1->CFGR1 |= ADC_CFGR1_DMAEN;
  //配置外围数据寄存器地址
  DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
  //配置内存地址
  DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
  //配置待传输的数据数 的数量
  DMA1_Channel1->CNDTR = 6;
  //配置使能存储器递增模式、存储器16 位模式、外设16 位模式,
  //传输错误中断使能和传输完成中断使能
  DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 \
    | DMA_CCR_TEIE | DMA_CCR_TCIE;
  //使能DMA
  DMA1_Channel1->CCR |= DMA_CCR_EN;
  
  //启用中断DMA通道1
  NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  //设置优先级的DMA通道1
  NVIC_SetPriority(DMA1_Channel1_IRQn,2);
}



void  ADC_Init(void)
{
  //使外围时钟GPIOA GPIOC
  //AD1=PA4=IN4  AD2=PA5=IN5  AD3=PA0=IN0 AD4=PC3=IN13
  RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOCEN;
  //设置口线为模拟输入
  GPIOA->MODER |= (GPIO_MODER_MODE0|GPIO_MODER_MODE4|GPIO_MODER_MODE5);
  GPIOC->MODER |= GPIO_MODER_MODE3;
  //使外围ADC的时钟
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;   
  //ADCCLK(异步时钟模式)
  ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE;        
  //选择连续转换模式
  ADC1->CFGR1 |= ADC_CFGR1_CONT;        
  ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL4 | ADC_CHSELR_CHSEL13 \
    | ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL17 | ADC_CHSELR_CHSEL18;
  //采样时间选择39.5 个 ADC 时钟周期
  ADC1->SMPR = ADC_SMPR_SMP_0 | ADC_SMPR_SMP_2;
  //采样时间选择79.5 个 ADC 时钟周期
  //ADC1->SMPR = ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2;
  //使能溢出中断 OVR 位置 1 时产生中断
  ADC1->IER = ADC_IER_OVRIE;  
  //使能 VREFINT,使能温度传感器
  ADC->CCR |= (ADC_CCR_VREFEN|ADC_CCR_TSEN);
  //ADC上启用中断
  NVIC_EnableIRQ(ADC1_COMP_IRQn);     
  //为ADC设置中断优先级
  NVIC_SetPriority(ADC1_COMP_IRQn,3);
  if(vref_vol == 0)
  {
    //以下几行为ADC 校准
    //确保 ADEN=0
    if ((ADC1->CR & ADC_CR_ADEN) != 0)
    {
      ADC1->CR &= (uint32_t)(~ADC_CR_ADEN);  
    }
    //将 ADCAL 置 1
    ADC1->CR |= ADC_CR_ADCAL;
    //等待,直至 ADCAL=0
    while ((ADC1->ISR & ADC_ISR_EOCAL) == 0)
    {
      
    }
    //校准已完成
    ADC1->ISR |= ADC_ISR_EOCAL;
    /* 计算内部Vref电压(mV) */
    vref_vol = (uint16_t)( 3000.0 * (*(uint16_t *)0x1FF80078) / 4095.0);
    Vrefint_cal=(*(uint16_t *)0x1FF80078);         
  }
  ConfigureDMA();  //函数配置ADC的DMA
}
wgcrdg 回答时间:2018-2-9 09:09:36
本帖最后由 wgcrdg 于 2018-2-9 09:17 编辑

ADC采集数据时,单片机是不进入停止模式的,采集完成后,才进入停止模式,单片机采集数据,采用的是ADC+DMA的方式,DMA中断。ADC与DMA的初始化,在开始程序中完成。ADC打开采集与关闭在唤醒后while(1){   }中使用。
Tcreat 回答时间:2018-2-9 08:44:26
如果低功耗方案 理论上进入低功耗前外设时钟都会关闭的 你这没有阐述什么级别的功耗模式 也不说明前因后果  所以提问的同时  也要阐明条件

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wenyangzeng 回答时间:2018-2-9 09:52:35
唤醒后延时一下再ADC转换试看看

评分

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

查看全部评分

回答时间:2018-2-9 09:53:38
在重新开始时,是否重新配置了时钟。

评分

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

查看全部评分

wgcrdg 回答时间:2018-2-9 10:32:34
本帖最后由 wgcrdg 于 2018-2-9 10:33 编辑

没有重新配置时钟,时钟配置在开始的程序中,已经配置了。唤醒后,打开EnableADC(); 采集完成后,DisableADC();,然后, __WFI();,周而复始。


wgcrdg 回答时间:2018-2-9 10:35:29
这种情况只偶尔的出现,可能几百次里面出现一次,但是一次也不行啊。电池供电的,要确保低功耗。
回答时间:2018-2-9 10:38:36
楼主可以试着重新配置一下时钟。我在使用的时候会将时钟关闭,还有很多外设等,用于降低功耗。唤醒后再重新配置时钟。
hello_bug 回答时间:2018-2-9 10:44:33
在停止模式下,所有时钟都关闭了吧。你唤醒后,得重新配置时钟,启动外设时钟吧。

评分

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

查看全部评分

12下一页
关于 意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
13245底部标题123相同标题
12底部标题123相同标题
33333底部标题123相同序号
3435底部标题-无链接
关注我们
st-img 微信公众号
st-img 手机版