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