Forum: Mikrocontroller und Digitale Elektronik Problem Timerinterrupt und Sleepmodus


von Rudolfi (Gast)


Lesenswert?

Hallo,

ich habe aus Kombination der hier vorgestellten Artikel und 
Beispielcodes versucht, eine LED durch Timerinterrupt langsam togglen zu 
lassen. Das funktioniert soweit. Jetzt möchte ich, dass der AVR zwischen 
den Toggleoperationen schlafen geht.

Mein Code funktioniert nicht. Wenn ich den Inhalt von while() 
auskommentiere, blinkt die LED wie gewünscht, aber eben ohne Sleep 
zwischendurch. Woran liegt das?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/sleep.h>
4
#include <util/delay.h>
5
 
6
7
int main(void)
8
{
9
  DDRB=0xff;
10
  OCR1A = 0xf40;
11
12
  TCCR1B |= (1 << WGM12);
13
  // Mode 4, CTC on OCR1A
14
15
  TIMSK1 |= (1 << OCIE1A);
16
  //Set interrupt on compare match
17
18
  TCCR1B |= (1 << CS12) | (1 << CS10);
19
  // set prescaler to 1024 and start the timer
20
21
  sei();
22
  // enable interrupts
23
24
  while (1)
25
  {
26
    // we have a working Timer
27
    
28
    set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
29
    sleep_enable();
30
    sei();
31
    sleep_cpu();
32
    sleep_disable();
33
  
34
  }
35
  
36
  
37
}
38
39
40
 
41
ISR (TIMER1_COMPA_vect)
42
{
43
  if (PORTB == 0x00)
44
  PORTB = 0xFF;
45
  else
46
  PORTB = 0x00;
47
}

von Falk B. (falk)


Lesenswert?

@ Rudolfi (Gast)

>zwischendurch. Woran liegt das?


>    set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
>    sleep_enable();

>ISR (TIMER1_COMPA_vect)

Im extended stand by läuft kein TImer, nur der Oszillator! Siehe Artikel 
Sleep Mode.

von Thomas E. (thomase)


Lesenswert?

Nimm den Watchdog-Timer. Der läuft in allen Sleep-Modi. Auch im 
PWR_DOWN.

mfg.

von Rudolfi (Gast)


Lesenswert?

Ich habe jetzt Timer2 verwendet. Der ist lt. Datenblatt auch zum 
aufwecken. So funktioniert es mit schlafen zwischendurch.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/sleep.h>
4
#include <util/delay.h>
5
6
int c=0;
7
8
int main(void)
9
{
10
  DDRB=0xff;
11
  OCR1A = 0xff;
12
  
13
  ASSR  = (1<< AS2);
14
  _delay_ms(1000);
15
16
  TCCR2B |= (1 << WGM21);
17
  // Mode 2, CTC on OCRA
18
19
  TIMSK2 |= (1 << OCIE2A);
20
  //Set interrupt on compare match
21
22
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
23
  // set prescaler to 1024 and start the timer
24
25
  sei();
26
  // enable interrupts
27
28
  while (1)
29
  {
30
    // we have a working Timer
31
    
32
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
33
    sleep_enable();
34
    //sei();
35
    sleep_cpu();
36
    sleep_disable();
37
    
38
  }
39
  
40
  
41
}
42
43
44
45
ISR (TIMER2_COMPA_vect)
46
{
47
  c++;
48
  if (c==20)
49
  {
50
    c=0;
51
    if (PORTB == 0x00)
52
    PORTB = 0xFF;
53
    else
54
    PORTB = 0x00;
55
  }
56
  
57
}

Trotzdem gibt es noch eine Unklarheit: Es ist ein 16 MHz Quarzoszillator 
angeschlossen, entsprechend ist SUT_CKSEL auf EXTOSC_8MHz_XX...... 
eingestellt.
Das Ganze funktioniert, egal ob ich ASSR  = (1<< AS2); aufrufe, oder 
auskommentiere. Meiner Meinung nach dürfte es ohne Asynchronmodus gar 
nicht funktionieren???? Außerdem steht im DB: "The CPU main clock 
frequency must be more than four times the Oscillator frequency." Ist 
bei meinem Aufbau aber nicht so. Es ist 16 MHz angeschlossen, damit wird 
meinem Verständnis nach der Timer2 hochgezählt (mit 1024 prescaler), und 
der Haupttakt ist auch 16 MHz, allerdings mit CKDIV8, also 2 MHz.

Jetzt wollte ich den AVR mit seiner eigenen, integrierten Taktquelle 
8MHz arbeiten lassen, dann passiert aber gar nichts mehr. Liegt das 
vielleicht daran:? "The CPU main clock frequency must be more than four 
times the Oscillator frequency."?

von Rudolfi (Gast)


Lesenswert?

Wenn ich den internen 8MHz verwende, funktioniert es nur, wenn ich ASSR 
= (1<< AS2); NICHT setze.....

von Rektal Invasiver (Gast)


Lesenswert?

Rudolfi schrieb:
> Wenn ich den internen 8MHz verwende, funktioniert es nur, wenn ich ASSR
> = (1<< AS2); NICHT setze.....

Danke für den Hinweis. Er wird auch Anderen nützen, wenn ihnen das 
Gleiche widerfährt.

von Thomas E. (thomase)


Lesenswert?

Rudolfi schrieb:
> Das Ganze funktioniert, egal ob ich ASSR  = (1<< AS2); aufrufe, oder
> auskommentiere.

Natürlich nicht.
Wenn als Taktquelle für deinen 328er Quarzbetrieb eingestellt, steht der 
Asynchronmodus des Timer2 nicht mehr zur Verfügung. Das ginge z.B bei 
einem 644. Der hat verschiedene Anschlüsse für CPU-Takt und 
Asynchrontakt.

Rudolfi schrieb:
> Jetzt wollte ich den AVR mit seiner eigenen, integrierten Taktquelle
> 8MHz arbeiten lassen, dann passiert aber gar nichts mehr. Liegt das
> vielleicht daran:? "The CPU main clock frequency must be more than four
> times the Oscillator frequency."?

Das liegt auch daran, dass der Asynchron-Oszillator den Quarz nicht zum 
Schwingen bekommt. Dieser Oszillator ist für den Betrieb mit einem 
Uhrenquarz gedacht. Womit sich die passenden Frequenzverhältnisse dann 
i.a.R. von selbst ergeben.

mfg.

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.