arm cortex m0 einsteigerfrage

Gast #2963357
Lesenswert?

Hallo Leute,

ich arbeite mich grade in die ARM contrller ein. Hab mir das LPCxpresso 
LPC1114 Board von nxp zum einarbeiten gekauft.

Auf Seite 34 ist der Schaltplan.
http://www.nxp.com/documents/other/LPCXpresso_Getting_Started_Guide.pdf

Ich wollte die LED zum blinken bringen.
Beim suchen nach Beispielen hab ich hier folgendes gefunden. 
Beitrag "Re: Einsteigerfrage zu Cortex M0 mit LPCXpresso"
1
#ifdef __USE_CMSIS
2
#include "LPC11xx.h"
3
#endif
4

5
#include <cr_section_macros.h>
6
#include <NXP/crp.h>
7

8
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
9

10
#define PinNummer 7
11

12
int main(void)
13
{
14
  SystemInit();
15

16
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
17

18
  //  Pin als Ausgang konfigurieren
19
  LPC_GPIO0->DIR  |=  (1<<PinNummer);
20

21
  int i,j;
22
  while(1)
23
  {
24
    // Pin auf 1 setzen
25
    LPC_GPIO0->MASKED_ACCESS[1<<PinNummer]= (1 << 7);
26
    for (i=0; i<=1000; i++)
27
    {
28
      for (j=0; j<=1000; j++)
29
      {
30
      }
31
    }
32
    // Pin auf 0 setzen
33
    LPC_GPIO0->MASKED_ACCESS[1<<PinNummer]= (0 << 7);
34
    for (i=0; i<=1000; i++)
35
    {
36
      for (j=0; j<=1000; j++)
37
      {
38
      }
39
    }
40
  }
41
  return 0 ;
42
}
Den Code verstehe ich zum größten Teil aber es bleiben zwei Fragen.
Was macht
1
SystemInit();
 und muss man bei
1
LPC_GPIO0->MASKED_ACCESS[1<<PinNummer]
 den Pin angeben also in meinem Fall PIN23 oder die  PIO 
Bezeichnung(Pio0_7) also 7?

Im Usermanual finde ich zwar etwas zu GPIO versteh es aber nicht ganz 
und zu SystemInit(); gibt’s überhaupt keine Aussage.
Wenn ich den LPC1114 damit programmiere passiert nichts.
Habs auch schon mit dem Oszie kontrolliert die Led leuchtet durchgehend.
Was übersehe ich?
Gast #2963392
Lesenswert?

Hallo Alex,

ich bin auch neu in die Welt der AMR eingetaucht.
in einem meiner BSP programme wird das so gelöst:

/* Macros */
#define LED1_PIN  (1<<11) (Pin Nummer des GPIO1 Ports)
#define LED1INIT LPC_GPIO1->DIR  |= (LED1_PIN)
#define LED1OFF  LPC_GPIO1->DATA |=  LED1_PIN
#define LED1ON   LPC_GPIO1->DATA &= ~LED1_PIN
#define LED1TOG  LPC_GPIO1->DATA ^=  LED1_PIN

Zur SystemInit Funktion.
Das ist bestandteil des CMSIS.
Diese Funkton steht in system_LPC11xx.c und stellt hauptsächlich den 
Systemclock ein. (CLK, PLL, Startup, usw.)
ev. findest du noch mehr wenn du nach CMSIS und SystemInit suchst.
Gast #2963467
Lesenswert?

Danke für den Hinweis,
war davor auch schon drauf. Muss mir aber was falschen runter geladen 
haben da die Beispiele nicht so gut waren. Hab jetzt ein anderes Packet, 
auf den ersten Blick scheint es besser zu passen.
Gast #2963469
Lesenswert?

>     LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = (1 << 7);
>     LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = (0 << 7);

Da sollte man besser rechts statt 7 auch PinNummer schreiben.

> Was macht
1
SystemInit();

Beim 1114 wahrscheinlich die Taktfrequenz einstellen,
das hängt aber vom Einzelfall ab.
Ggf. mußt du die Datei mit dem Code finden und dort nachsehen.
Bei größeren Systemen wird dort z.B. auch externer Speicher 
konfiguriert.

Am besten läßt du das erstmal in Ruhe oder kommentierst es aus.

>
1
LPC_GPIO0->MASKED_ACCESS[1<<PinNummer]
 den Pin angeben also in
> meinem Fall PIN23 oder die  PIO Bezeichnung(Pio0_7) also 7?

Für P0_7 sollte das so richtig sein.
Dort wird über die Adresse eine Teilmenge der Pins bestimmt,
auf die zugegriffen wird (im Beispiel genau einer).

> Im Usermanual finde ich zwar etwas zu GPIO versteh es aber nicht ganz

Das Diagram auf Seite 188 unter 12.4.1 Write/read data operation ist 
doch ganz hübsch.

Alternativ kann man auch ganz konventionell über
1
LPC_GPIO0->DATA
 auf den Port zugreifen:
1
LPC_GPIO0->DATA |= 1 << 7;
2

3
LPC_GPIO0->DATA &= ~(1 << 7);

Beide Methoden funktionieren hier mit einem LPC1114FN28.

Jürgen
#2963473
Lesenswert?

Ich würde empfehlen, sich bei ARMs solche GPIO-Bitoperationen wie
  port |= mask;
nicht erst anzugewöhnen. Dann muss man sich das nämlich später nicht 
erst wieder abgewöhnen.

Alle aktuellen ARMs besitzen irgendwelche Möglichkeiten, GPIO-Bits 
gezielt zu setzen oder zu löschen, ohne erst den vorigen Stand zu lesen. 
Das können getrennte Register für setzen/löschen sein, oder wie bei den 
LPC1100 eine Bitmaske als Teil der Adresse. Ebendies ist der Hintergrund 
von sowas wie
  LPC_GPIO0->MASKED_ACCESS[1<<PinNummer] = ~0; //setzen
  LPC_GPIO0->MASKED_ACCESS[1<<PinNummer] = 0;  //löschen

Das ist nicht nur effizienter, sondern ist auch mit Interrupts 
verträglich. Zur Begründung siehe "Hintergrund" in ARM Bitbanding. 
Wohlgemerkt, es geht mir nur um die Begründung dafür, weshalb man auf 
"port |= mask;" verzichten sollte, nicht um die dort beschriebe Methode.
#2963481
Lesenswert?

>>     LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = (1 << 7);
>>     LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = (0 << 7);
>
> Da sollte man besser rechts statt 7 auch PinNummer schreiben.

Das wirkt auf mich übermässig kompliziert und führt aufgrund der 
Umständlichkeit nur dazu, dass man es nicht verwendet. Wenn in der Maske 
bereits festgelegt wird, dass nur Bit 7 beeinflusst wird, dann kann man 
ebensogut aber kürzer und lesbarer auch gleich
       LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = ~0;
und
       LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = 0;
schreiben. Wer mag, der baut sich Konstanten SET/CLR für ~0/0:
       #define CLR 0
       #define SET (~0)
       LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = SET;
       LPC_GPIO0->MASKED_ACCESS[1 << PinNummer] = CLR;
Gast #2963555
Lesenswert?

Danke euch allen für die Hilfe,
ich selbst bin kein Fan von Bitmasken aber das ist Geschmackssache...

Nach Betrachtung der Beispiele,des UM und des Schaltplannes muss dieser 
Code doch funktionieren. Die LED müsste im Takt blinken.

Tut sie aber nicht. Habs mit Oszi Kontrolliert.

Langsam krieg ich die  Krise, beim AVR war das irgendwie einfacher.
1
#ifdef __USE_CMSIS
2
#include "LPC11xx.h"
3
#endif
4

5
#include <cr_section_macros.h>
6
#include <NXP/crp.h>
7

8
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
9

10
int main(void) {
11
  /* Enable AHB clock to the GPIO domain. */
12
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
13

14
  LPC_GPIO0->DIR |= (1<<7);   //Als Ausgang setzen
15
  
16
  while(1) {
17
    LPC_GPIO0->MASKED_ACCESS[1<<7] = (1<<7);
18
    LPC_GPIO0->MASKED_ACCESS[1<<7] = (0<<7);
19
  }
20
  return 0 ;
21
}
Gast #2963606
Lesenswert?

Lothar schrieb:
> Alex schrieb:
>> LPC_GPIO0->MASKED_ACCESS[1<<7] = (1<<7);
>> LPC_GPIO0->MASKED_ACCESS[1<<7] = (0<<7);
>
> LPC_GPIO0->MASKED_ACCESS[1<<7] = (1<<7);
> Delay(1000);
> LPC_GPIO0->MASKED_ACCESS[1<<7] = (0<<7);
> Delay(1000);

this

oder benutz gleich nen timer, um die LED zu toggeln. Vlt am Anfang 
einfach mit einer if/else.

zb. mit SysTick oder TMR32
Gast #2963649
Lesenswert?

Schau dir mal die Programmierbeispiele an, die NXP erstellt hat. Die 
sind zwar steinalt (uralte CMSIS-Version) und teilweise sollte man sich 
auch nicht drauf versteifen, da sie eben nicht versuchen den einfachsten 
Betriebsfall anzugeben, aber meist geben sie einen Einblick, was wie 
geht.

http://ics.nxp.com/support/lpcxpresso/

Du solltest auf jeden Fall direkt mit der CMSIS-Version 2.0 starten.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren