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

关于stm32f302的进入睡眠和唤醒模

[复制链接]
alisa123 提问时间:2015-8-10 17:58 /
我想通过检测AD采样的电压低于U1的时候进入睡眠,当高于U2的时候唤醒,求高手指点,谢谢!
收藏 评论18 发布时间:2015-8-10 17:58

举报

18个回答
茅坑的石头 回答时间:2015-8-11 10:07:17
以下是功能实现其中的DMA中断服务函数,你先自己参考参考吧,我最近忙
void DMA1_Channel1_IRQHandler(void)
{
    float Voltage    = 0;                        //电压变量
    float Thermistor = 0;                        //热敏电阻阻值变量
    int   Temp       = 0;                        //热敏电阻测出的温度变量
        
    if(DMA_GetITStatus(DMA1_IT_TC1))
    {   
        //电压采样处理
        Voltage  = g_ADCConvertedValue[2]*3.3/4096;         
        
        #if DEBUG
        /*if(++g_Printf_Count > 300)
        {
            g_Printf_Count = 0;
            printf("Voltage = %f\n", Voltage);
        }*/
        #endif   
        
        Voltage *= VOLTAGE_FACTOR;
        Voltage += 0.35;
        if(Voltage < voltage_sill)                //电压值低于阀值
        {
            if(++g_VoltageLow_Count > 10 )         
            {
                g_VoltageLow_Count = 0;
                g_VoltageLow_Flag  = 1;          //设置电压过低的标志
                g_VoltageLow_Flag_backup = 1;    //设置电压过低标志的备份            
            }
            g_VoltRecovery_Count = 0;
        }
        else if(Voltage > voltage_sill + 0.5)
        {                     
            if(g_VoltageLow_Flag_backup)         //电压过低标志的备份置1表示电压曾经过低,现在表示电压恢复
            {
                if(++g_VoltRecovery_Count > 10 )
                {
                    g_VoltRecovery_Count = 0;
                    g_VoltageLow_Flag_backup = 0;
                    g_VoltageLow_Flag = 2;
                }                    
            }
            else
            {
                g_VoltRecovery_Count = 0;
            }
            
            g_VoltageLow_Count = 0;
        }
        else
        {
            g_VoltRecovery_Count = 0;
            g_VoltageLow_Count   = 0;
        }

        //热敏电阻采样处理,根据计算公式可得Rt = R1*U0/(2*U1-U0),
        //或者Rt = R1*U0/(Vcc-U0)     
        if(2*g_ADCConvertedValue[1] > g_ADCConvertedValue[0])
        {            
            Thermistor = (float)(10.0*g_ADCConvertedValue[0]/(2*g_ADCConvertedValue[1]-g_ADCConvertedValue[0]));
            Temp = ThermalLookUp(Thermistor);        //从热敏电阻阻值查表得到相应温度

            if(Temp < HEAT_TEMPERATURE2)             //低于二级温度阀值
            {
                if(++g_ThermalCount > 200)           //当时间超过2秒时,应该设置加热标志
                {
                    g_ThermalCount = 0;
                    g_ThermalHeat_Flag = 2;
                }            
            }
            else if(Temp < HEAT_TEMPERATURE1)
            {
                if(++g_ThermalCount > 200)
                {
                    g_ThermalCount = 0;
                    g_ThermalHeat_Flag = 1;
                }
            }
            else
            {
                g_ThermalCount = 0;
                g_ThermalHeat_Flag = 0;
            }
               
            #if DEBUG
            //if(++g_Printf_Count > 200)
            //{        
            //    g_Printf_Count = 0;            
            //    printf("Vol0 = %f,Vol1 = %f\n",g_ADCConvertedValue[0]*3.3/4096,g_ADCConvertedValue[1]*3.3/4096);
            //    printf("Thermistor  = %f\n", Thermistor);
            //    printf("Temperature = %d\n", Temp);
            //}
            #endif   
        }
        else
        {
            g_ThermalCount = 0;
            g_ThermalHeat_Flag = 0;
        }
        
        DMA_ClearITPendingBit(DMA1_IT_GL1);
    }
}
茅坑的石头 回答时间:2015-8-24 13:42:06
stop_mode:
#if DEBUG
                                                printf("S M\n");
#endif

                                                        RTC_Configuration();
                                                        //PWR_BackupAccessCmd(ENABLE);        //使能RTC和后备寄存器访问                                       
                                                        //RTC_ITConfig(RTC_IT_ALR, ENABLE);
                                                        //RTC_WaitForLastTask();                                       
                                                        //RTC_ClearFlag(RTC_FLAG_SEC);
                                                        //while (RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);
                                                        //RCC_ClearFlag();










                                                //set the all GPIO as general GPIO 、remap IRDA in EXIT0 and disable TIM4 interrupt
                                                lowLevelGPIOCfg();

                                                ADC_Cmd(ADC1, DISABLE);
                                                DMA_Cmd(DMA1_Channel1, DISABLE);
                                                WireControl_EXTI_Enable();

                                                GPIO_ResetBits(Led_Power, Led_Power_Pin);
                                                //GPIO_SetBits(Led_Power, Led_Power_Pin);

                                                BKP_WriteBackupRegister(BKP_DR3, 0xFFFF);  //设置为睡眠状态
                                                #if DEBUG
                                                GPIO_SetBits(GPS_ON,GPS_ON_Pin);
                                                #endif

                                                //Enter a stop mode
                                                //Request to enter STOP mode with regulator in low power mode, wake by any exit interrupt
                                                IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
                                                IWDG_SetReload(0xffe);
                                                IWDG_ReloadCounter();

                                                GPIO_SetBits(LED_SD1_G, LED_SD1_G_Pin);
                                                GPIO_SetBits(LED_SD2_G, LED_SD2_G_Pin);
                                                GPIO_SetBits(LED_CAM1, LED_CAM1_Pin);
                                                GPIO_SetBits(LED_CAM2, LED_CAM2_Pin);
                                               
                                                mcu_iwdg_flag = 1;
                                                delay_ms(RESET_INTERVAL);

                                            EXTI_ClearITPendingBit(ACC_EXTI_Line |  EXTI_Line0 | EXTI_Line17 | EXTI_Line11);
                                                PWR_EnterSTOPMode(PWR_Regulator_LowPower,
                                                                PWR_STOPEntry_WFI);

                                                GPIO_ResetBits(LED_SD1_G, LED_SD1_G_Pin);
                                                GPIO_ResetBits(LED_SD2_G, LED_SD2_G_Pin);
                                                GPIO_ResetBits(LED_CAM1, LED_CAM1_Pin);
