R8C Codebeispiele: Unterschied zwischen den Versionen

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche
K (Ein bischen Show muss sein ;-))
KKeine Bearbeitungszusammenfassung
Zeile 110: Zeile 110:
#include "sfr_r813.h"
#include "sfr_r813.h"


#define F_OSC 20000000UL
#define F_OSC     20000000UL
#define BITRATE 19200UL
#define BITRATE     19200UL


/* Implementierung siehe R8C Codebeispiel */
/* Implementierung siehe R8C Codebeispiel */
Zeile 121: Zeile 121:
{
{
   /* Auf extern 20 MHz umschalten */
   /* Auf extern 20 MHz umschalten */
   Init_Takt_Extern();
   Init_Takt_Extern();  


   /*  
   /*  
Zeile 129: Zeile 129:
   **
   **
   ** Anm.: UART1 ist vom Debugger belegt.
   ** Anm.: UART1 ist vom Debugger belegt.
   **
   */
 
  /*  
   ** 'UART0 bit rate generator' setzen abhängig
   ** 'UART0 bit rate generator' setzen abhängig
   ** von (externem) Takt und gewünschter Bitrate  
   ** von (externem) Takt und gewünschter Bitrate  
Zeile 144: Zeile 146:
   smd1_u0mr    = 0;
   smd1_u0mr    = 0;
   smd2_u0mr    = 1;
   smd2_u0mr    = 1;
   /* Internal (!) Takt auswählen */
   /* Internal (!) Takt auswählen */
   ckdir_u0mr = 0;  
   ckdir_u0mr = 0;  
   /* 1 Stopbit auswählen */
   /* 1 Stopbit auswählen */
   stps_u0mr = 0;
   stps_u0mr = 0;
   /* Parity disable (none) */
   /* Parity disable (none) */
   prye_u0mr = 0;  
   prye_u0mr = 0;  


   /*
   /*
   ** Übertragung erlauben (einschalten)
   ** Übertragung erlauben
   */
   */


   /* Enable Transmission */
   /* Enable Transmission */
   te_u0c1 = 1;
   te_u0c1 = 1;
   /* Enable Reception */
   /* Enable Reception */
   re_u0c1 = 1;
   re_u0c1 = 1;


   /*
   /*  
  ** 1. Anwendung:
   ** Terminal löschen  
   ** Terminal löschen  
   ** FORMFEED hex. 0x0C oct. 014
   ** FORMFEED hex. 0x0C oct. 014
Zeile 178: Zeile 175:
       unsigned char RXError = 0;
       unsigned char RXError = 0;


       /* Zeichen am Empfang (RX) abholen */
       /* Zeichen am Empfang (RX) abholen   */
       /* Warten bis Empfangspuffer (1 Zeichen!) voll */
       /* Warten bis Emfangspuffer voll */
       while (!ri_u0c1)
       while (!ri_u0c1)
         ;
         ;
       /* Empfangspuffer auslesen */
       /* Empfangspuffer auslesen */
       zeichen = u0rbl;
       zeichen = u0rbl;
       RXError = u0rbh; /* Wichtig! Löscht gleichzeitig ri_u0c1 */
       RXError = u0rbh;   /* löscht gleichzeitig ri_u0c1 ! */
     
       /* hier ggf. Fehlerbehandlung */
       /* hier ggf. Fehlerbehandlung */


Zeile 195: Zeile 191:
         zeichen = zeichen - 'A' + 'a';
         zeichen = zeichen - 'A' + 'a';


      /* LED Anzeige ;-) */
      pd1 |= 0b00000001; 
      if (zeichen == '0')
        p1_0 = 0;
      if (zeichen == '1')
        p1_0 = 1;
     
       /* Zeichen beim Sender (TX) abgeben */
       /* Zeichen beim Sender (TX) abgeben */
       /* Warten bis Sendepuffer frei */
       /* Warten bis Sendepuffer frei */
       while (!txept_u0c0 || !ti_u0c1)
       while (!txept_u0c0 || !ti_u0c1)
         ;
         ;
 
       /* Sendepuffer beschreiben */
       /* Sendepuffer (1 Zeichen!) beschreiben */
       u0tbl = zeichen;
       u0tbl = zeichen;


Zeile 214: Zeile 216:
       while (!txept_u0c0 || !ti_u0c1)
       while (!txept_u0c0 || !ti_u0c1)
         ;
         ;
       /* Sendepuffer beschreiben */
       /* Sendepuffer beschreiben */
       u0tbl = *stext++;
       u0tbl = *stext++;

Version vom 26. März 2006, 17:01 Uhr

R8c hello world led.gif

Hello World ;-)

Das typische hello world Programm für einen Mikrocontroller ist wohl eine blinkende LED.

Mit so einem sehr einfachen Beispiel kann man grundlegend die Installation und Funktionsfähigkeit der Entwicklungstools und der Hardware testen.

Beim folgenden Beispiel wird davon ausgegangen, dass eine LED mit der Anode (+) an Port 1.0 angeschlossen ist und über einen 1KOhm Widerstand von Kathode (-) zu GND (Vss).

/* Definitionen der SFR (special funktion register) einbinden */
#include "sfr_r813.h"

void main(void)
{
   /* Port Direction Register 1.0 = Pin 0 an Port 1 auf Ausgabe (Output) schalten */
   pd1 |= 0b00000001;   

   /* für immer und ewig... */
   while(1)
   {
      unsigned long i;
   
      /* Port 1.0 zwischen HIGH und LOW umschalten */
      p1_0 ^= 1;

      /* etwas warten... */
      for (i = 0; i < 123456UL; i++)
         ;
   }
}

Vorschläge fürs weitere Experimentieren?

Dieses Beispiel läuft mit dem CPU Takt, den der R8C nach einem RESET besitzt. Das sind 1/8-tel Taktfrequenz des low speed oscillator, d. h. 125/8 KHz.

  • Wie ändert sich die Blinkfrequenz, wenn eine externe Taktquelle benutzt wird?
  • Wie kann man im Programmcode beide Varianten berücksichtigen?

Studieren geht über Probieren!

  • Wenn man pdx und px_y im Programm anpasst, ist es dann egal, an welchen Output-Pin die LED angeschlossen wird?
  • Wieviele LEDs kann man anschliessen und betreiben?


Externen Haupttakt einschalten

Der Haupttakt (main clock) des R8C kann von internem Oszillator (on-chip oscillator) auf einen externen Oszillator (0-20 MHz) umgestellt werden. Das Verfahren dazu ist im R8C Hardware Manual Kapitel 6 beschrieben.

Es muss natürlich externe Taktquelle (z.B. Quarz) funktionsfähig angeschlossen sein. Es folgt ein Beispiel für den R8C/13, so wie er inklusive 20 MHz Quarz auf der Prozessorplatine von Glyn/Elektor zu finden ist:

/* Definitionen der SFR (special funktion register) einbinden */
#include "sfr_r813.h"

void Init_Takt_Extern(void)
{
   prc0 = 1;   /* 1 = Schreibschutz für wichtige SFR aufheben */

   /* Anschluss festlegen */
   cm13 = 1;   /* 1 = 'main clock' ist an XIN-XOUT Pins angeschlossen */
   cm15 = 1;   /* 1 = 'XIN-XOUT drive capacity' HIGH */
   cm05 = 0;   /* 0 = 'main clock stop bit' (XIN-XOUT) ON */
               /*      d.h. Pins XIN-XOUT nicht abschalten */

   /* Taktrate festlegen */
   cm16 = 0; 
   cm17 = 0;
   cm06 = 0;   /* 0 = 'CPU clock division' durch cm16 und cm17 bestimmt */
               /* cm16=0 und cm17=0 => kein Teilung des Taktes */

   /* kurz warten bis externe Taktquelle stabil läuft */
   asm("nop"); 
   asm("nop");
   asm("nop");
   asm("nop");

   /* CPU Takt auf gerade festgelegte externe Taktquelle umschalten */
   ocd2 = 0;   /* 0 = 'main clock' als CPU clock auswählen */

   prc0 = 0;   /* Schreibschutz für wichtige SFR wieder einschalten */
}

Vorschläge fürs weitere Experimentieren?

Diese Funktion schaltet nur die externe Taktquelle ein und zwar mit full speed.

  • Wie kann man auf einen der beiden internen Oszillatoren (high speed / low speed) zurückschalten?
  • Wie kann man feststellen, mit welchem Takt gearbeitet wird?

Studieren geht über Probieren!

  • Was passiert beim Ausfall des externen Oszillators?


Serielle Datenübertragung (Polling-Verfahren)

Im folgenden Codebeispiel wird die Initialisierung der seriellen Schnittstelle des R8C/13 und das Empfangen/Senden einzelner Zeichen gezeigt.

Als serielle Schnittstelle des R8C/13 wird UART0 benutzt, da UART1 z.B. auf dem Elektor-Applikationsboard bereits durch den Debugger belegt ist.

Die Übertragung wird bei 19200 Baud, 8 Datenbits, 1 Startbit (unveränderlich), 1 Stoppbit und keine Parität und kein Handshake durchgeführt. Das Terminalprogramm auf dem PC muss entsprechend eingestellt sein.

Beim Polling-Verfahren wird die serielle Schnittstelle im Anwendungsprogramm von Hand zu Fuß bedient.

/* Definitionen der SFR (special funktion register) einbinden */
#include "sfr_r813.h"

#define F_OSC      20000000UL
#define BITRATE      19200UL

/* Implementierung siehe R8C Codebeispiel */
extern void Init_Takt_Extern(void);

void uart0_willkommen(unsigned char *stext);

void main(void)
{
   /* Auf extern 20 MHz umschalten */
   Init_Takt_Extern();   

   /* 
   ** UART0 initialisieren 
   ** Clock Asynchrous Serial I/O (UART) Mode
   ** s. a. Hardware Manual Kap. 13 Serial Interface
   **
   ** Anm.: UART1 ist vom Debugger belegt.
   */

   /* 
   ** 'UART0 bit rate generator' setzen abhängig
   ** von (externem) Takt und gewünschter Bitrate 
   ** Hardware Manual Kap. 12.2.3
   */
   u0brg = (unsigned char) (((F_OSC) / ((BITRATE) * 16)) - 1);

   /*
   ** Übertragungsformat einstellen
   */

   /* 8 Datenbits einstellen */
   smd0_u0mr    = 1;
   smd1_u0mr    = 0;
   smd2_u0mr    = 1;
   /* Internal (!) Takt auswählen */
   ckdir_u0mr = 0; 
   /* 1 Stopbit auswählen */
   stps_u0mr = 0;
   /* Parity disable (none) */
   prye_u0mr = 0; 

   /*
   ** Übertragung erlauben
   */

   /* Enable Transmission */
   te_u0c1 = 1;
   /* Enable Reception */
   re_u0c1 = 1;

   /* 
   ** Terminal löschen 
   ** FORMFEED hex. 0x0C oct. 014
   ** + Begrüssungstext
   */
   uart0_willkommen("\014R8C/13 UART0 Codebeispiel\n\r");

   /* Für immer... */
   while(1)
   {
      unsigned char zeichen = '#';
      unsigned char RXError = 0;

      /* Zeichen am Empfang (RX) abholen    */
      /* Warten bis Emfangspuffer voll */
      while (!ri_u0c1)
         ;
      /* Empfangspuffer auslesen */
      zeichen = u0rbl;
      RXError = u0rbh;   /* löscht gleichzeitig ri_u0c1 ! */
      
      /* hier ggf. Fehlerbehandlung */

      /* Etwas mit dem Zeichen machen ;-) */
      if (zeichen >= 'a' && zeichen <= 'z')
         zeichen = zeichen - 'a' + 'A';
      else if (zeichen >= 'A' && zeichen <= 'Z')
         zeichen = zeichen - 'A' + 'a';

      /* LED Anzeige ;-) */
      pd1 |= 0b00000001;   
      if (zeichen == '0')
         p1_0 = 0;
      if (zeichen == '1')
         p1_0 = 1;
      
      /* Zeichen beim Sender (TX) abgeben */
      /* Warten bis Sendepuffer frei */
      while (!txept_u0c0 || !ti_u0c1)
         ;
      /* Sendepuffer beschreiben */
      u0tbl = zeichen;

   } /* end while(1) */
}

void uart0_willkommen(unsigned char *stext)
{
   while(*stext)
   {
      /* Zeichen beim Sender (TX) abgeben */
      /* Warten bis Sendepuffer frei */
      while (!txept_u0c0 || !ti_u0c1)
         ;
      /* Sendepuffer beschreiben */
      u0tbl = *stext++;
   }
}

Vorschläge fürs weitere Experimentieren?

  • Wie kann man die Sende- und Empfangsanweisungen in sinnvolle Funktionen packen?
  • Wie könnte man grössere Texte empfangen oder senden, ohne dass Zeichen verloren gehen?

Studieren geht über Probieren!

  • Welche anderen Verfahren gibt es statt Polling und welche Vorteile haben diese Verfahren?