Forum: Mikrocontroller und Digitale Elektronik XC167CI: Blinky in Assembler


von MrAndyCool (Gast)


Lesenswert?

Hallo,

als Dateianhang habe ich ein Mini-C-Programm eingefügt, das eine LED 
blinken lässt. Arbeite mit dem Infineon XC167CI-Board von Phytec und 
Keil µVision 2 als Entwicklungsumgebung. In C bin ich inzwischen ganz 
fit, und hab schon Mächtigere Dinge programmiert ;) Allerdings brauche 
ich exemplarisch noch Assembler-Code, bekomme aber nichts Kompilierbares 
zustande.

FRAGE: Kann mir jemand eine Starthilfe geben, wie ich ein 
kompilierfähiges Assemblerprogramm erstelle, oder kann mir gar jemand 
das Blinky-Programm kurz übersetzen ?

Ich danke euch im voraus!
Gruß MrAndyCool

von MrAndyCool (Gast)


Lesenswert?

     ---   HIER DAS PROGRAMM:   ---
1
/* FLASH.C - LED Flasher for Phytecs Rapid Development Kits              */
2
3
#include <XC167.h>                /* special function register for XC161 */
4
5
sbit  P9_0 =  P9^0;               /* declare portpin to use              */
6
sbit  DP9_0 = DP9^0;              /* declare direction bit to use        */
7
8
void wait (void)  {               /* wait function                       */
9
  ;                               /* only to delay for LED flashes       */
10
}
11
12
void main (void)  {               
13
unsigned long i=0;                /* delay var                           */
14
15
  DP9_0 = 1;                      /* init direction to output            */
16
  while (1)               /* loop forever                        */
17
  {                               /* An embedded program does not stop   */
18
19
    P9_0 = 0;                     /* output to LED port                  */
20
    for (i=0; i<100000; i++) {    /* delay for 150000 counts             */
21
      wait ();                    /* call wait function                  */
22
    }
23
24
    P9_0 = 1;                     /* output to LED port                  */
25
    for (i=0; i<100000; i++) {    /* delay for 150000 counts             */
26
      wait ();                    /* call wait function                  */
27
    }
28
  }
29
}

  

von Reinhard B. (brainstorm)


Lesenswert?

Ich weiß nicht, ob der Code lesbar ist, aber bei den 
Projekt-Einstellungen gibts normalerweise ein Hackerl, mit dem man 
ASM-Sourcen erzeugen lassen kann.

mfg

von MrAndyCool (Gast)


Lesenswert?

Habs gerade versucht, das funktioniert (im Listing-File), danke. Die 
Codeschnipsel kann ich verwenden. ABER das Programmieren ist auch nicht 
das Haupt-Problem:

Ich brauche eine Starthilfe, WIE man überhaupt in Assembler 
programmiert:

1. Welche Datei muss ich anlegen ? (*.A66 ?)
2. Was muss ich am Header schreiben ? ($MODV2 ??? $include ???  ORG ???)

Ich will schlicht erst mal kompilieren können.

von Reinhard B. (brainstorm)


Lesenswert?

Puh...hab den XC bis jetzt nur in C programmiert. Vielleicht hilft dir 
aber noch ein Blick in den startup-code den uVision dabei hat, der 
sollte einigermaßen gut dokumentiert sein.

mfg

von Blub B. (Firma: none) (crumbjunk)


Lesenswert?

Erst einmal ein herzliches Hallo an alle im Forum!!!!
Ist mein erster Beitrag hier :)

So, tut mir leid das ich diesen Thread ausgrabe, aber ich komme einfach 
nicht weiter...

Ich benutze seit kurzem das ekxc167ci und wollte es wahlweise mit c, 
oder c++ programmieren.
Auf der Suche nach einem Code-Beispiel bin ich auf den oben 
dargestellten Code gestoßen.
Er lässt sich in Keil uVision 4 auch compilieren und linken. Aber:

