Hallo, ich hab ein Problem mit meinem AT90S2313 und seinem Timer1. Zum Programm: Ich gebe am PortB eine Vorwahl an und je nachdem soll das Compare Match Register mit einem Wert geladen werden. Der Timer soll dan per externen Clock (zum testen verwende ich einen Taster) bis zu dem entsprechendem Wert hochzählen und den Interrupt ausführen. Soweit die Theorie... In der Praxis aber durchlaufe ich nicht die "if(pump==1)"-Anweisung, was wahrscheinlich bedeutet das der Interrupt nicht auslöst. (Am PD0 hängt eine LED, zum testen) Hab ich irgendwas übersehen? sei() entspricht doch dem 'I'-Bit im SREG, oder?
Erstens hast du die FAQ nicht gelesen: http://www.nongnu.org/avr-libc/user-manual/FAQ.html Gleich der erste Punkt... Zweitens: SREG|=(1<<7); Bitte nicht. Bitte nimm #include <avr/interrupt.h> und schreibe sei() dort hin. Das ist nicht nur besser lesbar, sondern auch schneller.
Du verschwendest unnötig SRAM, Flash und Zeit, wenn Du int nimmst, wo ein char dicke ausreicht. Zusätzlich handelst Du Dir Probleme ein, da ein int nicht atomar zugegriffen werden kann. Ein int (long, float), welches ein Interrupt ändert, muß im main unter Interruptsperre gelesen werden, damit es gültig ist. Der Optimierer ist etwas zu übereifrig. Er möchte ein volatile sehen bei globalen Variablen, die in Interrupts beeinflußt werden. Bei den Timerregistern machst Du es Dir zu umständlich, der AVR-GCC kann die nämlich 16-Bittig (einfach mal ins io***.h File sehen). Peter
Danke euch zwei. der Tipp mit 'volatile' hat geholfen, der Interrupt wird ausgeführt. Allerdings hab ich jetzt ein neues Problem. Da die LED jetzt durch die "if(pump==1)"-Anweisung eingeschaltet wird, soll sie jetzt kurze Zeit später wieder "gelöscht"werden. Dazu hab ich das Programm wie folgt umgeschrieben: while(1) { if(pump==1) { PORTD|=(1<<PB0); _delay_ms(50); PORTD|=(0<<PB0); pump=0; } } Ich weiss 50ms sind zuwenig um das Leuchten wahrzunehmen...jedoch geht sie an aber nicht wieder aus!? Ich könnte mir nur vorstellen das die if-Anweisung immer wieder durchlaufen wird, so das man das "löschen" nicht mehr wahrnimmt. Aber wieso? Ich setze doch 'pump' auf 0 zurück und betätige auch nicht den Taster zum hochzählen! Ich hab int auch durch char ersetzt. Das mit dem 16-Bit Register wusste ich nicht, werde ich demnächst mal ändern. ;-)
> jedoch geht > sie an aber nicht wieder aus!? Weil das hier Unsinn ist: PORTD|=(0<<PB0); Die rechte Seite ist eine umständlich hingeschriebene 0. Wenn du eine Null in ein Byte ver-oderst, bleibt das Byte einfach nur in voller Schönheit erhalten. Du willst: PORTD &= ~(1 << PB0); haben. Denk bei _delay_ms() an den gültigen Wertebereich. Für alle derzeit bei AVRs zulässigen Taktfrequenzen ist 10 ms immer ein gültiger Wert (das ist meine Faustformel, weil ich mir das gut merken konnte :), dann machst du 'ne Sekunde draus: uint8_t i; for (i = 0; i < 100; i++) _delay_ms(10);
Oh man da hab ich den Wald vor lauter Bäumen nicht mehr gesehen. OK soweit funktioniert das Programm jetzt einwandfrei. Vielen Dank!
Hallo, ich muss mich leider nochmal melden :-( Ich habe ein neues seltsames Problem. Ich habe das Programm noch ein wenig erweitert, eigentlich nur um eine Tasterabfrage und eine Vorwahlüberprüfung. (siehe Anhang) Ich weiss das es mal ohne Probleme lief, hab zuerst vermutet den µC geschossen zu haben. Aber auch ein neuer µC hat nichts gebracht. Irgendwie werden die 'else if' Anweisungen nicht mehr durchlaufen. Der Taster (an T1) löst komischerweise jedesmal den Interrupt aus, anstatt hochzuzählen. Ab und zu funktioniert dann das zählen wieder aber ich kann die Stufe quasi nicht mehr einstellen. Ich weiss es ist schwierig zu erklären aber vielleicht habt ihr mein Problem verstanden.
Wenn Du der Variablen 'vorwahl' eine Zahl größer als 9 zuweist, ist es klar, dass die if-Abfragen ergebnislos bleiben. Wie sieht denn überhaupt die Vorwahleingabe an Port B aus? Entweder PINB bei der Eingabe maskieren. Wozu ist überhaupt der Pull-Up von PORTB.4 aktiviert? Wenn da nix dranhängt (Pin offen), kriegste immer Zahlen größer als 9. Ansonsten mal eine Default-Aktion einbauen (else...). Ich würde das ganze aber eh mit einer switch...case-Anweisung machen. Ist weniger Schreibarbeit und übersichtlicher! Gruß Johnny
Also die Vorwahl geschieht über einen Hex-Drehschalter (0-9), also kann 'vorwahl' nie größer als 9 werden. Der Schalter hängt mit seinen vier Pins an PB0 bis PB3. An PB4 hängt ein Taster, zur manuellen Steuerung, der Masse schaltet. Deshalb der Pullup. ...Ah! Jetzt geht mir auch ein Licht auf, es muss an dem Taster liegen. Wenn ich PINB einlese wird dieser ja auch mitgelsen und da der immer auf High (durch dien Pullup) liegt ändert das natürlich meine Zahl. Da muss ich mir was einfallen lassen wie ich nur die ersten vier Pins abfrage...?
Ah, der Euro fällt centweise:-) Aber das mit dem 'einfallen lassen' ist ja wohl nicht so schwer, oder? Habs ja oben schon gesagt: Maskieren! Ansonsten viel Spaß noch beim Basteln. Und überleg bei Gelegenheit mal, ob Du Deine if-Abfrage nicht wirklich besser durch ne switch-Anweisung ersetzt. Solche if...else if...-Würmer sind einfach nicht schön. Gruß Johnny
Ich hatte dabei an eine EXOR Verknüpfung gedacht. Also quasi PB4 mit EXOR 1 auf Null setzten. Wie war das noch gleich in C...?
Wieso EXOR????? vorwahl = PINB & 0x0f; Du solltest vielleicht wirklich mal C-Grundlagen pauken... Gruß Johnny
Wenn Du aus einem Byte die vier LSB übernehmen und den Rest zu null machen willst, dann mach es mit &. Alles andere ist völliger Käse. Und mit Deinem EXOR setzt Du das Bit nur dann auf Null, wenn es vorher gesetzt ist. Wenn es nämlich vorher null ist, dann setzt Du es auf '1'! Deshalb scheidet das völlig aus. Gruß Johnny
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.