找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1175|回复: 18
打印 上一主题 下一主题
收起左侧

MCU暂停运行程序,等待唤醒命令

  [复制链接]
跳转到指定楼层
楼主
ID:1087674 发表于 2023-7-30 19:03 来自手机 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
单片机可不可以运行到某处暂停(休眠),然后等触发按键后才继续运行下面程序呢?不是跳转运行其他程序,是暂停,就是什么也不做,先停一下,然后按键松开后才继续
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:275826 发表于 2023-7-30 20:23 | 只看该作者
可以,低功耗模式
回复

使用道具 举报

板凳
ID:342822 发表于 2023-7-30 20:38 | 只看该作者
运行到某处进入循环暂停,当某键按下跳出循环继续向下执行。
回复

使用道具 举报

地板
ID:525244 发表于 2023-7-30 22:08 来自手机 | 只看该作者
可以设置下降沿中断,单片机休眠,按键按下,0V唤醒单片机。从休眠下一条指令开始执行!
回复

使用道具 举报

5#
ID:468209 发表于 2023-7-30 22:18 来自手机 | 只看该作者
空闲模式  外部中断唤醒  
回复

使用道具 举报

6#
ID:1087674 发表于 2023-7-31 01:21 来自手机 | 只看该作者
zgrfox110 发表于 2023-7-30 22:08
可以设置下降沿中断,单片机休眠,按键按下,0V唤醒单片机。从休眠下一条指令开始执行!

有没相应的程序看看是怎样的呢?
回复

使用道具 举报

7#
ID:1087674 发表于 2023-7-31 01:21 来自手机 | 只看该作者
1860774xxxx 发表于 2023-7-30 22:18
空闲模式  外部中断唤醒

有没相应程序学下呢
回复

使用道具 举报

8#
ID:1087674 发表于 2023-7-31 01:23 来自手机 | 只看该作者
taotie 发表于 2023-7-30 20:38
运行到某处进入循环暂停,当某键按下跳出循环继续向下执行。

就是在里面空转咯?这个可以试试。
回复

使用道具 举报

9#
ID:468209 发表于 2023-7-31 06:51 来自手机 | 只看该作者
农民阿伯 发表于 2023-7-31 01:21
有没相应程序学下呢

芯片手册自己看看贝 空闲模式和掉电模式
回复

使用道具 举报

10#
ID:883242 发表于 2023-7-31 06:51 | 只看该作者
农民阿伯 发表于 2023-7-31 01:23
就是在里面空转咯?这个可以试试。

不可以,空转太费电了,进入休眠状态连时钟都停了才能真正做到省电。
回复

使用道具 举报

