Forum: Mikrocontroller und Digitale Elektronik c++ programmierung µc


von Bernd S. (mms)


Lesenswert?

Hallo,

ich möchte meinen ersten mikrocontroller programmieren - leider ist es 
schon ein ARM7, allerdings in einer einfachen schaltung - sprich als 
erstes ziel hab ihc mir gesetzt, die serielle schnittstelle zum leben zu 
erwecken (damit ich mit im hyper terminal sachen ausgeben kann).

Wie sieht die prinzipielle Struktur von so einem Programm aus - am 
anfang muss ich ein startup-file haben, in dem nach einem reset ständig 
alle ports etc. richtig geschalten werden und wird hier dann auch gleich 
die main routine aufgerufen? die main routine besitzt wahrscheinlich 
keinen return-wert, oder (weil dieser an niemanden zurückgegeben werden 
kann)?

Wie spreche ich das externe Flash z.B. an? oder einzelne Ports? Muss ich 
hier PortB als variable definieren? Kennt jmd. gute seiten, in denen 
erklärt wird wie man am besten mit c oder besser c++ einen 
mikrocontroller programmiert bzw. welche strukturen man einhalten muss?

Bernd

von Peter D. (peda)


Lesenswert?

Bernd Schuster wrote:
> ich möchte meinen ersten mikrocontroller programmieren - leider ist es
> schon ein ARM7, allerdings in einer einfachen schaltung

Naja, mit externen Flash drangepappt ist das keine einfache Schaltung 
mehr, da ist schon ne ganze Menge Holz auf dem Board. Den Schaltplan 
hast Du doch  und weißt ihn zu lesen?


> Wie sieht die prinzipielle Struktur von so einem Programm aus

Du mußt auf nichts Rücksicht nehmen, alles ist erlaubt.
Strukturier Dein Programm ganz so, wie es Dir gefällt.
Es muß eine main-Funktion drin stehen, das ist alles.


> - am
> anfang muss ich ein startup-file haben, in dem nach einem reset ständig
> alle ports etc. richtig geschalten werden

Nö, das Startup kümmert sich nur um die Compilersachen (Stack, 
Interruptvertoren, Variablen initialisieren)

Wenn Du Ports verwenden willst, mußt Du Dich selber drum kümmern.


> und wird hier dann auch gleich
> die main routine aufgerufen? die main routine besitzt wahrscheinlich
> keinen return-wert, oder (weil dieser an niemanden zurückgegeben werden
> kann)?

Main darf nie enden (Endlos-Schleife).


> Wie spreche ich das externe Flash z.B. an? oder einzelne Ports?

ARM ist nicht gleich ARM, ohne genaue Typangabe kann keiner was dazu 
sagen.

Die ARM von NXP haben z.B. das lustige Feature, daß es für die Ports 
getrennte Setz- und Löschregister gibt.

Du mußt also den Schaltplan und das Datenblatt (Usermanual) Deines ARM 
zur Hand nehmen.

Und da beginnt dann auch der Unterschied zu nem AVR-MC. Beim AVR ist die 
Beschreibung noch handlich, beim ARM wirst Du förmlich erschlagen (über 
tausend Seiten auf viele PDFs verteilt).

Richtig lustig wirds aber erst, wenn Du Interrupts programmierst (wird 
ne ganze Weile dauern).


> Muss ich
> hier PortB als variable definieren?

Ich kenne die ARM nur mit numerierten Ports (PORT0, Port1 usw.).
Z.B. bei den ST-ARM werden die Ports über Pointer mit Offset 
angesprochen, sonst macht sich der ARM tot mit ständig neue Adressen 
laden. Sieht allerding nicht sehr leserlich aus. Ist ne Sache, wie der 
Compilerhersteller die Headerfiles angelegt hat.


Peter

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Hallo Bernd,

