Forum: Mikrocontroller und Digitale Elektronik Silabs 8051f020 AD Wandlung


von Kay (Gast)


Lesenswert?

Guten Tag miteinander,
Kennt sich jemand mit dem C8051f020 aus ? Ich habe Probleme mit einer 
AD-Wandlung welche nicht funktionniert. Wäre super wenn mir jemand eine 
Hilfestellung geben könnte.

Grüsse,
Kay

von Ralf (Gast)


Lesenswert?

> Kennt sich jemand mit dem C8051f020 aus ?
Mit SiLabs an sich hab ich schon gearbeitet, nicht mit dem F020 direkt.

> Ich habe Probleme mit einer AD-Wandlung welche nicht funktionniert.
Hm... Geh mal mit dem Auto in die Werkstatt und sag es funktioniert 
etwas nicht. Glaubst du, die Aussage reicht? Ich nicht. Denn kein 
Werkstätter wird sich von vorn bis hinten die Karre angucken, nur um 
festzustellen, dass er das Motorausbauen hätte sein lassen können, 
weil's nur das Nummernschild ist, das wackelt... ;)

> Wäre super wenn mir jemand eine Hilfestellung geben könnte.
Gerne:
- Datenblatt lesen
- SiLabs IDE runterladen & installieren
- Examples-Ordner nach dem Beispielcode durchsuchen
- Nochmal Datenblatt lesen (und mit dem Beispielcode vergleichen um zu 
verstehen was da passiert)
- Eigene Implementierung schreiben (Initialisieren, Konfigurieren, 
Interrupts bedienen, Messwert auswerten und ggf. konvertieren)
- Fertig

Reicht das? :)

Ralf

von kay (Gast)


Lesenswert?

Ralf schrieb:
> Hm... Geh mal mit dem Auto in die Werkstatt und sag es funktioniert
>
> etwas nicht. Glaubst du, die Aussage reicht? Ich nicht. Denn kein
>
> Werkstätter wird sich von vorn bis hinten die Karre angucken, nur um
>
> festzustellen, dass er das Motorausbauen hätte sein lassen können,
>
> weil's nur das Nummernschild ist, das wackelt... ;)

Ist mir schon klar das ein paar details nötig sind, wollte aber zuerst 
sichergehen das sich jemand auskennt :D

Ralf schrieb:
> - Datenblatt lesen
>
> - SiLabs IDE runterladen & installieren
>
> - Examples-Ordner nach dem Beispielcode durchsuchen
>
> - Nochmal Datenblatt lesen (und mit dem Beispielcode vergleichen um zu
>
> verstehen was da passiert)
>
> - Eigene Implementierung schreiben (Initialisieren, Konfigurieren,
>
> Interrupts bedienen, Messwert auswerten und ggf. konvertieren)

Habe ich schon gemacht, auch die Examples hab ich "studiert" diese sind 
mir aber zu komplex ( bin Anfänger )
Ich möchte es möglichst einfach halten ( ohne interrupts oder timer, 
zuerst möchte ich die basics verstehen. :))

QuellCode :

#include "C8051F020.h"

sbit Sensor11 = P2^0;                 // Definitionen Port Outputs
sbit Sensor12 = P2^1;
sbit Sensor21 = P2^2;
sbit Sensor22 = P2^3;
sbit Sensor31 = P2^4;
sbit Sensor32 = P2^5;

void Port_IO_Init()
{
        P1MDIN    = 0x00;
        P2MDOUT   = 0xFF;
        XBR0    = 0x10;
        XBR2    = 0x40;            //Crossbar enable
        WDTCN   = 0xDE;        //Watchdog disable
        WDTCN   = 0xAD;
}
void ADC_Init()
{
        ADC1CN    = 0x88;
        REF0CN    = 0x02;

}

void main(void)
{
 Port_IO_Init();
  while(1)
    {

      int ist_feuchte;

      ADC_Init();
      ist_feuchte =Feuchte();
      if (ist_feuchte > 0 )
      {
         Sensor12 = 1;
         Sensor21 = 1;
      }else
      {
      P2 = 0;
      }
    }

}


int ist_feuchte;Feuchte()
{
  int ist_feuchte;
  AMX1SL0x01;        // select ADC-Channel P1.1
  AD0BUSY=1;        // starte ADC

  while(AD0BUSY == 1){}  // Warten während Wandlung
  ADC1 = ist_feuchte;
  return ist_feuchte;
}

