Hallo,
Für eine Schulprojekt möchte ich mit einem Atmel 89C51CC01 (mit einem
12.000 MHz Quarz für den Takt) Daten von einem HCSR04 - Modul empfangen
und die Entfernung damit berechnen und ausgeben. Als
Entwicklungsumgebung verwende ich Keil. Meinen bisheriger Code
funktioniert leider soweit noch nicht, daher hoffe ich, dass ihr mich
vielleicht auf den richtigen Weg bringen könnt. Die Suchleiste habe ich
bereits verwendet allerdings nichts passendes gefunden.
Aktuell bin ich soweit :
sbit trigger = 0x91; //Trigger an Port 0x91
sbit echo = 0x92; //Echo an Port 0x92
unsigned int x = 1; //Zählervariable
double abstand = 0;
double zeit = 0;
double merk = 0;
unsigned char txt[10];
void main (void)
{
init_lcd(); //LCD initzialisieren
clear(); //Bildschirm löschen
EA = 1; //Allgemeine Interrupt Freigabe
ET0 = 1; //Timer 1 Freigabe
TMOD = 2; //Timermodus 2
TH0 = 254; //Nach einem Takt überlauf
TL0 = 254;
IT0 = 1;
while(1)
{
zeit = 0;
trigger = 0; //Trigger wird auf 0 gesetzt
msec(5); //Wartezeit
trigger = 1;
msec(10); //Wartezeit
trigger = 0; //Trigger aus
home(); //LCD wird an anfang gesetzt
sprintf(txt,"%2.2lf cm",abstand);
lcdsend(txt);
if(trigger == 1 && echo == 1)
{
TR0=1;
}
else
{
zeit = merk;
merk = 0;
TR0 = 0;
abstand = (zeit/2)*0.03432;
}
}
}
void timer(void) interrupt 1
{
x--;
if(x == 0)
{
x = 1;
merk++; //Variable für Microsekunde
}
}
Danke schonmal für eure Ratschläge !
LG M4tt3
Linus K. schrieb:> Meinen bisheriger Code> funktioniert leider soweit noch nicht,
Was funktioniert wie genau nicht? Da fehlt eine Fehlerbeschreibung.
Float und Double will man auf 8051 nicht wirklich benutzen, schon gar
nicht im Interrupt.
Jim M. schrieb:> Linus K. schrieb:>> Meinen bisheriger Code>> funktioniert leider soweit noch nicht,>> Was funktioniert wie genau nicht? Da fehlt eine Fehlerbeschreibung.>> Float und Double will man auf 8051 nicht wirklich benutzen, schon gar> nicht im Interrupt.
Die Datentypen habe ich geändert, danke für den Tipp. Fehlermeldung
werden nicht angezeit, nur Warnungen für das angeschlossenen LCD.
linking...
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?RSHIFT?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?LSHIFT?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?CURRSHIFT?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?CURLSHIFT?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?DIS_OFF?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?DIS_ON2?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?DIS_ON3?FVS_BIB_LCD
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?_POS?FVS_BIB_LCD
Program Size: data=63.1 xdata=0 code=3292
creating hex file from "hexfile"...
"hexfile" - 0 Error(s), 8 Warning(s).
Marc V. schrieb:> Linus K. schrieb:>> TH0 = 254; //Nach einem Takt überlauf>> TL0 = 254;>> Wenn das stimmt, kann das Ganze ja gar nicht funktionieren.
Wieso ? Die x - Variable wir um eins runtergezählt es gibt einen
Zählerüberlauf und die merk - Variable wird um eins erhöht, dass ist
doch dann exakt eine Mycrosekunde oder nicht ?
Linus K. schrieb:> Wieso ? Die x - Variable wir um eins runtergezählt es gibt einen> Zählerüberlauf und die merk - Variable wird um eins erhöht, dass ist> doch dann exakt eine Mycrosekunde oder nicht ?
Aha.
Und der Sprung zur ISR, retten der Register, x--, Integer vergleichen,
double hochzählen, wiederherstellen der Register, Rücksprung ?
Was glaubst du, wieviele Takte werden dafür gebraucht ?
P.S.
Kenne mich mit 89xx nicht aus, aber wo hast du Interrupt on OVFLW
gesetzt ?
P.P.S.
Wieso TH0, TL0, ET0, IT0 wenn du mit Timer 1 arbeitest, sollten
diese nicht TH1, TL1, etc. heissen ?
Linus K. schrieb:> TH0 = 254; //Nach einem Takt überlauf
Der 8051 hat keine FPU, d.h. float Berechnungen können unmöglich nur
einen CPU-Takt lang dauern.
Und das LCD-Zeugs auch nicht.
Nimm den Gate-Modus und laß den Timer die Zeit messen.
Oder das PCA im Capture-Modus.
Marc V. schrieb:> Linus K. schrieb:>> Wieso ? Die x - Variable wir um eins runtergezählt es gibt einen>> Zählerüberlauf und die merk - Variable wird um eins erhöht, dass ist>> doch dann exakt eine Mycrosekunde oder nicht ?>> Aha.> Und der Sprung zur ISR, retten der Register, x--, Integer vergleichen,> double hochzählen, wiederherstellen der Register, Rücksprung ?> Was glaubst du, wieviele Takte werden dafür gebraucht ?
Mist, dass habe ich nicht bedacht, danke für den Hinweis !!
> P.P.S.> Wieso TH0, TL0, ET0, IT0 wenn du mit Timer 1 arbeitest, sollten> diese nicht TH1, TL1, etc. heissen ?
Schreibfehler von mir meinte Timer 0
Am einfachsten geht es mit dem PCA. Auf beide Flanken capturen und die
beiden Timestamps voneinander abziehen.
Man kann aber auch 2 Capture-Module nehmen und deren Eingänge parallel
schalten.
Danach bat man alle Zeit der Welt, die Differenz in float umzurechen und
auf dem LCD anzuzeigen. Assembler ist unnötig und bringt keine höhere
Auflösung.
Ein ständiges Clear läßt das LCD deutlich sichtbar flackern.
Professioneller ist es daher, einfach nur den alten Text mit dem neuen
zu überschreiben.
Theoretisch kann das PCA sogar mit XTAL/2 schneller als ein CPU-Takt
zählen. Kann aber sein, daß das nur für die Fast-PWM gedacht ist.
Ich würds daher erstmal nur mit XTAL/6 takten.
Wieso Mikrosekunden-Auflösung bei der Zeitmessung??
Ultraschall verbreitet sich mit ca. 340m/s. Ein Hindernis in einem Meter
Entfernung bedeutet t=s/v => s=2m, t=2m/340m/s = 5,88ms Laufzeit. Wenn
du erstmal auf einen cm genau messen willst, dann sind das immer noch
59µs.
Aber das ist hier erstmal egal. Die Laufzeit kann man direkt messen:
Stelle den Timer im 16-Bit Modus mit Gate ein, Anfangswert auf 0. Dann
den Trigger auslösen. Der Echo-Ausgang des HC04 kommt auf den
Gate-Eingang (P3.3 bei Timer1). Solange der Echo-Impuls da ist läuft der
Timer, mit der fallenden Flanke bleibt der Timer automatisch stehen und
du kannst den Zählerstand gemütlich auslesen (sogar in µs-Auflösung).
Wenn Du Interrupt verwenden willst/sollst, dann bitte den externen
Interrupt1 auf Flankentrigger. Damit gibt es den Interrupt, sobald der
Echo-Impuls weg ist und der Timer steht.