Forum: Mikrocontroller und Digitale Elektronik 8051, ADC, Ports und Register


von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Hallo!

Ich programmiere beruflich eine 8051 MCU von Atmel, Typ At89C51CC03.
Deren Port 1 hat 8 ADC Kanäle. Ich will davon P1.1, also Kanal 1, als 
ADC benutzen und habe demnach das entsprechende Register ADCF mit 0x02 
beschrieben.
Wenn der ADC aktiviert wird mit ADCON |= 0x20 wird allerdings der Pin 
1.0 auf 1 gesetzt. Er soll aber als Eingang dienen und daher nicht 
gesetzt werden.

Selbst das zwangsweise Setzen des Ports auf 0 mit P1_0 = 0 funktioniert 
danach nicht mehr.

Es sieht nach einem Hardwarebug aus, aber bei Atmel in den Errata-Sheets 
findet sich nichts.

Hatte jemand diesen Fehler auch schon und irgendwie gelöst? Mir fällt 
dazu momentan nichts ein. Danke schon mal.

von Ralf (Gast)


Lesenswert?

Lies dir mal den Abschnitt über "quasi-bidirektionale" Ports im 
Hardware-Manual durch. Ein 8051-Port-Pin, der als Eingang funktionieren 
soll, MUSS mit 1 beschrieben werden.

> ADCON |= 0x20
Was befindet sich vorher in dem Register?
Probier's mal mit

ADCON = 0x02
ADCON |= 0x20

Ralf

von Peter D. (peda)


Lesenswert?

Maik Staberock wrote:
> Es sieht nach einem Hardwarebug aus, aber bei Atmel in den Errata-Sheets
> findet sich nichts.

Nö, der ADC funktioniert genau so wie im Datenblatt "Routines examples" 
beschrieben.

Du solltest Dich bloß mal einigen, obs nun P1.0 oder P1.1 sein soll.

ADCF = 0x02; disabled P1.1 als digital-IO
ADCON |= 0x01; schaltet dann P1.1 zum ADC durch.


Peter

von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Ralf wrote:
> Lies dir mal den Abschnitt über "quasi-bidirektionale" Ports im
> Hardware-Manual durch. Ein 8051-Port-Pin, der als Eingang funktionieren
> soll, MUSS mit 1 beschrieben werden.
> Ralf

Jein. Es funktioniert auch so, nur dann ohne Pullup. In einer anderen 
Hardware, wo dieselbe Software drauf läuft, wo aber der ADC nicht 
genutzt und demnach nicht konfiguriert wird, funktioniert's ja.

von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Peter Dannegger wrote:
> Du solltest Dich bloß mal einigen, obs nun P1.0 oder P1.1 sein soll.
> ADCF = 0x02; disabled P1.1 als digital-IO
> ADCON |= 0x01; schaltet dann P1.1 zum ADC durch.
> Peter

Mit ADCON |= 0x20 wird zunächst nur der ADC aktiviert. Die Auswahl des 
Ports ist abhängig von einem Define und wird bei der Verwendung des ADC 
erledigt. Demnach ist P1.0 im ADCON nicht als ADC-Kanal verwendet und 
müßte Eingang bleiben und nicht gesetzt werden. Mir geht es darum, daß
ADCON |= 0x20 den Port nicht setzen dürfen sollte. ADCON = 0x20 hat 
natürlich denselben Effekt
Gut, den Port auf 1 zu setzen ist von Atmel's Seite her laut deren 
Portbeschreibung richtig, aber leider muß dann hier die Schaltung 
umdesignt werden, die den Port auf low ziehen soll, weil der Pull-up nun 
aktiv ist. Eingänge sollten keine interne Pull-ups haben, das stört nur.

von Robert W. (rweber)


Lesenswert?

Maik Staberock wrote:
> Gut, den Port auf 1 zu setzen ist von Atmel's Seite her laut deren
> Portbeschreibung richtig, aber leider muß dann hier die Schaltung
> umdesignt werden, die den Port auf low ziehen soll, weil der Pull-up nun
> aktiv ist. Eingänge sollten keine interne Pull-ups haben, das stört nur.