Ich hoffe du kannst mir noch ein bisschen mehr Hilfe geben oder einen 
Hinweis :)
Grüsse
Kay

von Patrick (Gast)


Lesenswert?

Ohne mich mit den Silabs auszukennen:

Zumindest das hier:

> ADC1 = ist_feuchte;

ist natürlich falschrum.

Ich gehe auch davon aus, dass das

> ist_feuchte

in der Zeile

> int ist_feuchte;Feuchte()

ein Copy&Paste-Fehler ist? Würde mich stark wundern, wenn das compiliert 
wird.

von kay (Gast)


Lesenswert?

Patrick schrieb:
> Copy&Paste-Fehler ist?

Jawohl da hast du recht.

Patrick schrieb:
> int ist_feuchte;Feuchte()

Habe ich getauscht , funktionniert immer noch nicht. ( Variable 
ist_feuchte = 0 in Simulation )

Gruss & danke trotzdem

von Ralf (Gast)


Lesenswert?

> Ist mir schon klar das ein paar details nötig sind, wollte aber zuerst
> sichergehen das sich jemand auskennt :D
Okay, aber selbst wenn es hier keinen gäbe der den F020 speziell kennt: 
es sind mit Sicherheit Leute da, die soviel Erfahrung mit MCUs haben, 
dass es fast egal ist, um welchen es geht. Zumal die grundlegenden 
Vorgehensweisen fast immer identisch sind.

> Habe ich schon gemacht, auch die Examples hab ich "studiert" diese sind
> mir aber zu komplex ( bin Anfänger )
> Ich möchte es möglichst einfach halten ( ohne interrupts oder timer,
> zuerst möchte ich die basics verstehen. :))
Du darfst die Examples trotzdem verwenden :)

- Ein Timer erzeugt einen Interrupt in bestimmten Abständen
- Innerhalb des Timer-Interrupts wird eine bestimmte Aktion ausgeführt 
(beispielsweise das Starten einer AD-Wandlung -> AD-Wandlungen in 
bestimmten Zeitabständen)
- Der AD-Interrupt signalisiert, wenn die Wandlung abgeschlossen ist und 
das Ergebnis abgeholt werden kann

Jaaa, so einfach ist das :)

> Ich hoffe du kannst mir noch ein bisschen mehr Hilfe geben oder einen
> Hinweis :)
Gerne, ich gebe sogar gleich mehrere Hinweise:
1) Nirgends steht was jetzt nicht tut oder wo's hapert
2) Was du gepostet hast sind C-Instruktionen. Code ist dokumentiert, 
das heisst, es steht dran, was er machen soll. Das dient dir, um zu 
beschreiben, was getan werden soll (v.a. wenn du in vier Wochen den Code 
modifizieren musst: ohne Kommentare wirst du nur schwer erkennen können, 
was du da getrieben hast), und uns um zu erkennen, was getan werden 
soll und was tatsächlich getan wird -> hilfreich für uns, um Fehler 
zu finden und für dich ebenfalls hilfreich, da du auch vergleichen 
kannst, was du tun willst und was tatsächlich getan wird...
3) Wie Patrick schon schrieb:
>> ADC1 = ist_feuchte;
> ist natürlich falschrum.
... und zweitens bezweifle ich, dass das Datenregister tatsächlich ADC1 
heisst, das würde dem was ich von SiLabs bzgl. Register 
Naming-Convention kenne widersprechen.
Heisst für mich, der Compiler müsste hier Fehler spucken.
4) Und spätestens hier:
> AMX1SL0x01;
trifft das:
> ...ein Copy&Paste-Fehler ist?
zu, denn das wird mit Sicherheit Fehler spucken.
5) Basierend auf 4) behaupte ich: Entweder der oben gezeigte 
Code...äh... die oben gezeigten Instruktionen entsprechen nicht dem, was 
du compilierst, oder du compilierst tatsächlich das, ohne zu sagen, dass 
Fehler gespuckt werden (was für uns hilfreich wäre, wenn du das sagen 
würdest, dann müssten wir nicht im Nebel stochern) :)

Versteh's nicht falsch, aber du hast geschrieben:
> bin Anfänger
deswegen trimm ich dich gleich mal drauf, wie man's richtig macht 
(sowohl mit Code als auch mit Informationsweitergabe an uns wenn was 
nicht tut)