11#
ID:213173 发表于 2023-7-31 07:29 | 只看该作者
设置一个条件,当满足条件,MCU进入休眠。当用按键或其它方式触发唤醒,MCU继续工作。给你一个示例参考
  1. //适合STC15/STC8系列,测试平台 TX-1C 开发板
  2. //#include <STC15F2K60S2.H>
  3. #include <STC8H.H>
  4. #include "intrins.h"
  5. #define uchar unsigned char
  6. #define uint unsigned int

  7. sbit key  = P3^2;//S14
  8. sbit GND  = P3^4;//矩阵键盘P3.4模拟接地

  9. uchar Temp;
  10. uchar Key_value; //键值
  11. uint  keyTim;    //按键时长
  12. bit   flag1ms;   //1ms中断标志
  13. bit   on_off;    //开关标志
  14. bit   allow;     //允许关机标志

  15. void Timer0Init(void)//1毫秒@11.0592MHz
  16. {
  17.         AUXR |= 0x80;                //定时器时钟1T模式
  18.         TMOD &= 0xF0;                //设置定时器自动重载模式
  19.         TL0 = 0xCD;                        //设置定时初始值
  20.         TH0 = 0xD4;                        //设置定时初始值
  21.         TF0 = 0;                                //清除TF0标志
  22.         TR0 = 1;                                //定时器0开始计时
  23.         ET0 = 1;                                //允许T0中断
  24. //        EA  = 1;                                //开总中断
  25. }

  26. void key_scan()    //按键扫描函数
  27. {
  28.         if(flag1ms)  //1ms时间标志
  29.         {
  30.                 flag1ms = 0;//1ms时间标志清0
  31.                 if(!key && !on_off)
  32.                 {
  33.                         if(++keyTim>1000)keyTim=1001;//防止溢出

  34.                         if(keyTim==20) //大于20ms小于1s算短按
  35.                         {
  36.                                 Key_value=0x01;
  37.                         }
  38.                         if(keyTim==1000) //达到1s算长按
  39.                         {
  40.                                 Key_value|=0x10;
  41.                         }
  42.                 }
  43.                 else
  44.                 {
  45.                         keyTim=0;        //按键松手keyTim清0
  46.                         on_off=0;        //开关标志清0
  47.                 }
  48.         }
  49. }

  50. void key_service()//按键服务函数
  51. {//短按等松手响应,长按达1s不论是否松手即响应
  52.         if((keyTim==0||keyTim==1000) && Key_value!=0x00)
  53.         {
  54.                 if(Key_value==0x01)//短按任务
  55.                 {
  56.                         Temp++;
  57.                         P1=~Temp;
  58.                 }
  59.                 if(Key_value==0x11)//长按关机
  60.                 {
  61.                         allow=1;
  62.                 }
  63.                 Key_value=0x00;//任务完成后键值清0
  64.         }
  65. }

  66. void Shutdown()//掉电模式函数
  67. {
  68.         if(allow)
  69.         {
  70.                 P1=0xff;                //关闭LED显示
  71.                 //关闭所有在用硬件,减小能耗
  72.                 EX0 = 1;                //打开中断
  73.                 PCON = 0x02;//MCU进入掉电模式
  74.                 _nop_();    //掉电模式被唤醒后,首先执行此语句,然后再进入中断服务程序
  75.                 _nop_();    //中断服务程序执行完再接着此句继续执行
  76.                 EX0 = 0;                //关闭中断
  77.                 while(!key);//等待按键松手,防止按键扫描程序误读
  78.                 //打开所有在用硬件,恢复正常运行
  79.                 P1=~Temp;                //恢复LED显示
  80.                 allow=0;                //清0
  81.         }
  82. }

  83. void main()
  84. {
  85.         P0M0 = 0x00;//初始化IO
  86.         P0M1 = 0x00;
  87.         P1M0 = 0x00;
  88.         P1M1 = 0x00;
  89.         P2M0 = 0x00;
  90.         P2M1 = 0x00;
  91.         P3M0 = 0x00;
  92.         P3M1 = 0x00;
  93.         P4M0 = 0x00;
  94.         P4M1 = 0x00;
  95.         P5M0 = 0x00;
  96.         P5M1 = 0x00;
  97.         P6M0 = 0x00;
  98.         P6M1 = 0x00;
  99.         P7M0 = 0x00;
  100.         P7M1 = 0x00;
  101.         GND  = 0;
  102.         IT0 = 1;//设置INT0的中断类型为下降沿唤醒
  103. //        EX0 = 1;//使能INT0中断
  104.         EA  = 1;//开总中断                                                        
  105.         Timer0Init();//定时器初始化函数
  106.         while (1)
  107.         {
  108.                 key_scan();                //按键扫描函数
  109.                 key_service(); //按键服务函数
  110.                 Shutdown();                //掉电模式函数
  111.         }
  112. }
  113. //INT0中断服务程序
  114. void exint0() interrupt 0
  115. {
  116.         on_off=1;//开关标志置1
  117. }
  118. //T0中断服务程序
  119. void interruptTimer0() interrupt 1
  120. {
  121.         flag1ms = 1;    //1ms标志
  122. }
复制代码
回复

使用道具 举报

12#
ID:320306 发表于 2023-7-31 09:16 | 只看该作者
可以的,有很多方式,有些单片机低功耗的时候就停在程序那里,但是这种功耗肯定不是最低的。
回复

使用道具 举报

13#
ID:711539 发表于 2023-7-31 09:33 | 只看该作者
  1. //方式一:
  2. void fun_Enter_LPM(void){
  3.         ADEN = 0;                                //关闭ADC使能
  4.         VREFEN = 0;                                //关闭内部参考电压

  5.         Y_LED = 1;                                //LED灯灭

  6.     KIF = 0;                                //清按键中断标志
  7.         KIE = 1;                                //使能按键中断唤醒
  8.         KMSK0 = 1;                                //打开中断唤醒 (按键)

  9.         LPM = 0;                                //进入IDLE0模式
  10.     RCEN = 0;                                //关狗
  11.     CLRWDT();                                //清除看门狗定时器
  12.     IDLE();                                        //
  13.     CLRWDT();                                //清除看门狗定时器
  14.     RCEN = 1;                                //开狗
  15.        
  16.         Y_LED = 0;                                //LED灯亮
  17. }

  18. //方式二:
  19. void fun_Wait_Run(void){
  20.         while(1){
  21.                 CLRWDT();                        //清除看门狗定时器
  22.                 if(X_key == 0){                //按键按下
  23.                         DelayXms(10);        //阻塞式延时消抖,10ms
  24.                         if(X_key == 0)        //按键真的按下,不是误动作
  25.                                 break;                //跳出等待的循环,运行函数调用处之后的程序
  26.                 }
  27.         }
  28. }
复制代码


方式一实现,休眠配合外部中断,需要在进入休眠前使能外部中断
方式二实现,直接调用函数

51黑.png (36.81 KB, 下载次数: 53)

51黑.png
回复

使用道具 举报

14#
ID:1087674 发表于 2023-7-31 11:30 来自手机 | 只看该作者
菜鸟yc 发表于 2023-7-31 09:33
方式一实现,休眠配合外部中断,需要在进入休眠前使能外部中断
方式二实现,直接调用函数

看不懂,还是方法二适合我,慢慢学。请问下,方式二中,如果我是按键释放时跳出循环,语句 if(X_key == 0) 改为if(X_KEY==1)就可以吗?
回复

使用道具 举报

15#
ID:1087948 发表于 2023-7-31 12:40 | 只看该作者
是的,单片机可以做到这一点。你可以使用中断来实现这个功能。

在你想要暂停的地方,你可以让单片机进入休眠模式或者无限循环等待,然后设置一个按键触发的中断。当按键被按下时,中断会被触发,然后单片机就会从休眠状态唤醒或者跳出无限循环,继续执行下面的程序。

以下是一个简单的示例代码(基于STM32):

c
#include "stm32f1xx_hal.h"

void EXTI0_IRQHandler(void)
{
  /* 确认中断标志 */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
   
    /* 在这里添加按键按下后需要执行的代码 */
  }
}

int main(void)
{
  /* 初始化和配置代码... */

  while(1)
  {
    /* 在这里添加主循环代码... */
   
    /* 想要暂停的地方 */
    __WFI(); // 进入休眠模式,等待中断唤醒
   
    /* 按键被按下,中断被触发,单片机唤醒,继续执行下面的代码... */
  }
}
在这个示例中,__WFI()函数使单片机进入休眠模式,等待任何中断来唤醒它。当按键被按下时,EXTI0中断被触发,然后单片机就会被唤醒,继续执行__WFI()之后的代码。

请注意,这只是一个基本的示例,实际的代码可能需要根据你的具体需求进行修改。例如,你可能需要配置GPIO为输入模式,并启用相应的中断;你也可能需要在中断处理程序中添加一些去抖动的代码等。
回复

使用道具 举报

16#
ID:396024 发表于 2023-7-31 16:44 来自手机 | 只看该作者
可以,有的单片机有sleep命令。
回复

使用道具 举报

17#
ID:57657 发表于 2023-7-31 18:29 | 只看该作者
进入掉电模式晶振停止震荡,可由外部中断或复位唤醒。
回复

使用道具 举报

18#
ID:1087674 发表于 2023-8-1 12:59 | 只看该作者
菜鸟yc 发表于 2023-7-31 09:33
方式一实现,休眠配合外部中断,需要在进入休眠前使能外部中断
方式二实现,直接调用函数

能否帮我修改一下,特别是那个看门狗程序,不会弄。
#include"intrins.h"
#include <reg52.h>
#define uchar unsigned char
#define uint  unsigned int
sfr P5 =0xC8;//P5地址
sbit key  = P5^4;
sbit led  = P5^5;

/***********************200ms延时函数*****************************/
void Delay200ms()                //@12.000MHz
{
        unsigned char data i, j, k;

        _nop_();
        _nop_();
        i = 10;
        j = 31;
        k = 147;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}

/***********************10ms延时函数*****************************/
void Delay10ms()                //@12.000MHz
{
        unsigned char data i, j;

        i = 20;
        j = 113;
        do
        {
                while (--j);
        } while (--i);
}

/***********************等待刹车松开函数*****************************/
void fun_Wait_Run(void)
{
        while(1)
        {
                CLRWDT();                     //清除看门狗定时器
                if(key == 1)                  //按键松开
                {                           
                        Delay10ms();         //阻塞式延时消抖,10ms
                     if(key == 1)          //按键真的松开,不是误动作
                     {        
                          break;          //跳出等待的循环,运行函数调用处之后的程序
                     }
                 }
        }
}

/******************主程序**********************/
void main()
{
        while(1)
         {
                 if(key == 0)                     //刹车
                 {
                    Delay10ms();                   //延时消抖,10ms
                    if(key == 0)
                     {                             //真刹车。
                        led = 0;                     //输出低电平。
                        Delay200ms();                //输出延时。
                      }
                   fun_Wait_Run;                  //等待松开手刹
                  }
                 if(key == 1)                      //松开手刹
                 {
                    Delay10ms();                 //延时消抖,10ms
                    if(key == 0)                 //真松开手刹。
                     {
                        led = 0;                 //输出低电平。
                        Delay200ms();             //输出延时。
                        led = 0;                  //再次输出低电平。
                        Delay200ms();
                      }
                  }
         }
}
回复

使用道具 举报

19#
ID:1087674 发表于 2023-8-3 11:55 | 只看该作者
自己顶上去,求助高手给弄下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表