[STM32L1]

香主请进!高手来!急!STM32L151低功耗与ADC配置及退出问题

[复制链接]
12627|20
手机看帖
扫描二维码
随时随地手机跟帖
keno52|  楼主 | 2013-10-24 20:02 | 显示全部楼层 |阅读模式
本帖最后由 keno52 于 2013-10-25 08:40 编辑

现在正在用STM32L151这个片子在做低功耗设计,现遇到如下情况,不知能否帮助解决:

系统上电配置进入StopMode静态电流为50uA左右(系统中用了其它模块比较耗电),这个属于正常情况。

当使用外部中断唤醒后,做相应的配置,其中包括ADC和USART等,将事情处理结束退出系统进入StopMode,静态电流达到1.15mA,经过排查发现,将AD初始化配置的代码注释掉,系统重新进入StopMode正常。

问题描述清楚,现请教如何在进入StopMode之前,有效的关闭ADC的相关配置?

ADC的配置代码如下:
/***********************************************************
Function name  : ADC_InitConfiguration
Function type   : void
Description       : ADC初始化配置
Parameter        : none
Return             : none
***********************************************************/
void ADC_InitConfiguration(void)
{
        
        ADC_InitTypeDef ADC_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        
        /* ---配置GPIOA的ADC_INPUT_CTL为推挽输出,无上下拉 ---*/
        
        GPIO_InitStructure.GPIO_Pin                 = ADC_INPUT_CTL;
        GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_2MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        
        Open_ADC1Source();        //打开电池电压采样输入

        /*------------------ DMA1 配置 -----------------------*/

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                //使能DMA1时钟

        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS;                       //外设地址                                
        DMA_InitStructure.DMA_MemoryBaseAddr    = (uint32_t)&ADC_ConvertedValue;     //内存地址
        DMA_InitStructure.DMA_DIR                        = DMA_DIR_PeripheralSRC;                   //外设为源
        DMA_InitStructure.DMA_BufferSize               = 1;                                                       //缓存为1字节        
        DMA_InitStructure.DMA_PeripheralInc          = DMA_PeripheralInc_Disable;                //外设地址固定
        DMA_InitStructure.DMA_MemoryInc            = DMA_MemoryInc_Disable;                   //内存地址固定        
        DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;     //半字
        DMA_InitStructure.DMA_MemoryDataSize    = DMA_MemoryDataSize_HalfWord;        //半字
        DMA_InitStructure.DMA_Mode                     = DMA_Mode_Circular;                            //循环传输
        DMA_InitStructure.DMA_Priority                  = DMA_Priority_High;                               //高优先级
        DMA_InitStructure.DMA_M2M                      = DMA_M2M_Disable;                               //内存到内存不使能
         DMA_Init(DMA1_Channel1, &DMA_InitStructure);

        DMA_Cmd(DMA1_Channel1, ENABLE);                //DMA1通道1使能
        
        /*------------------ ADC1 配置 -----------------------*/
        
        RCC_HSICmd(ENABLE);        //使能HSI
               
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);                //使能GPIOA的时钟
        
        //配置GPIOA_Pin1为AD输入模式
        GPIO_InitStructure.GPIO_Pin  = ADC_CHANL;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);             //等待HSI起振并稳定
        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);        //使能ADC1时钟
        
        ADC_InitStructure.ADC_ScanConvMode                  = DISABLE;        //禁止扫描模式
        ADC_InitStructure.ADC_ContinuousConvMode        = ENABLE;        //开启连续转换
        ADC_InitStructure.ADC_ExternalTrigConvEdge        = ADC_ExternalTrigConvEdge_None;        //不使用外部触发中断
        ADC_InitStructure.ADC_DataAlign                            = ADC_DataAlign_Right;                            //右对齐
        //ADC_InitStructure.ADC_Resolution                        = ADC_Resolution_12b;
        ADC_InitStructure.ADC_NbrOfConversion                = 1;                  //要转换的通道数为1
        ADC_Init(ADC1, &ADC_InitStructure);
        
        ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_4Cycles);                //PA1对应ADC1的通道1
        
        ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);                //ADC1转化结束后使能DMA请求

        ADC_DMACmd(ADC1, ENABLE);                //使能ADC1 DMA模式

        ADC_Cmd(ADC1, ENABLE);                        //使能ADC1

        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);        //等待ADC1准备好

        ADC_SoftwareStartConv(ADC1);        //ADC1使用软件触发
}
wookongbun| | 2013-10-24 21:38 | 显示全部楼层
关闭ADC的时钟不行吗

使用特权

评论回复
keno52|  楼主 | 2013-10-25 08:32 | 显示全部楼层
本帖最后由 keno52 于 2013-10-25 08:34 编辑
wookongbun 发表于 2013-10-24 21:38
关闭ADC的时钟不行吗

