Hallo, für ein Uniprojekt muss ich einen ATMEGA48A programmieren und habe beim herumprobieren ein Problem. Ich habe einen simples Programm geschrieben bei dem LEDS Leuchten nachdem ein Interrupt ausgeführt wird. Mein Problem ist aber das die LEDs nur leuchten während der Interrupt aktiv ist. Das muss also bedeuten das die Variable trotz volatile immer nach ende des Interrupts wieder auf 0 gesetzt wird. Im Simulator von Atmel Studio 7 funktioniert das Programm normal aber beim richtigen Controller nicht. Danke für etwaige Ideen und Lösungsvorschläge. Hier der Code: #define F_CPU 1000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <stdbool.h> volatile uint8_t test; int main(void) { EIMSK|=(1<<INT1); //Interrupt 1 enabled EIMSK|=(1<<INT0); //Interrupt 0 enabled PCMSK2|=(1<<PCINT20); //Pin Change Interrupt für Pin 20 PCICR|=(1<<PCIE2); //Pin Change Interrupt enabled DDRD|=0b11100011; DDRC|=0b0111111; PORTD|=0b00011100; //Pullup für Eingänge wiederstände werden aktiviert test=0; sei(); while (1) { for(int i=0; i<=(20-pwm); i++){ _delay_us(100); } if (test==1) { PORTC|=0b0111111; PORTD|=0b11100011; } for(int i=0; i<=pwm; i++){ _delay_us(100); } PORTC&=~(0b0111111); PORTD&=~(0b11100011); } } ISR(INT1_vect){ test=1; }
PORTC&=~(0b0111111); PORTD&=~(0b11100011); Was ist damit? Das löscht doch die LEDs. Also praktisch hast du damit ein PWM gemacht. Mal gucken ob die LED unter ossczi doch nicht kurz leuchten?
Genau die LEDs leuchten ganz normal (flackern schnell da pwm) wenn man das if(test==1) weglässt. Mit dem If leuchten sie aber immer nur einmal ganz kurz auf, als würde die Variable test nach dem Interrupt wieder auf ihren Initialwert gesetzt werden. Ansonsten würde test ja nach dem Interrupt 1 bleiben und das Licht würde die ganze Zeit leuchten.
Wo kommt denn ›pwm‹ (in den Verzögerungsschleifen) her?
Habe jetzt mal uint32 und uint16 probiert aber hat keinen Unterschied gemacht.
Programmiert ist es in C. Die Variable PWM ist immer 1. Ich habe jetzt einmal probiert das aktivieren der LEDS in den Interrupt zu verschieben also: ISR(INT1_vect){ test++; if (test==3) { PORTC|=0b0111111; PORTD|=0b11100011; } } Das funktioniert jetzt plötzlich wie ich es erwarte. Also die LEDS leuchten nach dreimaligen Aufruf des Interrupts. Das Problem liegt also irgendwie darin die Variable in der main Funktion korrekt aufzurufen.
Beitrag #7617047 wurde vom Autor gelöscht.
Finn schrieb: > Das Problem liegt also > irgendwie darin die Variable in der main Funktion korrekt aufzurufen. Variablen werden nicht "aufgerufen", sondern gelesen oder geschrieben. Und beim AVR8 (auch der ATmega48A ist so einer), gibt es dabei zwei Sachen zu beachten: 1) Wenn aus ISRs und aus main() darauf zugegriffen wird, muss man dem Compiler das mittels des Schlüsselworts volatile in der Variablendeklaration mitteilen. Das zwingt ihn dazu, wirklich für jede Operation auf diese Variable den Speicher zu verwenden, in dem sie steht und nicht den Inhalt irgendwelcher MCU-Register, in den er früher(tm) mal den Speicherinhalt geladen hat. 2) Wenn die Variable breiter als 8Bit ist, muß man Zugriffe darauf aus dem main()-Kontext zusätzlich mit einem ATOMIC_BLOCK-Konstrukt gegen zwischenzeitliche Änderungen durch die ISR(s) schützen. Nur zwei primitive Regeln. Wende sie einfach an. Beispiele findest du unzählige. Einfach mal Google benutzen.
Finn schrieb: > Die Variable PWM ist immer 1. Und die Variable pwm, die dein Code benutzt? LG, Sebastian
Sebastian W. schrieb: > Und die Variable pwm, die dein Code benutzt? Ich sehe in diesem ganzen "Werk" nirgendwo eine Variable namens pwm. Bei der Anwendung üblicher C-Compiler kann daraus also schonmal kein Programm entstehen. > Hat er doch! Woher, zum Teufel, willst du das in vollständiger Absenz der Variablendeklaration wissen?
Hallo, test ist volatile und ein Byte ist per se atomar. Was allerdings wirklich nirgends deklariert/definiert ist die Variable pmw, die in den for Schleifen verwendet wird. So wie eingangs gepostet sollte das nicht kompilieren. Irgend etwas fehlt.
Veit D. schrieb: > test ist volatile und ein Byte ist per se atomar. jo, ich seh nur irgendwie nicht das nach dem einmaligen Setzen in der ISR dies auch mal wieder auf null gesetzt wird.
Finn schrieb: > Hier der Code: Bitte die angegebenen Formatierungsregeln beachten! Offenbar ist der gezeigte Code nicht der, den du auf dem µC laufen lässt, denn du verwendest eine Variable namens pwm, die nirgends definiert oder geschrieben wird. Du schaltest außerdem den Pin-Change-Interrupt und den INT 0 ein, definierst dafür aber keine ISRs. Das default-Verhalten, wenn ein solcher Interrupt ausgelöst wird, ist ein Reset des µC. Was mir weiter auffällt ist, dass du INT0 und INT1 auf level-Triggering eingestellt hast. Das heißt, deine ISR wird permanent immer wieder aufgerufen, solange der Pin auf low ist. Meist will man aber eher, dass die ISR nur bei jeder Änderung einmal aufgerufen wird.
:
Bearbeitet durch User
Irgend W. schrieb: > jo, ich seh nur irgendwie nicht das nach dem einmaligen Setzen in der > ISR dies auch mal wieder auf null gesetzt wird. Hinweis. Wenn dein Thread nicht zum Scherz degradieren soll, empfehle ich dir dringend auf die Fragen bzw. Fragezeichen der Helfer einzugehen und es nicht oberflächlich abzuhandeln.
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.