mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Sharp GP2D02 Sensor auslesen mit CodeVisionAVR und einem AT90S8515


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Julian (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe hier einen STK200(+) mit einem AT90S8515. Daran habe ich einen 
Sharp GP2D02 Sensor und eine BCD-Anzeige. Ich möchte nun mit dem GP2D02 
eine Entfernung messen, die dann direkt an das Display ausgegeben wird. 
Wenn die Entfernung kleiner als 40cm ist, dann soll eine LED leuchten.
Das ganze in C und in CodeVision.
Ich habe eigentlich keine Ahnung, wie man den Sensor auslesen soll. D.h. 
ich habe nun die Frage, wie man denn jetzt den Sensor ansteuern soll, 
dass dieser mir einen Wert zurück gibt.
Hier ist mal das Datenblatt zum GP2D02: 
http://pdf1.alldatasheet.com/datasheet-pdf/view/42836/SHARP/GP2D02.html

Im Anhang habe ich mal ein Bild von meinem Controller.

Zu den Ports:
Der Sensor ist an Port C
Die Anzeige ist an Port A
LEDs an Port B

Es wäre echt nett von euch, wenn ihr mir helfen könntet. Danke schon mal 
im Voraus!

Ich habe so gut wie kein Code bis jetzt. Ich habe nur mal die Ports 
definiert:

////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///                weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abk?rzungen
#include <delay.h>                  //Deklarationen


//Bekanntmachund der Methoden
void port_init(void);                //Bekanntmachung der Methode port_init
//void timer_init(void);               //Bekanntmachung der Methode timer_init 
//Vereinbarungen/Deklarationen  
                                 

//Hauptprogramm//

void main(void)                      
{
    port_init();                    //Port-Initialisierung 
    //timer_init();                   //Timer-Initialisierung
    //SREG=0x80;                      //Globale Interrupt Freigabe// Alternativ: #asm("sei")
    while (1)
    {
    }
                                        
}

//interrupt[TIM1_OVF] void timer1_ovf_isr(void)
//{       
//}
  

void port_init(void)
{
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
     DDRC=                          //?
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
}


//void timer_init(void)
//{
//    TCCR1B=0x02;                   //Vorteiler 8->1 Durchlauf 0,131s
//    TCNT1H=0x77;                   //Timer Start Wert...
//    TCNT1L=0x48;                   //...fuer 70ms setzen
//    TIMSK=0x80;                    //Timer1-Overflow-Interrupt freigeben        
//}


Autor: Julian P. (jupa1337)
Datum:
Angehängte Dateien:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo,
ich habe hier einen STK200(+) mit einem AT90S8515. Daran habe ich einen
Sharp GP2D02 Sensor und eine BCD-Anzeige. Ich möchte nun mit dem GP2D02
eine Entfernung messen, die dann direkt an das Display ausgegeben wird.
Wenn die Entfernung kleiner als 40cm ist, dann soll eine LED leuchten.
Das ganze in C und in CodeVision.
Ich habe eigentlich keine Ahnung, wie man den Sensor auslesen soll. D.h.
ich habe nun die Frage, wie man denn jetzt den Sensor ansteuern soll,
dass dieser mir einen Wert zurück gibt.
Hier ist mal das Datenblatt zum GP2D02:
http://pdf1.alldatasheet.com/datasheet-pdf/view/42836/SHARP/GP2D02.html
Hier habe ich mal ein Bild von meinem Controller. 
https://imgur.com/a/7TQJsdi

Zu den Ports:
Der Sensor ist an Port C
Die Anzeige ist an Port A
LEDs an Port B

Es wäre echt nett von euch, wenn ihr mir helfen könntet. Danke schon mal
im Voraus!

Ich habe so gut wie kein Code bis jetzt. Ich habe nur mal die Ports
definiert:
////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///                 weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abk?rzungen
#include <delay.h>                  //Deklarationen


//Bekanntmachund der Methoden
void port_init(void);                //Bekanntmachung der Methode port_init
//void timer_init(void);               //Bekanntmachung der Methode timer_init 
//Vereinbarungen/Deklarationen  
                                 

//Hauptprogramm//

void main(void)                      
{
    port_init();                      //Port-Initialisierung 
    //timer_init();                   //Timer-Initialisierung
    //SREG=0x80;                      //Globale Interrupt Freigabe// Alternativ: #asm("sei")
    while (1)
    {
    }
                                        
}

//interrupt[TIM1_OVF] void timer1_ovf_isr(void)
//{       
//}
  

void port_init(void)
{
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
     DDRC=                          //?
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
}


//void timer_init(void)
//{
//    TCCR1B=0x02;                   //Vorteiler 8->1 Durchlauf 0,131s
//    TCNT1H=0x77;                   //Timer Start Wert...
//    TCNT1L=0x48;                   //...fuer 70ms setzen
//    TIMSK=0x80;                    //Timer1-Overflow-Interrupt freigeben        
//}

: Bearbeitet durch User
Autor: spess53 (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Hi

Da steht:

Forum: Projekte & Code

Hier könnt ihr eure Projekte, Schaltungen oder Codeschnipsel vorstellen 
und diskutieren. Bitte hier keine Fragen posten!

Gelesen?

MfG Spess

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Du hast also bis jetzt exakt NICHTS an Software geschrieben/versucht.
Du hast es nicht mal geschafft, einen konkreten link zu dem Sensor zu 
posten.

Nun ja, kann man so machen und versuchen - ob es viel Erfolg hat?

Autor: Julian P. (jupa1337)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Den Link hat es wohl verhauen; Sollte jetzt aber wieder gehen. Hier ist 
der Link nochmal: 
http://pdf1.alldatasheet.com/datasheet-pdf/view/42836/SHARP/GP2D02.html

Wie soll ich einen Code schreiben, wenn ich nicht weiß, wie ich ihn 
ansteuern soll? Versucht habe ich schon einiges aber bis jetzt kam 
nichts vernünftiges bei rum und deshalb melde ich mich ja jetzt hier im 
Forum.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Steht doch in der Timing Chart, ich übersetze das mal:
1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
2. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach 
der fallenden Flanke den Output - MSB kommt zuerst.
3. Wiederhole das 8 mal.
4. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden. 
Der Sensor geht in Power Off.

: Bearbeitet durch User
Autor: Julian P. (jupa1337)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Steht doch in der Timing Chart, ich übersetze das mal:
> 1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
> 2. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach
> der fallenden Flanke den Output - MSB kommt zuerst.
> 3. Wiederhole das 8 mal.
> 4. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden.
> Der Sensor geht in Power Off.

Okay, danke schon mal.
Aber ich hätte da noch ein paar Fragen:
Wenn Laut Sensor VOUT das Bit 7 ist, dann ist das doch PORTC.7 oder?
Das Gleiche dann für VIN: Bit 4 ist dann PORTC.4?

Wie genau muss ich dann PORTC oder DDRC definieren? Eingänge sind 0 und 
Ausgänge sind 1, also würde das dann bedeuten 0b01111111 also 0x7F?

Der Port C sollte doch 0-Aktiv sein: dann müsste low ja 1; und high ja 0 
bedeuten oder?

Ihr könnt ja mal mein Code anschauen und mir schreiben, was ich falsch 
mache. Danke!
////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///                weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abk?rzungen
#include <delay.h>                  //Deklarationen


//Bekanntmachund der Methoden
void port_init(void);                  //Bekanntmachung der Methode port_init
void read(void);                       //Bekanntmachung der Methode read
void anzeige(void);                    //Bekanntmachung der Methode anzeige
unsigned char r_rotate (unsigned char bitmuster);       //Bekanntmachung der Methode r_rotate 
//Vereinbarungen/Deklarationen
unsigned char wert;
unsigned char bitmuster;
int k;                                 

//Hauptprogramm//

void main(void)                      
{
    port_init();                      //Port-Initialisierung 
    while (1)
    {
    read();
    }
                                        
}


void read(void)
{
    PORTC.4=1;                       //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
        PORTC.4=0;                   //VIN auf high
        delay_us(100);               //fuer 100us
        PORTC.4=1;                   //VIN auf low
        delay_us(100);               //fuer 100us
        wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der Methode um linkszuschieben
    }
}  

unsigned char r_rotate (unsigned char bitmuster)
{
     bitmuster=bitmuster>>1;        //linksschieben, damit MSB rechts steht
     return bitmuster;
}

void anzeige(void)
{
    PORTA=wert;                     //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
}

void port_init(void)
{
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
     DDRC=0x7F;                     //?
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
}


Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> PORTC.4=1;                       //VIN auf low

Ich weiss ja nicht, was du da für einen Compiler benutzt, aber eine 1 
bedeutet im Allgemeinen high und eine 0 steht für low.

: Bearbeitet durch User
Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ja wenigstens mal ein Anfang.
Lass die direkten Ports aus dem Programm, erhöht die Lesbarkeit und 
macht es einfacher, dass später vielleicht mal auf einen anderen 
Port/Pin zu schieben.
#define VIN PORTC.4

.
VIN=0;
.
VIN=1;

Entweder falsch gedacht oder nur der Kommentar falsch?
>PORTC.4=0;                   //VIN auf high

Das ist auf jeden Fall falsch:
>wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der
> Methode um linkszuschieben
Gelesen wird nicht von PORTC.7, sondern von PINC.7
Und ob man dafür noch eine extra Funktion verwenden sollte? Kann man 
machen, muss man nicht.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Julian P. schrieb:
>> PORTC.4=1;                       //VIN auf low
>
> Ich weiss ja nicht, was du da für einen Compiler benutzt, aber eine 1
> bedeutet im Allgemeinen high und eine 0 steht für low.

Ok. Ich benutze den "CodeVisionAVR C Compiler" also denke ich einen ganz 
normalen C Compiler.
So sieht jetzt meine Methode read() aus aber es funktioniert immer noch 
nichts. Auf dem Display wird immer noch 00 Angezeigt.
void read(void)
{
    PORTC.4=0;                       //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
       PORTC.4=1;                   //VIN auf high
        delay_us(100);               //fuer 100us
        PORTC.4=0;                   //VIN auf low
        delay_us(100);               //fuer 100us
        wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der Methode um linkszuschieben
    }
}


Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> wert=r_rotate(PORTC.7);      //VOUT auslesen und verwendung der
> Methode um linkszuschieben

