STM32待机模式唤醒测试以及独立看门狗测试

论坛 期权论坛 脚本     
匿名技术用户   2021-1-4 03:03   49   0

STM32待机模式唤醒测试以及独立看门狗测试

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

环境:

主机:WIN7

开发环境:MDK4.23

MCU:STM32F103CBT6


说明:

在上篇文章中http://blog.csdn.net/jdh99/article/details/7369844,进行了一些STM32待机模式的测试.其中关于如何在再次启动时判断是否是待机模式没有进行测试.另外上篇文章有个问题,闹钟中断在待机模式下是进入不了的.

本文进行了独立看门狗IWDG测试,以及待机模式更详细的测试.

STM32中,复位分为3种:

1.系统复位:外部复位,WWDG,IWDG,SW复位,低功耗管理复位.除复位标志寄存器RCC_CSR不被复位,全部都被复位

2.电源复位:上电/掉电复位,从待机模式复位.上电/掉电复位除备份域外寄存器全部复位.待机复位不会复位备份域寄存器以及PWR_CSR寄存器.

3.备份域复位.

寄存器说明:

由图可以看出,可以通过WUF位来判断是否由待机模式唤醒.

RCC_CSR寄存器:

由图可以看出,RCC_CSR寄存器的IWDGRSTF位可以指示是否发生独立看门狗复位.

因为在看门狗复位时如果系统不处在待机模式,PWR_CSR寄存器也会被复位,所以WUF位也可以指示是否发生独立看门狗复位.

源代码:

独立看门狗复位测试:

//检查唤醒标志是否设置
if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET)
{
 //首次启动,或者独立看门狗复位 
 //初始化备份寄存器
 //BKP_DeInit();

 //RTC功能开启
 //使能外部晶振
 RCC_LSEConfig(RCC_LSE_ON);
 //等待外部晶振准备好
 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

 //设置RTC时钟为外部晶振
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

 //使能RTC时钟
 RCC_RTCCLKCmd(ENABLE);
 //等待RTC_CTL寄存器中的RSF位(寄存器同步标志)被硬件置1
 RTC_WaitForSynchro();
 RTC_WaitForLastTask();  

 //使能闹钟中断   
 RTC_ITConfig(RTC_IT_ALR, ENABLE);  
 RTC_WaitForLastTask();  

 //分频系数为1,即最小时间单位1/2^15 = 30.5us
 RTC_SetPrescaler(RTC_PRESCALE);  
 RTC_WaitForLastTask();

 //启动独立看门狗
 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);      //访问之前要首先使能寄存器写
 IWDG_SetPrescaler(IWDG_Prescaler_64);       //64分频 一个周期1.6ms
 IWDG_SetReload(1250);           //最长12位 [0,4096] 1250*1.6 = 2s
 IWDG_ReloadCounter();           //喂狗
 //使能开门狗
 IWDG_Enable(); 
 
 if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd)
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_11) ;
  BKP_WriteBackupRegister(BKP_DR6,0);
 }
 else
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_11) ;
  BKP_WriteBackupRegister(BKP_DR6,0xabcd);
 }           
}
else
{ 
 //从待机模式中退出 
 //清除唤醒标志
 RCC_ClearFlag(); 

 if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd)
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_8) ;
  BKP_WriteBackupRegister(BKP_DR7,0);
 }
 else
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_8) ;
  BKP_WriteBackupRegister(BKP_DR7,0xabcd);
 }
}
while (1);


测试结果PA11引脚所连的LED不断闪烁,PA8所连的LED常亮,这说明不断进入看门狗复位.

待机模式RTC闹钟唤醒测试:

//检查唤醒标志是否设置
if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET)
{
 //首次启动,或者独立看门狗复位 
 //初始化备份寄存器
 //BKP_DeInit();

 //RTC功能开启
 //使能外部晶振
 RCC_LSEConfig(RCC_LSE_ON);
 //等待外部晶振准备好
 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

 //设置RTC时钟为外部晶振
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

 //使能RTC时钟
 RCC_RTCCLKCmd(ENABLE);
 //等待RTC_CTL寄存器中的RSF位(寄存器同步标志)被硬件置1
 RTC_WaitForSynchro();
 RTC_WaitForLastTask();  

 //使能闹钟中断   
 RTC_ITConfig(RTC_IT_ALR, ENABLE);  
 RTC_WaitForLastTask();  

 //分频系数为1,即最小时间单位1/2^15 = 30.5us
 RTC_SetPrescaler(RTC_PRESCALE);  
 RTC_WaitForLastTask();

 //启动独立看门狗
 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);      //访问之前要首先使能寄存器写
 IWDG_SetPrescaler(IWDG_Prescaler_64);       //64分频 一个周期1.6ms
 IWDG_SetReload(1250);           //最长12位 [0,4096] 1250*1.6 = 2s
 IWDG_ReloadCounter();           //喂狗
 //使能开门狗
 //IWDG_Enable(); 
 
 if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd)
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_11) ;
  BKP_WriteBackupRegister(BKP_DR6,0);
 }
 else
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_11) ;
  BKP_WriteBackupRegister(BKP_DR6,0xabcd);
 }           
}
else
{ 
 //从待机模式中退出 
 //清除唤醒标志
 RCC_ClearFlag(); 

 if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd)
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_8) ;
  BKP_WriteBackupRegister(BKP_DR7,0);
 }
 else
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_8) ;
  BKP_WriteBackupRegister(BKP_DR7,0xabcd);
 }
}
//延时1s
for (i = 0;i < 100;i++)
{
  _delay_ms(10);
}
//打开待机模式,1s后唤醒
open_standy_mode(30000);

每次刚上电所有LED会亮,进入待机模式则全部灭.测试结果PA8引脚所连的LED会亮1s进入灭进入待机模式,下次则常灭进入待机模式.PA11所连的LED随着低功耗进入正常亮灭,这说明不断发生闹钟唤醒(看门狗已关).

待机模式IWDG唤醒测试:

//检查唤醒标志是否设置
if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET)
{
 //首次启动,或者独立看门狗复位 
 //初始化备份寄存器
 //BKP_DeInit();

 //RTC功能开启
 //使能外部晶振
 RCC_LSEConfig(RCC_LSE_ON);
 //等待外部晶振准备好
 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

 //设置RTC时钟为外部晶振
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

 //使能RTC时钟
 RCC_RTCCLKCmd(ENABLE);
 //等待RTC_CTL寄存器中的RSF位(寄存器同步标志)被硬件置1
 RTC_WaitForSynchro();
 RTC_WaitForLastTask();  

 //使能闹钟中断   
 RTC_ITConfig(RTC_IT_ALR, ENABLE);  
 RTC_WaitForLastTask();  

 //分频系数为1,即最小时间单位1/2^15 = 30.5us
 RTC_SetPrescaler(RTC_PRESCALE);  
 RTC_WaitForLastTask();

 //启动独立看门狗
 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);      //访问之前要首先使能寄存器写
 IWDG_SetPrescaler(IWDG_Prescaler_64);       //64分频 一个周期1.6ms
 IWDG_SetReload(1250);           //最长12位 [0,4096] 1250*1.6 = 2s
 IWDG_ReloadCounter();           //喂狗
 //使能开门狗
 IWDG_Enable(); 
 
 if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd)
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_11) ;
  BKP_WriteBackupRegister(BKP_DR6,0);
 }
 else
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_11) ;
  BKP_WriteBackupRegister(BKP_DR6,0xabcd);
 }           
}
else
{ 
 //从待机模式中退出 
 //清除唤醒标志
 RCC_ClearFlag(); 

 if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd)
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_8) ;
  BKP_WriteBackupRegister(BKP_DR7,0);
 }
 else
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_8) ;
  BKP_WriteBackupRegister(BKP_DR7,0xabcd);
 }
}

//延时1s
for (i = 0;i < 100;i++)
{
 _delay_ms(10);
}
 
//打开待机模式,2s后唤醒
open_standy_mode(60000);

每次刚上电所有LED会亮,进入待机模式则全部灭.测试结果PA11引脚所连的LED会亮1s进入灭进入待机模式,下次则常灭进入待机模式.PA8所连的LED随着低功耗进入正常亮灭,而且待机模式是待机2s加延时1s应该是3s唤醒,LED闪烁频率2s左右说明被提前唤醒.这说明不断发生看门狗唤醒.