Ralf

von Ralf (Gast)


Lesenswert?

Nachtrag:
> Variable ist_feuchte = 0 in Simulation
Der Simulator kann das nicht simulieren, der Wert wird immer 0 sein, 
wenn du im Keil nicht ein UserProgramm für die AD-Simulation schreibst.
Der wesentlich einfachere und Anfängerfreundlichere Weg ist einen 
BreakPoint an das return-statement der Mess-Funktion zu setzen und den 
Variablen-Inhalt im Watch-Fenster zu ändern.

Wieso machst du das eigentlich im Simulator, wenn man mit den 
SiLabs-MCUs doch sooooo schön direkt auf dem Controller debuggen kann?

Ralf

von Kay (Gast)


Angehängte Dateien:

Lesenswert?

Ralf schrieb:
> Jaaa, so einfach ist das :)

Sobald diese AD Wandlung läuft möchte ich in mein Programm Timer & 
Interrupts einprogrammieren, werde sicher darauf zurückkommen im Forum 
:D

Ralf schrieb:
> Code ist dokumentiert,

:

#include "C8051F020.h"                // Standart Header für 8051er

sbit Sensor11 = P2^0;                 // Definition Port2 Bit 0 = Output
sbit Sensor12 = P2^1;                 // Definition Port2 Bit 1 = Output
sbit Sensor21 = P2^2;                 // Definition Port2 Bit 2 = Output
sbit Sensor22 = P2^3;                 // Definition Port2 Bit 3 = Output
sbit Sensor31 = P2^4;                 // Definition Port2 Bit 4 = Output
sbit Sensor32 = P2^5;                 // Definition Port2 Bit 5 = Output

void Port_IO_Init()
{
        P1MDIN    = 0xC0;            // Definition P1 als 6 bit analog 
Eingang
        P2MDOUT   = 0xFF;           // Definition Port2 PushPull als 
ausgang
        XBR2    = 0x40;           //Crossbar enable
        WDTCN   = 0xDE;            //Watchdog disable
        WDTCN   = 0xAD;

}
void ADC_Init()
{
        ADC1CN    = 0x88;        // ADC1CN enable ( 8bit)
        REF0CN    = 0x02;        // Enable internal bias Generator

}
// Funktions-Prototypen
int Feuchte(void);       // Funktionsdeklaratiion AD Wandlung

void main(void)
{
 Port_IO_Init();               // Start Port Initialisationen
  while(1)                      // Damit Programm dauernd läuft
    {

      int ist_feuchte;          // Deklaration Variable

      ADC_Init();                 // Aufruf AD Wandler initialisation
      ist_feuchte =Feuchte();    // Start 8-bit AD Wandlung
      if (ist_feuchte == 0 )     // Wenn Ergebnis von Wandlung 0
      {
         Sensor12 = 1;          // Port2 Bit 0 = 1
         Sensor21 = 1;          // Port2 Bit 1 = 1
      }else
      {
      P2 = 0;                  // Wenn Ergebnis P2 = 0;
      }
    }

}


int Feuchte()                            // Unterfunktion
{
  int ist_feuchte;                      // Deklaration übergabevariable
  AMX1SL = 0x01;                  // select ADC-Channel P1.1
  AD0BUSY=1;                     // starte ADC

  while(AD0BUSY == 1){}        // Warten während Wandlung
  ADC1 = ist_feuchte;          // Resultat von 8bit Wandlung in Variable 
speichern
  return ist_feuchte;         // Variable übergeben an Hauptprogramm
}

Ralf schrieb:
> Heisst für mich, der Compiler müsste hier Fehler spucken.

Mein Ehrenwort 0 Errors , 0 Warnings

Kurz für was dass ganze ist; ich habe einen feuchtigkeitssensor 
gebastelt der mir je nach feuchte 0- 3 V liefert diese möchte ich am uC 
auswerten und dann antsprechend eine Pumpe ansteuern welche giesst. Das 
ganze nennt sich dann bewässerungsanlage :)

Ralf schrieb:
> Der Simulator kann das nicht simulieren, der Wert wird immer 0 sein,

Uvision3 kann das sehr gut simulieren habe mal eine Bild der Simulation 
gepostet.

Ralf schrieb:
> BreakPoint an das return-statement der Mess-Funktion zu setzen und den
> Variablen-Inhalt im Watch-Fenster zu ändern.

? return-statement ? ich habe leider noch nicht herausgefunden wie man 
die variablen Inhalte während der simulation anschauen kann, weisst du 
dies per zufall :) wäre froh :)

SO mein Problem besteht darin, das, dass Resultat der AD Wandlung immer 
0 ist. Also stellt sich mir die Frage was ich falsch gemacht habe... ?

Danke für die Antworten & Gruss
Kay

von Ralf (Gast)


Lesenswert?

> Sobald diese AD Wandlung läuft möchte ich in mein Programm Timer &
> Interrupts einprogrammieren, werde sicher darauf zurückkommen im Forum
Kein Problem :)
Aber rechne damit, dass du ein neues Programm schreibst, und nicht das 
alte unbedingt änderst (muss nicht sein, kann aber passieren). Warum? 
Weil man als Anfänger zwangsläufig feststellt, dass man auch gleich 
"passend" für die gewählte Programmstruktur programmieren muss. Kommt 
aber dem Lerneffekt zugute :)

>> Ralf schrieb:
> Code ist dokumentiert...
Brav ;) Jetzt sehe ich was getan wird und was getan werden sollte.

Los geht's...
Funktion Port_Init():
1
P1MDIN    = 0xC0;            // Definition P1 als 6 bit analog Eingang
Kommentar passt nicht. Dem Kommentar nach müsste es lauten:
1
P1MDIN    = 0xBF;            // Definition P1 als *BIT 6* analog Eingang
1
        WDTCN   = 0xDE;            //Watchdog disable
2
        WDTCN   = 0xAD;
macht man nicht in Port_Init(), entweder in der Main() so früh wie 
möglich, oder wenn durch die Keil-Konfiguration das interne XRAM 
gelöscht wird sogar schon in der StartUp.A51. Der Grund: Bei einigen 
SiLabs MCUs ist der Watchdog per default nach einem Reset bereits 
aktiviert. Wird nun beispielsweise das interne XRAM durch die 
StartUp.A51 gelöscht, kann das länger dauern als der Watchdog zulässt -> 
Der Controller wird sich dann ständig selber resetten.

Funktion ADC_Init():
1
       REF0CN    = 0x02;        // Enable internal bias Generator
Die Referenzspannung liegt wirklich extern an? Wenn du die interne 
verwenden willst, muss Bit 3 soweit ich sehen kann ebenfalls gesetzt 
werden.

Funktion Feuchte():
1
AMX1SL = 0x01;                  // select ADC-Channel P1.1
Oben schreibst du im Kommentar dass du P1.6 als Analog-Eingang verwenden 
willst, hier steht im Kommentar P1.1 -> Was jetzt?
Wenn du immer auf dem gleichen Kanal misst, kannst du diese Zeile auch 
in die ADC_Init() Funktion verschieben.
1
AD0BUSY=1;                     // starte ADC
Schön... Und welchen ADC? Hättest du ADC1 reingeschrieben, wär dir 
vielleicht beim Drüberlesen aufgefallen, dass du aber den ADC0 
startest :)
1
while(AD0BUSY == 1){}        // Warten während Wandlung
Dasselbe hier...
1
ADC1 = ist_feuchte;          // Resultat von 8bit Wandlung in Variable
Hiermit würdest du ins Datenregister des ADC1 schreiben, du willst aber 
von dort lesen, also:
1
ist_feuchte = ADC1;          // Resultat von 8bit Wandlung in Variable

>> Heisst für mich, der Compiler müsste hier Fehler spucken.
> Mein Ehrenwort 0 Errors , 0 Warnings
Ich ziehe meine Aussage von weiter oben zurück, du hast recht, für den 
ADC1 mit nur 8-Bit breitem Datenregister lautet die Bezeichnung des 
Datenregister tatsächlich ADC1 -> Sorry!!!
Bei den neueren MCUs von SiLabs ist die Namensgebung etwas anders :/

> Kurz für was dass ganze ist; ich habe einen feuchtigkeitssensor
> gebastelt der mir je nach feuchte 0- 3 V liefert diese möchte ich am uC
> auswerten und dann antsprechend eine Pumpe ansteuern welche giesst. Das
> ganze nennt sich dann bewässerungsanlage :)
Nettes Projekt, für einen Einsteiger graaaaad noch so an der Grenze. 
Aber das kriegen wir schon hin :)