diese kleinen mistigen LEDs wohlen nicht leuchten... und ich weis 
einfach nicht warum...

Soweit ich das noch weis, muss ich doch nur den Pin der LED (also für 
mehrere LEDs die Pins) deklarieren, auf Ausgang setzen und an- und 
ausschalten.
Ich bring die LED nicht mal nur zum leuchten...

Könnte mir bitte wer helfen? Benutze ich die falschen Befehle?

Würde mich über Eure Hilfe sehr freuen und hoffe das kit nicht aus dem 
Fenster feuern zu müssen ;)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

blub blubba schrieb:
> Erst einmal ein herzliches Hallo an alle im Forum!!!!
> Ist mein erster Beitrag hier :)
Sieht man: wozu einen mehr als 5 Jahre alten Thread kapern?
> Autor:Reinhard B. (brainstorm)
>       Datum: 07.05.2007
> Autor: blub blubba (Firma: none) (crumbjunk)
>       Datum: 14.12.2012
Besser wäre es, einen neuen Thread anzulegen und auf den alten zu 
verlinken, wenn der relevant ist.

blub blubba schrieb:
> das ekxc167ci
Link zum Manual?
> Soweit ich das noch weis, muss ich doch nur den Pin der LED (also für
> mehrere LEDs die Pins) deklarieren, auf Ausgang setzen und an- und
> ausschalten.
Und wie sieht das bei dir genau aus?
(längeren C-Quelltext als Anhang mit Dateieindung *.c)
Kannst du Einzelschritt debuggen?

von Blub B. (Firma: none) (crumbjunk)


Lesenswert?

Hi Lothar

danke für deinen Hinweis. Das nächste mal werde ich einen neuen Thread 
aufmachen und den alten bei Relevanz verlinken.

So, zu meinem Problem. Die LEDs leuchten jetzt! Leider aber nicht so wie 
sie sollen...
1
#include <XC167.h>                  /* special function register for XC161 */
2
3
sbit blink = P1L^0;
4
5
6
void wait (void)
7
{
8
  unsigned long i;
9
  while (i < 10000000)
10
  {
11
    i = i + 1;
12
  }
13
}
14
15
void main (void)  
16
{
17
  endless:
18
    DP1L =  0xff;
19
    wait();
20
    DP1L =  0x00;
21
    wait();
22
  goto endless;
23
}

Sie sollten nun ja eigentlich blinken. Leider leuchten sie erst ca. 1 
Sekunde hell und werden dann dunkler und bleiben dann so...

