Hallo! Ich teste gerade einen ARM7-Prozessor. Prompt stehe ich vor meinem ersten Problem: Ich möchte ein Grafikdisplay ansteuern, von dem ich den 8-Bit Datenport auf z.B. P1.16 bis P1.23 gelegt habe . Kann ich diese 8 Bits mit einem einzelnen Befehl setzen? Der gesamte Port1 wird nornmalerweise über folgendes Register beschrieben: #define IOPIN1 (*((volatile unsigned long *) 0xE0028010L)) Folgendes habe ich nun gestestet: #define IOPIN1A (*((volatile unsigned char *) 0xE0028010L)) #define IOPIN1B (*((volatile unsigned char *) 0xE0028011L)) #define IOPIN1C (*((volatile unsigned char *) 0xE0028012L)) #define IOPIN1D (*((volatile unsigned char *) 0xE0028013L)) while(1) { IOPIN1C = i++; wait (); /* call wait function */ } ... wie erwartet zählt auf dem Eva-Board der Port mit den LEDs hoch. (Die LEDs hängen an P1.16-P1.23) Aber bei: while(1) { IOPIN1A = i++; wait (); /* call wait function */ } Zählt der Port mit den LEDs ebenfalls hoch, was er nicht machen dürfte. Hier sollten nur die unteren acht Bits klappern. Das gleich auch bei IOPIN1D und IOPIN1B Was ist die Erklärung dafür? Kann ich das Problem anders (elegant) lösen, oder muss ich die Read-Modyfy-Write-Lösung mit schieben usw. machen? Gruss, Holger
Die Erklärung dafür ist, daß der Prozessor keine Bytezugriffe auf das IOPIN1-Register machen kann. Jeder Zugriff ist also in Wirklichkeit ein 32-Bit-Zugriff, der auch anderes verändert. Daher ist der Schreibzugriff auf das Register recht sinnlos, wie auch das Programmierhandbuch zumindest der LPC21xx-Reihe von Philips beschreibt. Das ist aber auch gar nicht nötig - Du musst im IOSET-Register nur die zu setzenden Bits setzen und im IOCLR die zu löschenden Bits setzen. Andere Bits werden davon nicht beeinflusst. #define IO1PIN (*(volatile unsigned long *)0xe0028010) #define IO1SET (*(volatile unsigned long *)0xe0028014) #define IO1DIR (*(volatile unsigned long *)0xe0028018) #define IO1CLR (*(volatile unsigned long *)0xe002801c) //Bit 16 setzen IO1SET = 0x10000; //Bit 16 löschen IO1CLR = 0x10000; // Deinen Zähler auf Bits 16..23 ausgeben IO1SET = (i & 0xFF) << 16; IO1CLR = (~(i & 0xFF)) << 16;
Hi,
>"Das ist aber auch gar nicht nötig..."
Würde ich nicht unbedingt sagen. Durch IO1SET und IO1CLR werden die
Bits ja nacheinander gesetzt bzw. gelöscht, d.h. zwischenzeitlich steht
eine u.U. nicht gewollte Bitkombination am Port.
Gruss,
Ingo.
"Durch IO1SET und IO1CLR werden die Bits ja nacheinander gesetzt bzw. gelöscht, d.h. zwischenzeitlich steht eine u.U. nicht gewollte Bitkombination am Port" Hmm. Da hast Du recht. Wenn das ein Problem sein sollte, wird man am Read-modify-write-Zugriff auf das IO1PIN-Register nicht vorbeikommen. Zitat aus Philips-Usermanual LPC210x: "GPIO Pin Value Register (IOPIN - 0xE0028000) This register provides the value of the GPIO pins. This value reflects any outside world influence on the pins. Note: for test purposes, writing to this register stores the value in the output register, bypassing the need to use both the IOSET and IOCLR registers. * This feature is of little or no use in an application because * it is not possible to write to individual bytes in * this register." Das Usermanual der LPC211x-Reihe (Mai 04) erwähnt gar nicht erst, daß das Register beschreibbar sei.
Ist die "ungewollte" Bitkombination wirklich kritisch? Dem (G)LCD ist doch "wurscht" was am Datenport anliegt, solange Enable nicht "gestrobt" wird. Hab zumindest keine Probleme mit einem KS0107/8 GLCD an einem LPC2106. Vorgehenesweise im Prinzip wie bereits von Rufus T. F. beschrieben. Vielleicht hilfreich: http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/glcd_dcf77/index.html (zip-Archiv glcd.h/glcd.c.) HTH, Martin
Hi, @Rufus: Ich habe im Manual sogar einen Hinweis darauf gefunden, dass IOPIN read-only ist, so ein Qutasch :-) @mthomas: Beim GLCD ist es egal (läuft im übrigend inzwischen), aber es war auch eine grundsätzliche Frage. Jetzt sind ja immer mehrere Befehle zum Setzen eines Ausgangswertes erforderlich (ohne Beeinflussung anderer Bits) - aber wenn es hardwaretechnisch nicht geht..... Einen ARM-Webserver sind wir jetzt ja einen kleinen Schritt näher - zumindest haben wir ein "Hello World" vom ARM. Wir benutzen als IDE übrigends WinARM. Gruss, Ingo.
Hallo! folgende Antwort bekam ich von Philips: Ein Zugriff auf GPIOs muß immer mit 32-bit-Befehlen geschehen. Selbst wenn wie hier 8-bit-Zeiger definiert werden, führt die Hardware letztlich immer 32-bit breite Zugriffe aus. Am einfachsten kann man auf einzelne Bits über die IOCLR/IOSET-Register zugreifen. Das funktioniert auch für einzelne Bits, z.B. für die 8 LEDs: IOCLR1 = (~i & 0xFF) << 16; IOSET1 = (i & 0xFF) << 16; Wenn die Pins alle simultan schalten sollen, kann man direkt IOPIN1 beschreiben, dann werden allerdings immer alle als Ausgang geschalteten Pins gleichzeitig beschrieben.Hier ist die beste Lösung ein Shadow-Register im RAM zu verwenden, dort die Bit-Manipulationen vorzunehmen, und am Schluß diese Register nach IOPIN zu schreiben. Gruss, Holger
Das IOSET Register ist rücklesbar und enthält immer die Ausgangswerte, daher kann man dieses als Shadow nehmen: #define MASK 0xFF0000L // 3. Byte IOPIN1 = IOSET1 & ~MASK | (daten<<16) & MASK; Dürfte vom erzeugten Code sogar kürzer und schneller sein. Ich habe z.B. das Problem, mehrere schnelle 12Bit DACs zu setzen, damit gelöst. Ein ungleichzeitiges Setzen und Löschen hätte zu Spannungssprüngen geführt. Die Aussage "This feature is of little or no use" ist also absoluter Schwachsinn. Peter
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.