Hi, ich bin blutiger Anfänger was die Programmierung von AVR Chips angeht und wollte fragen ob es eine gesammelte Quelle an aufbereiteten Informationen gibt. Ich kenne das beispielsweise vom Pi Pico als SDK, oder, wenn auch ein etwas anderer Usecase, von der JAVA APi. Ich frage, weil ich jetzt schon seit über einer Stunde daran scheitere, einen simplen Timerinterrupt zum laufen zu bekommen. Ja, die Daten stehen im Datenblatt, aber das ist ja nicht wirklich anfängerfreundlich zu lesen. Tut mir leid, wenn das als blöde Frage gilt Danke für eure Ratschläge
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Adam P. schrieb: > https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR Diesen Beitrag habe ich schon gefunden und habe versucht ihn zu befolgen. Leider hab ich das nicht zum laufen bekommen. Ich nutze einen Atmega1284p, falls das einen Unterschied macht
Sowas vielleicht? https://github.com/jfpoilpret/fast-arduino-lib für C++ - Enthusiasten. Da hast du dann Code wie
1 | constexpr const board::Timer NTIMER = board::Timer::TIMER1; |
2 | using CALCULATOR = timer::Calculator<NTIMER>; |
3 | using TIMER = timer::Timer<NTIMER>; |
4 | constexpr const uint32_t PERIOD_US = 1000000; |
5 | |
6 | constexpr const TIMER::PRESCALER PRESCALER = CALCULATOR::CTC_prescaler(PERIOD_US); |
7 | constexpr const TIMER::TYPE COUNTER = CALCULATOR::CTC_counter(PRESCALER, PERIOD_US); |
8 | [...]
|
9 | |
10 | TIMER timer{timer::TimerMode::CTC, PRESCALER, timer::TimerInterrupt::OUTPUT_COMPARE_A}; |
11 | timer.begin(COUNTER); |
12 | [...]
|
(Ganzer Code: https://github.com/jfpoilpret/fast-arduino-lib/blob/master/tuto-samples/fastarduino/timer_1_ctc.cpp ) Deutlich mehr Tipparbeit als die handvoll Register von Hand zu setzen, aber "cleaner"?
David P. schrieb: > Leider hab ich das nicht zum laufen bekommen. Wenn du weiterkommen willst dass müsstest du uns eben zeigen was du schon gemacht hast und welche Probleme dabei auftauchen. So richtig gute Hellseher sind wir hier alle nicht ....
David P. schrieb: > Ich nutze einen > Atmega1284p, falls das einen Unterschied macht Ja da heißen die Register ein wenig anders.
David P. schrieb: > aber das ist ja nicht wirklich anfängerfreundlich zu lesen. Wo ist denn das Problem? Atmel-Datenblätter sind verhältnismäßig gut. Vor allem ist es ein Dokument pro Chip-Gruppe; nicht wie bei STM32, wo es ein Datenblatt, ein Reference- und ein Programming-Manual mit jeweils zig-tausend Seiten gibt.
David P. schrieb: > die Daten stehen im Datenblatt, > aber das ist ja nicht wirklich anfängerfreundlich zu lesen. Dur wirst keine "schöneren" Datenblätter finden, als die von AVR Mikrocontroller. > Dann suche ich etwas für "ein Schritt nach blutiger Anfänger" http://stefanfrings.de/mikrocontroller_buch/index.html Die Timer sind allerdings schon recht komplex. Am besten fängst du erst mal mit einfacheren Funktionen an, bis du mit dem Style des Datenblattes vertraut bist. Mein "Buch" leitet dich dazu an.
1 | /*
|
2 | * 1284p test.c
|
3 | *
|
4 | * Created: 16.02.2022 17:51:14
|
5 | * Author : David
|
6 | */
|
7 | #define F_CPU 128000L
|
8 | #include <avr/io.h> |
9 | #include <avr/interrupt.h> |
10 | #include <util/delay.h> |
11 | |
12 | int help; |
13 | char sekunden; |
14 | int main(void) |
15 | {
|
16 | DDRA =0xFF; |
17 | DDRC =0xFF; |
18 | DDRD =0xFF; |
19 | TCCR0A = (1<<CS00); // |
20 | TIMSK0 |= (1<<TOIE0); |
21 | sei(); |
22 | |
23 | while(1){ |
24 | // PORTD=sekunden;
|
25 | // PORTD |= (1<<0);
|
26 | // _delay_ms(100);
|
27 | // PORTD&= ~(1<<0);
|
28 | // _delay_ms(100);
|
29 | ;
|
30 | }
|
31 | }
|
32 | ISR( TIMER0A_OVF_vect ) { |
33 | help++; |
34 | if(help%2) |
35 | PORTD |= (1<<1); |
36 | else
|
37 | PORTD |= ~(1<<1); |
38 | |
39 | }
|
Das ist der Code, den ich mir aus dem Internet zusammengesucht habe. Wenn ich das richtig verstehe, sollte die LED, die an PD1 angeschlossen ist jetzt schnell blinken oder "halbhell" leuchte, allerdings bleibt sie aus.
Mal die Warnungen im Compiler ('-Wall') einschalten - bei mir kommt da ein "... appears to be a misspelled signal handler ...".
STK500-Besitzer schrieb: > das sollte wohl eherPORTD &= ~(1<<1); > heissen! Hab ich geändert, aber da gar keine LED an geht, ist das wohl nicht das Problem S. Landolt schrieb: > Mal die Warnungen im Compiler ('-Wall') einschalten - bei mir kommt da > ein "... appears to be a misspelled signal handler ...".
1 | ISR( TIMER0_OVF_vect ) { |
Die Zeile hab ich geändert, entfernt die Warnung, tut sonst aber nichts
David P. schrieb: > Die Zeile hab ich geändert, entfernt die Warnung, tut sonst aber nichts kannst du die LED auch ohne Timer ansteuern? Einfach mal eine Endlosschleife in der die LED ein- und ausgeschaltet wird. Dazu dann noch ein paar Warteschleifen. So kann man zumindest Hardware-Fehler ausschließen.
STK500-Besitzer schrieb: > David P. schrieb: >> Die Zeile hab ich geändert, entfernt die Warnung, tut sonst aber nichts > > kannst du die LED auch ohne Timer ansteuern? > Einfach mal eine Endlosschleife in der die LED ein- und ausgeschaltet > wird. > Dazu dann noch ein paar Warteschleifen. > So kann man zumindest Hardware-Fehler ausschließen. Jap, das funktioniert. Dafür hatte ich die auskommentierte While Schleife benutzt.
David P. schrieb: > #define F_CPU 128000L Bist du sicher das das so richtig ist, auch wenn es nichts mit deinem Problem zu tun hat? Also du hast nun den Timer mit dem TIMER0A_OVF_vect Interrupt verwendet, hier noch mal ein Bsp. mit TIMER0_COMPA_vect. Den Pin musst halt auf den richtigen ändern.
1 | // Bsp. für ATmega1284P mit 16Mhz
|
2 | #include <avr/io.h> |
3 | #include <avr/interrupt.h> |
4 | #include <stdint.h> |
5 | |
6 | uint16_t ms; |
7 | |
8 | ISR(TIMER0_COMPA_vect) |
9 | {
|
10 | ms--; |
11 | |
12 | if (ms == 0) |
13 | {
|
14 | ms = 1000; |
15 | PORTD ^= (1 << PIND5); |
16 | }
|
17 | }
|
18 | |
19 | int main(void) |
20 | {
|
21 | ms = 1000; |
22 | |
23 | DDRD = (1 << DDD5); |
24 | |
25 | /* Timer0 (1ms) */
|
26 | TCCR0A = (1 << WGM01); |
27 | TCCR0B = (1 << CS01) | (1 << CS00); |
28 | OCR0A = 249; |
29 | TIMSK0 |= (1 << OCIE0A); |
30 | |
31 | sei(); |
32 | |
33 | while(1) |
34 | {
|
35 | |
36 | }
|
37 | |
38 | return 0; |
39 | }
|
:
Bearbeitet durch User
Adam P. schrieb: > #define F_CPU 128000L steht doch für 128KHz oder? Wenn ja, sollte es richtig sein.
Mitlerweile habe ich meinen Code soweit geändert. Die Anzgeige auf Port d klappt, die auf PortA gar nicht und auf PortC die ersten 2 Bits. Jemand ne idee, woran das liegen könnte?
1 | /*
|
2 | * 1284p test.c
|
3 | *
|
4 | * Created: 16.02.2022 17:51:14
|
5 | * Author : David
|
6 | */
|
7 | #define F_CPU 128000L
|
8 | #include <avr/io.h> |
9 | #include <avr/interrupt.h> |
10 | #include <util/delay.h> |
11 | |
12 | int help; |
13 | char sekunden; |
14 | char minuten; |
15 | char stunden; |
16 | void updateTime(){ |
17 | if(sekunden==59){ |
18 | sekunden=0; |
19 | if(minuten==59){ |
20 | stunden=(stunden+1)%24; |
21 | minuten=0; |
22 | }
|
23 | else{ |
24 | ++minuten; |
25 | }
|
26 | }
|
27 | else{ |
28 | ++sekunden; |
29 | }
|
30 | }
|
31 | int main(void) |
32 | {
|
33 | DDRA =0xFF; |
34 | DDRC =0xFF; |
35 | DDRD =0xFF; |
36 | TCCR0B = (1<<CS00); |
37 | TIMSK0 |= (1<<TOIE0); |
38 | sei(); |
39 | |
40 | while(1){ |
41 | PORTD=sekunden; |
42 | PORTA=stunden; |
43 | PORTC=minuten; |
44 | |
45 | }
|
46 | }
|
47 | ISR( TIMER0_OVF_vect ) { |
48 | help++; |
49 | if(help==500){ |
50 | updateTime(); |
51 | help=0; |
52 | }
|
53 | }
|
David P. schrieb: > Mitlerweile habe ich meinen Code soweit geändert. Die Anzgeige auf Port > d klappt, die auf PortA gar nicht und auf PortC die ersten 2 Bits. > Jemand ne idee, woran das liegen könnte? ja, Infos zu den Ports findest du im Datenblatt. Da der Code ja inzwischen umfangreicher wird, solltest du ihn als Anhang mitliefern.
Adam P. schrieb: > David P. schrieb: >> PORTA=stunden; > > Dann musst du halt auch mindestens 1 Std. warten. Um das ganze zu testen, habe ich den CPU Takt erhöht, sollte also deutlich weniger als ne stunde dauern STK500-Besitzer schrieb: > Da der Code ja inzwischen umfangreicher wird, solltest du ihn als Anhang > mitliefern. Mache ich in Zukunft.
Dann versuch es doch mal so: PORTD = sekunden; PORTA = sekunden; PORTC = sekunden;
Ändert leider nichts. PORTA ist komplett aus, Bei PORTC funktionieren die ersten 2 Bits, der rest leuchtet sehr schwach
S. Landolt schrieb: > PORTC2..5 wird von JTAG benutzt - ist das abgeschaltet? Nein, noch nicht. Danke für den Tipp, ich schaue mal nach, wie das geht
Und mach Mal vor die Variablen die im Interrupt Context verwendet werden ein volatile davor.
S. Landolt schrieb: > PORTC2..5 wird von JTAG benutzt - ist das abgeschaltet? Aber nicht das er nur ein JTAG Adapter (Kabel) hat, sonst wars das dann mit wieder ändern.
S. Landolt schrieb: > Ist AVcc angeschlossen, d.h. mit Strom versorgt? Jetzt ja, und schon funktioniert PortA
S. Landolt schrieb: > Ist AVcc angeschlossen, d.h. mit Strom versorgt? Man lernt nie aus...das wusst ich auch noch nicht. Ich bin davon ausgegangen das AVcc lediglich für den Analog Teil ist, nicht das es auch "grundsätzlich" den PORTA versorgt. Edit: AVCC is the supply voltage pin for Port F and the Analog-to-digital Converter. It should be exter- nally connected to VCC , even if the ADC is not used. If the ADC is used, it should be connected to V CC through a low-pass filter.
:
Bearbeitet durch User
> Aber nicht das er nur ein JTAG Adapter (Kabel) hat, > sonst wars das dann mit wieder ändern. Man muss ja nicht per Fuse abschalten, per Software (zu Programmbeginn) geht auch.
S. Landolt schrieb: > Man muss ja nicht per Fuse abschalten, per Software (zu Programmbeginn) > geht auch. Sollte das nicht mit dieser Zeile funktionieren?
1 | MCUCR |= 0x80; |
Zweimal. "The application software must write this bit [JTD] to the desired value twice within four cycles to change its value.
S. Landolt schrieb: > "The application software must write this bit [JTD] to the desired value > twice within four cycles to change its value. Ah danke, das muss ich überlesen haben. Edit: Klappt, danke
:
Bearbeitet durch User
David P. schrieb: > Adam P. schrieb: >> #define F_CPU 128000L > > steht doch für 128KHz oder? > Wenn ja, sollte es richtig sein. Darf ich fragen, warum du den Controller so langsam laufen lässt?
Adam P. schrieb: > Darf ich fragen, warum du den Controller so langsam laufen lässt? Zum Strom sparen. Ich wollte es mal so niedrig wie möglich probieren, wenn das von der rechenleistung nicht reicht, kann ich ja immer noch mehr nehmen
David P. schrieb: > Zum Strom sparen. Dann lässt man ihn eher normal schnell laufen und benutzt den sleep-Mode wann immer es geht.
Da es hier offenbar um eine Uhr geht, uneingeschränkt: ja. Aber auch sonst sehr oft, zumindest von der Verarbeitungskapazität her gesehen; allerdings sind viele Peripherieeinheiten dann abgeschaltet.
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.