Hallo,
ich muss euch mal fragen ob das Verhalten von TCA normal ist oder nicht.
Im Manual lese ich nichts von der Notwendigkeit das TCA CNT Register auf
1 setzen zu müssen statt auf 0 nach Reset zu belassen. Den Testcode habe
ich für die Gemeinde in Barmetall umgeschrieben damit es jeder
ausprobieren kann wer möchte.
Der Code soll die Overflows der RTC zählen. Alles im Sekundentakt. Das
wird über das Eventsystem angebunden. Alles wie gehabt. TCA wurde wegen
Arduinovoreinstellungen komplett resetet und dann neu konfiguriert. Wer
die Arduino IDE verwendet muss allerdings den MegaCoreX von MCUdude
verwenden. Er hat TCA komplett freigeschaufelt. Ohne dessen CorePackage
funktioniert millis nicht, da hängt der TCA noch mit drin.
Ich musste jedenfalls feststellen das TCA nur beginnt zu zählen wenn ich
CNT auf 1 nach Reset setze und nicht auf 0. Ich kann mir nicht erklären
warum man das machen muss. Ist das bei euch auch so? Mit einem AVRxDB
gibt es keine solchen Probleme. Im Errata lese ich davon auch nichts.
Mach ich was falsch oder ist das so?
Was ich auch soeben getestet habe ist, wenn ich den nächsten TCA
Überlauf provoziere mit Einstellung 65530 nach Reset, dann zählt er bis
65535, geht auf 0 und bleibt auf 0. Man müßte hier auch wieder
nachhelfen und auf 1 setzen.
1 | /*
|
2 | IDE 1.8.19
|
3 | Arduino Nano Every
|
4 | MegaCoreX erforderlich
|
5 | TCA0 zählt über den Event Eingang die Überläufe der RTC
|
6 | */
|
7 |
|
8 | #include <avr/io.h>
|
9 | #include <avr/interrupt.h>
|
10 | #include <util/atomic.h>
|
11 |
|
12 | void setup (void)
|
13 | {
|
14 | Serial.begin(9600);
|
15 | Serial.println("\nuReset ### ###");
|
16 | initRTC();
|
17 | initTCA0();
|
18 | initEventSystem();
|
19 | }
|
20 |
|
21 | void loop (void)
|
22 | {
|
23 | readCounter(Serial, 1000);
|
24 | }
|
25 |
|
26 | void readCounter(Stream &cout, const uint32_t interval)
|
27 | {
|
28 | static unsigned long lastMillis {0};
|
29 |
|
30 | if (millis() - lastMillis >= interval) {
|
31 | lastMillis += interval;
|
32 | cout.print("count ");
|
33 | cout.println(TCA0.SINGLE.CNT);
|
34 | }
|
35 | }
|
36 |
|
37 | void initEventSystem (void)
|
38 | {
|
39 | EVSYS.CHANNEL7 = EVSYS_GENERATOR_RTC_OVF_gc; // Generator 'RTC OVF' mit Channel 7 verbinden
|
40 | EVSYS.USERTCA0 = EVSYS_CHANNEL_CHANNEL7_gc; // Channel 7 mit User 'TCA0' verbinden, damit reagiert TCA0 auf RTC OVF
|
41 | }
|
42 |
|
43 | void initTCA0 (void)
|
44 | {
|
45 | // alles reseten wegen Arduino Voreinstellungen
|
46 | TCA0.SINGLE.CTRLA = 0;
|
47 | TCA0.SINGLE.CTRLB = 0;
|
48 | TCA0.SINGLE.CTRLC = 0;
|
49 | TCA0.SINGLE.CTRLD = 0;
|
50 | TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESET_gc;
|
51 | TCA0.SINGLE.EVCTRL = 0;
|
52 | TCA0.SINGLE.INTCTRL = 0;
|
53 | TCA0.SINGLE.INTFLAGS = 0xFF;
|
54 | TCA0.SINGLE.DBGCTRL = 0;
|
55 | TCA0.SINGLE.CNT = 1; // größer 0 erforderlich
|
56 | TCA0.SINGLE.PERBUF = 0;
|
57 | TCA0.SINGLE.PER = 0;
|
58 | TCA0.SINGLE.CMP0 = 0;
|
59 | TCA0.SINGLE.CMP1 = 0;
|
60 | TCA0.SINGLE.CMP2 = 0;
|
61 |
|
62 | TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc;
|
63 | TCA0.SINGLE.EVCTRL = TCA_SINGLE_EVACT_POSEDGE_gc;
|
64 | // TCA0.SINGLE.EVCTRL = TCA_SINGLE_EVACT_ANYEDGE_gc;
|
65 | TCA0.SINGLE.EVCTRL = TCA0.SINGLE.EVCTRL | TCA_SINGLE_CNTEI_bm;
|
66 | TCA0.SINGLE.CTRLA = TCA0.SINGLE.CTRLA | TCA_SINGLE_ENABLE_bm;
|
67 | }
|
68 |
|
69 | void initRTC (void)
|
70 | {
|
71 | while (RTC.STATUS > 0) { ; } // warten auf Register Syncronisierung
|
72 | RTC.CLKSEL = RTC_CLKSEL_INT32K_gc; // Periodendauer 30,518µs
|
73 | RTC.PER = 64; // = 1000ms / 15,625ms
|
74 | // RTC.CTRLA Bug, see Errata
|
75 | byte temp {0};
|
76 | temp |= RTC_PRESCALER_DIV512_gc; // Prescaler 512 -->> 30,518µs * 512 = 15,625ms
|
77 | temp |= RTC_RTCEN_bm; // RTC aktivieren
|
78 | RTC.CTRLA = temp;
|
79 | }
|