MEGA 168 - UART geht nicht nach Power Down

OP #2252358
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
}
Gast #2252527
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
#2252551
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren