Hallo, ich versuche mich gerade in ein LPC 1768 einzuarbeiten. Leider verstehe ich nicht ganz wie ich in ein Register schreibe um ein PIN auf z.b. auf High zusetzen. Bei den AVR's war es irgendwie einfach zu verstehen und nachvollzuziehen. z.B: DDRD = 0x00; /* alle Pins von Port D als Eingang */ PORTD = 0xff; /* interne Pull-Ups an allen Port-Pins aktivieren */ aber bei denn ARM verstehe ich es irgendwie nicht.
Eigentlich genauso, nur das es nicht DDRD usw. heißt. Kommt auf die Headerdatei drauf an. Lade dir mal http://www.lpcware.com/content/nxpfile/lpcopen-software-development-platform-lpc17xx-packages herunter. Und schau mal generell nach LPCOpen.
Es geht genauso wie beim AVR auch: Datenblatt lesen. Zu den LPC's gibt es die in sehr ausführlich... Oliver
Ich hab das Datenblatt mir angeschaut. Aber irgendwie scheint das doch anders zu sein mit dem beschreiben. Wenn ich es so z.b. versuche: FIO2DIR=0x0001; FIO2SET=0x0001; bekomme ich ein Fehler. ich hab jetzt ein Beispiel aus dem Internet versucht was zwar funktioniert ich es aber nicht nachvollziehen kann. #define LED (1 << 18) … int main (void) { … LPC_GPIO1->FIODIR |= LED; //aktiviere LED-Ausgang … }
Schau dir zunächst mal die prozessorspezifischen Header an. Warum die das so machen, wie sie es machen, ist zwar eine berechtigte Frage, aber die Antwort lautet halt: Ist einfach so. Was von dem, was du nicht dann immer noch nicht nachvollziehen kannst, steht nicht in deinem C-Buch? Oliver
Im Standard-Header lpc17xx.h ist der Zugriff auf die Register über structs realisiert. Wahrscheinlich ist dir das nicht geläufig. Man macht sich dabei die Tatsache zu Nutze, dass die Register für die jeweiligen Hardware-Blöcke im Controller (z.B. GPIO oder UART) unmittelbar nacheinander im Adressraum liegen, eben wie Variablen einer struct. Das hat den Vorteil, dass man beispielsweise für die 4 GPIO-Ports nicht jedes Register einzeln mit Adresse definieren muss. Stattdessen definiert man bloß ein einziges mal das "Layout" der Register für einen GPIO-Block allgemein als struct und braucht dann nur noch die "Startadressen" der 4 Blöcke zu hinterlegen. Mal ein Beispiel aus dem Header für die drei I2C-Blöcke des μC:
1 | // Als erstes die allgemeine Definition der struct für einen I2C-Block
|
2 | typedef struct |
3 | {
|
4 | __IO uint32_t I2CONSET; |
5 | __I uint32_t I2STAT; |
6 | __IO uint32_t I2DAT; |
7 | |
8 | // usw...
|
9 | |
10 | } LPC_I2C_TypeDef; |
11 | |
12 | // ...
|
13 | // Jetzt kommen die Startadressen der drei Blöcke
|
14 | #define LPC_I2C0_BASE (LPC_APB0_BASE + 0x1C000)
|
15 | #define LPC_I2C1_BASE (LPC_APB0_BASE + 0x5C000)
|
16 | #define LPC_I2C2_BASE (LPC_APB1_BASE + 0x20000)
|
17 | |
18 | // ...
|
19 | // Und anschließend die "Verknüpfung" - Hier steht im Prinzip:
|
20 | // Interpretiere die Speicherstellen LPC_I2C0_BASE bis LPC_I2C2_BASE
|
21 | // als Zeiger auf structs vom Typ LPC_I2C_TypeDef
|
22 | #define LPC_I2C0 ((LPC_I2C_TypeDef *) LPC_I2C0_BASE )
|
23 | #define LPC_I2C1 ((LPC_I2C_TypeDef *) LPC_I2C1_BASE )
|
24 | #define LPC_I2C2 ((LPC_I2C_TypeDef *) LPC_I2C2_BASE )
|
Dadurch kann man dann im Code über LPC_I2C0->I2STAT auf das Statusregister vom I2C-Block 0 zugreifen. Die Adresse wird dann vom Compiler indirekt berechnet (Startadresse des Blocks LPC_I2C0 + 4 Byte Offset). Ansonsten ist die Verwendung exakt so wie bei den Registerdefinitionen aus dem AVR-Bereich.
jo schrieb: > LPC_GPIO1->FIODIR |= LED; für den Port1 wird im DIR-Register der als LED definierte Pin gesetzt das entspricht beim AVR #define LED 1 DDRA |= LED; Das ganze erschließt sich anhand der lpc17xx.h in der veralteten lpc176x.h waren Register so definiert: #define FIO1DIR (*(volatile uint32_t*)0x2009C020) Da konnte man das Reguister tatsächlich mit FIO1DIR=0x0001; ändern. Das war m.E. besser und einfacher. es geht aber auch bei den Stucturen immer darum, in dem Register 0x2009C020 bestimmte Bits zu setzen.
Ich weiß noch, am Anfang bin ich auch drüber gestolpert. Ist aber ganz einfach: #define LED (1 << 18) bedeutet ja, dass Bit 18 gesetzt ist, die anderen sind Null, man könnte statt LED auch schreiben: 0x00020000 (hab's jetzt hoffentl. nicht falsch gezählt). LPC_GPIO1->FIODIR |= LED; ist also LPC_GPIO1->FIODIR |= 0x00020000; oder anders geschrieben LPC_GPIO1->FIODIR = LPC_GPIO1->FIODIR | 0x00020000; Das Bit setzt im Richtungsregister FIODIR (Eingang/Ausgang) von GPIO-Port 1 eine '1'. Das Pin wird damit zum Ausgang.
Mir ist mehr das Zeichen -> nicht ganz klar. Also LPC_GPIO1->FIODIR.
In einem Buch hatte ich gelesen, ist schon ein paar Jahre her: "Bei dem Thema Pointer gehen selbst hartgesottene Programmierer erst mal zum Tee-Automaten." - Fand ich ganz witzig. Damit hat es zu tun. Schau mal in die LPC17xx.h ganz unten. Dort ist LPC_GPIO1 als Pointer deklariert, zB. #define LPC_GPIO1 ((LPC_GPIO_TypeDef *) LPC_GPIO1_BASE ) Von da aus kann man sich nach oben hangeln zu LPC_GPIO1_BASE und zur Definition der Struktur LPC_GPIO_TypeDef. Da steht auch das FIODIR drin. In C gibt es die abgekürzte Schreibweise für Zugriffe auf Struktur-Elemente über Pointer, das ist der Zeiger auf ein Struktur-Element '->'. http://openbook.galileocomputing.de/c_von_a_bis_z/021_c_dyn_datenstrukturen_001.htm#ix0cd2389809be2a6e4c1b84329ffa8439 an dieser Stelle ist es zB. erklärt. Geht aber nur bei Pointern. Ein paar mal gemacht, und man denkt nicht mehr drüber nach.
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.