Hab ich mich nur verrechnet? (Board hat einen 40 MHz Takt.
Oder stimmt doch was an meinem Code nicht?

Oh, jetzt hätte ich es fast vergessen: hier ist das manual:
http://www.infineon.com/dgdl/xc167_32_ds_v1.1_2006_08.pdf?folderId=db3a304412b407950112b408e8c90004&fileId=db3a304412b407950112b41c637b2e04&sId=db3a30443b92f0fc013b9575aefe055e

von fvbq34g1 (Gast)


Lesenswert?

So ein Murks.

Das "sbit blink = P1L^0;" kannst Du Dir ganz schnell löschen.

Registerdefinitionen sind schon in Deinen µC-Definitionen
"#include <XC167.h>" drin.


Bitte ERST die entsprechenden Port-Richtungsregister einmalig setzen
(auf Output), dann die Pins toggeln.

Was machst Du da mit dem GOTO?
Ist das Dein erster C-Code?

Umständlich...

von Blub B. (Firma: none) (crumbjunk)


Lesenswert?

Hehe, danke für den Hinweis das es Murks ist... die goto-loop war noch 
ein Überbleibsel von Assembler und wie ich auf den ständigen 
direction-Wechsel gekommen bin... mh... keine Ahnung^^

Naja, was solls. Jetzt läufts. Für alle die es vielleicht interessiert:
1
#include <XC167.h>                  /* special function register for XC161 */
2
3
4
5
void wait (void)
6
{
7
  double i;
8
  while(i < 40000)
9
  {
10
    i = i+1;
11
  }
12
}
13
14
void main (void)  
15
{
16
  
17
  DP1L = 0xff;        // port P1L output
18
  while(1)            // endless loop
19
  {
20
    P1L =  0x00;      // P1L (all LEDs) on
21
    wait();
22
    P1L =  0xff;      // P1L (all LEDs) off
23
    wait();
24
  }
25
}

Vielen Dank für Eure helfenden Beiträge!

von 32 Bit (Gast)


Lesenswert?

blub blubba schrieb:
> double i;

Warum floating point?
1
unsigned long i;

von Blub B. (Firma: none) (crumbjunk)


Lesenswert?

Ja, das ist was, was ich auch nicht ganz verstehe. Wenn i vom Typ 
unsigned long ist und i bis 40.000.000 gezählt wird, dann leuchten die 
LEDs ziemlich genau 8 Sekunden lang hell, und werden dann dunkler.
Nun hat ja das Board einen Takt von 40 MHz, also sollten die LEDs doch, 
wenn ich i bis 40.000.000 hochzählen lasse, jede Sekunde an, bzw. aus 
gehen.

Sie gehen aber, wenn i vom Typ double ist und i bis 80.000 gezählt wird 
ziemlich genau jede Sekunde an und dann aus.

Warum?

von fvbq34g1 (Gast)


Lesenswert?

Ja... Genau aus dem Grund macht man das ja auch so nicht mit seinen 
Delay-Schleifen. ODer besser ausgedrückt: Delay-Schleifen sind immer zu 
vermeiden.

Organisiere das mal mit einem Timer, dann muss man sich auch nicht 
wundern,
dass ein 16-Bit-µC (wie der XC167) eine andere Zeit braucht, um double
-Fließkomma-Variablen (!) zu handeln, als ein anderer µC.

Für die oben im Code gezeigten 40000 reicht hier auch ein unsigned short 
int aus, das wären dann 16 Bit. Ich bin mir aber sehr sicher, dass der 
XC mit
unsigned short ints schneller "umgehen kann", als mit Fließkommazahlen.

von fvbq34g1 (Gast)


Lesenswert?

Was Du machst, ist irgend einen Datentypen zu nehmen und so lange am 
Schräubchen zu drehen, bis da ungefähr 1 Sekunde raus kommt.

Sei froh, dass sie LED sichtbar blinkt, damit war's dann auch schon
mit dem Demo-Code.

von 32 Bit (Gast)


Lesenswert?

blub blubba schrieb:
> Nun hat ja das Board einen Takt von 40 MHz, also sollten die LEDs doch,
> wenn ich i bis 40.000.000 hochzählen lasse, jede Sekunde an, bzw. aus
> gehen.

1. Der Takt aussen am Board ist noch lange nicht der Core Takt für die 
CPU.
2. Verschiedene Befehle haben unterschiedliche Verarbeitungszeiten. Es 
gibt Pipelines und Compileroptimierungen, die eine zeitliche Bestimmung 
der Programmablaufgeschwindigkeit erheblich erschweren.
3. Für Zeitreferenzen gibt es Timer. Die melden sich üblicherweise per 
Interrupt.

Wenn du mit deinem Experiment noch weiter basteln möchtest, nutze den 
unsigned long und schalte jegliche Optimierung aus. Dann spielst du mit 
dem i und fügst ein paar _nop() ein, bis dir die Werte gefallen. Aber 
das ist nur basteln ohne Lerneffekt.

von Blub B. (Firma: none) (crumbjunk)


Lesenswert?

So, hab`s jetzt. Das Problem lag ja eigentlich auf der Hand.
wait() zählt einmal hoch und bleibt dann auf dem hochgezählten Wert 
stehen (ich hab ja nie zurückgesetzt). Daher leuchten die LEDs hell bis 
einmal hochgezählt wurde. Anschließend wird ohne wait() ständig ein- und 
ausgeschaltet und so leuchten die LEDs schwächer.

Hier ist mal ein Lauflicht, bei dem der Zähler immer wieder mit dem 
Parameter 0 gestartet wird.
1
 
2
#include <XC167.h>                  /* special function register for XC161 */
3
4
5
6
void wait (unsigned long i)
7
{
8
  
9
  while(i < 4000000)
10
  {
11
    i = i+1;
12
  }
13
}
14
15
void main (void)  
16
{
17
  
18
  DP1L = 0xff;        // port P1L output
19
  P1L = 0xff;          // all LEDs off
20
  while(1)
21
  {
22
    wait(0);
23
    P1L = 0xfe;
24
    
25
    wait(0);
26
    P1L = 0xfd;
27
    
28
    wait(0);
29
    P1L = 0xfb;
30
    
31
    wait(0);
32
    P1L = 0xf7;
33
    
34
    wait(0);
35
    P1L = 0xef;
36
    
37
    wait(0);
38
    P1L = 0xdf;
39
    
40
    wait(0);
41
    P1L = 0xbf;
42
    
43
    wait(0);
44
    P1L = 0x7f;
45
    
46
    wait(0);
47
    P1L = 0xbf;
48
    
49
    wait(0);
50
    P1L = 0xdf;
51
    
52
    wait(0);
53
    P1L = 0xef;
54
    
55
    wait(0);
56
    P1L = 0xf7;
57
58
    
59
    wait(0);
60
    P1L = 0xfb;
61
    
62
    wait(0);
63
    P1L = 0xfd;
64
  }
65
}

Funktioniert wunderbar und wait() läuft mit unsigned long so wie 
erwartet.

@ fvbq34g1
Vielen Dank für die Info. Bei Gelegenheit werde ich das Progrämmchen mit 
einem Timer realisieren!

@ fvbq34g1
Unnütz...

@ 32 Bit
Danke, wie gesagt, den Timer werde ich bei nächster Gelegenheit mal 
ausprobieren! Das es Verzögerungen gibt, da die Befehle verarbeitet 
werden müssen habe ich gewusst, nur das es doch soviel ausmacht hätte 
ich nicht erwartet. Danke nochmal.

von 32 Bit (Gast)


Lesenswert?

blub blubba schrieb:
> #include <XC167.h>                  /* special function register for XC161 */
>
>
>
> void wait (unsigned long i)
> {
>
>   while(i < 4000000)
>   {
>     i = i+1;
>   }
> }
>
> void main (void)
> {
>
>   DP1L = 0xff;        // port P1L output
>   P1L = 0xff;          // all LEDs off
>   while(1)
>   {
>     wait(0);
>     P1L = 0xfe;
>
>     wait(0);
>     P1L = 0xfd;
>
>     wait(0);
>     P1L = 0xfb;

noch ein Tipp für die Schleife, obwohl man das natürlich mit einem Timer 
macht.
1
void wait (void)
2
{
3
  unsigned long i;
4
5
  for(i = 0;i < 4000000;i++)
6
    _nop_();                      // #include <INTRINS.H>
7
    _nop_();
8
    _nop_();
9
}
10
11
void main (void)  
12
{
13
  DP1L = 0xff;        // port P1L output
14
  P1L = 0xff;          // all LEDs off
15
  while(1)
16
  {
17
    wait();
18
    P1L = 0xfe;
19
    
20
    wait();
21
    P1L = 0xfd;
22
    
23
    wait();
24
    P1L = 0xfb;
25
...

von 32 Bit (Gast)


Lesenswert?

32 Bit schrieb:
> for(i = 0;i < 4000000;i++)
>     _nop_();                      // #include <INTRINS.H>
>     _nop_();
>     _nop_();

Mist!

for(i = 0;i < 4000000;i++)
{
     _nop_();                      // #include <INTRINS.H>
     _nop_();
     _nop_();
}

Klammern vergessen.

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.