Stimmt nicht. Datenblatt I/O Configurations/Port 1, Port 3 and Port 
4/Figure 1.

Da steht:

Note: The internal pull-up can be disabled on P1 when analog function is 
selected.

von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Robert Weber wrote:
> Maik Staberock wrote:
>> Gut, den Port auf 1 zu setzen ist von Atmel's Seite her laut deren
>> Portbeschreibung richtig, aber leider muß dann hier die Schaltung
>> umdesignt werden, die den Port auf low ziehen soll, weil der Pull-up nun
>> aktiv ist. Eingänge sollten keine interne Pull-ups haben, das stört nur.
>
> Stimmt nicht. Datenblatt I/O Configurations/Port 1, Port 3 and Port
> 4/Figure 1.
>
> Da steht:
>
> Note: The internal pull-up can be disabled on P1 when analog function is
> selected.

Was hat das mit meinem Problem zu tun? Es geht nicht um den Port, der 
als ADC benutzt wird, es geht um den anderen. Der wird auf 1 gesetzt 
(strong pull-up) durch das Setzen von ADCON, und zwar nur, weil die 
unteren 3 Bits von ADCON sagen, der Port soll kein ADC-Kanal sein. Das 
ist unlogisch.
Ob der Pull-up aktiv sein soll und ob Eingang oder Ausgang, das sollte 
der Anwender selbst bestimmen. Denn den Pull-up danach wieder zu 
deaktivieren ist nicht so einfach.
Die Schaltung am Pin hatte vorher einen 1k Widerstand in Reihe zum auf 
Null ziehenden Signal (Schutzbeschaltung). Dieser muß diese 
Portspielerei des Prozessors nun auf 100R geändert werden, weil der 
interne Pull-up zu stark ist.

von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Leider ist es dann so, daß das Register P1 dann trotzdem noch 1 meldet, 
auch wenn der Port auf low gezogen wurde. Ist eigentlich auch kein 
Wunder, denn Setzen eines Ports funktioniert ihn logischerweise als 
Ausgang um.

von Robert W. (rweber)


Lesenswert?

Achso der andre PIN, das hab ich falsch verstanden.

Das Verhalten ist aber nicht unlogisch, sondern ganz normal fuer 
Quasi-Bidirectionale Ports. Wenn Dir das nicht gefaellt musst du die CPU 
wechseln. Es gibt auch 8051'er mit konfigurierbaren IO Ports. Die LPC9xx 
von NXP zum Bleistift.

PS: So stark ist der Pullup nun auch wieder nicht, der Port soll ja auch 
als Eingang dienen koennen. Warum kann deine Schaltung den nicht auf 0 
ziehen? Laut Datenblatt zieht der Pin gerade mal 50µA ergibt 100k, also 
nicht wirklich stark.

von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Robert Weber wrote:
> PS: So stark ist der Pullup nun auch wieder nicht, der Port soll ja auch
> als Eingang dienen koennen. Warum kann deine Schaltung den nicht auf 0
> ziehen? Laut Datenblatt zieht der Pin gerade mal 50µA ergibt 100k, also
> nicht wirklich stark.
Kann sie ja. Wie gesagt, Register P1 sagt dann trotzdem noch, der Port 
wäre 1.

Unlogisch ist es, einen Pullup für einen Eingang zu schalten. Daß Atmel 
das so macht, kann ich momentan nicht umgehen. Der Pin würde für meinen 
Fall besser funktionieren, wenn p3 nicht wäre (siehe Figure im 
Datenblatt).
Die Hardware wurde um diesen Prozessor herumdesignt, da kann man nicht 
mal eben auf einen anderen wechseln. Der CC03 wurde ja auch nicht 
einfach so ausgewählt.

von Robert W. (rweber)


Lesenswert?

Maik Staberock wrote:
> Robert Weber wrote:
>> PS: So stark ist der Pullup nun auch wieder nicht, der Port soll ja auch
>> als Eingang dienen koennen. Warum kann deine Schaltung den nicht auf 0
>> ziehen? Laut Datenblatt zieht der Pin gerade mal 50µA ergibt 100k, also
>> nicht wirklich stark.
> Kann er ja. Wie gesagt, Register P1 sagt dann trotzdem noch, der Port
> wäre 1.
>

