Hallo Alle, Hier eine Frage eines blutigen Anfängers: ich habe eine ATMEGA32 die ich versuche als Funktionsgenerator ein zu setzen (schien mir ein schönes, ausbaufähiges Anfängerprojekt; erst mal einen Sinus erzeugen, dann Tasten anschliessen um Frequenz etc. zu ändern, später noch ein Display, usw. Ausserdem konnte ich existierenden Code aus einem Buch einfach "klauen"). Das programm schickt digitale Werte an PORTB die dann von einer R2R-Leiter in einem analogen Signal umgewandeld werden. Das Funktioniert alles noch. So weit, so gut. Jetzt habe ich an den INT0 und INT1-pins Tasten angeschlossen (über eine einfache Entprellbeschaltung) und ISRs definiert, die die Frequenz und die Form des Signals ändern sollen, wenn eine Taste gedrückt wird (der Pin wird durch drücken der Taste auf Hoch geschaltet). Dazu habe ich die volatile ints "waveform" und "step" definiert, die im Hauptprogramm die Signalform und die Frequenz beeinflüssen. (siehe Code im Anhang). Auch dachte ich die entsprechenden Bits in MCUCR und GIMSK richtig gesetzt zu haben... Auch sind die Interrupts "enabled" mit sei() und tauschen ISRs und Hauptprogramm Daten nur aus über volatile ints. Jetzt habe ich aber ein komisches Problem - wenn ich das ganze einschalte passiert erst mal gar nichts, bis ich die INT0-Taste drücke. Dann bekomme ich, solange die Taste gedrückt ist, ein Dreieckssignal. Lasse ich die Taste wieder los, passiert nichts mehr. Ich habe warscheinlich etwas ganz einfaches falsch gemacht, und wäre für jede Hilfe sehr dankbar. Viele Grüsse, Thomas
cli(); und sei(); solltest du nicht in der ISR aufrufen! ich kann mir vorstellen das der speicher nicht ausreicht. Du verwendest schon 3*256*2 = 1536byte und der Atmege hat nur 2048. Aber C braucht auch noch platz für den Stack und in paar variablen.
1 | {
|
2 | cli(); |
3 | waveform=waveform+1; |
4 | if (waveform>5) |
5 | {waveform=1;} |
6 | sei(); |
7 | }
|
cli und sei restlos streichen, das geht automatisch.
1 | ISR(INT1_vect) |
Hier auch.
1 | volatile int waveform = 1; |
2 | volatile int step = 0; |
Mach da mal uint8_t (stdint.h) draus, ansonsten muss der Zugriff atomar erfolgen.
1 | #define outp(a, b) b = a
|
2 | ...
|
3 | outp((1<<ISC01)|(1<<ISC00), MCUCR); // trigger int0 on rising flank |
4 | outp((1<<ISC11)|(1<<ISC10), MCUCR); // trigger int1 on rising flank |
Das funktioniert so nicht. Der Sinn dieses Makros erschließt sich mir sowieso nicht. Das ist doch ein reines "Verschleierungs-Makro", das noch nicht einmal Tipparbeit einspart.
Mir ist der Sinn eigentlich auch nicht klar, habe es jetzt mal in
1 | GIMSK = (1<<INT0)|(1<<INT1); |
2 | MCUCR = (1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10); |
geändert, und die von den Anderen gemachten Korrekturen durchgeführ, und jetzt funktioniert es! Es war also nicht nur einen, sondern gleich mehrere Anfängerfehler.... :) Vielen Dank an alle, Thomas
Schön das es läuft. Hier noch ein paar Anregungen: - die Felder können als uint8_t definiert werden. Das spart reichlich Speicher. - die Felder können als const im FLASH verschwinden, wenn RAM knapp wird. - die Ausgaben in den while Schleifen sollten im Timer Interrupt laufen. Das aktive Warten fällt weg und es bleibt Zeit für Weiteres. - die Tasten können in der main loop gepollt werden. Das erlaubt eine einfache SW Entprellung.
Danke! Das erste habe ich eingebaut, es spart gewaltig Speicher! An den beiden anderen Sachen bin ich dran. Frohe Ostern, Thomas
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.