Forum: Mikrocontroller und Digitale Elektronik MEGA 168 - UART geht nicht nach Power Down


von G. B. (garyb)


Lesenswert?

Hallo zusammen,

ich "spiel" gerade mit dem Sleep-Modes des AVR um in einem kleinen 
Hobby-Projekt Strom zu sparen. Im Sleep-Mode "Idle" läuft alles schön, 
d.h. er versendet das Zeichen, Antwortet auf empfangene Zeichen und 
lässt LEDs blinken.
Nun habe ich aber das Problem das der UART nach dem Sleep-Mode PowerDown 
oder ADC nicht mehr richtig sendet, d.h. es kommen falsche Zeichen 
"raus".
Die LEDs blinken aber und empfangen wird auch ab und an was.

Meine erste Vermutungen war, das die internen Clock noch nicht richtig 
laufen, aber selbst eine Verzögerung von 100ms hat nix gebracht.

Der Controller läuft mit 8Mhz internal RC und der Fuse Clk/8, also mit 1 
Mhz. Zum Wecken aus dem Sleep-Mode wird hier der Timer2 als CTC 
verwendet

Anbei mein Test-Code in der Hoffnung - das jemand hier sofort "Dödel" 
schreit ;)
1
/* Test Sleep-Modes
2
    hardware: AVR Mega168
3
    Clock     1Mhz
4
*/
5
6
#define BAUD 4800L          // Baudrate/2!
7
 
8
// Berechnungen
9
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
10
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
11
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille 
12
 
13
#include <avr/io.h>
14
#include <avr/sleep.h>
15
#include <avr/interrupt.h>
16
#include <util/delay.h>
17
 
18
// globale Variablen
19
volatile uint8_t uart_flag;
20
volatile uint8_t uart_data;
21
22
// funktionen
23
void init_t2(void);
24
void init_uart(void);
25
 
26
int main (void) {
27
 
28
// IO konfigurieren
29
    //DDRA = 0xFF;
30
    DDRB = 0xFF;
31
    DDRC = 0xFF;
32
    DDRD = 0xFF;
33
// UART konfigurieren
34
    init_uart();
35
// Timer 2 
36
    init_t2();
37
// Interrupts freigeben
38
     sei(); 
39
// Endlose Hauptschleife
40
    while(1) {
41
            //set_sleep_mode(SLEEP_MODE_IDLE); 
42
            //set_sleep_mode(SLEEP_MODE_ADC); 
43
            set_sleep_mode(SLEEP_MODE_PWR_SAVE);
44
        sleep_mode();                   // in den Schlafmodus wechseln
45
 //   init_uart();
46
    _delay_ms(10);
47
        // hier wachen wir wieder auf
48
        if (uart_flag==1) {
49
            uart_flag =0;
50
            PORTB ^= (1 << PB0);                // LED an/aus wenn zeichen Empfangen
51
        while ((UCSR0A & 1<<UDRE0) == 0); 
52
        UDR0 = uart_data;                
53
        }
54
        // Sende Zeichen '_' 
55
        while ((UCSR0A & 1<<UDRE0) == 0); 
56
        UDR0 = 95; 
57
    }
58
} // Ende Main
59
/****************************************************************************/
60
/* Timer/Counter2 Compare Match A */
61
ISR (TIMER2_COMPA_vect) {
62
  PORTB ^= 1<<PB1; // Toggle bit
63
}
64
65
// UART RX complete interrupt
66
 
67
ISR(USART_RX_vect) {
68
    uart_flag = 1;              // signalisiere neue Daten
69
    uart_data = UDR0;            // Daten auslesen, dadurch wird auch der Interrupt gelöscht
70
    PORTB ^= 1<<PB2; // Toggle bit
71
}
72
73
void init_t2(void){
74
   TCCR2A = 0x00;
75
   TCCR2A |= (1<<WGM21)|(0<<WGM20)               // Waveform Generation Mode: CTC -WGM22=0
76
          |  (0<<COM2A1)|(0<<COM2A0);           // Compare Output Mode, Non-PWM Mode - disconnect OC2
77
   TCCR2B = 0x00;
78
   TCCR2B &= ~(1<<WGM22);                       // Waveform Generation Mode: CTC
79
   TCCR2B |= (1<<CS22) |(1<<CS21) |(1<<CS20);   // Prescaler 1024
80
    OCR2A = 0xFF;
81
    ASSR &= ~(1<<AS2);                          // AS2=0 - clock from internal clock
82
    TIMSK2 |= (1<<OCIE2A);                      //Timer/Counter2 Output Compare Match Interrupt Enable  
83
};
84
85
void init_uart(void){
86
    UBRR0H = UBRR_VAL >> 8;
87
    UBRR0L = UBRR_VAL & 0xFF;
88
    UCSR0B = (1<<RXCIE0) | (1<<RXEN0); 
89
    UCSR0B |= ( 1 << TXEN0 ) ;
90
    UCSR0A |= (1<<U2X0); // double transmission speed
91
}

von Turbo J (Gast)


Lesenswert?

Je nach Controller wird in tieferen Schlafmodi die Clock deaktiviert, 
aus denen der UART seinen Baudratentakt generiert. Dann kann nichts mehr 
empfangen werden.

von G. B. (garyb)


Lesenswert?

Turbo J schrieb:
> Je nach Controller wird in tieferen Schlafmodi die Clock deaktiviert,
> aus denen der UART seinen Baudratentakt generiert. Dann kann nichts mehr
> empfangen werden.

aber wenn ich 100 ms warte?

von G. B. (garyb)


Angehängte Dateien:

Lesenswert?

PS:
ClkIO ist gemäß der Tabelle aus dem Handbuch der gemeinsame 
"Unterschied" zwischen IDLE und ADC/Power.... selbst 2000ms reichen aber 
nicht aus - selbst wenn clock prellt sollte das wohl reichen?
auch eine erneute Initialisierung des Uart hilft nicht.

von Martin (Gast)


Lesenswert?

Guten Tag,

ich hatte mal das gleiche Problem und es hing damit zusammen das der 
Sleep Modus die UART deaktiviert.

Leider weis ich aus dem Kopf nicht mehr welches BIt es war das man 
vorher wieder setzen musste. Beim aufwachen setzt der Controller nicht 
automatisch alle Bits in den Uhrzustand.


Ich hoffe der Hinweis hilft dir schon weiter, da ich leider gerade nicht 
weis welches Bit es genau war.



MfG Martin

von Thomas E. (thomase)


Lesenswert?

Martin schrieb:
> Ich hoffe der Hinweis hilft dir schon weiter, da ich leider gerade nicht
>
> weis welches Bit es genau war.

• Bit 1 - PRUSART0: Power Reduction USART0
Writing a logic one to this bit shuts down the USART by stopping the 
clock to the module. When waking up the USART again, the USART should be 
re initialized to ensure proper operation.

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.