Hi,
ich möchte ein Byte über UART im Atmega169 pro Sekunde senden lassen.
Ein 32.768kHz Quarz wird für Timer2 eingesetzt und der interne RC
Oszillator wird als Systemtakt verwendet.
Das Problem ist, wenn der 169 aus dem Schlafmodus „Power Save“ erweckt
wird, sendet dieser falsche Bytes. Ohne Schlafmodus ist alles OK.
Zu bemerken: In diesen falschen Bytes gibt es sogar Regel: Das richtige
Byte 0x5A wird alle 25 Bytes gesendet, dazwischen nur 0x00 und 0xEB,
also
5A 00 EB 00 EB 00 EB 00 EB 00 EB 00 EB 00 EB 00 EB 00 EB 00 EB 00 EB 00
EB 5A
Ich vermute mal, dass der Systemtakt von 1MHz nach dem Schlafmodus
verstellt ist, aber wieso? Inzwischen habe ich auch versucht, alle
Initialisierungen nach jedem Schlafmodus neu zu machen, erfolgslos!
Der Code ist hier:
1 | int main( void )
|
2 | {
|
3 | clock_init_1MHz();
|
4 |
|
5 | RTC_init();
|
6 | USART_Init(12); // 9600bps bei 1MHz
|
7 |
|
8 | __enable_interrupt();
|
9 |
|
10 | for(;;)
|
11 | {
|
12 | Delay(1000); // wait for 1 sec to let the Xtal stabilize after a power-on
|
13 | Usart_Tx(0x5A);
|
14 | while(!(UCSR0A & (1<<TXC0)));
|
15 |
|
16 | SMCR = (3<<SM0) | (1<<SE); // Enable Power-save mode
|
17 | __sleep(); // Go to sleep
|
18 |
|
19 | SMCR = 0; // Just woke, disable sleep
|
20 | }
|
21 | }
|
22 |
|
23 | void clock_init_1MHz(void)
|
24 | {
|
25 | CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable
|
26 |
|
27 | // set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
|
28 | CLKPR = (1<<CLKPS1) | (1<<CLKPS0);
|
29 | }
|
30 |
|
31 | void Delay(unsigned int millisec)
|
32 | {
|
33 | int i;
|
34 |
|
35 | while (millisec--)
|
36 | for (i=0; i<125; i++);
|
37 | }
|
38 |
|
39 | void RTC_init(void)
|
40 | {
|
41 | Delay(1000); // wait for 1 sec to let the Xtal stabilize after a power-on,
|
42 |
|
43 | __disable_interrupt(); // disabel global interrupt
|
44 |
|
45 | cbi(TIMSK2, TOIE2); // disable OCIE2A and TOIE2
|
46 |
|
47 | ASSR = (1<<AS2); // select asynchronous operation of Timer2
|
48 |
|
49 | TCNT2 = 0; // clear TCNT2A
|
50 | TCCR2A |= (1<<CS22) | (1<<CS20); // select precaler: 32.768 kHz / 128 = 1 sec between each overflow
|
51 |
|
52 | while((ASSR & (0x01 | 0x04))); // wait for TCN2UB and TCR2UB to be cleared
|
53 |
|
54 | TIFR2 = 0xFF; // clear interrupt-flags
|
55 | sbi(TIMSK2, TOIE2); // enable Timer2 overflow interrupt
|
56 |
|
57 | OCR2A = 200; // set timer2 compare value
|
58 |
|
59 | __enable_interrupt(); // enable global interrupt
|
60 | }
|
61 |
|
62 | #pragma vector = TIMER2_OVF_vect
|
63 | __interrupt void TIMER2_OVF_interrupt(void)
|
64 | {
|
65 | }
|
66 |
|
67 | void USART_Init(unsigned int baudrate)
|
68 | {
|
69 | // Set baud rate
|
70 | UBRR0H = (unsigned char)(baudrate>>8);
|
71 | UBRR0L = (unsigned char)baudrate;
|
72 |
|
73 | // Enable 2x speed
|
74 | UCSR0A = (1<<U2X0);
|
75 |
|
76 | // Enable receiver and transmitter
|
77 | UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(0<<RXCIE0)|(0<<UDRIE0);
|
78 |
|
79 | // Async. mode, 8N1
|
80 | UCSR0C = (0<<UMSEL0)|(0<<UPM00)|(0<<USBS0)|(3<<UCSZ00)|(0<<UCPOL0);
|
81 | }
|
82 |
|
83 | void Usart_Tx(char data)
|
84 | {
|
85 | while (!(UCSR0A & (1<<UDRE0)));
|
86 | UDR0 = data;
|
87 | }
|
Hat jemand Ideen?
Gruss
Owen