Forum: Mikrocontroller und Digitale Elektronik PIC12F629 Sleep-Mode


von microman (Gast)


Lesenswert?

Ich habe eine Steuerung für einen Belichter entworfen.
Ich würde gerne den PIC aus dem Sleep Mode aufwecken
indem man 5V an GP3 legt.

Also über eine positive Flanke.
Wie geht das?

Ich würde mich über Vorschläge freuen.


  list     p=12f629
  #include <p12f629.inc>


  ;         MCLR aus  Power on Timer, kein Watchdog, int-Oscillator, 
kein Brown out, Code Protection aus
  __CONFIG  _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & 
_BODEN_OFF & _CP_OFF
;----------------------------------------------------------------------- 
-
D    equ  0x20  ; Variable für Schleife
CounterA  equ  0x21  ; Variable für Schleife
CounterB  equ  0x22  ; Variable für Schleife
CounterC  equ  0x23  ; Variable für Schleife
CounterD  equ  0x24  ; Variable für Schleife

  org  0x00     ; prg. beginnt an adr. 00(hex)
        goto main     ; sprung an hauptprogramm marke
;----------------------------------------------------------------------- 
-
main
  bcf  STATUS, RP0  ; Bank 0
  clrf  GPIO    ; aus

  movlw  0x07    ; comparator aus
  movwf  CMCON    ; alle Pins digital (nicht Comparator)
  bsf  STATUS, RP0  ; Bank 1
  clrf  TRISIO    ; alle output
  bcf  STATUS, RP0  ; Bank0

        ; interner Taktgenerator
  bsf  STATUS, RP0  ; Bank 1
  call  0x3FF    ; get the calibration value
  movwf  OSCCAL    ; 4-MHz-Kalibrierung
  bcf  STATUS, RP0  ; Bank 0

;----------------------------------------------------------------------- 
-
loopmain

  btfss  GPIO,3    ; GP3=5V? (Start)
  goto  loopmain  ; nein
  bsf  GPIO,0    ; ja (GP0=5V) -> Belichter ein
  call  Wait1    ; 60s warten

  bcf  GPIO,0    ; GP0=0V -> Belichter aus

        ; LED an GP2 blinkt und Summer an GP1 ertönt
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V

  sleep

  goto loopmain    ; Abfrage für Neustart
;----------------------------------------------------------------------- 
-
;PIC Time Delay = 60,0000010 s with Osc = 4 MHz

Wait1
  movlw  D'2'
  movwf  CounterD
  movlw  D'51'
  movwf  CounterC
  movlw  D'146'
  movwf  CounterB
  movlw  D'18'
  movwf  CounterA
loop1  decfsz  CounterA,1
  goto  loop1
  decfsz  CounterB,1
  goto  loop1
  decfsz  CounterC,1
  goto  loop1
  decfsz  CounterD,1
  goto  loop1
  return
;----------------------------------------------------------------------- 
-
;PIC Time Delay = 0,5000020 s with Osc = 4 MHz

Wait2
  movlw  D'3'
  movwf  CounterC
  movlw  D'140'
  movwf  CounterB
  movlw  D'83'
  movwf  CounterA
loop2  decfsz  CounterA,1
  goto  loop2
  decfsz  CounterB,1
  goto  loop2
  decfsz  CounterC,1
  goto  loop2
  return
;----------------------------------------------------------------------- 
-
  org     0x3ff
  retlw   0x20

  end

von macroman (Gast)


Lesenswert?

Hallo,

Ich hab mach das zwar mit C, aber wenn im Sleep-Mode an GP2 eine 
positive Flanke kommt wacht er automatisch auf! Bin mir nicht sicher ob 
man ihn auch von den anderen Ports aus dem Sleep holen kann!

von microman (Gast)


Lesenswert?

Heißt das ich muss einfach an GP2 ein positive Flanke anlegen
und der PIC arbeitet weiter.

Ich denke nur da muss man doch im Programm was schreiben damit das auch 
wirklich funktioniert.

Oder einfach nur ne pos. flanke anlegen und funzt

von macroman (Gast)


Lesenswert?

Einfach positive Flanke anlegen und es geht;-) Probiers mal!

von microman (Gast)


Lesenswert?

einfach ne pos. flanke anlegen funzt net

ich denke man muss im programm definieren das ein interrupt ausgelöst 
wird

ich kann eure hilfe echt gebrauchen

von macroman (Gast)


Lesenswert?

HAb ich aber heute gemacht! Und hat Gefunzt.

Mach mal vor dem Sleep GIE=0 und nach dem Sleep GIE=1!

von microman (Gast)


Lesenswert?

kannst du mir mal den code geben
ich arbeite ja mit assembler

von macroman (Gast)


Lesenswert?

Ja, und ich arbeite mit C:

Hier die Initialisierung für den Interrupt an GP2:
1
//GP2 Interrupt Init
2
INTEDG = 1;    //Rising Edge
3
INTE = 1;    //Enable
4
INTF = 0;    //Flag = 0
5
GIE = 1;    //Global Interrupt Enable


Und hier der Wesentliche Teil meiner main-Routine:
1
while(1)
2
{
3
  if((led_on == 1) && (led_dimmmode == 0))
4
    GPIO1 = 1;
5
  if(led_on == 0)                    
6
  {
7
    GPIO1 = 0;
8
    GIE = 0;
9
    SLEEP();
10
    GIE = 1;
11
  }
12
  if(touchtime >= 5)                   
13
    led_dimmmode = 1;
14
    
15
}

von microman (Gast)


Lesenswert?

Ich hab jetzt das Programm raufgeprogt
Der Pic geht schon in den sleep mode
nur wenn ich ihm eine negative Flanke gebe tut sich nix
er will nicht aufwachen

  list     p=12f629
  #include <p12f629.inc>


  ;         MCLR aus  Power on Timer, kein Watchdog, int-Oscillator, 
kein Brown out, Code Protection aus
  __CONFIG  _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & 
_BODEN_OFF & _CP_OFF
;----------------------------------------------------------------------- 
-
D    equ  0x20  ; Variable für Schleife
CounterA  equ  0x21  ; Variable für Schleife
CounterB  equ  0x22  ; Variable für Schleife
CounterC  equ  0x23  ; Variable für Schleife
CounterD  equ  0x24  ; Variable für Schleife

  org  0x00     ; prg. beginnt an adr. 00(hex)
        goto main     ; sprung an hauptprogramm marke
;----------------------------------------------------------------------- 
-
main
  bcf  STATUS, RP0  ; Bank 0
  clrf  GPIO    ; aus

  movlw  0x07    ; comparator aus
  movwf  CMCON    ; alle Pins digital (nicht Comparator)
  bsf  STATUS, RP0  ; Bank 1
  clrf  TRISIO    ; alle output
  bcf  STATUS, RP0  ; Bank0

        ; interner Taktgenerator
  bsf  STATUS, RP0  ; Bank 1
  call  0x3FF    ; get the calibration value
  movwf  OSCCAL    ; 4-MHz-Kalibrierung
  bcf  STATUS, RP0  ; Bank 0

;----------------------------------------------------------------------- 
-
loopmain

  btfsc  GPIO,3    ; GP3=5V? (Start)
  goto  loopmain  ; nein
  bsf  GPIO,0    ; ja (GP0=5V) -> Belichter ein
  call  Wait1    ; 60s warten

  bcf  GPIO,0    ; GP0=0V -> Belichter aus

        ; LED an GP2 blinkt und Summer an GP1 ertönt
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V
  bsf GPIO,2    ; GP2=5V
  call Wait2    ; 0.5s warten
  bsf GPIO,1    ; GP1=5V
  bcf GPIO,2    ; GP2=0V
  call Wait2    ; 0.5s warten
  bcf GPIO,1    ; GP1=0V

  sleep

  goto loopmain    ; Abfrage für Neustart
;----------------------------------------------------------------------- 
-
;PIC Time Delay = 62,0000020 s with Osc = 4 MHz

Wait1
  movlw  D'2'
  movwf  CounterD
  movlw  D'61'
  movwf  CounterC
  movlw  D'193'
  movwf  CounterB
  movlw  D'105'
  movwf  CounterA
loop1  decfsz  CounterA,1
  goto  loop1
  decfsz  CounterB,1
  goto  loop1
  decfsz  CounterC,1
  goto  loop1
  decfsz  CounterD,1
  goto  loop1
  return
;----------------------------------------------------------------------- 
-
;PIC Time Delay = 0,5000020 s with Osc = 4 MHz

Wait2
  movlw  D'3'
  movwf  CounterC
  movlw  D'140'
  movwf  CounterB
  movlw  D'83'
  movwf  CounterA
loop2  decfsz  CounterA,1
  goto  loop2
  decfsz  CounterB,1
  goto  loop2
  decfsz  CounterC,1
  goto  loop2
  return
;----------------------------------------------------------------------- 
-
  org     0x3ff
  retlw   0x20

  end

von macroman (Gast)


Lesenswert?

INTEDG = 1;    //Rising Edge

Welcher Wert hat diese Bit bei dir denn???

von Chris N. (lamda)


Lesenswert?

Hallo, im STATUS register, oder war es im OPTION, eher da, gibt es ein 
bit,
mit dem du WAKE_UP_ON_CHANGE einschalten kannst. Das brauchst du,
aber ich weiss im Moment nicht, welcher Pin das ist, jedenfalls glaube 
ich
bei dem MCU nur 1 pin, bei anderen MCU´s können es mehr sein.
Noch was, vergiss das mit dem Sleep, sondern mach sowas, das ist besser.

dosleep:
  sleep
main:
  .....
  goto dosleep

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Mal sehen ob ich es noch zusammen bekomme. Eines meiner ersten Proggs 
war ein Minilauflicht mit 5 LED (Batteriebetrieben). Ich hatte damals 
auch den GPIO3 als Eingang benutzt um das Lauflicht aus dem Sleep 
aufzuwecken.

Du brauchst tatsächlich den Interrupt. Als erstes musst du im 
IOC-Register den entsprechenden Pin maskieren, damit der zugehörige 
Eingang überhaupt auf Interrupts regiert.
1
  MOVLW  B'00001000'  ;GP3 (Taster) für Int einschalten
2
  MOVWF  IOC

Dann musst du im INTCON-Register den GPIE und den GIE einschalten
1
  MOVLW  B'10001000' ;GIE und GPIE ein
2
  MOVWF  INTCON    ;Interupt für Taster freigeben

Vorher musst du natürlich ab Adresse 0x04 eine Interruptroutine 
schreiben. Also Register sichern, das GPIF-Bit im INTCON-Register 
abfragen um zu sehen ob der Interrupt durch einen Taster ausgelöst 
wurde. Wenn ja, dann deine Befehle ausführen. Am Ende GPIF wieder 
zurücksetzen, Register zurücksichern und aus der Routine springen.

Das Programm macht dann bei dem Befehl nach dem SLEEP weiter.

Probiers mal aus.

Gruß
Sven

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Sehe gerade, dass es natürlich noch das INT-Pin (GP2) gibt. Hier musst 
du im INTCON-Register das INTE-Bit einschalten (und natürlich das 
GIE-Bit). Mit dem INTF-Bit fragst du dann in der Interruptroutine ab, ob 
es der INT-Interupt war, der auslöste. Der INT-Interrupt arbeitet nur 
auf einer Flanke. Ob der Interrupt bei steigender oder bei fallender 
Flanke ausgelöst werden soll stellst du mit dem INTEDG-Bit im OPTION_REG 
Register ein (1=steigend, 0=fallend).

Den INT Interrupt gibt es nur am GP2-Pin. Da ich aber den GP3-Pin damals 
benutzen wollte (er kann nicht als Ausgang geschaltet werden) hatte ich 
mich für den Interrupt on Change (IOC) entschieden. Der löst bei jeder 
Flanke aus und kann für jeden Pin (GP0-GP5) eingeschaltet werden.

Ciao

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Hab gerade bei sprut dazu noch etwas gefunden:

---------------------
Der Sleep-Befehl versetzt den Prozessor in den stromsparenden 
stand-by-Mode.
Durch die einige bestimmte Interrupts wird der PIC wieder geweckt. Falls 
das zum Interrupt zugehörige Interrupte-Enable-Bit gesetzt ist, läuft 
der PIC einfach im Programm weiter. Ist auch noch das GIE-Bit gesetzt, 
wird zusätzlich noch die Interruptbehandlungsroutine aufgerufen.
---------------------

Heist also, dass das Programm einfach nach dem SLEEP weitermachen 
müsste, wenn man das GIE-Bit nicht setzt. Dann müsste man sich auch die 
ISR sparen können. Hab ich selbst aber noch nicht so ausprobiert.

Sven

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.