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