PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Brauche Hilfe um Funktion fertig zu stellen



Nerb
05.04.2008, 18:35
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:




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;
}
}
}

Was noch wichtiges anzumerken ist:
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 :lol: ) 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

Hubert.G
06.04.2008, 13:53
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.

Nerb
06.04.2008, 15:30
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

Felix G
06.04.2008, 15:59
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.

Nerb
06.04.2008, 17:12
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:

#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);
}

}
}


Beim compilieren kommten folgende Fehlermeldungen

../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'

Wie kann ich die Fehler beheben. Kann mir jemand Tipps geben?

mfg

Besserwessi
06.04.2008, 18:02
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.

Nerb
06.04.2008, 18:28
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

Hubert.G
06.04.2008, 20:21
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.