完整的测试程序:判断出首次启动程序,单片机处于正常状态时看门狗复位,单片机处于待机模式下被闹钟唤醒/看门狗唤醒.

注意:每次看门狗复位都要被重新配置启动

//检查是否正常状态发生看门狗复位
if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
{
 //清楚标志位
 RCC_ClearFlag();

 //RTC功能开启
 //使能外部晶振
 RCC_LSEConfig(RCC_LSE_ON);
 //等待外部晶振准备好
 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

 //设置RTC时钟为外部晶振
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

 //使能RTC时钟
 RCC_RTCCLKCmd(ENABLE);
 //等待RTC_CTL寄存器中的RSF位(寄存器同步标志)被硬件置1
 RTC_WaitForSynchro();
 RTC_WaitForLastTask();  

 //使能闹钟中断   
 RTC_ITConfig(RTC_IT_ALR, ENABLE);  
 RTC_WaitForLastTask();  

 //分频系数为1,即最小时间单位1/2^15 = 30.5us
 RTC_SetPrescaler(RTC_PRESCALE);  
 RTC_WaitForLastTask();

 //启动独立看门狗
 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);      //访问之前要首先使能寄存器写
 IWDG_SetPrescaler(IWDG_Prescaler_64);       //64分频 一个周期1.6ms
 IWDG_SetReload(1250);           //最长12位 [0,4096] 1250*1.6 = 2s
 IWDG_ReloadCounter();           //喂狗
 //使能开门狗
 IWDG_Enable();

 if (BKP_ReadBackupRegister(BKP_DR5) == 0xabcd)
 {
  GPIO_SetBits(GPIOA,GPIO_Pin_12) ;
  BKP_WriteBackupRegister(BKP_DR5,0);
 }
 else
 {
  GPIO_ResetBits(GPIOA, GPIO_Pin_12) ;
  BKP_WriteBackupRegister(BKP_DR5,0xabcd);
 } 
}
else
{
 //检查唤醒标志是否设置,判断是否首次启动
 if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET)
 {
  //首次启动
  //初始化备份寄存器
  //BKP_DeInit();

  //RTC功能开启
  //使能外部晶振
  RCC_LSEConfig(RCC_LSE_ON);
  //等待外部晶振准备好
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
 
  //设置RTC时钟为外部晶振
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
 
  //使能RTC时钟
  RCC_RTCCLKCmd(ENABLE);
  //等待RTC_CTL寄存器中的RSF位(寄存器同步标志)被硬件置1
  RTC_WaitForSynchro();
  RTC_WaitForLastTask();  

  //使能闹钟中断   
  RTC_ITConfig(RTC_IT_ALR, ENABLE);  
  RTC_WaitForLastTask();  

  //分频系数为1,即最小时间单位1/2^15 = 30.5us
  RTC_SetPrescaler(RTC_PRESCALE);  
  RTC_WaitForLastTask();

  //启动独立看门狗
  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);      //访问之前要首先使能寄存器写
  IWDG_SetPrescaler(IWDG_Prescaler_64);       //64分频 一个周期1.6ms
  IWDG_SetReload(1250);           //最长12位 [0,4096] 1250*1.6 = 2s
  IWDG_ReloadCounter();           //喂狗
  //使能开门狗
  IWDG_Enable(); 
  
  if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd)
  {
   GPIO_ResetBits(GPIOA, GPIO_Pin_11) ;
   BKP_WriteBackupRegister(BKP_DR6,0);
  }
  else
  {
   GPIO_SetBits(GPIOA,GPIO_Pin_11) ;
   BKP_WriteBackupRegister(BKP_DR6,0xabcd);
  }           
 }
 else
 { 
  //从待机模式中退出,有闹钟唤醒或者看门狗唤醒 
  //清除唤醒标志
  RCC_ClearFlag(); 

  if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd)
  {
   GPIO_ResetBits(GPIOA, GPIO_Pin_8) ;
   BKP_WriteBackupRegister(BKP_DR7,0);
  }
  else
  {
   GPIO_SetBits(GPIOA,GPIO_Pin_8) ;
   BKP_WriteBackupRegister(BKP_DR7,0xabcd);
  }
 }
}

//延时1s
for (i = 0;i < 100;i++)
{
 _delay_ms(10);
}

//打开待机模式,2s后唤醒
open_standy_mode(60000);
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP