dxstar 发表于 2010-10-11 15:20:01

关于PIC单片机的“休眠”和“唤醒”

关于PIC单片机的“休眠”和“唤醒”自己还是不太会用。希望各位大虾能给点指导。
现在主要是用PIC12F635单片机。用其中一个引脚GP0做为按键输入,其中一个引脚GP4作为输出。要达到的效果就是:平时都是“休眠”状态,当有按键按下时,单片机立即“唤醒”,GP4开始发出某段波形。就是想问一问这“休眠”与“唤醒”,具体怎么设置,希望有朋友写一小段用C的休眠和唤醒程序。让我能入个门。

Arsenal 发表于 2010-10-11 15:26:51

选择有唤醒功能的I/O接按键就好啦

yinqiu009 发表于 2010-10-11 15:46:46

休眠的概念源自低功耗,如果系统没有低功耗需求,应该不要考虑这个问题。

zq186 发表于 2010-10-11 21:58:58

void goSleep()
{
        asm("MOVLW 9");
        asm("TRIS 6");
        GP0=1;
        GP1=1;
        asm("MOVLW 79");//电平唤醒使能,弱上拉禁用,分频器分配给WDT
        asm("OPTION");
        asm("SLEEP");       
}

手头有个程序,我是这样处理进入休眠的
唤醒的话就是引脚电平变化,程序就从头开始运行

cwl0580 发表于 2010-10-12 00:48:04

如果有电平变化中断,开启就可以了,我现在用没中断的单片机,唤醒出了点问题,顺便也向大家求教!

cwl0580 发表于 2010-10-12 01:18:41

http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_589116U06OZI.jpg
12f629关于休眠唤醒的描述 (原文件名:629.jpg)

http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_589117L4CK5J.jpg
mcv08关于休眠唤醒的描述 (原文件名:mcv08.jpg)


对比了12F629和MCV08两个中文手册,关于唤醒,发现如下问题:
12F629唤醒后是先进中断(如果中断开),然后从程序休眠处继续往下跑。
MCV08这类没有中断的单片机,是单片机重新复位,程序从头开始跑。
不知道我的理解是否正确!?
现在问题来了,如果MCV08是复位,那我中间运行的一些变量是不是都要重新赋初值,那就实现不了我的预想的目的了,怎么办?

millwood0 发表于 2010-10-12 02:05:24

"不知道我的理解是否正确!? "

yes.

"现在问题来了,如果MCV08是复位,那我中间运行的一些变量是不是都要重新赋初值,那就实现不了我的预想的目的了,怎么办?"

1) you ask the start-up not to initialize global variable;
2) or you use static variables (in C).

rainyss 发表于 2010-10-12 06:43:31

1.变量初始化不要在定义时做
2.初始化里作上电检测,非上电重启时跳过初始化
3.程序流程复杂时使用状态机实现,以便立即回到唤醒前状态.

cwl0580 发表于 2010-10-12 09:12:22

非常感谢楼上两位,我照你们的办法试试!

cwl0580 发表于 2010-10-12 15:17:11

今天做了实验,发现休眠后RAM数据无法保存,也就是说所有变量都被清零了,静态全局变量也一样被清零!
“millwood0”和 “rainyss ”请看一下我的程序,看是不是程序问题!?

/////////////////////////////////////////////////////////////////////////////////////////////////
#include <pic.h>
#define uchar unsigned char

#define Weak_upGP3//I
#define LED   GP0        //o

//__CONFIG(0x06);//内部4M晶振,代码保护开,WDT开
__CONFIG(0x02);//内部4M晶振,代码保护开,WDT 0ff

//////////////////////////////////////////////////////////////////////////////////////////////////////////
static bit POWER_flag;//开关机标记
static uchar        Sleep_count;//休眠延时
//////////////////////////////////////////////////////////////////////////
////////////////////初始化程序//////////////////////////////////////////////
void Init(void)//初始化程序
{
       
        OPTION = 0x00;//T0分频:2;上拉开,唤醒开
    TRIS = 0x3E;//设置IO口方向3E:111110
        CM1CON0 = 0xF7;//电压比较器关
        ADCON0=0x00;//AD关

        if(PD)//如果是上电复位
        {
               
                GPIO = 0x00;//输出口清零
                POWER_flag=1;//开机
                //LED=POWER_flag;//上电led亮
                LED=1;//上电led亮
        }
        else//如果不是上电复位
        {       
                if(GPWUF)//如果是电平变化唤醒
                {
                        GPWUF = 0;    //清除唤醒标志
                        Sleep_count=255;//休眠延时计数赋值
                        POWER_flag=!POWER_flag;//开关机标记取反
                        //LED=POWER_flag;//LED无法取反,一直亮,所以我认为无论什么复位,POWER_flag每次都被清零了
                        LED=!LED;//LED状态正常取反
                }
        }

}


void main()            //主程序
{
    Init();                                //初始化
       
    while (1)         //主循环
    {        
               
                if(Sleep_count)//进入休眠延时
                        Sleep_count--;
                else//进入休眠
                {       
                        if(Weak_up)        //进入休眠前读端口,这点很重要,否则不正常               
                        asm("sleep"); //休眠                                       
                }
        }

}

rainyss 发表于 2010-10-13 23:02:14

每次重新执行main()就初始化?楼上不是有人说过从休眠退出时就相当于重启,会执行main()不.

cwl0580 发表于 2010-10-14 01:33:44

MCV08唤醒会执行main(),但我在Init()里面可以通过PD位判断是上电复位还是唤醒,从而决定对不对变量赋初值,现在感觉无论是唤醒还是复位都对变量清零了!

millwood0 发表于 2010-10-14 07:58:15

I am not going to write the code for you but here is an example where the pic wakes up from a wdt reset and retains its value.

============code====================

#include <htc.h>
#include "gpio.h"

__CONFIG(MCLRDIS & WDTEN & BORDIS & PWRTEN & INTIO);

#define LED_PORT                GPIO
#define LED_DDR                        TRISIO
#define LED_PINs                0xff

void mcu_init(void) {
        ANSEL=0x00;                        //all pins digital
        CMCON=0x07;                        //analog comparators off
        PSA=1;                                                                                //prescaller to wdt
//        PS2=1, PS1=1, PS0=1;                                                //prescaler to 1<<0b111. time-out period=18ms*128=2s
        PS2=0, PS1=1, PS0=1;                                                //prescaler to 1<<0b011. time-out period=18ms*8=160ms
        IO_CLR(LED_PORT, LED_PINs);        //led_pins low
        IO_OUT(LED_DDR, LED_PINs);
}

void
main(void)
{
        static unsigned char wdt_counter=0;
       
        mcu_init();
        while (1){
                //TODO Auto-generated main function
                if (!TO) {
                        //CLRWDT();                        //clear wdt status
                        wdt_counter++;                //if wdt reset
                        LED_PORT = wdt_counter;
                        while (1);                        //wait for the next wdt
                }
                //do something here
        }
}
==============end code==========================

millwood0 发表于 2010-10-14 08:03:59

the code sets up the wdt to wake the mcu up ever 160ms.

Once the mcu wakes up, it sets up the port / wdt, and then goes into the main while() loop.

in the main while loop, it checks to see if it is waking up. if it is, it increments a counter (wdt_counter). and then it outputs the wdt_counter on LED_PORT (GPIO here). after that, it goes into an infinite loop.

what you will see is that GPIO's pins will increment with each reset (every 160ms), with the exception that GPIO3 will not change as it is an input only pin on this mcu.

the code is compiler so that it does NOT clear data segments (bss Psects in Hi-Tech PICC talk).

here is the sim.

hope it helps.


http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_589673FL795W.PNG
(原文件名:12f675 wdt.PNG)

cwl0580 发表于 2010-10-14 13:49:20

找到原因了,如 millwood0 所说:the code is compiler so that it does NOT clear data segments (bss Psects in Hi-Tech PICC talk).

原来是编译器的问题,编译的时候clear bss不要打开,否则编译系统编译的时候会在初始化之前自动加上一些对RAM清零的代码,这样每次复位都会把RAM数据都清零,我也是仔细检测了汇编代码才发现的,我用的是PICC 9.8.
非常感谢 millwood0!!

tlang 发表于 2010-11-12 09:02:08

各位大侠,有个简单但很急的问题,PIC24fj64G怎么进入休眠模式,最好有程序

adamj 发表于 2011-3-29 20:52:25

终于见识到了真正的高手对话,学习!!!!

cwl0580 发表于 2011-4-2 13:06:20

晕,这个问题又被困扰了一次,唉,记性真不好,原来去年十月份已经解决了!!

baolei 发表于 2011-4-17 21:54:13

SLEEP();

LGY910 发表于 2013-7-3 14:32:50

mark;;{:smile:}

SevenWans 发表于 2013-7-22 22:04:14

mark!!!!{:smile:}

dgdzas 发表于 2013-7-25 10:58:29

millwood0,niu ren

retome 发表于 2015-6-22 22:42:15

millwood0 哪个国家的?

maplewang 发表于 2015-7-28 14:00:28

受教了,面临同样的问题。
页: [1]
查看完整版本: 关于PIC单片机的“休眠”和“唤醒”