Es kommt darau an, wie Du den Portzustand ausliest. Ich tippe mal auf 
Assembler. Die Befehle, welche den Port Latch und nicht den PIN einlesen 
stehen im Datenblatt unter "Read-Modify-Write Instructions".


> Unlogisch ist es, einen Pullup für einen Eingang zu schalten. Daß Atmel
> das so macht, kann ich momentan nicht umgehen. Die Hardware wurde um
> diesen Prozessor herumdesignt, da kann man nicht mal eben auf einen
> anderen wechseln. Der CC03 wurde ja auch nicht einfach so ausgewählt.

Ich verstehe ehrlich gesagt nicht, was dich daran so stoert. Wenn ich 
einen Port als Eingang haben will, schreibe ich eine 1 rein (ist sowieso 
der Power-On default) und gut is. Der Einzige Nachteil der 
Bidirektionalen Ports ist, dass sie nicht nach High treiben koennen. 
Wenn man das Schaltungsdesign beruecksichtigt, ist das aber (meistens) 
kein Problem.

von Maik S. (Firma: Elektro-Automatik) (mstaberock)


Lesenswert?

Ich hab's gefunden. Die Logik im Prozessor ist hier falsch.
Wenn ich mit ADCF = 0x02 nur P1.1 als ADC-Kanal festlege, dann dürften 
die unteren Bits in ADCON mit 000 nicht bestimmen, daß AN0, also P1.0, 
verwendet wird als Meßkanal. Da sich das hier nicht ausschließt, muß ich 
nur ADCON |= 0x21 setzen und es geht wieder.

von Peter D. (peda)


Lesenswert?

Maik Staberock wrote:

> Was hat das mit meinem Problem zu tun? Es geht nicht um den Port, der
> als ADC benutzt wird, es geht um den anderen.

Dann wird die Sache klarer.
Du hast ne ODER-Verknüpfung zwischen ADCF und ADCON, d.h. der Pin der in 
ADCF gesetzt ist oder in ADCON zum ADC durchgeschaltet wird, ist kein 
digital-IO mehr. Damit ist er tristate aber auch nicht mehr digital 
lesbar oder setzbar.

Ist in ADCON P1.0 ausgewählt, ist er also analog Input.
Wird nun in ADCON auf P1.1 gewechselt, ist damit P1.0 wieder normaler 
digitaler IO, da er nicht in ADCF gesetzt ist.
D.h. in dem Augenblick muß P1.0 auf Pullup oder low gehen.
Dein beobachtetes Verhalten entspricht also völlig dem Datenblatt.


> Ob der Pull-up aktiv sein soll und ob Eingang oder Ausgang, das sollte
> der Anwender selbst bestimmen.

Was der Anwender möchte, interessiert nicht, sondern was Intel 
implementiert hat und ins Datenblatt geschrieben.
Hochohmig können nur die Pins von P0 werden, da der keine Pullups hat. 
Alle anderen Ports haben immer Pullups (außer an P1 als ADC-Eingänge).


> Die Schaltung am Pin hatte vorher einen 1k Widerstand in Reihe zum auf
> Null ziehenden Signal (Schutzbeschaltung).

Das ist unsicher.
Bei High schaltet der 8051 noch einen mittleren Pullup parallel so daß 
der 1k nicht garantiert auf Low zieht.
Ist einmal Low erkannt, ist nur noch der schwache Pullup (~50µA) aktiv.

Stört der Pullup, muß man P0 verwenden.


Peter

von Gonzo (Gast)


Lesenswert?

Hier scheinen ja mal endlich paar Fachleute am Werk zu sein.

Ich benötige eine Rampe für den DAC0 oder DAC1. Es sollen alle 0.001sek 
immer höhere Spannungen von 0.1 bis 5V ausgegeben werden.

Vielleicht kann ja einer helfen

von (Gast)


Lesenswert?

helfen wobei???
sollen andere für dich kostenlos arbeiten???

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.