Du hast aber schon den Beitrag von crazyhorse gelesen? PORTC auszulesen 
bringt dir gar nichts. Du musst das PINC Register lesen, um den Pegel an 
einem Eingang zu lesen.

Julian P. schrieb:
> bitmuster=bitmuster>>1;        //linksschieben, damit MSB rechts
> steht
>      return bitmuster;

Ausserdem möchten die meisten von uns, das das MSB links steht und auch, 
das der Pin tatsächlich ins bitmuster wandert. Hier mal ein altes 
Konstrukt von mir mit GCC, was sowas macht:
bitmuster <<= 1;  /* shift one bit to the left - MSB comes first */ 
     if (bit_is_set(PINC,4)) {
  bitmuster |= 0x01 ; /* set the lowest data bit */
     }

: Bearbeitet durch User
Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, nein tatsächlich habe ich den Kommentar überlesen. Danke für den 
Hinweis!! Ich bin tatsächlich ein weinig durcheinander was rechts und 
links angeht aber ich hoffe ich bekomme das dennoch hin.
bitmuster <<= 1;  /* shift one bit to the left - MSB comes first */ 
     if (bit_is_set(PINC,4)) {
  bitmuster |= 0x01 ; /* set the lowest data bit */
     }
das mit dem if habe ich nicht ganz verstanden, da es bei mir kein 
"bit_is_set" gibt (Error: C:\Users\vm\Desktop\entfernungssensor.c(62): 
undefined symbol 'bit_is_set')

Meine Anzeige zeigt immer noch 00 an. Wie muss ich den in meiner 
port_init() DDRC definieren? Ist 0x7F richtig?

Hier mal der geupdatete Code:
////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///        weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                //Header-Datei mit controllerspezifischen Abkuerzungen
#include <delay.h>                 
#define VIN PORTC.4
#define VOUT PINC.7
#define LED PORTB
#define BCDAnzeige PORTA
//Bekanntmachund der Methoden
void port_init(void);                  //Bekanntmachung der Methode port_init
void read(void);                       //Bekanntmachung der Methode read
void anzeige(void);                    //Bekanntmachung der Methode anzeige
void warnung(void);                    //Bekanntmachung der Methode anzeige
unsigned char r_rotate (unsigned char bitmuster);       //Bekanntmachung der Methode r_rotate 
//Vereinbarungen/Deklarationen
unsigned char wert;
unsigned char bitmuster;
int k;
int reading=0;                                 

//Hauptprogramm//

void main(void)                      
{
    port_init();                      //Port-Initialisierung 
    while (1)
    {
    read();
    }
                                        
}


void read(void)
{
    VIN=0;                           //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
        VIN=1;                       //VIN auf high
        delay_us(100);               //fuer 100us
        VIN=0;                       //VIN auf low
        delay_us(100);               //fuer 100us
        wert=r_rotate(VOUT);         //VOUT auslesen und verwendung der Methode um linkszuschieben
    }
}


unsigned char r_rotate (unsigned char bitmuster)
{
     bitmuster=bitmuster<<=1;        //linksschieben, damit MSB links steht
     bitmuster|=0x01;                //setzt das niedrigste Bit
     return bitmuster;
}

void warunung(void)
{
  if (wert<=40)                     //Wenn der Wert also die Entfernung unter 40cm liegt
  {
    LED=~0x01;                      //dann leuchted die LED an PB.0
  }
}
void anzeige(void)
{
    BCDAnzeige=reading;             //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
}

void port_init(void)
{
     DDRB=0xFF;                     //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                     //Alle Pins am PORTD sind Eingaenge
     DDRC=0x7F;                     //?
     DDRA=0xFF;                     //Alle Pins am PORTA sind Ausgaenge                   
}


Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> bitmuster=bitmuster<<=1;        //linksschieben, damit MSB links
> steht

Das solltest Du Dir nochmal genauer ansehen. In der Zeile stehen gleich 
zwei Zuweisungen.

Rotieren bedeutet außerdem nicht, daß das unterste Bit zwangsweise auf 1 
gesetzt wird.

Wenn man die vier Bits abcd rotiert, sollte nach einem Durchlauf bcda, 
nach dem zweiten cdab, nach dem dritten dabc und nach dem vierten wieder 
abcd herauskommen; bei Dir aber kommt nach dem vierten Durchlauf 1111 
heraus.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zumal in deinem 'bitmuster' ja VOUT steht, was du als 'PINC.7' 
definierst.
Setz mal PINC.7 statt bitmuster ein und du siehst, das da Unsinn 
rauskommt.

Am sinnvollsten machst du also eine extra Variable für das Ergebnis, in 
das du den Bitzustand von PINC.7 reinschiebst. Ob du da eine static in 
der Unterfunktion nimmst oder die Schleife einfach in die Lesefunktion 
verlegst, ist dabei wurscht.

Julian P. schrieb:
> das mit dem if habe ich nicht ganz verstanden, da es bei mir kein
> "bit_is_set" gibt

Zugegeben, das ist eine antiquierte Funktion aus den alten GCC Zeiten. 
Mir gings eher um die Trennung von Pin und Ergebnisvariable.

: Bearbeitet durch User
Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Am sinnvollsten machst du also eine extra Variable für das Ergebnis, in
> das du den Bitzustand von PINC.7 reinschiebst. Ob du da eine static in
> der Unterfunktion nimmst oder die Schleife einfach in die Lesefunktion
> verlegst, ist dabei wurscht.

Okay, d.h.

ich nehme z.B.
unsigned char messung;
und mache dann einfach
messung=VOUT;            //VOUT auslesen
und dann hat "messung" entweder den Wert 0 oder 1; diesen schiebe ich 
dann?So?
bitmuster=messung << 1;
Oder gibt es eine elegante Lösung um einer Variable 8 Bits nach einander 
zuzuweisen?

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> Oder gibt es eine elegante Lösung um einer Variable 8 Bits nach einander
> zuzuweisen?

Du kannst doch in meiner o.a. Funktion 'bit_is_set' einfach durch if 
(VOUT) ersetzen.
Also:
unsigned char r_rotate(void) {   // muss eigentlich l_rotate heissen
static unsigned char messung;
messung <<= 1; // schiebs nach links
if (VOUT) messung |= 0x01;
return messung; // erst nach 8 durchläufen richtig. 

Aber sinnvoll ist das nicht so richtig. Besser ist es, den ganzen Kram 
gleich in die Leseroutine zu verlegen. Also :
unsigned char read(void)
{
unsigned char result = 0;
    VIN=0;                           //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
        VIN=1;                       //VIN auf high
        delay_us(100);               //fuer 100us
        VIN=0;                       //VIN auf low
        delay_us(100);               //fuer 100us
        result <<= 1;                // schiebs nach links
        if (VOUT) result |= 0x01;    // setze das niedrigste bit, wenn VOUT high
    }
    VIN = 1; 
    delay_ms(2);
   return result;
}
Ich bin sicher kein Kenner von Codevision, aber auch dieser Compiler 
sollte 0 als false definieren und 1 als true.

: Bearbeitet durch User
Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke! Nun, die Übergabe an das Display. Die Methode sollte ja 
eigentlich nach dem die for Schleife beendet ist den Wert result tragen. 
Allerdings zeigt mein Display immer noch 00 an.
void anzeige(void)
{
    BCDAnzeige=read();                 //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
}

: Bearbeitet durch User
Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> Allerdings zeigt mein Display immer noch 00 an.

Ich habe mich gerade mal kurz über Bit Operationen mit Codevision 
belesen:
https://www.avrfreaks.net/comment/26024

Da steht, das du doch mit dem Lesen von PORTC.7 recht hattest, also doch
#define VOUT PORTC.7
gültig ist zum Lesen von Bit 7 des Port C. Schreibs also wieder um.

Die Funktion BCDAnzeige ist uns allerdings unbekannt und erwartet sicher 
ein Argument. Es könnte also sein, das sowas wie
BCDAnzeige(read()); 
richtiger wäre.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deine viele Hilfe.
Leider zeigt mein Display immer noch 00 an.
Hier nochmal ein Update:
////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///                weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                   //Header-Datei mit controllerspezifischen Abkuerzungen
#include <delay.h>                 
#define VIN PORTC.4
#define VOUT PORTC.7
#define LED PORTB
#define BCDAnzeige PORTA
//Bekanntmachung der Methoden
void port_init(void);                  //Bekanntmachung der Methode port_init
unsigned char read(void);              //Bekanntmachung der Methode read
void anzeige(void);                    //Bekanntmachung der Methode anzeige
void warnung(void);                    //Bekanntmachung der Methode anzeige

//Vereinbarungen/Deklarationen
unsigned char wert;
int k;                               

//Hauptprogramm//

void main(void)                      
{
    port_init();                        //Port-Initialisierung 
    while (1)
    {
    read();
    }
                                        
}


unsigned char read(void)
{
unsigned char result = 0;
    VIN=0;                           //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
        VIN=1;                       //VIN auf high
        delay_us(100);               //fuer 100us
        VIN=0;                       //VIN auf low
        delay_us(100);               //fuer 100us
        result <<= 1;                //schiebs nach links
        if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
    }
    VIN = 1; 
    delay_ms(2);
   return result;
}

void warunung(void)
{
  if (wert<=40)                         //Wenn der Wert also die Entfernung unter 40cm liegt
  {
    LED=~0x01;                          //dann leuchted die LED an PB.0
  }
}
void anzeige(void)
{
    BCDAnzeige=(read());                 //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
}

void port_init(void)
{
     DDRB=0xFF;                        //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                        //Alle Pins am PORTD sind Eingaenge
     DDRC=0x7F;                        //?
     DDRA=0xFF;                        //Alle Pins am PORTA sind Ausgaenge                   
}

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann sein dass es da steht, stimmt aber trotzdem nicht. Soll der 
Compiler ahnen, ob man jetzt das Portregister oder den Pin lesen will?
Das sind nun mal unterschiedliche Dinge mit unterschiedlichen 
Ergebnissen

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H.Joachim S. schrieb:
> Kann sein dass es da steht, stimmt aber trotzdem nicht.

Kann ich dir nicht sagen, bin eben kein Codevision Benutzer. Ich muss 
also glauben, was die AVRFreaks da sagen.

Man sollte mal in Ruhe testen, indem man einfach einen Pin liest und auf 
einem anderen Pin ausgibt. Das sollte nicht so schwierig sein. Erst, 
wenn klar ist, wie man Portpins setzt und liest, ist es sinnvoll, sich 
mit dem Programm weiter zu beschäftigen.
Hier ist jedenfalls das CVAVR Manual, mit dem sich der geneigte Leser 
mal beschäftigen kann:
https://www.uni-due.de/~hl271st/Lehre/SMR/cvavr_manual.pdf
Und da steht wieder, das du doch recht hast. Also PINC.7 ist richtig zum 
Lesen des Pins.

Dämliches Internet - die Hälfte von dem, was man da findet, ist Bockmist 
:-P
Ok, und BCDAnzeige ist einfach nur ein Alias für PORTA. Also sollte 
PORTA = read(); eigentlich klappen.
Entferne auch mal den Schreibfehler in der Funktion warnung(), sollte 
der Compiler eigentlich anmeckern.

: Bearbeitet durch User
Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir ist aufgefallen, dass es ja auch eventuell schlau wäre die Methode 
anzeige(); irgendwo einbauen, sonst wird die ja nie geladen und es ist 
klar, dass die nie was anzeigt. Das beste wäre doch einfach das in die 
read(); zu schreiben. Ich erhalte nur jetzt so eine nette Warnung
"Linker warning: C:\Users\vm\Desktop\entfernungssensor.c(43): function 
'read' not used in data stack usage calculation due to possible 
recursive calls"

Die BCDAnzeige zeigt immer noch 00 an aber die Methode anzeige wird 
geladen, da ich in diese LED=~0x01; als test hinzugefügt habe und es 
leuchtet nur die LED PB.0. Also so wie es soll. Nur die BCDAnzeige will 
nicht.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> Nur die BCDAnzeige will
> nicht.

Was passiert denn, wenn du z.B. mal
PORTA = 0x55;
schreibst? Da muss ja dann eine 55 im Display stehen.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also nehmen wir einmal an ich schreibe in der main
void main(void)                      
{
    port_init();                       //Port-Initialisierung 
    while (1)
    
    {
    PORTA=0x55;
    }
                                        
}
Dann erscheint auf dem Display eine 55.
Habe ich in der Main read();
void main(void)                      
{
    port_init();                       //Port-Initialisierung 
    while (1)
    
    {
    read();
    }
                                        
}
und in read()
unsigned char read(void)
{
unsigned char result = 0;
    VIN=0;                           //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
        VIN=1;                       //VIN auf high
        delay_us(100);               //fuer 100us
        VIN=0;                       //VIN auf low
        delay_us(100);               //fuer 100us
        result <<= 1;                //schiebs nach links
        if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
    }
    VIN = 1; 
    delay_ms(2);
   return result;
   anzeige();
}
und ich schreibe in die anzeige()
void anzeige(void)
{
    PORTA=0x55;                 //Wert an Anzeige ausgeben //Wert muss noch konvertiert werden!!!
}
Dann erscheint auf dem Display auch eine 55.

: Bearbeitet durch User
Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> delay_ms(2);
>    return result;
>    anzeige();

Das ist Quark, anzeige() wird nie aufgerufen, da es nach return steht.

void main(void)
{unsigned char sensor;
    port_init();                       //Port-Initialisierung
    while (1)

    {
    sensor=read();
    anzeige (sensor);
    if (sensor <  xx) LED=1;
         else LED=0;
    }

}

Ansonsten:
-du solltest dich vom 90S8515 trennen, Uralt-Chip. Klar, wenn es eine 
einmalige Spielerei ist, kann man den immer noch benutzen
-falls der MC später auch noch irgendwas anderes als messen und anzeigen 
machen soll, wirst du dich mit den Timern beschäftigen müssen. 
Insbesonders die 70ms delay sind dann übel, aber  auch die anderen delay 
sind in der Summe nicht ohne.
Wie gesagt, wenn du sonst nichts zu tun hast, kann man das auch so 
lassen, besser aber sich gar nicht erst dran gewöhnen.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H.Joachim S. schrieb:
> -du solltest dich vom 90S8515 trennen, Uralt-Chip. Klar, wenn es eine
> einmalige Spielerei ist, kann man den immer noch benutzen

Man kann aufs STK200 aber einen aktuelleren ATMega8515 in den gleichen 
Sockel stecken.

@TE: Bitte poste jetzt mal dein Programm komplett. Irgendwie habe ich 
den Eindruck, das du den Wert gar nicht an PORTA übergibst.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:

> @TE: Bitte poste jetzt mal dein Programm komplett. Irgendwie habe ich
> den Eindruck, das du den Wert gar nicht an PORTA übergibst.
////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///        weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                   //Header-Datei mit controllerspezifischen Abkuerzungen
#include <delay.h>                 
#define VIN PORTC.4
#define VOUT PINC.7
#define LED PORTB
#define BCDAnzeige PORTA
//Bekanntmachung der Methoden
void port_init(void);                  //Bekanntmachung der Methode port_init
unsigned char read(void);              //Bekanntmachung der Methode read

//Vereinbarungen/Deklarationen

unsigned char sensor;
int k;                               

//Hauptprogramm//

void main(void)                      
{
    port_init();                         //Port-Initialisierung 
    while (1)
    {
    sensor=read();
    BCDAnzeige=sensor;
  if (sensor<=40)                         //Wenn der Wert also die Entfernung unter 40cm liegt
  {
    LED=~0x01;                          //dann leuchted die LED an PB.0
  }
    }
                                        
}


unsigned char read(void)
{
unsigned char result = 0;
    VIN=0;                           //VIN auf low
    delay_ms(70);                    //fuer 70ms
    for (k=0; k<8; k++)              //wiederhole 8 mal
    {
        VIN=1;                       //VIN auf high
        delay_us(100);               //fuer 100us
        VIN=0;                       //VIN auf low
        delay_us(100);               //fuer 100us
        result <<= 1;                //schiebs nach links
        if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
    }
    VIN = 1; 
    delay_ms(2);
   return result;
}

void port_init(void)
{
     DDRB=0xFF;                        //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                        //Alle Pins am PORTD sind Eingaenge
     DDRC=0x7F;                        //?
     DDRA=0xFF;                        //Alle Pins am PORTA sind Ausgaenge                   
}
Die Anzeige ist immer noch auf 00 aber die LED leuchtet, da der Wert 
wohl unter 40 sein muss.

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mega16 geht auch, allerdings auf der anderen 40poligen Fassung.
Ich habe gerade gesehen, dass man das Teil immer noch kaufen kann :-), 
gabs vor 20 Jahren bei einer Präsentation von MSC geschenkt und es 
existierten nur ganz wenige AVR-Typen.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich habe jetzt noch mal in meinem alten ASM Programmen nachgeschaut, 
was es mit dem Sensor auf sich hat.
Mein Fehler war, das der Sensor selber OUTPUT anhebt, wenn er soweit 
ist.
Hier mal der Auszug aus dem ASM Programm:
;  make a single measurement
measure:
  cbi  PORTB,Vin        ; start sensor by pulling VIN low
  ldi  del,w70msec     ; call wozniaks wait routine 
  rcall  wozwait         ; for 70ms delay
measa:  sbis  PINB,Vout  ; wait for a high 
  rjmp  measa
  sbi  PORTB,Vin       ; set VIN high
  rcall  w100            ; wait 100µs
  cbi  PORTB,Vin       ; set VIN low
  clr  result          ; clear the place for the result
  ldi  counter,8       ; now clock out
measb:  rcall  w100            ; 100µs wait
  sbic  PINB,Vout       ; check for high on output line
  ori  result,0x01     ; its high, shift in a 1
  lsl  result          ; shift left
  sbi  PORTB,Vin       ; 
  rcall  w100
  cbi  PORTB,Vin
  dec  counter         ; count down
  brne  measb           ; not yet 8 bits
  rcall  w100            ; wait 100µs
  sbi  PORTB,Vin       ; deactivate
        rcall   w2ms            ; and let it rest 
  ret    
Also:
1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
2. Warte, bis der Sensor Output auf high zieht und takte einmal VIN mit 
100µs high und 100µs low.
3. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach
der fallenden Flanke den Output - MSB kommt zuerst.
4. Wiederhole das 8 mal.
5. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden.
Der Sensor geht in Power Off.

: Bearbeitet durch User
Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Also:
> 1. Halte VIN für min. 70ms auf Low, der Sensor macht seine Messung.
> 2. Warte, bis der Sensor Output auf high zieht und takte einmal VIN mit
> 100µs high und 100µs low.
> 3. Takte VIN mit 100µs high und anschliessend 100µs low und lese nach
> der fallenden Flanke den Output - MSB kommt zuerst.
> 4. Wiederhole das 8 mal.
> 5. Halte VIN für mindestens 1,5ms high, um den Auslesemodus zu beenden.
> Der Sensor geht in Power Off.
unsigned char read(void)
{
unsigned char result = 0;
    VIN=0;                           //VIN auf low
    delay_ms(70);                    //fuer 70ms
    if (VOUT==1)
    {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us   
       for (k=0; k<8; k++)              //wiederhole 8 mal
        {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us
            result <<= 1;                //schiebs nach links
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
        }
    }
    VIN = 1; 
    delay_ms(2);
   return result;


Also wenn ich es richtig verstanden habe, dann müsste es doch so 
aussehen. Die Anzeige zeigt keinen Wert an, da der Wert sehr 
wahrscheinlich über 0x99 ist. Somit müsste ich nun das Konvertieren 
starten.
Hier mal ein paar Werte, die ich im Internet gefunden habe:
https://docs.google.com/spreadsheets/d/1BcGZW3ky9fWrDV6F9KvR5Kfz6GdRlXk2HgEJJ3y4N1s/

Also könnte man ja einfach ein Array machen in dem man die Werte in cm 
einträgt und den Sensor Wert einfach -105. Falls der Wert unter 0 ist 
einfach auf 0 setzen:
//Vereinbarungen/Deklarationen
unsigned char  array [] = {80, 77, 74, 72, 70, 67, 65, 63, 61, 59, 57, 55,
                53, 52, 51, 49, 47, 45, 44, 43, 42, 41, 40, 39, 38, 37,
        36, 35, 34, 34, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28,
        28, 27, 27, 26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 23,
        22, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19,
        19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17,
        16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14,
        14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12,
        12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11,
        11, 11, 10, 10, 10, 10};
unsigned char entfernung;
unsigned char sensor;
int k;                               

//Hauptprogramm//

void main(void)                      
{
    port_init();                         //Port-Initialisierung 
    while (1)
    {
    sensor=read();
    entfernung=sensor-105;
    if (entfernung<0) {entfernung=0;}
    entfernung=array[entfernung];
    BCDAnzeige=entfernung;
  if (entfernung<=40)                         //Wenn der Wert also die Entfernung unter 40cm liegt
  {
    LED=~0x01;                          //dann leuchted die LED an PB.0
  }
    }
                                        
}
nur dann bekomme ich diesen Fehler "Linker error: global RAM variables 
size: 130 bytes is too large"
Also brauche ich entweder einen besseren Controller oder ich muss meinen 
Code optimieren.

: Bearbeitet durch User
Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du brauchst das array ja auch gar nicht im RAM, nur zum lesen:
flash unsigned char  array []...

Ausserdem: nimm lieber lokale Variablen.
k gehört in die read-funktion. Und warum ist gerade die int??

entfernung und sensor in die main.

entfernung=sensor-105;
    if (entfernung<0) {entfernung=0;}


das tut nicht, was du denkst dass es tun sollte (unsigned char).

Unter Project -> C-Compiler kannst du die Verteilung des RAMs 
einstellen.

: Bearbeitet durch User
Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian P. schrieb:
> if (VOUT==1)

Da arbeiten wir aber nochmal dran. Wenn VOUT 1 ist, tut er das dadrunter 
- aber wenn nicht, dann springt er drüber weg und Ende Banane.

Besser ist es also mit
while (!VOUT) {}; //warte, bis VOUT high (true) wird
zu warten.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt zwar ein Sensor, den ich auslesen kann aber es werden 
keine Werte auf dem Display angezeigt, da ich die Messwerte noch 
umwandeln muss.
Da scheiter ich gerade. Ich versuche einfach die Binär Zahl die mir der 
Sensor (hoffentlich) ausgibt in Dec umzuwandeln, damit ich das Array 
auslesen kann. Wenn ich das gleiche in Java mache klappt alles. Leider 
dies nicht so in C. Hier mal den Wandler, den ich verwende: 
https://www.sanfoundry.com/c-program-binary-number-into-decimal/
flash unsigned char  array [] =    {0x80, 0x77, 0x74, 0x72, 0x70, 0x67, 0x65, 0x63, 0x61, 0x59, 0x57, 0x55,
                                0x53, 0x52, 0x51, 0x49, 0x47, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x39, 0x38, 0x37,
                            0x36, 0x35, 0x34, 0x34, 0x33, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x29, 0x29, 0x28,
                            0x28, 0x27, 0x27, 0x26, 0x26, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23,
                            0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x19, 0x19,
                            0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
                            0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x14,
                               0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12,
                               0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
                            0x11, 0x11, 0x10, 0x10, 0x10, 0x10};
unsigned char entfernung;
int  num, binary_val, decimal_val = 0, base = 1, rem;                             

//Hauptprogramm//

void main(void)                      
{
    port_init();                         //Port-Initialisierung 

    while (1)
   {
        num=1101;
      binary_val = num;
      while (num > 0)
      {
          rem = num % 10;
          decimal_val = decimal_val + rem * base;
          num = num / 10 ;
          base = base * 2;
      }
      
        entfernung=decimal_val-105;
        if (entfernung<=0)
        {   
            entfernung=0;
        }
        else if (entfernung>=150)               //Wenn die Entfernung groesser als 150 ist, dann
        {
            entfernung=129;
        }
        entfernung=array[entfernung]; 
        BCDAnzeige=entfernung;
      if (entfernung<=0x40)                      //Wenn der Wert also die Entfernung unter 40cm liegt
      {
        LED=~0x01;                             //dann leuchted die LED an PB.0
      }                                   
    }
                                        
}
Auf meinem Display erscheint eine "12" dabei sollte eine "80" 
erscheinen. Wo liegt mein Fehler?

: Bearbeitet durch User
Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was machste denn jetzt wieder für einen Kram?
Die Idee, im array gleich die passenden Werte für BCD-Anzeige abzulegen 
und nicht den Umweg ist richtig. Es gibt nichts weiter umzuwandeln.

sensor=read();
if (sensor < xx)
   LED=1;
   else
       LED=0;    //das wieder ausschalten hast du bisher immer vergessen
if (sensor>=105)
   sensor=sensor-105;
   else
       sensor=0;
anzeige=array[sensor];

mehr isses nicht.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es wird immer "10" auf dem Display angezeigt. Die LED an PB.0 leuchtet. 
Somit muss das, was der Sensor ausgibt immer über 150 oder 10010110 
liegen. Das kann nicht sein, da das bei jedem Abstand eintritt. Egal ob 
der Sensor 80cm, 10cm, 40cm, 100cm, oder 0cm vom Objekt weg ist. Hier 
mein Code:
////////////////////////////////////////////////////////////////
////    Name:       entfernungssensor.c                     ////
////    Funktion:   Ein Abstand zwischen 10cm und 80cm wird ////
////                gemessen und an eine Anzeige            //// 
////                ausgegeben. Bei eine Entfernung von     ////
///                weniger als 40cm leuchtet eine LED      ////                                   
////    Anschlüsse: Anzeige PORTA,LED PORTB, Sensor PORTC   ////
////                                                        ////
////    Hardware:   STK200, AT90S8515, 4MHz                 ////
////    Anmerk.:    -                                       ////
////                                                        ////
////////////////////////////////////////////////////////////////
#include <90S8515.h>                   //Header-Datei mit controllerspezifischen Abkuerzungen
#include <delay.h>                
#define VIN PORTC.4
#define VOUT PINC.7
#define LED PORTB
#define BCDAnzeige PORTA
//Bekanntmachung der Methoden
void port_init(void);                  //Bekanntmachung der Methode port_init
unsigned char read(void);              //Bekanntmachung der Methode read

//Vereinbarungen/Deklarationen
flash unsigned char  array [] =    {0x80, 0x77, 0x74, 0x72, 0x70, 0x67, 0x65, 0x63, 0x61, 0x59, 0x57, 0x55,
                                0x53, 0x52, 0x51, 0x49, 0x47, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x39, 0x38, 0x37,
                            0x36, 0x35, 0x34, 0x34, 0x33, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x29, 0x29, 0x28,
                            0x28, 0x27, 0x27, 0x26, 0x26, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23,
                            0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x19, 0x19,
                            0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
                            0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x14,
                               0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12,
                               0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
                            0x11, 0x11, 0x10, 0x10, 0x10, 0x10};
unsigned char sensor;               

void main(void)                      
{
    port_init();                         //Port-Initialisierung 

    while (1)
   {
        sensor=read();
       if (sensor<=127)                            //Wenn der Wert also die Entfernung unter 40cm liegt
      {
        LED=~0x01;                             //dann leuchted die LED an PB.0
      }
        else
        {
            LED=~0x00;
        }
        sensor=sensor-105;
        if (sensor<=0)
        {   
            sensor=0;
        }
        else if (sensor>=150)               //Wenn die Entfernung groesser als 150 ist, dann
        {
            sensor=129;
        }
        BCDAnzeige=array[sensor];                             
    }
                                        
}


unsigned char read(void)
{
unsigned char result = 0;
unsigned char k;  
    VIN=0;                              //VIN auf low
    delay_ms(70);                      //fuer 70ms
    while (!VOUT)             //warte, bis VOUT high wird
    {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us   
       for (k=0; k<8; k++)               //wiederhole 8 mal
        {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us
            result <<= 1;                //schiebs nach links
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
        }
    }
    VIN = 1; 
    delay_ms(2);
   return result;
}

void port_init(void)
{
     DDRB=0xFF;                        //Alle Pins am PORTB sind Ausgaenge                                        
     DDRD=0x00;                        //Alle Pins am PORTD sind Eingaenge
     DDRC=0x7F;                        //Pin C.7 an DDRC sind Eingaenge und Pin C.6-0 sind Ausgaenge
     DDRA=0xFF;                        //Alle Pins am PORTA sind Ausgaenge                   
}
Wie ist das eigentlich, eigentlich müsste der Sensor ja immer aus und 
und an gehen und somit misst er kontinuierlich oder nicht?

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Liest du eigentlich, was man dir schreibt?

Matthias S. schrieb:
> Besser ist es also mit while (!VOUT) {}; //warte, bis VOUT high (true)
> wird
> zu warten.
Du sollst erst warten, bis VOUT H wird, dann erst die Leseorgie starten.

Julian P. schrieb:
> sensor=sensor-105;
>         if (sensor<=0)

du kannst keine unsigned-Variable auf < 0 testen. Sensor sei 104, du 
ziehst 105 ab. Ergebnis ist 0xff (was zwar -1 wäre) aber es wird als 255 
interpretiert (unsigned) und dein Tabellenzugriff läuft ins nirgendwo.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H.Joachim S. schrieb:
> Du sollst erst warten, bis VOUT H wird, dann erst die Leseorgie starten.
Wird das nicht so geschrieben?
 while (!VOUT)             //warte, bis VOUT high wird
    {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us   
       for (k=0; k<8; k++)               //wiederhole 8 mal
        {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us
            result <<= 1;                //schiebs nach links
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
        }
    }

> du kannst keine unsigned-Variable auf < 0 testen. Sensor sei 104, du
> ziehst 105 ab. Ergebnis ist 0xff (was zwar -1 wäre) aber es wird als 255
> interpretiert (unsigned) und dein Tabellenzugriff läuft ins nirgendwo.
Okay, danke.
Jetzt verwende ich ein int aber es wird nun immer "80" auf dem Display 
angezeigt.
Wie ist das eigentlich, eigentlich müsste der Sensor ja immer aus und 
und an gehen und somit misst er kontinuierlich oder nicht?

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein.
while (!VOUT);<-
.
.
.
Hat natürlich Potential zum Aufhängen des Programms, wenn der Sensor aus 
irgendeinem Grund eben kein H-Signal liefert. Da müsste dann ein timeout 
rein. Aber erst mal ist das so i.O.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned char read(void)
{
unsigned char result = 0;
unsigned char k;  
    VIN=0;                              //VIN auf low
    delay_ms(70);                      //fuer 70ms
    while (!VOUT);             //warte, bis VOUT high wird
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us   
            for (k=0; k<8; k++)               //wiederhole 8 mal
            {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us
            result <<= 1;                //schiebs nach links
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
             }
    VIN = 1; 
    delay_ms(2);
   return result;
}
Ich hoffe ich hab while (!VOUT); nun richtig implementiert. Es wird 
leider immer noch einfach "80" angezeigt.

Autor: H.Joachim S. (crazyhorse)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ui ui, habe mir gerade das Datenblatt nochmal angeschaut. Könnte sein 
dass dein Sensor tot ist.

Und mit dem Auslesen wie es Matthias beschrieben hat stimmt auch was 
nicht, es braucht 8 fallende Flanken, nicht 9.
Und wie es danach weiter geht ist irgendwie auch nicht eindeutig. Kann 
man nach dem LSB direkt in den power off gehen oder muss man den 
eingezeichneten Zinnober veranstalten? Oder ist das nur ein Beispiel für 
eine direkt folgende neue Messung?

Komisches Interface jedenfalls.

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H.Joachim S. schrieb:
> Ui ui, habe mir gerade das Datenblatt nochmal angeschaut. Könnte sein
> dass dein Sensor tot ist.
das wäre natürlich schlecht.


> Und mit dem Auslesen wie es Matthias beschrieben hat stimmt auch was
> nicht, es braucht 8 fallende Flanken, nicht 9.

also wieder so:
unsigned char read(void)
{
unsigned char result = 0;
unsigned char k;  
    VIN=0;                              //VIN auf low
    delay_ms(70);                      //fuer 70ms
    while (!VOUT);             //warte, bis VOUT high wird
            for (k=0; k<8; k++)               //wiederhole 8 mal
            {
            VIN=1;                       //VIN auf high
            delay_us(100);               //fuer 100us
            VIN=0;                       //VIN auf low
            delay_us(100);               //fuer 100us
            result <<= 1;                //schiebs nach links
            if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
             }
    VIN = 1; 
    delay_ms(2);
   return result;
}

Bringt leider nichts. Es wird immer noch "80" angezeigt.

Wie kann man denn überprüfen ob ein Sensor noch geht?

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, wenn da "absolute max. rating" steht, dürften die 5V zuviel 
gewesen sein. Vielleicht hat er deswegen nur nicht funktioniert, ist 
aber nicht kaputt gegangen.

Varianten:
-eine Diode in Reihe, vorzugsweise eine Schottky-Diode. Anode VIN, 
Katode AVR-Pin
-einen kleinen Mosfet oder auch npn benutzen, AVR-Ausgang muss dann 
umgekehrt arbeiten
-den AVR-Ausgang als open-drain benutzen.

init:
PORTC.7=0;  //L ins Portregister, interner pullup aus
DDRC.7=0;   //als Eingang, jetzt also hochohmig, Leitung führt H-Pegel 
durch pullup des Sensors

Ansteuerung:

DDRC.7=1;   //jetzt als Ausgang, L des Portregisters erscheint am Pin
DDRC.7=0;   //Ruhezustand (H)

Es steht auch nirgendwo, wie lange es dauert, bis nach fallender Flanke 
tatsächlich das Datenbit erscheint. So langsam, wie das Interface 
ansonsten arbeitet, kann man fast davon ausgehen, dass der AVR zu 
schnell ist wenn man direkt nach VIN=L einliest.
Also lieber so:

#define DDRC.7 VIN
#define active 1
#define passive 0

VIN=active;
delay_ms (70);
VIN=passive;

die Datenbits zu einem anderen Zeitpunkt lesen:

delay_us (100);
VIN=active;       //fallende Flanke
delay_us (100);   //erst danach lesen
result <<= 1;                //schiebs nach links
if (VOUT) result |= 0x01;    //setze das niedrigste bit, wenn VOUT high
VIN=passive;

Autor: Gerhard O. (gerhard_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wäre's denn, wenn vorhanden, Graf Oszillo zu Rate ziehen? Da sieht 
man doch gleich was los ist. Manchmal ist HW Vergleich ungemein 
einsichtsvoll.

Nur meine 2 cents...

Autor: Julian P. (jupa1337)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe leider kein Oszilloskop bei mir und ich denke auch nicht, dass 
ich an meinen STK200(+) eine Diode oder ein Mosfet machen kann 
geschweige denn ich besitze sowas nicht.

H.Joachim S. schrieb:

> #define DDRC.7 VIN
> #define active 1
> #define passive 0

Du meinst das eher, oder?
#define VIN DDRC.4

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H.Joachim S. schrieb:
> Und mit dem Auslesen wie es Matthias beschrieben hat stimmt auch was
> nicht, es braucht 8 fallende Flanken, nicht 9.

Die ASM Routine aus
Beitrag "Re: Sharp GP2D02 Sensor auslesen mit CodeVisionAVR und einem AT90S8515"

ist getestet und läuft mit dem GP2D02. Da sind wirklich ausführliche 
Kommentare dran und es ist auch leicht in C umzuschreiben.

H.Joachim S. schrieb:
> Naja, wenn da "absolute max. rating" steht, dürften die 5V zuviel
> gewesen sein. Vielleicht hat er deswegen nur nicht funktioniert, ist
> aber nicht kaputt gegangen.

Der alte GP2D02 läuft nominell mit 4,4V bis 7V. Max. Rating ist 10V.

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja - bei Julian läuft es eben nicht nicht und das muss ja einen Grund 
haben.

Matthias S. schrieb:
> Der alte GP2D02 läuft nominell mit 4,4V bis 7V. Max. Rating ist 10V.

Ja, Vcc und VOUT.
Aber VIN max. 3V. Steht da zumindest, wahrscheinlich nicht nur zum 
allgemeinen Rätselraten. Und wenn man da nun einen 5V-AVR-Ausgang im 
push/pull-Betrieb ohne weitere Massnahmen drannagelt, sind die 3V eben 
überschritten. Was dann passiert weiss keiner.
Unbeeindruckt davon - glaube ich nicht, dann hätten sie es nicht extra 
reingeschrieben.
Kaputt - gut möglich.
Funktioniert nur nicht - auch möglich.

Das Datenblatt und auch das Interface ist jedenfalls eine Zumutung - 
warum auch immer man so was baut.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.