这个是我进入睡眠的代码,
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
这里是进入睡眠的地方,睡眠需要注意的是,睡眠前清理一下中断悬挂
EXTI_ClearITPendingBit(ACC_EXTI_Line |  EXTI_Li.....
,配置好外部中断。
如果睡眠之前有独立看门狗的话,需要另外的处理。
alisa123 回答时间:2015-8-24 11:20:49
茅坑的石头 发表于 2015-8-24 08:59
这里只是中断服务函数,中断服务函数里面,仅仅读取电压(DMA会循环把ADC寄存器的数据扫到内存变量里),处 ...

谢谢你的回复,我明白你的意思,但是我现在的问题是调用进入睡眠的库函数就是进不到睡眠,请问你的主程序中进入睡眠是怎么进去的吗?我的进入睡眠的代码如下:
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
                PWR_DeInit();
                PWR_BackupAccessCmd(DISABLE);
                SCB->SCR &= 0xFFFFFFF0;
        //        SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
                NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP,DISABLE);
                NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,DISABLE);
                PWR_EnterSleepMode(PWR_SLEEPEntry_WFE);
        //        __WFE;
不知道那里出问题了,就是进不了睡眠。求帮忙指点,谢谢!
你好我好大家好! 回答时间:2015-8-10 18:38:06
帮顶            
alisa123 回答时间:2015-8-12 08:53:34
茅坑的石头 发表于 2015-8-11 10:07
以下是功能实现其中的DMA中断服务函数,你先自己参考参考吧,我最近忙
void DMA1_Channel1_IRQHandler(void ...

我先看看,又不明白的再请教你,谢谢你了!
alisa123 回答时间:2015-8-12 09:01:20
茅坑的石头 发表于 2015-8-11 10:07
以下是功能实现其中的DMA中断服务函数,你先自己参考参考吧,我最近忙
void DMA1_Channel1_IRQHandler(void ...

你的这个里面没有写怎么进入睡眠,还有进入之后怎么唤醒?在DMA中断中检测电压低于阈值多长时间置标志位,高于设定阈值请标志位,但始终没有写怎么进入睡眠。
茅坑的石头 回答时间:2015-8-24 08:59:56
这里只是中断服务函数,中断服务函数里面,仅仅读取电压(DMA会循环把ADC寄存器的数据扫到内存变量里),处理几个全局的标志而已,主程序里面会对这些标志进行判断,然后才进行相应的处理(比如休眠等等);至于多长时间置标志位,这个你可以自行设定,计时我是用的定时器累加实现计时的。差不多低于阀值300ms就会置标志位,然后主程序在循环中发现该标志位,就会进入休眠。至于怎么唤醒,这个也是主程序里实现的。在休眠之前会配置好几个外部中断,只要触发,就会唤醒。
茅坑的石头 回答时间:2015-8-24 13:43:21
睡眠之前有一些其他的操作,主要是关闭一些外设,这个是出于睡眠功耗的考虑。你根据你的外设情况自己定。
茅坑的石头 回答时间:2015-8-24 13:48:14
其实建议你单独,做一个小程序,仅仅做一个进入休眠的小程序,自己测试一下。排除其他因素的干扰,你看能不能行。
alisa123 回答时间:2015-8-24 14:16:52
茅坑的石头 发表于 2015-8-24 13:42
stop_mode:
#if DEBUG
                                                printf("S M\n");

你这个不是进入stop mode的?我想做的是进入sleep mode 的。还有你这个是在stm32f302上实现的吗?
废鱼 回答时间:2015-8-24 14:51:48
进入休眠以前,把所有的中断都关闭,再试试。
茅坑的石头 回答时间:2015-8-24 21:37:30
alisa123 发表于 2015-8-24 14:16
你这个不是进入stop mode的?我想做的是进入sleep mode 的。还有你这个是在stm32f302上实现的吗?
...

我用的是 stm32rbt6
我想,stopmode  和你那个sleep mode实现上 应该差不多吧。
你就做个简单的小程序,仅仅做个sleep mode 的功能看能不能实现。
alisa123 回答时间:2015-8-25 09:59:16
安 发表于 2015-8-24 14:51
进入休眠以前,把所有的中断都关闭,再试试。

谢谢你的回复,我试过了关闭中断还是不行。见鬼了,不知道哪里出问题了,看手册就要求三条(WFI (Wait for Interrupt) or WFE (Wait for Event) while:
– SLEEPDEEP = 0 and
– SLEEPONEXIT = 0
Refer to the Cortex-M4®F System Control register)
废鱼 回答时间:2015-8-25 11:17:19
我找的例程,楼主看一下,这个是标准库的。
楼主是否在线调试模式下测试?

PWR_CurrentConsumption.rar

下载

3.63 KB, 下载次数: 4, 下载积分: ST金币 -1

12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版