Warum nimmst du nicht den Timer-Interrupt
Ich weiss nicht welchen Kontroller du hast.
Eintrag in TIMSK|=(1<<TOIE1)
TIMER1_OVF_vect{ Hier den Code wenn Überlauf}
Das wäre für den Mega8.
Hallo,
so ich bin nun schon fast fertig mit dem code für den Ultraschallentfernungsmesser. Nur eins fehlt noch, nämlich die Erkennung von einem timer Überlauf ( der 16 bit timer wird benutzt). Als Neuling bringe ich das nicht auf die Reihe ohne Hilfe. Hier mein Code:
Was noch wichtiges anzumerken ist:Code:unsigned int messen (void) { unsigned int messwert; TCNT1 = 0xBB80; /* Vorladen auf 48000 */ PORTC |= (1<<PC5); /* Senden */ TCCR1B = 0x2; /* timer starten und Vorteiler auf 8 setzen */ _wait_us(25); PORTC &= ~(1<<PC5); /* Sender ausschalten*/ while (1) { if(PINC & (1<<PINC4)) { /* Wenn Signal zurückkommt... */ TCCR1B = 0x0; /* Timer stoppen */ messwert = TCNT1 - 48000; /* Vorladewert wieder abziehen */ messwert *= 0.0172; /* In Sekunden umrechnen */ return messwert; } if (1*) { /* Abbruch bei timer Überlauf */ return 0; } } }
Ich sende nur einen kurzen Impuls. Das wird später noch geändert werden ,falls sich rausstellen sollte, dass es nicht klappt.
Sind noch Fehler im Code? Und wie mache ich, dass er dort wo eine eins mit stern (1*, kein falschgeschriebener pointer ) in der If-Bedienung steht, der timer Überlauf erkannt wird und die Funktion 0 zurückgibt?
Lässt sich noch was optimieren?
danke schonmal im Vorraus für eure Hilfe
mfg
Warum nimmst du nicht den Timer-Interrupt
Ich weiss nicht welchen Kontroller du hast.
Eintrag in TIMSK|=(1<<TOIE1)
TIMER1_OVF_vect{ Hier den Code wenn Überlauf}
Das wäre für den Mega8.
Hallo,
ja ich nehme den mega8, aber ich weiß nicht was ich in die interruptfunktion reinschreiben soll. etwa return 0; ?
Der Rest stimmt so?
mfg
Also wenn du Zeiten messen möchtest, geht das auch einfacher...
Stell den Timer z.B. auf ein sehr kurzes Zeitintervall ein, also Überlauf nach vielleicht 100µs oder 1ms oder sowas in der Größenordnung (je nachdem was die kürzeste Zeit ist die gemessen werden muss). In der ISR startest du den Timer dann einfach nur neu, und zählst eine Variable hoch, quasi wie eine "Uhr".
Wenn du in deinem Programm dann eine Zeit messen möchtest, merkst du dir den Wert dieser Variablen zu Beginn des Zeitintervalls. Wenn die Messung beendet werden soll, ziehst du diesen Wert vom aktuellen Wert der Variablen ab, und erhälst so direkt die vergangene Zeit.
So viele Treppen und so wenig Zeit!
Hallo,
so ich habe meinen code verändert. Da ich nicht weiß inwieweit der Interrupt in die Funktion eingreifen kann, setze ich einen Flag a, der dann in der Funktion messen überprüft wird. Hier mein vollständiger code:
Beim compilieren kommten folgende FehlermeldungenCode:#include<stdlib.h> #include<avr/io.h> #define F_CPU 8000000 #include<util/delay.h> #include"lcd.h" volatile char a; unsigned int messen (void) { unsigned int messwert; TCNT1 = 0xBB80; /* Vorladen auf 48000 */ PORTC |= (1<<PC5); /* Senden */ TCCR1B = 0x2; /* timer starten und Vorteiler auf 8 setzen */ _wait_us(25); PORTC &= ~(1<<PC5); /* Sender ausschalten*/ while (1) { if(PINC & (1<<PINC4)) { /* Wenn Signal zurückkommt... */ TCCR1B = 0x0; /* Timer stoppen */ messwert = TCNT1 - 48000; /* Vorladewert wieder abziehen */ messwert *= 0.0172; /* In Sekunden umrechnen */ return messwert; } if (a=1) { /* Abbruch bei timer Überlauf */ return 0; } } } int main (void) { TIMSK|=(1<<TOIE1); TIMER1_OVF_vect{ a=1;} DDRC |= (1<<PC5); DDRD= 0xff; lcd_init(LCD_DISP_ON); /* lcd initialisieren */ lcd_clrscr(); /* Display löschen und cursor auf 1,1 setzen */ lcd_puts("distance: "); while(1) { lcd_gotoxy(11,1); lcd_puts("messen();"); lcd_gotoxy(15,1); lcd_puts("cm"); for(unsigned char i=0;i<256;i++) { /*warte*/ _wait_ms(1); } } }
Wie kann ich die Fehler beheben. Kann mir jemand Tipps geben?../Ultraschall.c: In function 'messen':
../Ultraschall.c:14: warning: implicit declaration of function '_wait_us'
../Ultraschall.c:23: warning: suggest parentheses around assignment used as truth value
../Ultraschall.c: In function 'main':
../Ultraschall.c:31: error: '__vector_8' undeclared (first use in this function)
../Ultraschall.c:31: error: (Each undeclared identifier is reported only once
../Ultraschall.c:31: error: for each function it appears in.)
../Ultraschall.c:31: error: expected ';' before '{' token
../Ultraschall.c:46: warning: comparison is always true due to limited range of data type
../Ultraschall.c:47: warning: implicit declaration of function '_wait_ms'
mfg
Die Intterrupt routine muss etwas so aussehen:
ISR(TIMER1_OVF_vect ) // timer 1 overflow
{ a = 1; }
Bei den _wait_us noch mal in delay nachsehen.
Da ist noch ein fieser, C typischer Fehler drin:
statt if (a=1) muss das if (a==1) heißen.
Die For-schleife mit wait_ms darf nur bis 254 laufen, oder i müßte als integer gewählt werden.
Wenn es nur darum geht die Messung beim Timerüberlauf abzubrechen, könnte man auch gleich das interrupt flag abfragen. Dann muß man allerdings während der Zeit alle interrupts per CLI sperren.
Hallo,
ja ich will bei timerüberlauf abbrechen (=return 0; ). In der ersten code-Version habe ich das auch mit einem If-Befehl gemacht. Wenn der Interrupt deaktiviert ist, kann überhaupt noch das interrupt flag gesetzt werden? Muss ich die Interrupts danach wieder aktivieren? Bin bei dem Thema noch sehr unsicher auf den Beinen
mfg
Das ISR(TIMER1_OVF_vect){ a=1;} gehört nicht ins main, das ist eine eigene Funktion.
Nach der if Abfrage a wieder auf 0 setzten und den Timer stoppen. Die if Abfrage in die while-Schleife integrieren.
Lesezeichen