Hallo Leute,
irgendwie stehe ich momentan total auf dem Schlauch mit dem Real-time
Timer des AT91SAM7x256.
Ich möchte mit dem Timer eine Echtzeit-Uhr basteln. (Ja ich weiß, läuft
von RC, nix gut bei Temperatur-Schwankungen etc. Der Timer wird später
über DCF77 gestellt). Als ich die Routinen gebastelt habe, habe ich bei
jedem RTT-IRQ eine LED ein- bzw. ausgeschaltet. Das funzte auch, die LED
blinkte mit ~0,5Hz.
Jetzt habe ich die "Echtzeit"-Uhr ergänzt und lese die Uhrzeit mit einem
Terminal-Programm aus. DCF77 ist noch nicht dran.
Problem: Die Uhr zählt anscheinend in 5er-Schritten hoch. Zumindest
kriege ich bei jedem Auslesen x0 oder 05 Sekunden - insgesamt läuft die
Zeit auch um etwa diesen Faktor zu schnell.
Wenn ich in der ISR die Uhrzeit ausgeben lasse (DEBUG nicht
auskommentiert), dann läuft plötzlich alles perfekt. Die Sekunden zählen
normal hoch!
Wahrscheinlich ein total trivialer Fehler, aber ich habe irgendwie
Tomaten im Hirn und Bohnen auf den Augen. *lecker!*
Mein Code:
1 | inline void RTC_ISR(void)
|
2 | {
|
3 | // Status lesen -> IRQ zurücksetzen
|
4 | unsigned long Status = *AT91C_RTTC_RTSR;
|
5 | if(Status==0) { return; }
|
6 |
|
7 | // Status auswerten
|
8 | if(Status & AT91C_RTTC_RTTINC) { // Timer inkrement
|
9 | InkrementTime();
|
10 | }
|
11 | if(Status & AT91C_RTTC_ALMS) { // Alarm
|
12 | }
|
13 |
|
14 | // DEBUG
|
15 | //DBGU_WriteByte(Zeit.sec%10 + 48);
|
16 | //DBGU_WriteByte(13);
|
17 | }
|
18 | //-----------------------------------------------------------------------------
|
19 | inline void InkrementTime(void)
|
20 | {
|
21 | // Echtzeit-Uhr weiterzählen
|
22 | Zeit.sec++; // Sekunden
|
23 | if(Zeit.sec==60) {
|
24 | Zeit.sec = 0;
|
25 | Zeit.min++; // Minuten
|
26 | if(Zeit.min==60) {
|
27 | Zeit.min = 0;
|
28 | Zeit.hour++; // Stunden
|
29 | if(Zeit.hour==24) {
|
30 | Zeit.hour = 0;
|
31 | InkrementDate();
|
32 | }
|
33 | }
|
34 | }
|
35 |
|
36 | // LED blinken
|
37 | if(Zeit.sec & 1) {
|
38 | LED_gelb_on();
|
39 | }
|
40 | else {
|
41 | LED_gelb_off();
|
42 | }
|
43 | }
|
44 | //-----------------------------------------------------------------------------
|
45 | inline void InkrementDate(void)
|
46 | {
|
47 | // Wochentag inkrementieren
|
48 | DOW++;
|
49 | if(DOW==7) {
|
50 | DOW=0;
|
51 | }
|
52 |
|
53 | // Datum imkrementieren
|
54 | Datum.day++;
|
55 | if(Datum.day>MaxDoM[Datum.day]) {
|
56 | Datum.day = 1;
|
57 | Datum.month++;
|
58 | if(Datum.month>12) {
|
59 | Datum.month = 1;
|
60 | Datum.year++;
|
61 | }
|
62 | }
|
63 | }
|
Die ISR wird übrigens von der SYS-ISR (IRQ0) aufgerufen, daher das
inline. Zeit und Datum sind volatile definiert.
Man muß den RTT doch nicht entprellen, oder? ;)
Andy