Hallo liebe Gemeinde,
hat jemand von euch vielleicht einen Beispielcode eines
LPC11C24-HalloWelt-Programms? Ich steige da als Anfänger durch die
ganzen Bibliotheken über Bibliotheken nicht durch...
Mein aktueller Versuch eine LED anzumachen (Low-Aktiv, GPIO0 3):
1
int main(void)
2
{
3
Board_Init();
4
SystemCoreClockUpdate();
5
// Initialisiere GPIO-Block
6
Chip_GPIO_Init(LPC_GPIO);
7
8
// Setze Datenrichtung des Pins
9
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 3);
10
11
LPC_GPIO->DIR |= (1UL<<3);
12
LPC_GPIO->DATA[1UL<<3] &= ~(1UL<<3);
13
14
while (1) {}
15
16
return 0;
17
}
So richtig komme ich auch nicht mit den Bibliotheken klar, weil ich
nicht verstehe, warum man nicht direkt eine Pin-/Bitzuweisung macht...
Danke euch im Voraus.
Note schrieb:> warum man nicht direkt eine Pin-/Bitzuweisung macht...
Weil man dafür das Datenblatt lesen müsste, was keiner kann, und die
Leute lieber raten wie man die Bibliotheksfunktionen nutzt.
Du kannst dir für diesen kleinen M0 die Bibliotheken komplett sparen.
Halt dich an die Doku und setze die Bits in den Registern so wie es da
steht. Dann hast du nur die Hälfte zum Lernen.
Natürlich brauchst du noch einen Startupcode und ein Linkerscript. Da
das jede IDE selber mitbringt und auch jede einen anderen Brei kocht
wäre es noch wichtig zu wissen wie deine IDE heisst.
wenn du LPCXpresso installiert hast sind da auch Beispiele drin,
ungefähr hier:
c:\NXP\LPCXpresso_8.2.2_650\lpcxpresso\Examples\LPCOpen\lpcopen_v2_00a_l
pcxpresso_nxp_lpcxpresso_11c24.zip
Über Import 'General/Exiistion Project into Workspace' einfügen.
@Johannes S.: Das war auch mein Gedanke, nur leider funktioniert es
nicht. Dachte mir auch, dass ich erst mal "blinky"-Beispiel modifiziere,
aber die LED geht eben nicht einmal an. Darum frage ich hier auch um Rat
:)
ich habe das oben genannte Beispiel auf ein LPCXpresso11C24 geflasht und
es blinkt sofort, die ist die LED nur an P0_7. Wie ich das sehe hat P0_3
auch keine Sonderfunktion, das ist eine Falle aber nur bei den SWD oder
I2C Pins.
Mit der IDE hast du doch auch einen feinen Debugger, hast du den schon
benutzt? Ist das Target auf den richtigen Prozessor eingestellt? Dann
kann man eigentlich nicht mehr viel falsch machen.
Hier hatte ich mal ein mbed Projekt für den 11C24 gepostet, auch das
sollte Plug&Play laufen:
Beitrag "Re: CAN UP - Aktor (LPC11Cxx)"
Nachtrag:
habe mal das main aus dem Beispiel gegen deinen Code getauscht und auf
P0_7 geändert, funktioniert auch.
Note schrieb:> LPCXpresso-IDE
Zum einen wird inzwischen der Nachfolger MCUXpresso empfohlen. Zum
anderen werden bei diesen GCC ARM IDE im Startup-Code undurchsichtige
Sachen gemacht. Ich habe aktuell auch das Problem, dass bei einem
LPC1700 alle Ports gehen bis auf Port 0
Da der LPC11C24 aber nur 32K Flash hat, würde ich für den Einstieg eine
professionelle IDE empfehlen, die sind kostenlos bis 32K z.B. IAR ARM.
Hier gibt es Beispiele für ein Board.
> Mein aktueller Versuch eine LED anzumachen (Low-Aktiv, GPIO0 3)
#define LED_ON() GPIO0DATA &= ~(1 << 3)
https://www.olimex.com/Products/ARM/NXP/LPC-P11C24/
LPCopen gibt es auch für IAR ARM
Lothar schrieb:> Zum> anderen werden bei diesen GCC ARM IDE im Startup-Code undurchsichtige> Sachen gemacht
Der startup code wird im Projekt angezeigt und ist bei NXP gut leserlich
in C geschrieben. Da passiert nix ominöses, es werden lediglich die data
und bss sections initialisert und vor dem main() noch SystemInit() zum
Takt einstellen aufgerufen. Wenn man im Debugger den Breakpoint auf den
Reset Handler setzt kann man da auch bequem durchsteppen.
Wenn P0 nicht funktioniert liegt es eher an den schon beschriebenen
Sonderfunktionen.
Und es gibt noch das Power Control Register PCON wo man einige
Peripherieteile erst einschalten muss, GPIO 0 ist aber per default an.
@Johannes S.: Vielen Dank für deine Hilfe, dann kann ich sowohl den
Beispiel- als auch meinen Code komplett ausschließen.
War eben auch mein Gedanke, dass es doch nicht so schwer sein kann -
irgendwas übersehe ich trotzdem. Habe es soeben spaßeshalber auf
PIO0_8/9 probiert, ebenfalls ohne Erfolg. Der LPC11Cxx lässt sich aber
flashen - also kann der ebenfalls nicht kaputt sein?
@Lothar: Hallo Lothar und danke für die Tipps. Ist die IDE wirklich
besser? Ich meine, ich finde mich in der LPCXpresso-IDE erst seit Kurzem
einigermaßen zurecht - lohnt sich der Umstieg wirklich?
Danke euch beiden, dann werde ich mal weiter suchen...
NXP hat ja die Kinetis dazugekauft und mit MCUXpresso das LPCXpresso für
diese erweitert. Es sieht alles gleich aus und LPCX Projekte werden
problemlos übernommen. Ich vermute das die Updates von GCC oder Eclipse
nur noch für MCUX gemacht werden, von daher ist der Umstieg wohl
sinnvoll.
Keil hat einen besser optimierenden Compiler (noch), gerade beim
Cortex-M0 macht das einiges aus. Aber das 32 k Limit finde ich nicht
zeitgemäss. Für 2€ bekommt man auch M0 mit 256k Flash, da würde ich
nicht versuchen auf Teufel kmmm raus zu optimieren.
und klaptt es?
Was mir noch einfällt, wie sieht dein Board aus? Wenn das ein
Minimalboard ist, hat es einen Quarz? Wenn nicht, musst du in SystemInit
den Takt auf den RC Oszi umschalten bzw. auf RC lassen weil der µC nach
Reset so startet und dann evtl. auf Quarz umgeschaltet wird. Un wenn
keiner da ist gehts nicht mehr weiter.
Nope, klappt nicht - irgendwas übersehe ich anscheinend. Das Board hat
einen externen Quarz, aber damit habe ich mich nicht beschäftigt - für
Pin an/aus brauche ich ihn nicht.
Muss man dem LPC irgenwas melden bzgl. Haupttakt? Habe angenommen, dass
er bereits mit einer Standardfrequenz hochfährt (Divider etc. sind ja
standardmäßig auf 1)
Note schrieb:> für> Pin an/aus brauche ich ihn nicht.
ja, nur das Beispiel ist für das LPCXpresso Board und das hat einen
Quarz. Das Projekt nxp_lpcxpresso_11c24_board_lib ist mit dem anderen
verlinkt (wenn du von dem LPCOpen Beispiel ansgegangen bist). Und da
wird in board_sysinit.c der Takt auf den Quarz eingeschaltet:
[QUOTE]
ja, nur das Beispiel ist für das LPCXpresso Board und das hat einen
Quarz.
[/QUOTE]
Da hast du Recht. Ich habe hier auf meinem Board einen 12MHz-Quarz, das
dürfte also weder bei der einen noch der anderen Einstellung Probleme
geben.
Was mir aber gerade aufgefallen ist - die Pullups sind standardmäßig
aktiviert, auf allen Pins. Suche mir gerade die ganzen
LPC_IOCON-Register zusammen, um die zu deaktivieren...
Johannes S. schrieb:> SystemInit() zum Takt einstellen
Genau das meine ich: wenn man das nicht nutzen will, muss man den
Startup-Code ändern. Der sollte aber nur das Nötigste machen und für
alle Projekte gleich bleiben.
Bei IAR ARM ist das Projekt erst mal leer und der LPC11C24 startet mit
dem internen Oszillator. Dann kann man alles testen und später den Quarz
zuschalten.
Lothar schrieb:> Ich habe aktuell auch das Problem, dass bei einem> LPC1700 alle Ports gehen bis auf Port 0
Und beim LPC810 habe ich in MCUXpresso das Problem, dass irgendwo:
SystemInit() ?? was mit den Waitstates gemacht wird. Und durch den
Zugriff auf Register über Pointer gehen dann Bits verloren.
In IAR ARM gibt es zudem direkte Unterstützung für die Bitregister: aus
P0_3=1 wird direkt STRB TRUE, [PIN0BASE, #3] also wie beim 8051
Bei MCUXpresso muss man das umständlich selbst machen:
volatile unsigned char *P0 = (unsigned char *) 0xA0000000;
(*(P0+3)) = 1;
@Johannes S.: Könntest du ein Minimalstprogramm hochladen, was bei dir
funktioniert? Vllt. fehlen mir irgendwelche Takteinstellungen...
Wenn nämlich auch das Programm nicht funktioniert, ist es wohl ein
kaputter Mikrocontroller....
@temp: Nun ja, damit habe ich eben weniger der in Bibliotheken
verschachtelten #define's. Aber klar, deins ist übersichtlicher.
Übrigens - wie schaltest du einzelne Pullups ab?
Note schrieb:> Nun ja, damit habe ich eben weniger der in Bibliotheken> verschachtelten #define's.
Das steht alles in einem einzigen Header: lpc11xx.h
Eigentlich braucht man auch nicht mehr. Ausser der CMSIS-Header
eventuell.
Für die PullUps sind die LPC_IOCON Register zuständig. Da kenne ich auch
keinen besseren Weg.
Beachten sollte man auch im SYSAHBCLKCTRL Register die Bits GPIO und
IOCON einzuschalten sonst wundert man sich warum das Beschreiben der
IOCON Register wirkungslos ist.
Was beim Header (lpc11xx.h) wirklich nicht so besonders ist, ist die
Tatsache, dass für die einzelnen Bits der Register keine defines
vorhanden sind. Das ist bei anderen Controllern besser gelöst. Wenn du
dir die Beispiele von NXP und auch den Quellcode ihrer eigenen Libs
ansiehst wirst du feststellen, dass die häufig auch mit Zahlen arbeiten.
Hier ein Auszug aus der gpio.c:
1
voidGPIOInit(void)
2
{
3
/* Enable AHB clock to the GPIO domain. */
4
LPC_SYSCON->SYSAHBCLKCTRL|=(1<<6);
5
LPC_IOCON->R_PIO1_1&=~0x07;
6
LPC_IOCON->R_PIO1_1|=0x01;
Es macht deshalb auch wenig Sinn deren Libs zu verwenden. Selbst wenn
man alle Header einbindet hat man auch nicht für jedes Bit eine
Definition. Dann lieber überhaupt keine und nur mit der lpc11xx.h
auskommen.
Note schrieb:> @Johannes S.: Könntest du ein Minimalstprogramm hochladen, was bei> dir funktioniert? Vllt. fehlen mir irgendwelche Takteinstellungen...> Wenn nämlich auch das Programm nicht funktioniert, ist es wohl ein
Ja, kann ich später machen. Es ist aber das o.g. Beispiel. Wenn das
schon nicht läuft solltest du mal die Hardware zeigen.
Note schrieb:> LPC_GPIO->DIR |= (1UL<<3);> LPC_GPIO->DATA[1UL<<3] &= ~(1UL<<3);
So kann das ja auch nicht gehen. Deshalb ganz oben der Tipp ins Manual
zu schauen und nicht in irgendwelche Libs.
Um das Pin 3 von Port 0 auf Ausgang zu setzen:
1
LPC_GPIO0->DIR|=(1<<3);// das UL kannst du dir hier sparen
Um das Bit zu setzen:
1
LPC_GPIO0->DATA|=(1<<3);
Oder Ausschalten:
1
LPC_GPIO0->DATA&=~(1<<3);
Dann gibt es noch die Möglichkeit ueber die Register MASKED_ACCESS die
Bits des Ports völlig unabhängig von einander zu setzen und ohne zuerst
den Port zu lesen:
Ich nehme dazu Makros da das am schnellsten geht:
temp schrieb:> Note schrieb:>> LPC_GPIO->DIR |= (1UL<<3);>> LPC_GPIO->DATA[1UL<<3] &= ~(1UL<<3);>> So kann das ja auch nicht gehen. Deshalb ganz oben der Tipp ins Manual> zu schauen und nicht in irgendwelche Libs.
Das ist nicht schön, funktioniert aber in diesem Fall weil GPIO0 die
gleiche Adresse hat. Ich hatte das Programm ja auf ein LPCXpresso Board
geladen und kann damit eine LED ein und auschalten.
Auch die LPCOpen Lib macht das nicht anderes, es ist eine Zeile inline
Code der keinen weiteren Overhead hat (nicht wie die ST HAL).
Und die PullUps haben auch nix zu melden wenn der Pin als Ausgang
konfiguriert ist: es wird ein MOSFet gegen GND oder VDD geschaltet.
Der LPC11C24 hat zwei GND und VDD Pins, sind jeweils beide
angeschlossen? Das ist soweit ich weiss auch wichtig, nicht das den
GPIOs der GND fehlt.
Für minimale Ansteuerung habe ich noch diese Seite gefunden:
https://www.eewiki.net/display/microcontroller/Getting+Started+with+NXP%27s+LPC11XX+Cortex-M0+ARM+Microcontrollers
Aber wie gechrieben, auch die NXP Beispiele funktionieren.
Hast du mal überlegt in welches Register du schreibst mit
LPC_GPIO->DATA[1UL<<3]? Jedenfalls nicht ins DATA Register zu Port 0.
Auch nicht wenn man davon ausgeht dass LPC_GPIO und LPC_GPIO0 das
gleiche ist.
temp schrieb:> Hast du mal überlegt in welches Register du schreibst mit> LPC_GPIO->DATA[1UL<<3]? Jedenfalls nicht ins DATA Register zu Port 0.
Der TO hatte aber nicht lpc1xx.h sondern gpio_11x_2.h benutzt und da
sieht die Definition so aus:
1
typedef struct { /*!< GPIO_PORT Structure */
2
__IO uint32_t DATA[4096]; /*!< Offset: 0x0000 to 0x3FFC Data address masking register (R/W) */
3
uint32_t RESERVED1[4096];
4
__IO uint32_t DIR; /*!< Offset: 0x8000 Data direction register (R/W) */
Ab jetzt bin ich raus. Jedenfalls für Fragen die mit diesen Libs
zusammen hängen. Ob die Debugger auch alle wissen wo nun genau das oder
die DATA-Register zu finden sind? Die lesen bekanntlich keine Header.
temp schrieb:> Ob die Debugger auch alle wissen wo nun genau das oder> die DATA-Register zu finden sind? Die lesen bekanntlich keine Header.
LPCXpresso und sicherlich alle normalen IDEs tun das aber, auf DATA
klicken, F3 und man ist in der Definition im richtigen headerfile.
Da das Debuggen damit wirklich einfach ist wundert es mich das es solche
Probleme beim 'blinky' gibt. Kann eigentlich nur noch ein Hardware
Problem sein.
Echt vielen Dank euch allen für die Geduld, weiß ich zu schätzen :)
lpc1xx.h habe ich eben nicht verwendet, weil die lpcopen-Beispielcodes
alle das gpio_11x_2.h benutzt hatten, vllt. steige ich noch um, sieht
für mich übersichtlicher aus.
@Johannes S.: Wenn man im LPXpresso STRG + Linksklick auf die jeweilige
Definition macht, gelangt man auch zu der jeweiligen Bibliothek, finde
ich recht angenehm :)
Das Ding will nur leider immer noch nicht. Die letzte Variante, bevor
ich mit dem Entlöten beginne, wäre, dass du einen bei dir
funktionierenden Code mit PinToggle kompilierst und mir dir .axf-Datei
zukommen lässt - dann würde ich sicher wissen, dass der gute LPC hinüber
ist.
@Jürgen Liegner, temp: Danke euch für die zahlreichen Erklärungen,
sobald das Grundgerüst läuft, werde ich die lpc1xx.h ausprobieren ;)
ok, im Anhang das .axf. Das sollte auf P0_3 und P0_7 mit ca. 12 Hz
blinken. Da ist eine einfache Zählschleife zur Verzögerung drin.
Insgesamt ist es ein Beispiel wie man es nicht machen sollte, aber
hauptsache es blinkt mal was...
Das Projekt ist in MCUXPresso erstellt, LPCX wird meckern beim Import,
aber das Update hatte ich ja schonmal empfohlen.
Und hast du schon mal versucht das im Debugger zu starten?
Note schrieb:> Echt vielen Dank euch allen für die Geduld, weiß ich zu schätzen :)
gerne, schön das mal jemand was ohne AVR und Arduino anfängt :-)
Beitrag "Re: LPC11C24 HalloWelt-Programm"
Anbei mal ein Screenshot vom Oszi, rate mal, was das bedeutet :))
Tatsächlich konnte ich das ganze Projekt nicht kompilieren, sehr wohl
aber die fertige .axf-Datei übertragen. Die PIO0_3 und PIO0_7
funktionieren (vgl. Screenshot).
Beim Kompillieren meldet er den Fehler
"Heap:Default: command not found
/bin/sh: Post: command not found"
Gut, also anscheinend funktioniert das Board und es sind irgendwelche
IDE-Einstellungen, die mir gefehlt haben...
Wie gehst du z.B. beim Erstellen eines Neuprojektes vor? Ich hatte halt
auf Neu->Project->New C-Project geklickt.
Weitere Erkenntnis: Wenn ich das "Blinky"-Beispiel modofiziere und auf
verschiedene GPIO den PinToggle weitergebe, habe ich auf manchen Pins
kein Signal (zufälligerweise auch auf den zwei Pins, auf denen ich die
Messung durchgeführt habe -.-)
Also vllt. irgendwelche Spezialfunktionen, suche die jetzt erstmal
heraus.
Glückwunsch :-)
Das Projektfile war für MCUX, für LPCX gehts auch wenn du
- .cproject von dem periph_blinky project im Texteditor öffnen
- nach 'heap and stack' suchen und diese Zeile löschen (gibt es zweimal)
Dann wird das Projekt geladen, aber mache lieber das Update auf MCUX.
Das Projekt hatte ich aus den Beispielen importiert, siehe
Beitrag "Re: LPC11C24 HalloWelt-Programm"
Das 'Introduction' Tutorial das mit installiert wird sollte man auch
erstmal durchblättern. Die IDE ist schon sehr umfangreich und der
Einstieg nicht ganz einfach.
Ein neues Projekt solltest als LPC/MCUXpresso Projekt anlegen. Beim
nackten C-Projekt fehlt dir der Startupcode und du müsstest auch eine
Warnung bekommen das 'ResetISR' nicht gefunden wurde, das dürfte
erklären das nichts lief.
So... bin dann mal auf MCUXpresso umgestiegen. Das Projekt nach der
Anleitung erstellt und sogar mein erster, hier reingestellter, Code hat
sofort funktioniert :)
Ich hätte aktuell noch zwei Fragen:
- Nach dem Flashvorgang muss ich, trotz der aktivierten Option "Reset
targen on completion", das Board resetten (oder eben die Stromzufuhr
unterbrechen). Womit könnte das zusammenhängen, dass das Board nicht
nach der Programmierung selbst resettet wird?
- Komischerweise lassen sich PIO0_8/9 immer noch nicht ansteuern. Laut
Datenblatt sind die Master-SPI (MISO/MOSI)-Pins. Haben die vllt. noch
eine Spezialfunktion, die ich übersehe?
Note schrieb:> - Komischerweise lassen sich PIO0_8/9 immer noch nicht ansteuern
wenn du das Beispielprojekt benutzt dann baut das ja auf dem LPCXpresso
board auf. Und in der nxp_lpcxpresso_11c24_board_lib ist das
board_sysinit.c, darin wird in der Initialisierung der SPI aktiviert.
Wenn du in der Pinmuxing Tabelle die Zeilen für P0_8 und P0_9
auskommentierst sollte es gehen.
Die saubere Lösung ist natürlich für ein eigenes Board auch eine eigene
board_lib zu erstellen und dann mit dem Applikations Projekt zu
verknüpfen (Properties vom Project / Project References).
Sieht für den Anfang komplizierter aus, macht aber Sinn wenn man mit
einem Board verschiedene Applikationen hat.
> - Nach dem Flashvorgang muss ich, trotz der aktivierten Option "Reset> targen on completion",
Ist am SWD auch die Reset Leitung angeschlossen? Und welches build
profile ist aktiv? Default ist Debug, da wird ein breakpoint auf main()
gesetzt.
Mein Gott, das hat tatsächlich funktioniert :D
Ich hatte das Board_Init() eigentlich auskommentiert gehabt, aber
anscheinend wird das trotzdem irgendwo ausgeführt? Im
startup_lpc(...)-Code?
So auf Anhieb finde ich den Start der SysInit() gar nicht...
Und bzgl. des Resetvorgangs:
- Reset-Leitung ist angeschlossen, mit einem Pullup.
- Build-Profil habe ich bei "Debug" belassen, weil mir der Linker beim
anderen (Release) Folgendes meldet:
Note schrieb:> Im> startup_lpc(...)-Code?
ja, richtig. Vor dem main, über SystemInit() -> Board_SystemInit().
Um den ganzen Ablauf zu sehen in Run/Debug Configurations, Debugger,
Stop on startup at: 'ResetISR' statt 'main' einstellen.
Wenn dann der Debugger gestartet wird geht es beim Reset los und man
sieht das es schon ein Leben vor dem main() gibt.
Das die Release Variante nicht übersetzt liegt wohl daran das die
verknüpften Projekte erstmal erzeugt werden müssen (auch in der Release
Version).
Gut, ich glaube es einigermaßen verstanden haben mit dem startup-Code,
werde mir wohl auch so eine recht bequeme boardInit-Bibliothek
erstellen.
Das Build[Release] hat nun ohne Fehler funktioniert, jedoch wird nach
wie vor nach dem Flachvorgang kein Reset ausgelöst - woran könnte das
liegen, muss man noch etwas beachten?