打印

寻求STM32的STOP_Mode 的用法文件?

[复制链接]
17406|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
TRUE_ARM|  楼主 | 2007-10-5 15:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请问有没有熟悉STM32的低功耗模式2:STOP_Mode 的用法?退出STOP_Mode不重新初始化不能工作,然后按照ST的例子重新初始化一遍也不能正常工作,寻求ST的帮助,急!谢谢! 
来自 2楼
TRUE_ARM|  楼主 | 2007-10-10 12:26 | 只看该作者

真相大白了:

首先谢谢ijk同志。
原因是:函数:PWR_EnterSTOPMode(u32 PWR_Regulator, u8 PWR_STOPEntry)
中的这个语句:
 /* Set SLEEPDEEP bit of Cortex System Control Register */
  *(vu32 *) SCB_SysCtrl |= SysCtrl_SLEEPDEEP_Set;
让内核进入深度休眠。
而我在程序中同时使用了:
         PWR_EnterSTOPMode();

         __WFI();    //这里原来是想进入SLEEP 模式的
可是因为上面的函数已经把内核设置深度休眠模式,所以进入的是STOP 模式,而导致的异常。

改进:
    退出STOP 时,增加以下语句:
    *(vu32 *) SCB_SysCtrl &= ~SysCtrl_SLEEPDEEP_Set;
这样就可以进入 SLEEP 模式了。

总结一下:
在设计STM32 时,如果想灵活利用各种低功耗模式,就要注意Cortex_M3 内部的寄存器了。由于也是首次使用Cortex_M3 ,没有完全了解,导致走了弯路。
希望我的经历能给需要低功耗设计的人带来实惠,少走弯路。
感谢论坛,也感谢ijk。
睡个好中午觉了。


使用特权

评论回复
板凳
TRUE_ARM|  楼主 | 2007-10-5 21:59 | 只看该作者

看来都放假了

希望假后能得到解答!

使用特权

评论回复
地板
ijk| | 2007-10-8 10:02 | 只看该作者

STM32的STOP_Mode

  STM32的低功耗模式2:退出STOP_Mode不重新初始化不能工作,然后按照ST的例子重新初始化一遍也不能正常工作。
  请问是哪个/哪些外设有这样的问题?

使用特权

评论回复
5
TRUE_ARM|  楼主 | 2007-10-8 13:44 | 只看该作者

我用到串口、ADC,内部DMA

内部RTC 报警唤醒,就是没有办法工作,

PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
不能正常工作;
改用 __WFI(); 正常
或者:
    while( RTC_GetCounter() <(32768/2/250) );
    RTC_SetCounter(0);  
    RTC_WaitForLastTask();
也正常,
说明RTC 是正常工作的,

我的做法是:让RTC定时唤醒CPU ,并进行ADC采样;在空闲时进入休眠,降低功耗。

 

使用特权

评论回复
6
TRUE_ARM|  楼主 | 2007-10-8 13:47 | 只看该作者

ST 的例子:

void EnterSTOPMode_RTCAlarm(void)
{  
  u32 tmp = 0;

  /* Clear the LCD */
  LCD_Clear();
  /* Set the LCD Back Color */
  LCD_SetBackColor(Blue);

  /* Set the LCD Text Color */
  LCD_SetTextColor(White);

  /* Disable the JoyStick interrupts */
  //关闭外部中断:
  IntExtOnOffConfig(DISABLE);
  
//先确认时钟是否正常
  if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
  {
    LCD_DisplayString(Line1, "Time and Date are not configured, please go the Calendar menu and set the time and date parameters. Press JoyStick to continue...");
    while(ReadKey() == NOKEY)
    {
    }
    /* Clear the LCD */
    LCD_Clear();
    /* Display the previous menu */
    DisplayMenu();
    /* Enable the JoyStick interrupts */
    IntExtOnOffConfig(ENABLE);
    return;  //退出
  }
  
  tmp = RTC_GetCounter();

  /* Save the Alarm value in the Backup register */
  BKP_WriteBackupRegister(BKP_DR6, (tmp & 0x0000FFFF));
  BKP_WriteBackupRegister(BKP_DR7, (tmp >> 16));
  
  Alarm_PreAdjust();
  LCD_ClearLine(Line8);
  LCD_DisplayStringLine(Line6, "  MCU in STOP Mode  "); 
  LCD_DisplayStringLine(Line7, " Wait For RTC Alarm ");

 
  /* Request to enter STOP mode with regulator ON */
  PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);

  /* Configures system clock after wake-up from STOP: enable HSE, PLL and select PLL
     as system clock source (HSE and PLL are disabled in STOP mode) */
  SYSCLKConfig_STOP();

  LCD_DisplayStringLine(Line4, "      STOP Mode     ");
  LCD_DisplayStringLine(Line5, "Wake-Up by RTC Alarm");
  LCD_DisplayStringLine(Line6, "Press JoyStick to   ");
  LCD_DisplayStringLine(Line7, "continue...         ");

  while(ReadKey() == NOKEY)
  {
  }

  /* Clear the LCD */
  LCD_Clear();
  /* Display the previous menu */
  DisplayMenu();
  /* Enable the JoyStick interrupts */
  IntExtOnOffConfig(ENABLE);
}

使用特权

评论回复
7
TRUE_ARM|  楼主 | 2007-10-8 13:53 | 只看该作者

希望得到ijk 等ST 的高手支持!

希望得到ijk 等ST 的高手支持!

使用特权

评论回复
8
ijk| | 2007-10-8 16:57 | 只看该作者

从STOP模式唤醒后,是不是ADC不能正常工作?

  你的做法是:让RTC定时唤醒CPU ,并进行ADC采样;在空闲时进入休眠,降低功耗。
  这是很常用的做法。

  我在ST的评估板上,用ST提供的Demo程序进行试验,情况挺正常的:进入STOP模式后,无论通过按键方式,还是通过RTC闹钟(ALARM)方式,都可以唤醒CPU,并且之后可以正常读取温度(使用i2c接口的LM75芯片)-这说明I2C接口在从STOP模式唤醒后可以正常工作;并且可以再次进入STOP模式,然后通过按键方式或RTC闹钟(ALARM)方式来唤醒,之后仍然可以正常读取温度。
  结论是,RTC在从STOP模式唤醒后,应该可以正常工作,因为它可以再次把CPU从STOP模式中唤醒。
  我估计,从STOP模式唤醒后,象I2C接口一样,串口应该可以正常工作。
  所以,想问的是,你的困难是否在于从STOP模式唤醒后,对ADC进行重新初始化也不能正常工作?

使用特权

评论回复
9
TRUE_ARM|  楼主 | 2007-10-8 18:50 | 只看该作者

困难在于:

请看下面简单的例子:
int main(void)
{
  static unsigned char k=0;
  unsigned int tmp;

  /* System Clocks Configuration */
  RCC_Configuration();
      
  /* Configure the GPIOs */
  GPIO_Configuration();
  
  /* Configure the USART1 */
  USART_Configuration();

//RTC   
  EXTI_ClearITPendingBit(EXTI_Line17);
  EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_Init(&EXTI_InitStructure);   
  
  RTC_Configuration();

  /* Clear reset flags */
  RCC_ClearFlag();
  
  /* NVIC configuration */
  NVIC_Configuration();
  
  /* Display time in infinte loop */
  while(1)
  {
    /* If 1s has paased */
    
    GPIO_WriteBit(GPIOA, GPIO_Pin_8, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_8)));
    
    /* Request to enter STOP mode with regulator ON */
    
    tmp=RTC_GetCounter();
    RTC_WaitForLastTask(); 
    RTC_SetAlarm( tmp+100 );          
    RTC_WaitForLastTask(); 

//两种方式比较,来说明的困难:
//使用STOP 休眠  
//不会有输出,IO 也没有输出,说明程序死了  
    PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);    
       
    SYSCLKConfig_STOP();

//软件查询等待方式    
//能正常工作,串口输出正常,IO输出也正常
    //while( RTC_GetCounter()  < (tmp+32768/2/250) );
    
    /* Configure the GPIOs */
    GPIO_Configuration();
  
    /* Configure the USART1 */
    USART_Configuration();
    
    USART_SendData(USART1, k++);     
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
    
  }
}

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* Enable the RTC Interrupt */
  //NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

使用特权

评论回复
10
TRUE_ARM|  楼主 | 2007-10-8 18:51 | 只看该作者

接上:

/*******************************************************************************
* Function Name  : RTC_Configuration
* Description    : Configures the RTC.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RTC_Configuration(void)
{
  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  
  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);

  /* Reset Backup Domain */
  BKP_DeInit();

  /* Enable LSE */
  RCC_LSEConfig(RCC_LSE_ON);
  /* Wait till LSE is ready */
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }
  /* Select LSE as RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);  

  /* Enable RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  
  /* Enable the RTC Second */  
  //RTC_ITConfig(RTC_IT_SEC, ENABLE);
  RTC_ITConfig(RTC_IT_ALR, ENABLE);
  
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  
  RTC_SetPrescaler(2-1); 
  
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask(); 
}

/*******************************************************************************
* Function Name  : RTCAlarm_IRQHandler
* Description    : This function handles RTC Alarm interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RTCAlarm_IRQHandler(void)
{
  if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
  {
    
    EXTI_ClearITPendingBit(EXTI_Line17);
    
    /* Check if the Wake-Up flag is set */
    if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
    {
      /* Clear Wake Up flag */
      PWR_ClearFlag(PWR_FLAG_WU);
    }
    
    /* Clear the RTC Second interrupt */
    RTC_ClearITPendingBit(RTC_IT_ALR);
       
    /* Enable time update */
    TimeDisplay = 1;

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    /* Reset RTC Counter when Time is 23:59:59 */
    if(RTC_GetCounter() == 0x00015180)
    {
      RTC_SetCounter(0x0);
      /* Wait until last write operation on RTC registers has finished */
      RTC_WaitForLastTask();
    }
  }  
}

使用特权

评论回复
11
TRUE_ARM|  楼主 | 2007-10-8 18:55 | 只看该作者

困惑:

如果RTC 没有工作的话,但使用查询方式能工作,说明RTC 是在工作的,
就是没有唤醒,折磨人啊。
而且不好仿真,无法停止CPU,用J-LINK。
不知道问题在那???

使用特权

评论回复
12
ijk| | 2007-10-9 12:16 | 只看该作者

从STOP模式唤醒后,到底什么不能正常工作?

  从STOP模式唤醒后,到底什么不能正常工作?
RTC?

使用特权

评论回复
13
TRUE_ARM|  楼主 | 2007-10-9 16:46 | 只看该作者

谢谢ijk:

我的休眠处理如下:
//第六部分:休眠处理     
    //进入SLEEP_MODE  
    //关中断:
    //USART_ITConfig(USART1, USART_IT_TXE, DISABLE); 
    USART1->CR1 &= ~(0x00000080);    //关闭发送中断
    UartSendBusyTmp = UartSendBusy;
    //USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
    USART1->CR1 |= (0x00000080);     //使能发送中断
     
    //开中断 
    
    if((UartSendBusyTmp==1) || (LowPowerEnter==1) )
    {//数据发送中,或者
        __WFI();     //
    }
    else
    {  //进入 STOP_MODE  
       //-----------------------------------------
       //无线模块休眠控制:
       #ifdef RF_SLEEP_EN
              RF_SLEEP_ENTER();   //低电平休眠
       #endif  
       
       #if CPU_TEST==1    //测试RUN、SLEEP 时间分布
           GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
       #endif      
       
       //是否需要关闭其他中断?  
           
       //自身休眠       
       PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); 
       //__WFI();
   //重新初始化:
       SYSCLKConfig_STOP();    
       LowPowerExitSysInit();  //这里不初始化也一样。     
       //启动ADC
       ADC_SoftwareStartConvCmd(ADC1, ENABLE);     
       LowPowerEnter = 1;
       
       #if CPU_TEST==1
           GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
       #endif          
     }  

使用__WFI() 功能正常;
但使用PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); 就异常了,不知道哪个外设,还没找到,不好仿真。
解释一下,上面是因为调试发现问题了,想用小程序测试(就是上面的程序),结果RTC 都唤醒不了,
现在使用如下初始化RTC 后,RTC 唤醒功能正常:
   RTC_Configuration();

   RTC_ClearFlag(RTC_FLAG_SEC);
   while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);
  
   RTC_SetAlarm(RTC_GetCounter()+ 32768/2/250);
   RTC_WaitForLastTask();

使用特权

评论回复
14
香水城| | 2007-10-10 13:30 | 只看该作者

为奖励TRUE_ARM同志这种刻苦钻研和分享经验的精神,特发裤子

裤子送到了13楼,请楼主查收。

使用特权

评论回复
15
TRUE_ARM|  楼主 | 2007-10-10 13:57 | 只看该作者

怎么收啊?

受宠若惊,不知所措?!

使用特权

评论回复
16
王营光| | 2007-10-30 07:51 | 只看该作者

学一学

我是新生,以后多多指教

使用特权

评论回复
17
MCU430| | 2007-11-28 08:10 | 只看该作者

好啊

使用特权

评论回复
18
hotpower| | 2008-1-5 23:46 | 只看该作者

学习学习~~~谢谢~~~

使用特权

评论回复
19
shengnan27| | 2014-3-25 09:30 | 只看该作者
我用IAR在线调试时能够利用RTC中断唤醒STOP模式,但是全速运行之后就唤醒不了了,求解释

使用特权

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

本版积分规则

124

主题

454

帖子

1

粉丝