Forum: Mikrocontroller und Digitale Elektronik HCSR04 mit Atmel 89C51CC01 in C


von Linus K. (m4tt3)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Linus K. schrieb:
> TH0 = 254;               //Nach einem Takt überlauf
>       TL0 = 254;

 Wenn das stimmt, kann das Ganze ja gar nicht funktionieren.

von Linus K. (m4tt3)


Lesenswert?

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 ?

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

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.

: Bearbeitet durch User
von Linus K. (m4tt3)


Lesenswert?

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

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Linus K. schrieb:
> Schreibfehler von mir meinte Timer 0

 Ok, trotzdem kannst du die Zeit so nicht messen.
 Schau dir das mal an:
 Beitrag "Re: HC SR 04 in Assembler"

von Peter D. (peda)


Lesenswert?

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.

von Bernhard S. (b_spitzer)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.