hat es einen realistischen Grund, dass Du gleich mit so einem starken 
Controller anfangen willst? Wenn Du Dich uebernimmst kannst Du leicht 
das Interesse verlieren, gerade am Anfang.

Michael

von Bernd S. (mms)


Lesenswert?

>Den Schaltplan hast Du doch  und weißt ihn zu lesen?

das Board hab ich zum Testen bekommen - also hardware-technisch dürfte 
es auf jeden fall funktionieren.

>hat es einen realistischen Grund, dass Du gleich mit so einem starken
>Controller anfangen willst? Wenn Du Dich uebernimmst kannst Du leicht
>das Interesse verlieren, gerade am Anfang.

mit einem Atmega8 hab ich schon so ganz kleine standard-sachen 
programiert in assembler (wie Leds an aus, Taster mit speziellen 
funktionien wie LEDs leuchten, und Interrupts - aber alles ganz basic 
(der Code war stets ca. ne seite auf monitor)...  jetzt möchte ich mich 
mit diesem ARM7 Board vertraut machen (ganz langsam und step by step)... 
also zuerst einmal die LEDs ansprechen und RS232 ansprechen (das wäre 
super, wenn ich da schon mal dann auch einen rückkanal hätte, damit ich 
sehe was ich mache...

deshalb suche ich auch nach praktischen beispielen, an denen ich lernen 
kann (also muss nicht auf den prozessor zugeschnitten sein, sondern mir 
nur zeigen wie ich was anspreche (blöd ausgedrückt - also z.B. wie 
abstrakt ich schon mit C oder C++ gegenüber Assembler sein darf bzw. wie 
ich die Register ansprechen muss (oder ob ich schon eine ebene darüber 
arbeite).. vielleicht hat jmd. einen bsp-code für mich, in dem nur 
vielleicht eine led an einem port aktiviert wird und auf ein paar 
register oder speicherstellen zugegriffen wird bzw. Werte gespeichert 
werden (gut dokumentiert)... ich glaub, dadurch könnte ich mir schon 
einiges ablesen, wie ich arbeiten muss... auch so der Aufbau - eine 
Main-Funktion und (in C), dann viele einzelne Funktionen, die nach 
einander oder bei bestimmten (Interrupts) Zuständen, aus Main aufgerufen 
werden --> dann muss ja alles wichtige gespeichert werden und nach der 
Interrupt-Methode wieder aus dem Speicher geholt werden...

Bernd

von Peter D. (peda)


Lesenswert?

Bernd Schuster wrote:
>>Den Schaltplan hast Du doch  und weißt ihn zu lesen?
>
> das Board hab ich zum Testen bekommen - also hardware-technisch dürfte
> es auf jeden fall funktionieren.

Um das Funktionieren geht es nicht, sondern darum, zu erkennen, wie und 
in welche Adreßbereiche der Flash und sonstige Peripherie gemappt ist, 
wie man in den Bootloader kommt usw.


> jetzt möchte ich mich
> mit diesem ARM7 Board vertraut machen (ganz langsam und step by step)...
> also zuerst einmal die LEDs ansprechen und RS232 ansprechen

Da dürfte die beste Quelle das Exampleverzeichnis Deiner 
Tools-Installation zu dem Board sein.

Ich nehme mal an, das Board war nicht nackt, sondern ne CD dazu und 
vielleicht sogar ein JTAG-USB-Debugger.


Es nimmt Dir auch keiner übel, wenn Du endlich mal damit rausrücken 
würdest um welchen ARM7 (Hersteller, Bezeichnung) es überhaupt geht.

Solange das keiner weiß, können die Antworten nur abstrakt sein.


Peter

von Gast (Gast)


Lesenswert?

anbei mal eine ARM Code den ich in der FH geschrieben hab...
1
#include <stdio.h>
2
3
/* define segments in terms of IO lines */
4
#define SEG_A (1 << 10)
5
#define SEG_B (1 << 11)
6
#define SEG_C (1 << 12)
7
#define SEG_D (1 << 13)
8
#define SEG_E (1 << 14)
9
#define SEG_G (1 << 15)
10
#define SEG_F (1 << 16)
11
12
#define DISP_0 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F)
13
#define DISP_1 (SEG_B | SEG_C)
14
#define DISP_2 (SEG_A | SEG_B | SEG_G | SEG_E | SEG_D)
15
#define DISP_3 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G)
16
#define DISP_4 (SEG_B | SEG_C | SEG_F | SEG_G)
17
#define DISP_5 (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G)
18
#define DISP_6 (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
19
#define DISP_7 (SEG_A | SEG_B | SEG_C)
20
#define DISP_8 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
21
#define DISP_9 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G)
22
#define DISP_A (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G)
23
#define DISP_B (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
24
#define DISP_C (SEG_A | SEG_D | SEG_E | SEG_F)
25
#define DISP_D (SEG_B | SEG_C | SEG_D | SEG_E | SEG_G)
26
#define DISP_E (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G)
27
#define DISP_F (SEG_A | SEG_E | SEG_F | SEG_G)
28
29
/*Funktion zur Intialisierung der LEDs und Sieben-Segment
30
  Ãœbergabewerte:  -keine-
31
  Rückgabewerte:  -keine-*/
32
void io_init(volatile unsigned int *);
33
34
/*Funktion um die LEDs auf den übergebenen Wert setzen
35
  Ãœbergabewerte:  char  wert  0-0xF
36
  Rückgabewerte:  -keine-*/
37
void leds(char wert,volatile  unsigned int *);
38
39
/*Funktion zum Einlesen der Schalter
40
  Ãœbergabewerte:  -keine-
41
  Rückgabewerte:  char  0-0xF*/
42
char schalter(volatile unsigned int *);
43
44
/*Funktion zum Setzen der Siebensegmentanzeige
45
  Ãœbergabewerte:  char  wert 0-0x0F
46
  Rückgabewerte:  -keine-*/
47
void segment(char wert,volatile  unsigned int *);
48
49
50
static const unsigned numeric_display[] = { DISP_0, DISP_1, DISP_2, DISP_3, DISP_4, DISP_5, DISP_6,
51
      DISP_7, DISP_8, DISP_9, DISP_A, DISP_B, DISP_C, DISP_D, DISP_E, DISP_F };
52
      
53
int main (void)
54
{
55
  volatile unsigned int *z_iopmod,*z_iopdata;
56
  char i;
57
  
58
  z_iopdata=(volatile unsigned *)(0x03FF0000 + 0x5008);
59
  z_iopmod=(volatile unsigned *)(0x03FF0000 + 0x5000);
60
  
61
  io_init(z_iopmod);
62
/*10 mal Hallo Welt ! auf der Konsole ausgeben*/
63
  for(i=0;i<10;i++)    
64
  {
65
    printf("Hallo Welt !");
66
    fflush(stdout);
67
  }
68
/*Alle möglichen Kombinationen auf LED und 7-Segmentanzeige ausgeben*/
69
  for(i=0;i<16;i++)
70
  {
71
    leds(i,z_iopdata);
72
    segment(i,z_iopdata);
73
  }
74
/*SChalter einlesen und auf LED und 7-Segmentanzeige ausgeben*/
75
  while(1)
76
  {
77
    i=schalter(z_iopdata);
78
    leds(i,z_iopdata);
79
    segment(i,z_iopdata);
80
  
81
  }
82
83
  return 0;
84
}
85
86
void io_init(volatile unsigned int *z_iopmod)
87
{
88
  *z_iopmod = ((1<<4)|(1<<5)|(1<<6)|(1<<7));
89
  // wo LEDS dran als Output
90
  *z_iopmod |= ((1<<10)|(1<<11)|(1<<12)|(1<<13)|(1<<14)|(1<<15)|(1<<16));
91
  // wo Sieben-Segment dran als Output
92
}
93
94
void leds(char wert,volatile  unsigned int *z_iopdata)
95
{
96
  wert &= (1|(1<<1)|(1<<2)|(1<<3));
97
  //schneide Wert passend zu
98
  *z_iopdata &=~ ((1<<4)|(1<<5)|(1<<6)|(1<<7));
99
  //lösche alten Wert
100
  *z_iopdata |= wert<<4;
101
  //schreibe Wert von 0 bis 0xF auf LEDs
102
}
103
104
char schalter(volatile unsigned int *z_iopdata)
105
{
106
  return (*z_iopdata & (1|(1<<1)|(1<<2)|(1<<3)));
107
  //hole Wert der Schalter und maskiere den Rest
108
}
109
110
void segment(char wert,volatile  unsigned int *z_iopdata)
111
{
112
  wert &= (1|(1<<1)|(1<<2)|(1<<3));
113
  //schneide Wert passend zu
114
  *z_iopdata &=~  ((1<<10)|(1<<11)|(1<<12)|(1<<13)|(1<<14)|(1<<15)|(1<<16));
115
  //lösche alten Wert
116
  *z_iopdata |= numeric_display[wert];
117
  //Passe wert an und suche dann passende Kombination aus dem Array numeric_display raus.
118
}

printf landet hierbei über JTAG im Debugger(PC-Software)

an ein 4 Pins hängen Schalter, an 4 LEDs, und dann noch ne 7-Segment 
Anzeige

ist aber alles herstellerabhängig, jeder Hersteller kann die Adresswerte 
anders verteilen...

Interrupt sind noch komplizierter, weil du alles selber schreiben musst 
bzw jeder Hersteller den IRQ Controller anders implementieren kann

da ARM eine Lizenz zum bauen von Kernen verkauft und selber keine CPUs 
verkauft

von Bernd S. (mms)


Lesenswert?

>Um das Funktionieren geht es nicht, sondern darum, zu erkennen, wie und
>in welche Adreßbereiche der Flash und sonstige Peripherie gemappt ist,
>wie man in den Bootloader kommt usw.

der Addressbereich steht im Datenblatt sehr gut aufgeschlüsselt drinnen. 
Benötigt man auch zu Beginn gleich einen Bootloader? Eigentlich wollte 
ich ganz ohne allem erst mal anfangen... der prozessor ist der LPC2212. 
Bei dem Board war eine CD mit dabei, mit Bootloader U-Boot und dazu 
Beispielprogrammen, aber ich möchte halt zuerst mal ohne Bootloader 
auskommen...


@Gast

vielen dank für dein beispiel, werde es mir morgn mal genau anschauen. 
Aber ein paar Fragen hab ich gleich beim Durchlesen gefunden.

1. was bedeutet denn fflush genau?
2. ist eine endlosschleife ohne abbruchkriterium gang und gebe?
3. das mit den ganzen defines muss ich mir noch mal anschauen
  genauso wie die Zeile
  z_iopdata=(volatile unsigned *)(0x03FF0000 + 0x5008);


Im Prinzip geht es mir darum, zu erlernen wie man was programmiert bzw. 
wie man vorgeht.

Bernd

von Gast (Gast)


Lesenswert?

zu 1. ist nur interessant wenn du eine Online Debugger hast...

fflush leert den Buffer in den Klammern, sonst kann es bei printf 
passieren das die Ausgabe erst erscheint wenn der Buffer irgendwann mal 
voll ist

(Standard C Fkt)

zu 2.

ja im µC Berich schon, weil was willst du den reinschreiben als Abbruch

zu 3.

z_io... ist ein zeiger im C, dessen Adresse wird auf den angegeben Wert 
gelegt dadurch kann man auf das Register zugreifen (die Register sind in 
diesem Fall memory mapped)

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.