不行!采用最傻的方式,将开的所有时钟依次关断,依然不行!
void ExitSystem(void)
{
        /* 所有GPIO在StopMode下的配置 */
        GPIO_StopModeConfig();                                                        
        
        /* 失能USART1时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, DISABLE);
        /* 失能USART2时钟 */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
        /* 失能USART3时钟 */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, DISABLE);
        
        /* 失能ADC1 */
        ADC_Cmd(ADC1, DISABLE);
        /* 失能ADC1 DMA模式        */
        ADC_DMACmd(ADC1, DISABLE);
        /* 失能ADC1转化结束后使能DMA请求 */        
        ADC_DMARequestAfterLastTransferCmd(ADC1, DISABLE);        
        /* 失能ADC1时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);        
        /* 失能HSI */
        RCC_HSICmd(DISABLE);
        /* 失能DMA1通道1使能 */
        DMA_Cmd(DMA1_Channel1, DISABLE);               
        /* 失能DMA1时钟 */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);        

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);        //选择中断优先级组0
        
        EXTI_Ca_InitConfiguration();         //外部中断初始化配置
        EXTI_Fin_InitConfiguration();         //外部中断初始化配置
        
        Flag_SystemStatus = StopMode;         //配置好后,系统状态标志设为StopMode
        
        PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);  //进入StopMode
}

使用特权

评论回复
keno52|  楼主 | 2013-10-25 08:42 | 显示全部楼层
话说ADC使用了HSI时钟,会不会是我上述代码不能有效关闭HSI时钟引起?

使用特权

评论回复
keno52|  楼主 | 2013-10-25 08:47 | 显示全部楼层
没有人遇到过这种问题吗?

使用特权

评论回复
keno52|  楼主 | 2013-10-25 10:32 | 显示全部楼层
没人能给予回答,版主结贴好了!!已搞定!!

使用特权

评论回复
香水城主| | 2013-10-25 11:13 | 显示全部楼层
嘿嘿,是不是你MCU外部的设备没有配置好?

分享一下怎么搞定的。

使用特权

评论回复
qrshi| | 2013-10-25 13:15 | 显示全部楼层
关注。

使用特权

评论回复
Tom_fengcheng| | 2013-11-17 17:11 | 显示全部楼层
"
RCC_HSICmd(ENABLE);        //使能HSI
               
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);                //使能GPIOA的时钟
        
        //配置GPIOA_Pin1为AD输入模式
        GPIO_InitStructure.GPIO_Pin  = ADC_CHANL;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);             //等待HSI起振并稳定
"

我觉得先让HSI稳定了,再配置GPIOA

使用特权

评论回复
euvjin| | 2014-7-11 17:14 | 显示全部楼层
/* 关掉ADC */
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);        //等待ADC1准备好
        ADC_Cmd(ADC1, DISABLE);

我来帮LZ结贴吧,这样关掉ADC就可以了,我也研究了半天,都是不认真看datasheet的后果。

使用特权

评论回复
zxm19820916| | 2016-6-17 09:41 | 显示全部楼层
keno52 发表于 2013-10-25 10:32
没人能给予回答,版主结贴好了!!已搞定!!

我也碰到同样的问题。
芯片STM32F030F4P6,使用了ADC1和DMA,进入STOP之后有780uA的待机电流。去掉ADC1和DMA的配置,进入STOP之后待机电流正常,非常低,十几uA左右。
楼主是怎么解决的?

使用特权

评论回复
zxm19820916| | 2016-6-17 09:43 | 显示全部楼层
euvjin 发表于 2014-7-11 17:14
/* 关掉ADC */
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);        //等待ADC1准备好
        ADC ...

这样可以吗?试试看

使用特权

评论回复
mwnn| | 2017-1-8 23:21 | 显示全部楼层
zxm19820916 发表于 2016-6-17 09:43
这样可以吗?试试看

你试验结果OK了吗?

使用特权

评论回复
vitasnokia| | 2017-1-13 11:59 | 显示全部楼层
楼主,请问怎么解决的

使用特权

评论回复
vitasnokia| | 2017-1-13 14:00 | 显示全部楼层
euvjin 发表于 2014-7-11 17:14
/* 关掉ADC */
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);        //等待ADC1准备好
        ADC ...

不行啊,,,这样子,直接卡死在这个while里面

使用特权

评论回复
bfl111| | 2017-3-30 09:17 | 显示全部楼层
大家这个ad问题是怎么解决的?请好心的前辈指点下吧!

使用特权

评论回复
yzjonathan| | 2017-6-9 14:25 | 显示全部楼层
ADC1关闭实测

使用特权

评论回复
yzjonathan| | 2017-6-9 14:26 | 显示全部楼层
ADC1关闭实测
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//由于采集完毕时已经关闭,需要重开
ADC_Cmd(ADC1, DISABLE);

使用特权

评论回复
kncoming2018| | 2018-7-23 14:14 | 显示全部楼层
keno52 发表于 2013-10-25 10:32
没人能给予回答,版主结贴好了!!已搞定!!

请问怎么搞定的呢?
我也遇到这个问题了

使用特权

评论回复
dikpoorcat| | 2018-8-30 17:33 | 显示全部楼层
本帖最后由 dikpoorcat 于 2018-8-30 17:40 编辑

我也遇到这个问题了,已解决:    在ADC_Cmd(ADC1, DISABLE);之前先ADC_DeInit(ADC1);就好了,功耗比没有DeInit时下降了46uA。

        ADC_DeInit(ADC1);                                                                                                                
        ADC_Cmd(ADC1, DISABLE);                                                                                                        //关ADC外设




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

28

帖子

2

粉丝