Forum: Mikrocontroller und Digitale Elektronik AVR m644 wakeup on sleep


von Joachim B. (jar)


Lesenswert?

habe etwas Probleme mit den sleep modi

sleep klappt nun
wakeup auch ABER

nach dem wakeup kommt etwas später ein hardreset, der durchläuft richtig 
power on , wieso ?

mir ist das Zusammenspiel EIMSK, EIFR noch nicht klar
der erste sleep kommt wie gewünscht nach 10 sekunden erste Abfrage +1000
nach dem aufwecken sollte wieder ein neuer sleep kommen nach 20 
sekunden, vorgeladen +1000, Abfrage auf +1000 = 20 sekunden, ABER statt 
2tem sleep kommt power on reset !

Code für in sleep going:

      if( !bedient && fast_it>alarm_beginn+1000 )
      {
        //stop(2);
        OCR1AL = 1; // hell;
        OCR1BL = 0;  // kon;
        cli();
         if(!alarm_set)
        {
          //stop(3);
          PCMSK3|=(1<<PCINT27);
          PCICR|=(1<<PCIE3);

          EIMSK|=(1<<INT1);

          sleep_enable();
            sei();
           POWER_LED_PORT   |= (1 << _powerLED); // _POWER_ON LED an
            sleep_cpu();

          sleep_disable();
          _delay_up25(3);

           POWER_LED_PORT   &= ~(1 << _powerLED); // _POWER_ON LEDaus
          alarm_beginn=fast_it+1000;
          //bedient=TRUE;
          //alarm_set=TRUE;
          bedient=FALSE;
          alarm_set=FALSE;
          OCR1AL = hell;
          OCR1BL = kon;
          res_key=get_key_press( ALL_KEYS | (1<<KEY7) );
          res_key=0;

          EIFR|=(1<<INTF1);
          //stop(4);
        }
         sei();

      } // if( !bedient && fast_it>(alarm_beginn+1000) )

code für int1;
SIGNAL (SIG_INTERRUPT1)
{  UBYTE nix;
  nix=1;
  PCMSK3&=~(1<<PCINT27);
  PCICR&=~(1<<PCIE3);
  //EIFR&=~(1<<INTF1);
  EIMSK&=~(1<<INT1);
  //war_alarm=TRUE;
}

von mthomas (Gast)


Lesenswert?

Gibt es einen Handler für PCINT3_vect/SIG_PIN_CHANGE3? Wie sieht der 
aus? Läuft der Pin-Change Interrupt 3 ins Leere?

Martin Thomas

von Joachim B. (jar)


Lesenswert?

mthomas wrote:
> Gibt es einen Handler für PCINT3_vect/SIG_PIN_CHANGE3? Wie sieht der
> aus? Läuft der Pin-Change Interrupt 3 ins Leere?
>
> Martin Thomas

hmmm, leider keine Ahnung

programmiert hab ich keinen weil, ich finde keine defines dafür

hab mal so gesucht (in *.h signal.h, interrupt.h ioxx4.h) wie mögliche 
Interrupthandler heissen können

ich denke es wird genauso über den interrupthandler 1 gesprungen

hab heute am Oszi mögliche Fehler gefunden, der IRQ muss lange genug 
anliegen sonst wird der interrupt nicht ausgeführt, der Oszi meint es 
ist zu kurz mit um 1ms, die wakeupzeit ist ja 4,1-65ms

aber egal im IRQ muss ich ja nix weiter machen als die IRQs wieder 
rauszunehmen

PCMSK3&=~(1<<PCINT27);
PCICR&=~(1<<PCIE3);

und zur sicherheit mache ich es auch hinter sleep, einer wird schon 
wirken

aber unklar bleibt

EIMSK|=(1<<INT1); setzen vor sleep ? nutze ich überhaupt INT1 ?
wenn ja gibt es danach einen INT1 und muss ich INTF1 manuell löschen ?
EIFR=(1<<INTF1);

ich war schon mal weiter, hab die CPU aus und anbekommen, je mehr ich 
lese umso unsicherer werde ich was mit wem gesetzt werden muss

im Moment bekomme ich sie aus
set_sleep_mode(SLEEP_MODE_PWR_DOWN);

aber nicht mehr an !

oder aber sie geht sofort nach aus von selbst wieder an !
je nach EIMSK und EIFR Nutzung

bin verwirrt

ich weiss auch nicht wirklich welche Flags ich vor dem cli() setzen darf 
oder muss und welche ich ausserhalb des cli setzen muss
ich weiss auch nicht ob ein sleep in einer unterroutine ausgeführt 
werden darf, springen die atmels über interrupts ?

UBYTE shutdown(void)
{  static UBYTE pwm1, pwm2, wakeup_from;
  wakeup_from=0;
  pwm1=OCR1AL;
  pwm2=OCR1BL;
  OCR1AL=0;
  OCR1BL=255;

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   //cli();
  EICRA |=(1<<ISC10);
  EICRA |=(1<<ISC11);
  PCMSK3|=(1<<PCINT27);
  PCICR|=(1<<PCIE3);
  EIMSK|=(1<<INT1);
  EIFR=(1<<INTF1);
   cli();


  POWER_LED_PORT   |= (1 << _powerLED); // _POWER_ON LED an

  sleep_enable();

 sei();
 sleep_cpu();
 _delay_up25(3);
  POWER_LED_PORT   &=~(1 << _powerLED); // _POWER_ON LED aus
  EIFR=(1<<INTF1);

   sleep_disable();
  OCR1AL=pwm1;
  OCR1BL=pwm2;

  PCMSK3&=~(1<<PCINT27);
  PCICR&=~(1<<PCIE3);
  EIMSK&=~(1<<INT1);
  //EIFR=1<<INTF1;

  if((wakeup_from=test_status_rtc())>0)
    return wakeup_from;
  else
    if((wakeup_from=get_key_press( ALL_KEYS ))>0)
      return wakeup_from;
  return wakeup_from;
}

von mthomas (Gast)


Lesenswert?

Ohne den Code genau durchgesehen zu haben (mir ist nicht ganz klar, 
warum INT1 und PCINT27 zusammen verwendet werden)
1
PCICR|=(1<<PCIE3);
aktivierte den Pin-Change Interrupt 3. "Any change on any enabled 
PCINT31..24 pin will cause an interrupt. The corresponding interrupt of 
Pin Change Interrupt Request is executed from the PCI3 Interrupt 
Vector." [Datenblatt]. Wo ist der Handler dafür? Es sieht so aus, also 
würde der Interrupt einfach "ins Leere" laufen, wenn bei gesetztem I-Bit 
eine Änderung an PCINT27 auftritt und daher der Reset ausgelöst. Das hat 
erstmal nichts mit dem externen Interrupt INT1 zu tun, für den es ja 
einen Handler gibt.

> ich finde keine defines dafür hab mal so gesucht (in *.h signal.h,
> interrupt.h ioxx4.h) wie mögliche Interrupthandler heissen können
Hmm. Alte Version der avr-libc? Aus der iomxx4.h "hier" (aus WinAVR 
5/07):
1
/* Pin Change Interrupt Request 3 */
2
#define PCINT3_vect      _VECTOR(7)
3
#define SIG_PIN_CHANGE3      _VECTOR(7)

Ja, für PinChange muss der "Change" eine Weile anliegen (wie lang genau 
weiss ich grade nicht, hatte damit aber auch Probleme für ein "wakup on 
pinchange an RX" bei 115200bps aus Mode power-save). Falls man 
"schneller" reagieren will und es nicht auf das letzte uA Stromverbrauch 
im Schlafmodus ankommt: (extended-)standby sleep-mode verwenden.

Zwischen sleep_cpu und sleep_disable würde ich keine Anweisungen 
zwischenschieben. Zum Test cli() ganz nach vorn und sei() erst wenn man 
alles fertig initialisiert hat. Am Ende der Initialisierung 
sicherheitshalber auch noch die Flags PCIF3 und INTF1 löschen ("cleared 
by writing a logical one"). Mglw. interessant: "Note that when entering 
sleep
mode with the INT2:0 interrupts disabled, the input buffers on these 
pins will be disabled. This may cause a logic change in internal signals 
which will set the INTF2:0 flags." [Datenblatt] Ansonsten noch ein 
Hinweis auf die Dokumentation der avr-libc. In neueren Versionen wurde 
"sleep.h" etwas erweitert.


Martin Thomas

von Joachim B. (jar)


Lesenswert?

mthomas wrote:
> Ohne den Code genau durchgesehen zu haben (mir ist nicht ganz klar,
> warum INT1 und PCINT27 zusammen verwendet werden)

war mir auch unklar , deswegen hab ich ja gefragt

> #define SIG_PIN_CHANGE3      _VECTOR(7)

das war der entscheidene Tipp , ich glaub ich bin auf dem richtigen Weg

ausschalten per Kommando klappt nun schon + Einschalten per Taste



   POWER_LED_PORT   |= (1 << _powerLED);     // _POWER_ON LED an
   EICRA |=(1<<ISC10);
   EICRA |=(1<<ISC11);
   PCMSK3|=(1<<PCINT27);
   PCICR|=(1<<PCIE3);

   cli();
  _delay_up25(3); WAR EIN VERSUCH UM DIE TASTENAUSSCHALTUNG ZU 
ÜBERLISTEN klappt nicht

  PCIFR=(1<<PCIF3); in der Hoffnung den Tastenwechselinterrupt zu 
löschen, der hängt ja schon beim Ausschalten dort und somit ist wieder 
an

  sleep_enable();
 sei();
 sleep_cpu();
 _delay_up25(3); die Warmlaufzeit 75ms

   POWER_LED_PORT   &=~(1 << _powerLED);     // _POWER_ON LED aus
   sleep_disable();
   PCMSK3&=~(1<<PCINT27);
   PCICR&=~(1<<PCIE3);

> Ja, für PinChange muss der "Change" eine Weile anliegen

so wie ich das DB lese ist die Zeit egal, hinter sleep gehts weiter, nur 
wenn der Pinchange lange genug war , dann geht es in den IRQ ! ergo zur 
Sicherheit, nix im IRQ machen was nicht auch hinter sleep gemacht wird 
oder werden kann, für mich ist der IRQ Handler nur schmückendes Beiwerk 
um den RTI zu erzeugen

SIGNAL (SIG_PIN_CHANGE3)
{  UBYTE nix;
  nix=1;
  PCMSK3&=~(1<<PCINT27);
  PCICR&=~(1<<PCIE3);
  PCIFR=(1<<PCIF3);
  //war_alarm=TRUE;
}



> Zwischen sleep_cpu und sleep_disable würde ich keine Anweisungen
> zwischenschieben. Zum Test cli() ganz nach vorn und sei() erst wenn man
> alles fertig initialisiert hat. Am Ende der Initialisierung
> sicherheitshalber auch noch die Flags PCIF3 und INTF1 löschen ("cleared
> by writing a logical one"). Mglw. interessant: "Note that when entering
> sleep
> mode with the INT2:0 interrupts disabled, the input buffers on these
> pins will be disabled. This may cause a logic change in internal signals
> which will set the INTF2:0 flags." [Datenblatt]

das hat mir leider nicht geholfen, mit Taste bekomme ich den nicht aus ! 
nur per IR , einschalten geht

ich muss morgen mit dem Oszi schauen was da los ist Timing Pegel ....



übrigend Danke , dein Beitrag hat mir wirklich sehr geholfen , den 
Knoten im Kopf zu lösen, das ist noch alles ziemlich neu für mich und 
dann hat das 644 Datenblatt auch noch Fehler, glücklicherweise merkt man 
das die 2 mal dasselbe Register geschrieben in einer Folge, ist aber 
doof wenn man im Kopf int1 hat und der int2: genannt wird

"which will set the INTF2:0 flags"

von Joachim B. (jar)


Lesenswert?

so Tastaturaus gelöst, ein

_delay_up25(4); erzeugt die notwendige Wartezeit 4 x 25ms um auch per 
Tastatur auszugehen, damit ist genug Zeit nach dem Tastendruck den Int 
zu löschen

EDIT, noch besser
while(get_key_press(1<<KEY6));
_delay_up25(4);
shutdown();

so nun noch das Problem das der PWM Timer offensichtlich stehenbleibt wo 
er will, mal mit heller LED Hintergrundbeleuchtung mal ohne, obwohl ich
OCR1AL=0; vorher auf NULL setze, LED Hintergrundbeleuchtung auf aus

evt. muss ich den noch manuell abschalten den PWM Timer ? , oder den 
Port ausschalten ?

so auch gelöst:
HELL_KON_DDR  &= ~(1 << _LED_hell);    // OC1A DDR out

von Joachim B. (jar)


Lesenswert?

so alles läuft fast nur vermute ich mein idle Modus ist nicht OK, power 
down läuft erwartunggemäß

was wird im idle modus alles getan ? der sollte lt. sleep Zeit 30s im 
idle schlafen und nix tun, aber er schläft idle viel kürzer, maximal 1-5 
Sekunden, Int0 hab ich aus, muss ich noch die PWM und Timer ohne 
gesetztes Int ausschalten ?  irgendwas weckt in bei idle, ich weiss nur 
nicht was....

Timer Overflow ?

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.