关于待机唤醒实验中的疑惑?

2019-07-21 04:48发布

 关于待机模式,我仔细的看了相关的资料! 进入待机模式后,如何退出待机模式有四种方式,在实验12中用的是WKUP上升沿来出发唤醒中断;
我想询问的是,假如当前CPU处于待机模式,那么我只用按一下那个WKUP按键,就会响应相应的唤醒中断,此时是先执行完这个中断的程序,再复位还是其他?
如果在执行唤醒中断程序,在唤醒中断程序中又进入了待机模式那么之前按下的唤醒中断相当于没有能够唤醒?
在下面的代码中,当我开机后没有按键,那么会进入待机模式,此刻下面这句话是不是相当于没有执行?( MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2)
那么这个没有设置EXTI0_IRQChannel优先级以及使能中断,后面怎么会通过WKUP来触发唤醒中断呢?
而当我只是按了一下WKUP按键的时候,应该会进入唤醒中断函数void EXTI0_IRQHandler(void),此时会执行这句if(Check_WKUP())//关机?
 {   
  Sys_Enter_Standby(); 
 }
但是因为Check_WKUP()返回的是0所以执行下面的那句话;
假如我只是按了一下的话,那么这个不会进入待机,这时候从中断返回后就重新复位,从main函数的第一句话开始执行么?那样的话,在执行void WKUP_Init(void)这个函数的时候又进入待机模式;
我再长按WKUP按键的时候,会进入唤醒中断,然后因为Check_WKUP()返回的是1,那么会执行  Sys_Enter_Standby();  这时候会进入待机模式啊?怎么会出现实验中的长按然后会进入正常模式呢?
根据实验来说我上面的理解肯定有误,希望有好心人能够帮忙解答下,万分感谢!
下面附上原子的代码:
void Sys_Enter_Standby(void)
{   
 //关闭所有外设(根据实际情况写)
    RCC->APB2RSTR|=0X01FC;//复位所有IO口
 Sys_Standby();//进入待机模式
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
//      0:错误的触发 
u8 Check_WKUP(void)
{
 u8 t=0;
 u8 tx=0;//记录松开的次数
 LED0=0; //亮灯DS0
 while(1)
 {
  if(WKUP_KD)//已经按下了
  {
   t++;
   tx=0;
  }else
  {
   tx++; //超过300ms内没有WKUP信号
   if(tx>3)
   {
    LED0=1;
    return 0;//错误的按键,按下次数不够
   }
  }
  delay_ms(30);
  if(t>=100)//按下超过3秒钟
  {
   LED0=0;   //点亮DS0
   return 1; //按下3s以上了
  }
 }

//中断,检测到PA0脚的一个上升沿.  
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{                           
 EXTI->R=1<<0;  //清除LINE10上的中断标志位   
 if(Check_WKUP())//关机?
 {   
  Sys_Enter_Standby(); 
 }
}
//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{      
 RCC->APB2ENR|=1<<2;     //先使能外设IO PORTA时钟   
 RCC->APB2ENR|=1<<0;     //开启辅助时钟   
  
 GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入  
 GPIOA->CRL|=0X00000008; 
 Ex_NVIC_Config(GPIO_A,0,RTIR);//PA0上升沿触发   
                      
 //(检查是否是正常开)机      
    if(Check_WKUP()==0)Sys_Standby();    //不是开机,进入待机模式 
 MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2
}
int main(void)
{
 Stm32_Clock_Init(9);
 delay_init(72);
 uart_init(72,9600);
 LED_Init();
 WKUP_Init();
 while(1)
 {
  LED0=!LED0;
  delay_ms(200);
 }
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
sunrise1990
1楼-- · 2019-07-22 11:06
void WKUP_Init(void) {       RCC->APB2ENR|=1<<2;     //先使能外设IO PORTA时钟     RCC->APB2ENR|=1<<0;     //开启辅助时钟      GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入    GPIOA->CRL|=0X00000008;   Ex_NVIC_Config(GPIO_A,0,RTIR);//PA0上升沿触发     // Ex_NVIC_Config(GPIO_A,0,FTIR);             //(检查是否是正常开)机           if(Check_WKUP()==0) // Sys_Standby();    //不是开机,进入待机模式  如果没有本句则进入运行状态和唤醒时不用等3秒钟  只要按过就可以唤醒  不知为什么 MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2 }
sunrise1990
2楼-- · 2019-07-22 13:06

Sys_Standby();   屏蔽与不屏蔽
u8 Check_WKUP(void)  { // u8 t1=0; u8 t=0; u8 tx=0;//记录松开的次数 LED0=0; //亮灯DS0   复位之后亮一下  其实就是这句话的效果  /* for(t1=0;t1<10;t1++) { delay_ms(300); } */ while(1) { if(WKUP_KD)//已经按下了 { t++; tx=0; }else  { tx++; //超过30ms内没有WKUP信号 if(tx>3) { LED0=1; return 0;//错误的按键,按下次数不够 } // delay_ms(300); } delay_ms(30);//大于3000ms毫秒   if(t>=100)//按下超过3秒钟 { LED0=0;  //点亮DS0  return 1; //按下3s以上了 } LED1=!LED1; } }  
void WKUP_Init(void) {     RCC->APB2ENR|=1<<2;     //先使能外设IO PORTA时钟     RCC->APB2ENR|=1<<0;     //开启辅助时钟     GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入   GPIOA->CRL|=0X00000008;   Ex_NVIC_Config(GPIO_A,0,RTIR);//PA0上升沿触发    // Ex_NVIC_Config(GPIO_A,0,FTIR);        //(检查是否是正常开)机           if(Check_WKUP()==0) Sys_Standby();    //不是开机,进入待机模式  如果没有本句则进入运行状态 MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//抢占2,子优先级2,组2 } 原子哥不知道我这样理解对不?小弟那里说错请大侠指点。 从待机模式唤醒后的代码执行等同于复位后的执行(手册42页)。 1、正常情况下上电即进入待机模式,原因u8 Check_WKUP(void) 返回零if(Check_WKUP()==0)条件成立, 则进入如待机模式。如果唤醒意味着代码从新执行,其实按一下键已经唤醒了从头开始执行,只不过一直 在u8 Check_WKUP(void)数数数到100返回1跳过,条件不成立if(Check_WKUP()==0)不进入Sys_Standby(); 待机模式, 就不待机了那就给人感觉跑马灯闪烁唤醒了。 2、如果Sys_Standby(); 被屏蔽则上电运行LED闪烁,想待机要经过中断(WFI)经过中断要经过3秒(其实
就是在中断里面调用u8 Check_WKUP(void) 数数够三秒则待机)。唤醒其实是从新执行代码,跳过待机。
正点原子
3楼-- · 2019-07-22 13:33
回复【14楼】sunrise1990:
---------------------------------
正确。
jiajia
4楼-- · 2019-07-22 15:23
顶!!!我也遇到了此类问题,哈哈。。。
ljjdglg520
5楼-- · 2019-07-22 19:28
 精彩回答 2  元偷偷看……
正点原子
6楼-- · 2019-07-22 22:15
回复【17楼】ljjdglg520:
---------------------------------
 是

一周热门 更多>