Atmega328p wacht nicht auf, wo steckt der Fehler?

Gast #3907719
Hallo,
ich möchte meinen MCU alle 2 Sekunden wecken, um ein Sensor kurz zu 
überprüfen und dann wieder schlafen legen lassen. Zusätzlich habe ich in 
der ISR eine Countdown Schaltung programmiert. Mit dem Flag zeige ich an 
wann der MCU alarmieren soll. Leider glaube ich das der MCU gar nicht 
aus dem Schlafmodus aufwacht, denn der Sensor reagiert nicht mehr und 
der Stromverbrauch ist konstant bei 42µA.

1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <avr/interrupt.h>
4
#include <avr/sleep.h>
5
#include <util/delay.h>
6

7
#define F_CPU 8000000L 
8

9
volatile uint8_t flag;
10

11
int main(void)
12
{
13

14
 
15

16
 
17
 DDRC |= (1<<PC5) | (1<<PC4); 
18
 DDRC &= ~(1<<PC3);
19
 
20
 
21
 GTCCR |= (1<<TSM) | (1<<PSRASY);
22
 ASSR |= (1<<AS2); 
23
 TCCR2A |= (1<<WGM21); 
24
 TCCR2B |= (1<<CS22) | (1<<CS21); 
25
 OCR2A = 256-1; 
26
 TIMSK2 |= (1<<OCIE2A); 
27
 GTCCR &= ~(1<<TSM); 
28
 
29

30
 
31
 sei(); 
32
 
33
 
34
 
35
 while(1)
36
    {
37

38
   
39
   set_sleep_mode(SLEEP_MODE_PWR_SAVE);
40
   sleep_mode();
41
 
42
 
43
   
44
   
45
   
46
   PORTC |= (1<<PC4); 
47
   _delay_ms(1); 
48
   
49
   while(!(PINC &= (1<<PINC3)))
50
   {
51
   PORTC |= (1<<PC5); 
52
   }
53
   
54
   PORTC &= ~(1<<PC5); 
55
   PORTC &= ~(1<<PC4); 
56
   
57
   
58
     
59
   while(flag==1)
60
   {
61
   PORTC|= (1<<PC5); 
62
   }
63
   
64
    }
65
 return (0);
66
}
67

68

69

70

71
ISR(TIMER2_COMPA_vect)
72
{
73
 static uint8_t zweitesekunde;
74
 static uint8_t minute=0;
75
 static uint8_t stunde=0;
76
 static uint8_t tag=0;
77
 
78
 zweitesekunde++;
79
 if(zweitesekunde==30)
80
 {
81
 zweitesekunde=0;
82
 minute++;
83
 }
84
    if(minute == 60)
85
    {
86
    stunde++;
87
    minute = 0;
88
    }
89
    if(stunde == 24)
90
    {
91
    stunde = 0;
92
 tag++;
93
 flag=1; 
94
    }
95
 
96
}
Gast #3907769
Das erste würde ich so lassen, weil ich solange der Input PINC3 ungleich 
high ist , die LED einschalten möchte und sie auch solange eingeschaltet 
bleiben soll bis der Input wieder zurück auf HIGH geht.

Beim zweiten hast du recht, da die Zeit überschritten wurde und dort die 
LED nur durch resetten zurückgesetzt werden kann.
#3907775
Solange eines der beiden Abfragen 1 ist, wird dort nichts in den 
Schlafmodus gehen.

Warum dauerhaft die Ports setzen?
1
  while(!(PINC &= (1<<PINC3)))
2
   {
3
   PORTC |= (1<<PC5); 
4
   }
5
   
6
   PORTC &= ~(1<<PC5); 
7
   PORTC &= ~(1<<PC4); 
8
   
9
   
10
     
11
   while(flag==1)
12
   {
13
   PORTC|= (1<<PC5); 
14
   }
