Forum: Mikrocontroller und Digitale Elektronik Ports setzen beim ARM7


von Holger B. (Gast)


Lesenswert?

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

von Rufus T. Firefly (Gast)


Lesenswert?

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;

von Ingo B. (Gast)


Lesenswert?

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.

von Rufus T. Firefly (Gast)


Lesenswert?

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

von mthomas (Gast)


Lesenswert?

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

von Ingo B. (Gast)


Lesenswert?

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.

von Holger B. (Gast)


Lesenswert?

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

von peter dannegger (Gast)


Lesenswert?

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