>> Der Simulator kann das nicht simulieren, der Wert wird immer 0 sein,
> Uvision3 kann das sehr gut simulieren habe mal eine Bild der Simulation
> gepostet.
Klar, µV kann die Peripherie-Einheiten sehr wohl simulieren, ich dachte 
du meintest deinen Sensor :)
Du kannst die Eingangsspannung in dem gezeigten Fenster manuell angeben, 
das ist gut.
Dafür solltest du wie von mir erwähnt einen Breakpoint verwenden. Mach 
mal (ohne Simulator) in der Feuchte() Funktion beim Befehl "AD1BUSY=1;" 
(Achtung, AD EINS) einen Doppelklick vor die Zeilennummer (dort, wo's in 
deinem Bild grün ist). Dort sollte dann ein roter Punkt erscheinen. 
Damit hast du einen Breakpoint gesetzt. Wenn du mit RUN im Simulator das 
Programm "volle Kanne" laufen lässt, wird der Simulator stoppen, wenn er 
diesen Befehl erreicht.
Wenn du dort bist, stelle die "Testspannung" ein, und du kannst mit 
Einzelschritten durch's Programm gehen.

Siehst du die beiden Symbole mit den Händen etwas von dem 
Simulator-Symbol? Das sind die Breakpoint-Funktion, damit geht das 
Setzen/Löschen bzw. Deaktivieren (Breakpoint wird nicht gelöscht, nur 
ignoriert) auch.

> ? return-statement ? ich habe leider noch nicht herausgefunden wie man
> die variablen Inhalte während der simulation anschauen kann, weisst du
> dies per zufall :) wäre froh :)
Mache einen Rechtsklick auf eine Variable deiner Wahl, im Menü dann 
"Watch-Window" (oder so ähnlich) wählen. Evtl. musst du das Watch-Window 
noch aktivieren. Lokale Variablen, das heisst die Variablen einer 
Funktion, in der du dich grad befindest, werden automatisch im 
Watch-Window angezeigt.
Du kannst dann im Watch-Window auch durch Anklicken einer Variablen den 
Wert "magisch" ändern, also auch mal einen Fehler simulieren o.ä. Oder 
beispielsweise, wenn ein bestimmter Wert kommen sollte und das nicht 
geht, weil's eben nur simuliert wird, kannst du die Variable auf diese 
Weise beeinflussen.

Meine Frage, warum du das alles simulierst und nicht direkt auf dem 
Controller laufen lässt (du kannst direkt aus Keil auf den Controller 
zugreifen und sehen was die echte Hardware macht!!!) blieb 
unbeantwortet. Hat das einen bestimmten Grund?

> SO mein Problem besteht darin, das, dass Resultat der AD Wandlung immer
> 0 ist. Also stellt sich mir die Frage was ich falsch gemacht habe... ?
Siehst du, geht doch, das ist ne Aussage, mit der ich eingrenzen kann, 
was los ist :)
Einer der Gründe dürfte mit Sicherheit das oben erwähnte 
P1.1/P1.6-Problem plus die fehlerhafte Portkonfiguration auf Analog und 
das Starten von AD0 und nicht AD1 sein.
Aaaalso, Aufgabe: Kommentare korrigieren, Code korrigieren, neuer 
Versuch, und Feedback geben :)

Ralf

von Kay (Gast)


Lesenswert?

Ralf schrieb:
> P1MDIN    = 0xC0;            // Definition P1 als 6 bit analog EingangKommentar 
passt nicht. Dem Kommentar nach müsste es lauten:P1MDIN    = 0xBF;            // 
Definition P1 als BIT 6 analog Eingang

Ich möchte 6 bits von Port1 als Analoge Eingänge verwenden, dort kann 
ich dann auch die Sensorausgänge dranhängen um die AD Wandlungen 
durchzuführen.

Ralf schrieb:
> Die Referenzspannung liegt wirklich extern an? Wenn du die interne
> verwenden willst, muss Bit 3 soweit ich sehen kann ebenfalls gesetzt
> werden.

Möchte die Interne verwenden, vertraue dir einfach mal :)

Ralf schrieb:
> Oben schreibst du im Kommentar dass du P1.6 als Analog-Eingang verwenden
> willst, hier steht im Kommentar P1.1 -> Was jetzt?
> Wenn du immer auf dem gleichen Kanal misst, kannst du diese Zeile auch
> in die ADC_Init() Funktion verschieben.

Ich möchte P1.0 bis P1.5 als Analoge Eingänge verwenden ( 6 Sensoren ) 
mit
AMX1SL = 0x01;   wähle ich doch P1.0 wo dann die erste Messung 
durchgeführt wird ? Oder liege ich da falsch ?

Ralf schrieb:
> Dafür solltest du wie von mir erwähnt einen Breakpoint verwenden.

Super Sache danke :)

Ralf schrieb:
> Mache einen Rechtsklick auf eine Variable deiner Wahl, im Menü dann
> "Watch-Window" (oder so ähnlich) wählen. Evtl. musst du das Watch-Window
> noch aktivieren. Lokale Variablen, das heisst die Variablen einer
> Funktion, in der du dich grad befindest, werden automatisch im
> Watch-Window angezeigt.

Danke auch dies hat mir sehr geholfen :D

Ralf schrieb:
> alles simulierst und nicht direkt auf dem
> Controller laufen lässt (du kannst direkt aus Keil auf den Controller
> zugreifen und sehen was die echte Hardware macht!!!) blieb
> unbeantwortet. Hat das einen bestimmten Grund?

Ich möchte als Anfänger sichergehen dass alles läuft, nicht dass ich 
einen "seich" programmiere und so den Controller zerstöre :)

Ralf schrieb:
> P1.1/P1.6-Problem plus die fehlerhafte Portkonfiguration auf Analog und
> das Starten von AD0 und nicht AD1 sein.

Dass mit der Portkonfiguration leuchtet mir noch nicht ein . laut 
Datenblatt heisst es : AIN1 pins also function as Port 1 I/O pins, and 
must be configured as analog inputs when used as ADC1 inputs. To 
configure an AIN1 pin for analog input, set to ‘0’ the corresponding bit 
in register P1MDIN . Und das habe ich ja gemacht..

Zum starten von AD1 steht dazu im Datenblatt :

The ADC1 subsystem (8-bit ADC, track-and-hold and PGA) is enabled only 
when the AD1EN bit in the ADC1 Control register (ADC1CN) is set to logic 
1

Wenn ich aber in meinem Programm AD1EN = 1; schreibe bringt mir der 
Compiler die fehlermeldung undefined Identifier ??

Ich blicke echt nicht mehr durch......

Ralf schrieb:
> Aaaalso, Aufgabe: Kommentare korrigieren, Code korrigieren, neuer
> Versuch, und Feedback geben :)

Ich danke dir das du dir die Zeit nimmst mir zu helfen :), ich denke es 
macht Sinn denn Code nochmals zu posten wenn die oben genannten Dinge 
geklärt sind, ich habe nämlich alle deine Ratschläge befolgt und 
trotzdem habe ich immer noch " 0 " in meiner Simulation


Grüsse,
Kay

von Ralf (Gast)


Lesenswert?

> Ich möchte 6 bits von Port1 als Analoge Eingänge verwenden, dort kann
> ich dann auch die Sensorausgänge dranhängen um die AD Wandlungen
> durchzuführen.
Dann ändere den Kommentar in "Port1.x bis Port1.y als Analog-Eingang" 
oder so ähnlich.

> Möchte die Interne verwenden, vertraue dir einfach mal :)
NICHT mir, dem Datenblatt! Lies die Beschreibung zum entsprechenden 
Register bzw. zum AD-Wandler, auch mir unterlaufen Fehler!

> Ich möchte P1.0 bis P1.5 als Analoge Eingänge verwenden ( 6 Sensoren )
> mit AMX1SL = 0x01;   wähle ich doch P1.0 wo dann die erste Messung
> durchgeführt wird ? Oder liege ich da falsch ?
Hm, wenn ich's noch richtig im Kopf hab, wär das dann eher P1.1 -> auch 
hier gilt wieder: Im Zweifel das Datenblatt (und ohne Zweifel am besten 
auch)

> Ich möchte als Anfänger sichergehen dass alles läuft, nicht dass ich
> einen "seich" programmiere und so den Controller zerstöre :)
Das fängt man in der Hardware ab, indem man an den kritischen Stellen 
beim Prototyp Serienwiderstände in die Leitungen einbringt, die den 
Strom begrenzen. Diese können dann entweder dringelassen werden, wenn 
sie nicht "stören", oder wenn die SW einigermaßen stabil ist dann eben 
rausgenommen werden.
Dann kann (fast) nix schiefgehen.