#3907785
David schrieb:
> Das erste würde ich so lassen, weil ich solange der Input PINC3 ungleich
> high ist , die LED einschalten möchte und sie auch solange eingeschaltet
> bleiben soll bis der Input wieder zurück auf HIGH geht.
>
> Beim zweiten hast du recht, da die Zeit überschritten wurde und dort die
> LED nur durch resetten zurückgesetzt werden kann.

Deine Timing-Vorstellungen verstehe ich nicht.
Erst schläfst du 2 Sekunden, dann willst sofort und gleich auf ein 
Eingangssignal reagieren.
Was wenn das Signal innerhalb des 2 Sekundenschlafs kommt?

Funktioniert denn dein Programm ohne Sleep?

Edit:
hier schon geschaut?:
http://www.mikrocontroller.net/articles/Sleep_Mode
Gast #3907813
Ja das Programm funktioniert ohne Sleep funktion wunderbar es geht mir 
eigentlich auch nur um die Sleep Funktion.
Ich habe das Programm jetzt einfach mal vereinfacht, damit es um das 
wesentliche geht, das aufwachen:
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include <avr/sleep.h>
6

7
#define F_CPU 8000000L
8

9
volatile uint8_t flag;
10

11

12
int main(void)
13
{
14

15
  
16
  //konfigurieren der PINS:
17

18
  
19
  DDRC |= (1<<PC5) | (1<<PC4); //Pin pc5 und pc4 als ausgang definieren
20
  //DDRC &= ~(1<<PC3); //Pin pc3 als eingang definieren
21
  
22
  
23
  //Start der Initalisierung des Timer 2:
24
  GTCCR |= (1<<TSM) | (1<<PSRASY); //Timer anhalten, Prescaler Resetten, um die Einschwingzeit des Oszillators zu überbrücken (Einschwingzeit 100ms-1000ms
25
  ASSR |= (1<<AS2); //Timer Asynchron-Mode einschalten 32768 RTC hängt an XTAL1+XTAL2
26
  TCCR2A |= (1<<WGM21); // Versetze in Compare Mode
27
  TCCR2B |= (1<<CS22) | (1<<CS21); //Prescaler auf 256
28
  OCR2A = 256-1; //(=OCR2A Compare Register) Berechnung der Aufwachzeit (32768/256)^-1*256= Aufwachzeit alle 2 Sekunden wird der MCU aufgeweckt
29
  TIMSK2 |= (1<<OCIE2A); //Timer 2 Interrupt Enable
30
  GTCCR &= ~(1<<TSM); //"Timer anhalten Bit" löschen
31
  
32

33
  
34
  sei(); // Global Interrupt Mode aktiviert
35
  
36
  
37
  
38
  while(1)
39
  {
40
    
41
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
42
    sleep_mode();
43
    
44
    
45
    // Hier wird aufgewacht
46
    
47
    if(flag==1)
48
    {
49
      PORTC |= (1<<PC5); //LED anschalten
50
      _delay_ms(100);
51
      PORTC &= ~(1<<PC5); //LED abschalten
52
      flag=0;
53
    }
54
    
55

56
    
57
  }
58
  return (0);
59
}
60

61

62

63

64
ISR(TIMER2_COMPA_vect)
65
{  
66
  flag=1;
67
}
Gast #3907819
Joachim B. schrieb:
> David schrieb:
>> set_sleep_mode(SLEEP_MODE_PWR_SAVE);
>
> womit soll er denn geweckt werden?
>
> möglich wäre:
> Timer 2
> ext. Interrupts
> TWI
> Watchdog
>
> wenn er schläft läuft er nicht mehr....

Deswegen habe ich eigentlich den Timer2 in Compare-Mode programmiert, im 
Power Save Mode sollte dann nur Timer 2 mit einem 32,768khz Quarz laufen 
sobald die 2 Sekunden um sind sollte der Interrupt erfolgen und ihn 
aufwecken, der dann das Hauptorogramm weiter ausführt.
#3907820
David schrieb:
> es geht mir
> eigentlich auch nur um die Sleep Funktion.

verstehe ich, nur wenn er schläft schläft er, ich schrieb ja schon die 
Aufwachmöglichkeiten, externer Uhrenquarz am Timer2 32kHz, watchdog, 
oder externer Interrupt.

Ich weiss immer noch nicht wie du den aufwecken willst wenn kein 
watchdaog programmiert ist, kein externer Uhrenquarz dranhängt und kein 
externer Interrupt ausgelöst wird.
#3907843
Thomas Eckmann schrieb:
> ???

so ähnlich bei mir auch

also mit sleepmodi hatte ich schon mal das Vergnügen, nur noch nicht mit 
der allgemein beliebten Timer Variante mit dem 32kHz Quarz am extra 
Eingang, nicht dem Systemquarz. Ich las immer davon das der den AVR 
aufwecken kann um alle Skunde die SoftUhr einen weiterlaufen zu lassen. 
Ich bevorzugte die RTC DS3231 die mit ihrem Alarmregister und /INT 
Ausgang am AVR per PCINT weckt, da muss der arme AVR nicht alle Sekunde 
gewckt werden, kann fröhlich pennen bis er wirklich dran ist.
Gast #3907867
Das ganze ist auf Breadbord,
die Kondensatoren sind 2 x 27 pF, da ich damals keine 22 pF 
Kondensatoren zur Hand hatte - diese habe ich jetzt aber wieder besorgt, 
soll ich diese mal anbringen?
Gast #3907919
Chris schrieb:
> Hast du den Quarz zwischen TOSC 1 und TOSC 2?
> Sonst klappt es nicht. Da benötigtst du auch keine extra Kondensatoren.

Ja hab ich.

Der Timer scheint jetzt zu funktionieren. Aber anstatt alle 2 Sekunden 
zu blinken braucht er jetzt fast 10 sekunden?

1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include <avr/sleep.h>
6

7
#define F_CPU 8000000L
8

9
volatile uint8_t flag;
10

11

12
int main(void)
13
{
14

15
  
16
  //konfigurieren der PINS:
17

18
  
19
  DDRC |= (1<<PC5) | (1<<PC4); //Pin pc5 und pc4 als ausgang definieren
20
  //DDRC &= ~(1<<PC3); //Pin pc3 als eingang definieren
21
  
22
  
23
  //Start der Initalisierung des Timer 2:
24
  GTCCR |= (1<<TSM) | (1<<PSRASY); //Timer anhalten, Prescaler Resetten, um die Einschwingzeit des Oszillators zu überbrücken (Einschwingzeit 100ms-1000ms
25
  ASSR |= (1<<AS2); //Timer Asynchron-Mode einschalten 32768 RTC hängt an XTAL1+XTAL2
26
  TCCR2A |= (1<<WGM21); // Versetze in Compare Mode
27
  TCCR2B |= (1<<CS22) | (1<<CS21); //Prescaler auf 256
28
  OCR2A = 256-1; //(=OCR2A Compare Register) Berechnung der Aufwachzeit (32768/256)^-1*256= Aufwachzeit alle 2 Sekunden wird der MCU aufgeweckt
29
  TIMSK2 |= (1<<OCIE2A); //Timer 2 Interrupt Enable
30
  GTCCR &= ~(1<<TSM); //"Timer anhalten Bit" löschen
31
  
32

33
  
34
  sei(); // Global Interrupt Mode aktiviert
35
  
36
  
37
  
38
  while(1)
39
  {
40
    _delay_ms(500);
41
    PORTC &= ~(1<<PC5); //LED abschalten
42

43
    
44
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
45
    sleep_mode();
46
    
47
    
48
    // Hier wird aufgewacht
49
    
50

51
    
52
  }
53
  return (0);
54
}
55

56

57

58

59
ISR(TIMER2_COMPA_vect)
60
{  
61
          PORTC |= (1<<PC5); //LED anschalten
62
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 11 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.