Hi, Ich bin neu hier im Forum und auf dem Gebiet der Mikrocontroller. Ein paar erfahrungen hab ich schon mit Arduinos gesammelt und wollte jetzt mal mehr machen. Zum Beispiel einen Timer zu Programmieren (klein anfangen und so..). Der ATmega ist auf einem Arduino Nano drauf. Das Programm sieht so aus: #define F_CPU 16E6 #include <avr/io.h> #include <avr/interrupt.h> #define RED (1 << 7) #define YELLOW (1 << 6) #define GREEN (1 << 5) #define BLUE (1 << 4) volatile uint8_t counter = 0; int main(void) { DDRD |= RED | YELLOW | GREEN | BLUE; TCCR0A |= (1 << CS02); sei(); while (1) { if (counter == 255) { PORTD ^= (RED | YELLOW | GREEN | BLUE); counter = 0; } } } ISR(TIMER0_OVF_vect){ counter++; } An dem Pins ist jeweils eine LED dran, die Schaltung hat keine Fehler (hab sie vorher mit delays ja schön laufen gehabt). Aber die LEDS bleiben einfach dunkel. Kann mir jemand sagen (wo der wahrscheinlich dumme aus unverständnis entstandene Fehler) liegt oder mir einen Tipp geben, was ich beachten muss, damit es klappt? Grüße Matthias
:
Bearbeitet durch User
Moin, Du musst das Timer-Interrupt noch aktivieren: TIMSK0 |= (1<<TOIE0) (siehe Seite 109 des Datenblatts) Gruß, Stefan
Hi, danke für dir schnelle Antwort. Wieder was dazu gelernt, aber wohl noch nicht genug. Das Register ist gesetzt, aber die LEDs gehen nicht an. Im Datenblatt auf Seite 109 steht aber auch noch etwas vom Status Register, dessen I-Bit gesetzt werden muss, was ja so geschieht(denke ich): SREG |= (1 << 7); oder passiert das durch den Aufruf: sei(); im Code? Gruß Matthias
Matthias H. schrieb: > oder passiert das durch den Aufruf: > sei(); > im Code? Ja. Aber dein Timer läuft nicht. Die CS-Bits werden im TCCR0B-Register gesetzt. mfg.
Jetzt leuchtet es!=) Danke. Aber nochmal zum Verständnis: TCCR0 besteht aus 2 Registern TCCR0A und TCCR0B. -TCCR0A ist der "der Timer" selbst, also das Register das inkrementiert wird -TCCR0B ist der Prescaler Stimmt das so? Wo das Ding jetzt so hübsch blinkt hab ich aber noch eine weiter Verständnisfrage(anderes Thema, ich stelle sie der bequemlichkeit halber aber einfach hier): Ich habe ja oben im Code die Angabe F_CPU 16E6, Heißt das, das der AVR mit 16.000.000 Hertz läuft?(Ich habe versucht diese angabe zu verstehen, aber empfinde alle beschreibungen bisher als sehr Kryptisch) Gruß Matthias
Matthias H. schrieb: > Jetzt leuchtet es!=) Danke. > Aber nochmal zum Verständnis: > TCCR0 besteht aus 2 Registern TCCR0A und TCCR0B. > -TCCR0A ist der "der Timer" selbst, also das Register das inkrementiert > wird > -TCCR0B ist der Prescaler > Stimmt das so? Der Timer ist Timer0. Das ist ein Stück Hardware im Controller. Diese Hardware wird mit einem Satz von Registern eingestellt. Welche das sind und was damit eingestellt wird, findest du im Datenblatt unter "Register Description". > Wo das Ding jetzt so hübsch blinkt hab ich aber noch eine weiter > Verständnisfrage(anderes Thema, ich stelle sie der bequemlichkeit halber > aber einfach hier): > Ich habe ja oben im Code die Angabe F_CPU 16E6, > Heißt das, das der AVR mit 16.000.000 Hertz läuft?(Ich habe versucht > diese angabe zu verstehen, aber empfinde alle beschreibungen bisher als > sehr Kryptisch) Der Takt ist Bestandteil der Hardware. Also wird auch die Frequenz durch die Hardware bestimmt. Im Falle deines Arduino dürfte es so sein, dass der Controller per Fuses auf "externer Quarz" eingestellt und ein Quarz mit 16MHz angeschlossen ist. Eingestellt wird mit F_CPU gar nichts. Die Angabe dient dazu, dem Compiler mitzuteien, dass der Controller mit eben dieser Frequenz läuft. Das wird benötigt um z.B. Timerkonfigurationen, Baudraten etc. mit Makros automatisch auszurechnen. Oder _delay_ms() zu konfigurieren. mfg.
Stimmt, danke für die gute Erklärung nochmal. Ich war nur wegen der Blink-frequnz etwas verwirrt. aber es gilt ja Taktfrequnz/Prescaler <=> 16.000.000/256 = 62500 also 62500 Inkrementierungen pro Sekunde und damit 62500/256 = 244 Timer-Overflows pro Sekunde das heißt, ich inkrementiere den counter 244 mal die Sekunde und daraus resultiert eine Frequenz von etwas mehr als einer Sekunde für die LEDs oder?
Ok, danke für deine Hilfe! hier jetzt nochmal zum Abschluss der korrigierte Code(ich wäre froh gewesen um den Thread und ein funktionierendes Codebeispiel :D)
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #define RED (1 << 7)
|
5 | #define YELLOW (1 << 6)
|
6 | #define GREEN (1 << 5)
|
7 | #define BLUE (1 << 4)
|
8 | |
9 | volatile uint8_t counter = 0; |
10 | int main(void) { |
11 | DDRD |= RED | YELLOW | GREEN | BLUE; |
12 | TCCR0B |= (1 << CS02); //Prescaler von 256 für den Timer0 |
13 | sei(); |
14 | while (1) { |
15 | if (counter == 244) { // LEDs werden jede Sekunde getogglet |
16 | PORTD ^= (RED | YELLOW | GREEN | BLUE); |
17 | counter = 0; |
18 | }
|
19 | }
|
20 | |
21 | }
|
22 | |
23 | ISR(TIMER0_OVF_vect){ |
24 | counter++; |
25 | }
|
Matthias H. schrieb: > -TCCR0A ist der "der Timer" selbst, also das Register das inkrementiert > wird > -TCCR0B ist der Prescaler > Stimmt das so? Öhm, nein. TCCR0A und TCCR0B sind die Controll-Register, damit wird der Timer0 konfiguriert. Das Register, das inkrementiert wird, nennt sich TCNT0. Das steht aber auch im Datenblatt beim entsprechenden Timer, hier Timer0
Matthias H. schrieb: > Ich habe ja oben im Code die Angabe F_CPU 16E6, > Heißt das, das der AVR mit 16.000.000 Hertz läuft? Die Angabe "16E6" für die Taktfrequenz ist ausgesprochen unübliche, m.a.W. hier sehe ich das zum ersten Mal. Diese Expnentialdarstellung ist eher für Float Zahlen mit großem Dynamikbereich vorgesehen. Und messtechnisch betrachtet, sollte die Stellenanzahl in der Zahlendarstellung alle signifikanten Stellen enthalten. Üblich ist die Angabe als vorzeichenlose Ganzzahl mit ausreichender Bitzahl, also in diesem Fall als unsigned long
1 | #define F_CPU 16000000UL |
Thomas W. schrieb: > Üblich ist die Angabe als vorzeichenlose Ganzzahl mit ausreichender > Bitzahl, also in diesem Fall als unsigned long
1 | #define F_CPU 16000000UL
|
Üblich ist die Angabe des Taktes in den Projekteinstellungen. Ein "define" im Quelltext ist eine weit verbreitete Unsitte. mfg.
:
Bearbeitet durch User
Thomas E. schrieb: > Üblich ist die Angabe des Taktes in den Projekteinstellungen. Ein > "define" im Quelltext ist eine weit verbreitete Unsitte. Warum soll das eine Unsitte sein?
Michael K. schrieb: > Warum soll das eine Unsitte sein? Falsche Frage. Warum ist das eine Unsitte? Weil ein Projekt i.a.R. aus mehreren Files besteht und die Einstellung dann in allen Files gemacht werden muss. Steht sie in den Projekteinstellungen, muss sie nur einmal gemacht werden und gilt für alle Files. Und auch nur für dieses Projekt. Benutzt man einzelne Files in mehreren Projekten, würde eine Änderung der defines sich u.U. auch in anderen Projekten auswirken. mfg.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.