> Dass mit der Portkonfiguration leuchtet mir noch nicht ein... Und das
> habe ich ja gemacht..
Jetzt isses mit 0xC0 auch in Ordnung, da jetzt auch für mich geklärt 
ist, dass es um P1.5-P1.0 und nicht P1.1/P1.6 geht. Also Entwarnung.

> Zum starten von AD1 steht dazu im Datenblatt :
> The ADC1 subsystem (8-bit ADC, track-and-hold and PGA) is enabled only
> when the AD1EN bit in the ADC1 Control register (ADC1CN) is set to logic
> 1
Nö, das heisst nur, dass der ADC aktiviert ist. Gestartet wird je nach 
Einstellung (in deinem Wunschfall) mit dem Schreiben einer 1 in AD1BUSY.
(nicht vergessen, AD1, nicht 0)

> Wenn ich aber in meinem Programm AD1EN = 1; schreibe bringt mir der
> Compiler die fehlermeldung undefined Identifier ??
Klar. Du versuchst das Flag AD1EN zu setzen, das geht aber nicht, weil 
das Register ADC1CN nicht bit-adressierbar ist -> nur SFRs, deren 
Adressen ohne Rest durch acht teilbar sind, sind bit-adressierbar.
Das heisst für dich, du musst das ganze Register modifizieren:
ADC1CN |= 0x80; //set AD1EN (bit 7)
Dasselbe für AD1BUSY:
ADC1CN |= 0x10; //set AD1BUSY (bit 4)

> Ich blicke echt nicht mehr durch......
Keine Sorge, das wird schon :)

> ich habe nämlich alle deine Ratschläge befolgt und trotzdem habe ich
> immer noch " 0 " in meiner Simulation
Eins nach dem anderen...

Verfolg in der Simulation doch mal mit, ob bei jedem vermeintlichen 
Zugriff auf den ADC1 (also die Register ADC1CN, AMX1SL, etc.) auch 
tatsächlich der angezeigte Wert des Registers verändert wird.
Zusätzlich stellst du die simulierte Spannung des Kanals mal auf ca. die 
Hälfte der Spannung.
Aber erst mal die o.g. Sachen umsetzen...

Ralf

von Kay (Gast)


Lesenswert?

Ralf schrieb:
> du musst das ganze Register modifizieren:

Habe ich erledigt bin mir aber nicht sicher ob ADC1CN |= 0x10;  in die 
Initialisation kommt, nehme an nicht weil damit wird ja der AD1 
gestartet..

Ralf schrieb:
> Keine Sorge, das wird schon :)

ich hoffs :)

Hier ist nochmals mein Programm mit den modifizierungen :D :

#include "C8051F020.h"                // Standart Header für 8051er

sbit Sensor11 = P2^0;                 // Definition Port2 Bit 0 = Output
sbit Sensor12 = P2^1;                 // Definition Port2 Bit 1 = Output
sbit Sensor21 = P2^2;                 // Definition Port2 Bit 2 = Output
sbit Sensor22 = P2^3;                 // Definition Port2 Bit 3 = Output
sbit Sensor31 = P2^4;                 // Definition Port2 Bit 4 = Output
sbit Sensor32 = P2^5;                 // Definition Port2 Bit 5 = Output


void Port_IO_Init()
{
        P1MDIN    = 0xC0;         // Definition Port1.0 bis Port1.5 als 
Analog Eingänge
        P2MDOUT   = 0xFF;        // Definition Port2 PushPull als 
ausgang
        XBR2    = 0x40;             //Crossbar enable

}

void ADC_Init()
{
  ADC1CN = 0x80;         //set AD1EN (bit 7)
        REF0CN    = 0x03;        // Enable internal Referenz Voltage
}
// Funktions-Prototypen
int  Feuchte();           // Funktionsdeklaration AD Wandlung

void main(void)
{
 WDTCN   = 0xDE;            //Watchdog disable
 WDTCN   = 0xAD;
 Port_IO_Init();                 // Start Port Initialisationen
  while(1)                        // Damit Programm dauernd läuft
    {

      int ist_feuchte;            // Deklaration Variable

      ADC_Init();                 // Aufruf AD Wandler initialisation
      ist_feuchte =Feuchte();      // Start 8-bit AD Wandlung
       if (ist_feuchte == 0 )       // Wenn Ergebnis von Wandlung 0
      {
         Sensor12 = 1;            // Port2 Bit 0 = 1
         Sensor21 = 1;            // Port2 Bit 1 = 1
      }else
      {
      P2 = 0;                    // Wenn Ergebnis>0 P2 = 0;
      }
    }

}


int Feuchte()                                // Unterfunktion
{
  int ist_feuchte;                            // Deklaration 
übergabevariable
AMX1SL=0x01;                           // Select AD Channel 1 ( AIN 1.0)
ADC1CN |= 0x10;           //set AD1BUSY (bit 4)

while(AD0BUSY == 1){}            // Warten während Wandlung
ist_feuchte = ADC1 ;             // Resultat von 8bit Wandlung in 
Variable speichern
 return ist_feuchte;            // Variable übergeben an Hauptprogramm
}

Ralf schrieb:
> also die Register ADC1CN, AMX1SL, etc.) auch
> tatsächlich der angezeigte Wert des Registers verändert wird.

Ja, die Werte werden richtig geändert also ADC1CN = 0x90, er fasst die 
Befehle zusammen wenn ich das richtig sehe :) auch AMX1SL wird richtig 
geändert...


Ralf schrieb:
> Keine Sorge, das wird schon :)
Bin ich mir nicht mehr so sicher..:\

Trotzdem danke dir & gruss :)
Kay

von Ralf (Gast)


Lesenswert?

> ADC_Init();                 // Aufruf AD Wandler initialisation
Der Aufruf sollte eigentlich einmalig reichen, beispielsweise vor oder 
nach dem Aufruf zur Portinitialisierung. Er tut dort wo er jetzt ist 
nicht weh, aber die Schleife könnte schneller durchlaufen werden).

> AMX1SL=0x01;     // Select AD Channel 1 ( AIN 1.0
Kommentar widersprüchlich: Von der Instruktion her ist es Channel 1 
(richtig) aber nicht AIN.0. Der erste Channel ist AIN.0, der zweite .1 
usw.
Schön verwirrend, gell? :)
Jedenfalls: Du hast ja P1.5-P1.0 als Analog deklariert, also vermute ich 
mal, du willst auch wirklich mit dem allerersten Channel beginnen, daher 
müsstest du auf AMX1SL = 0x00; stellen...

> Sensor12 = 1;            // Port2 Bit 0 = 1
> Sensor21 = 1;            // Port2 Bit 1 = 1
Der Kommentar passt bei beiden nicht (Bit 0 wäre Sensor11)...
Und kleiner Tipp: Du hast korrekterweise oben bereits kommentiert, 
welcher Name welchem Port entspricht. Du brauchst (und solltest) das 
nicht bei der Ansteuerung der Sensoren nochmals tun (das Bezeichnen 
welcher Port es ist), da du sonst an ALLEN Stellen im Code die 
jeweiligen Kommentare ändern müsstest. Das kann ganz schön aufwendig 
werden...

> Ja, die Werte werden richtig geändert
Guuuut :)

>> Keine Sorge, das wird schon :)
> Bin ich mir nicht mehr so sicher..:\
Doch doch, abwarten ^^
Wie ist denn jetzt der aktuelle Stand? Was tut schon und was noch nicht?

Ralf

von kay (Gast)


Lesenswert?

AD-Wandlung funktionniert.
AD1INT war der Fehler. Wenn du willst poste ich nch denn Code :)

gruss

Kay

von Ralf (Gast)


Lesenswert?

> AD-Wandlung funktionniert.
Siehst du, und du hast gezweifelt :)

> AD1INT war der Fehler. Wenn du willst poste ich nch denn Code :)
grins Ich hoffe, du konntest einiges lernen, was Code-Kommentierung 
und solche Sachen angeht :)
Hauptsache ist erstmal, dass es jetzt einigermaßen tut.
Du kannst gerne den Code posten, vielleicht hilft er ja irgendwann 
jemandem der ein ähnliches Problem hat. Aber glaub mir, dein Code wird 
noch wachsen und noch die eine oder andere Optimierung erfahren, da du 
jetzt feststellen wirst, dass du ein funktionsfähiges System hast, und 
du wirst automatisch beginnen, Optimierungen reinzubauen, da du dich 
jetzt auf den Ablauf und die Struktur konzentrieren kannst.

Ralf

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.