Hallo zusammen. was stimmt an dem folgenden Code nicht? Syntaxfehler sind keine vorhanden. Das Programm wurde schon kompiliert. Ich sehe bloß keine Änderungen an PORTD.0 und PORTD.1. Es liegt an der Interrupt-Routine. Die Interrupt-Routine wird jede Millisekunde aufgerufen. Sie wird erst freigegeben, wenn delay1ms() aufgerufen wird. #include <io1200.h> #include <macros.h> #pragma interrupt_handler tim0Ovf:2 #define CLOCK 4000000L // Taktfrequenz # define SETBIT(ADRESS,BIT) (ADRESS|=(1<<BIT)) # define CLRBIT(ADRESS,BIT) (ADRESS&=~(1<<BIT)) # define CHKBIT(ADRESS,BIT) (ADRESS & (1<<BIT)) static volatile unsigned int timeout_1ms; static void delay1ms (unsigned int n); void initT0Int(); static void delay1ms (unsigned int n) { timeout_1ms = n; SETBIT(TIMSK,TOIE0); // Interrupt Timer 0 frei while(timeout_1ms); CLRBIT(TIMSK,TOIE0); // Interrupt gesperrt } void tim0Ovf() { TCNT0 = 240; if(timeout_1ms) timeout_1ms--; } void initT0Int() { TCNT0 = 240; TCCR0 = 0x04; // Vorteiler =256, Timer 0 starten } void main() { DDRD=0x3F; PORTD=0x00; CLRBIT(PORTD,0); CLRBIT(PORTD,1); initT0Int(); // Timer0 initilisieren asm("sei"); // allg. Interrupt Freigabe SETBIT(PORTD,0); delay1ms(1000); CLRBIT(PORTD,0); delay1ms(1000); SETBIT(PORTD,1); delay1ms(1000); CLRBIT(PORTD,1); }
Hallo Peter. ICCAVR fügt while(1) automatisch am Programmende ein. Ich habe das Programm schon mit main-loop kompiliert und es lief trotzdem nicht. Meine Vermutung liegt beim Timer0-Interrupt. Ich habe in die ISR tim0Ovf() den Befehl CLRBIT(PORTD,4); eingefügt. Es passiert nichts. Es wird überhaupt nicht in die ISR gesprungen. Mit dem IAR-Compiler und dem 8515 hat alles gut geklappt. Interrupt-Vector kann es auch nicht sein. Würde IAR den 1200er unterstützen, würde ich es gar nicht probieren mit dem ICCAVR. Gruß Hilel
Hallo. Gibt es wirklich keinen ICCtiny-Anwender hier im Forum? Es wäre schön, wenn sich jemand melden würde. ich danke euch.
Hi, habe zwar keine Ahnung vom ICCtiny, aber ich denke der Fehler liegt in deiner Delay-Funktion. Du setzt am Anfang timeout_1ms gleich n und gehst dann in eine while-Schleife. Hier solltest Du timeout_1ms aber auch dekrementieren, sonst ist die Bedingung immer erfüllt (es sei denn, du übergibst eine 0 an die Funktion). static void delay1ms (unsigned int n) { timeout_1ms = n; SETBIT(TIMSK,TOIE0); // Interrupt Timer 0 frei while(timeout_1ms) { timeout_1ms--; //z.B. so } CLRBIT(TIMSK,TOIE0); // Interrupt gesperrt } Hoffe, das wars, viele Grüße, Ralf
nö, das wirds nicht sein, timeout wird ja in der Timer-ISR decrementiert, irgendwann wirds 0, und dann wird die while-Schleife auch wieder verlassen. Warum es nicht funktioniert, sehe ich aber auch nicht, sieht korrekt aus. Stell doch mal das erzeugte Assemblerlisting hier rein.
Hallo Ralf. >>Du setzt am Anfang timeout_1ms gleich n und gehst dann in eine while-Schleife. Hier solltest Du timeout_1ms aber auch dekrementieren, sonst ist die Bedingung immer erfüllt (es sei denn, du übergibst eine 0 an die Funktion). >> timeout_1ms soll eben nicht von der Routine static void delay1ms (unsigned int n) verändert werden. Das Dekrementieren von timeout_1ms übernimmt die ISR-Routine tim0Ovf(). void tim0Ovf() { TCNT0 = 240; if(timeout_1ms) timeout_1ms--; } Immer wenn ein Interrupt von Timer0 ausgelöst wird, wird timeout_1ms dekrementiert. Irgendwann erreicht timeout_1ms in der While-Schleife den Wert 0 und die Routine static void delay1ms (unsigned int n)wird bendet. Dasselbe Programm hat ja schon mit dem AT90S8515 beim IAR-Compiler funktioniert. Viele Grüße Hilel
Hallo zusammen. Ich stelle mal das erzeugte Assemblerlisting hier rein. Gruß Hilel
Hi! Ich habe zwar keine direkte Erfahrug mit AVR, aber es sieht so aus, als ob bei dir die Compileroptimierung zuschlägt:) Ist z.B. PortD als VOLATILE definiert? Füge doch mal zum Testen etwas mehr Code zwischen deine Makros ein, damit du die Optimierung überlistest... Gruß, Dirk.
Ich habe es: 1) void delay1ms(void) statt static void delay1ms(void) 2) Interruptvektor ist 3 statt 2 (2 ist eigentlich die Sprungadresse 0x0002). Im Datenblatt steht sogar eine 4, aber ich denke, das ist ein Tippfehler von ATMEL.Es gibt beim 1200er nur 4 Interruptvektoren: 1: RESET 2: INT0 3: TIMER0, OVF0 4: ANA_COMP #include <io1200.h> #include <macros.h> #define CLOCK 4000000L // Taktfrequenz # define SETBIT(ADRESS,BIT) (ADRESS|=(1<<BIT)) # define CLRBIT(ADRESS,BIT) (ADRESS&=~(1<<BIT)) # define CHKBIT(ADRESS,BIT) (ADRESS & (1<<BIT)) static volatile unsigned int timeout_1ms; #pragma interrupt_handler tim0Ovf:3 void tim0Ovf() { TCNT0 = 240; if(timeout_1ms) timeout_1ms--; } void delay1ms (unsigned int n) { timeout_1ms = n; SETBIT(TIMSK,TOIE0); // Interrupt Timer 0 frei while(timeout_1ms); CLRBIT(TIMSK,TOIE0); // Interrupt gesperrt } void tim0Ovf() { TCNT0 = 240; if(timeout_1ms) timeout_1ms--; } void initT0Int() { TCNT0 = 240; TCCR0 = 0x04; // Vorteiler =256, Timer 0 starten } void main() { DDRD=0x3F; PORTD=0x00; CLRBIT(PORTD,0); CLRBIT(PORTD,1); initT0Int(); // Timer0 initilisieren asm("sei"); // allg. Interrupt Freigabe SETBIT(PORTD,0); delay1ms(1000); CLRBIT(PORTD,0); delay1ms(1000); SETBIT(PORTD,1); delay1ms(1000); CLRBIT(PORTD,1); }
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.