Selbstverständlich müssen in C genauso wie in Assembler (ASM) die Konfiguration für den PIC bestimmt bzw. eingestellt werden. Wenn dies vergessen wird, kann der Mikrocontroller / PIC nicht arbeiten. In diesem (letzten) Kapitel konzentrieren wir uns auf Aspekte der Sprache C die in direkte Beziehung zu unseren PIC Mikrocontrollern stehen.

Nun unterscheidet sich die Einstellung der einzelnen Einheiten etwas. Hier ein beispiel wie Ihr in C, die Konfiguration für einen PIC vornehmen könnt:

#pragma config FOSC=HS   // Taktbereich
#pragma config PWRT=ON   // Power on timer
#pragma config BOR=OFF   // Brown out reset
#pragma config WDT=OFF   // Watchdog timer
#pragma config LVP=OFF   // Low voltage progr.
#pragma config MCLRE=ON  // Master clear reset

Durch die Einleitung #pragma weiß der PIC, dass es sich um Konfigurationsinformationen handelt. Natürlich könnt Ihr das Konfigurationswort bzw. die Konfigurationsbits auch manuell komfortabel über die IDE einstellen. Auf diese Weise müsst Ihr euch mit der genauen Schreibweise nicht auseinandersetzen. So werden die Konfigurationsbits mit MPLABX erstellt (siehe auch MPLABX Artikel):

Eingänge / Ausgänge

Als nächstes ein Beispiel, wie Ihr in der Sprache C Zustände von einzelnen Portpins oder ganzen Ports einlesen und wie Ihr Pins/Ports (Ausgang/Ausgänge) setzten oder löschen können:

// Ausgang löschen
LATAbits.LATA4 = 0;

// Ausgang setzten
LATBbits.LATB0 = 1;

// Wahl Ausgang(0)/Eingang(1)
TRISB = 0x80;

// Abfrage eines Ports (Eingang)
if (PORTB == 0xFF);

// Abfrage eines einzelnen Pins
if (PORTBbits.RB0 == 0);
 Anmerkung zum Beispiel
TRISB = 0x80;

Hier wurde nun das Bit 7 des Port-B als Eingang und die restlichen Bits als Ausgang definiert, denn 0x80 ist Hexadezimal und steht für Binär: 1000 0000

Also Schreibregel beim Setzten/Löschen von Ausgängen:

LATXbits.LXY = Z;
X: Hier wird der Port eingetragen (A, B,..).
Y: Hier kommt das Bit hinein (0-7) des Ports.
Z: Der Zustand den der Port-Pin annehmen soll.

Dabei darf man natürlich nicht vergessen die TRIS Bits dementsprechend einzustellen! Wir erinnern uns: Eine “1” im TRIS Register schaltet den jeweiligen Port-Pin als Eingang, eine “0” als Ausgang. Im obigen Beispiel seht Ihr ebenfalls wie Ihr die TRIS-Register beschreiben könnt.

Schreibregel beim Lesen von Eingängen:

if (PORTXbits.RXY == 0) {...} else {...}
X: Hier wird der Port eingetragen (A, B,..).
Y: Pin eintragen der gelesen werden soll (0-7)

Dies ist ein Beispiel, wie man in Abhängigkeit vom Zustand eines Einganges den Programmablauf steuern kann!

Wann PORT und wann LAT?

Ein weiterer wichtiger Punkt ist zu wissen, wann man mit PORT und wann mit LAT arbeiten muss. Ganz kurz und knapp: LAT bei Ausgängen und PORT bei Eingängen. Wer sich noch etwas mehr mit den Vorteilen der LAT-Register beschäften möchte kann mal hier rein schauen. Sehr interessant!

Interrupts

PIC Mikrocontroller unterscheiden zwei Interrupt Prioritäten. High und low. Wenn Ihr einen Interrupt programmiert habt und ein entsprechendes Event diesen auslöst, so wird der PIC in die so genannte Interrupt-Service-Routine springen. Im Grunde genommen ist das eine Art Funktion. Nur wird diese nicht vom Programmierer aufgerufen sondern vom PIC selber wenn ein entsprechendes Ereignis eintritt.

int tick_count;

void interrupt tc_int(void)
{
   if (TMR0IE && TMR0IF)
   {
      TMR0IF=0;
      ++tick_count;
      return;
   }
   // ...
}

/* Beziehungsweise ein Interrupt mit niedriger Priorität */

void interrupt low_priority tc_clr(void)
{
   if (TMR1IE && TMR1IF)
   {
      TMR1IF=0;
      tick_count = 0;
      return;
   }
   // ...
}

Häufige Fehler

Hier entsteht eine Sammlung von Fragen mit Antworten, welche sehr häufig gestellt werden. Außerdem wird eine Liste mit Fehlern erstellt, welche immer wieder vorkommen.

GLEICH = ist nicht gleich GLEICH ==

Ein Fehler der immer wieder gern gemacht wird ist, dass man bei einem Vergleich das falsche Zeichen wählt. Ein einfaches geschriebenes “=” Zeichen ist dafür da um z.B. Variablen einen Wert zu zuweisen aber nicht als Vergleichsoperator, dies würde einen Syntax Fehler nach sich ziehen und das Compilieren beenden. Siehe:

Falsch

if (A=B) {..} else {..}

Richtig

if (A==B) {..} else {..}

Funktion aufrufen

Wenn man eine Funktion aufrufen möchte die Assembler Leute kennen dies besser unter dem Namen Unterprogramm, dann sollte man doch auf die korrekte Schreibweise achten.(Am besten gleich den nächsten Punkt in diesem Kapitel lesen!) Siehe:

Falsch

void Funktion();
Funktion()
Funktion;

Richtig

Funktion();

Funktion anmelden

Dieser Fehler wird sehr häufig gemacht und dann wundert man sich warum beim Compilieren so ein seltsamer Fehler kommt. Bevor man eine Funktion innerhalb main-Routine aufrufen kann, muss man sie vorher angemeldet haben. Dafür gibt es zwei Möglichkeiten: Entweder man schreibt die Funktion oberhalb main-Routine oder aber man meldet sie vorher an. Siehe:

Falsch

void main (void)
{
  FunktionA();
}

void FunktionA (void) {..}

Richtig

void FunktionA (void) {..}
void main (void)
{
  FunktionA();
}

Oder aber man meldet Sie vorher an:

Richtig

void FunktionA (void);

void main (void)
{
  FunktionA();
}

void FunktionA (void) {..}

Schlusswort

Ich hoffe dieser kleine C Kurs hat Euch etwas geholfen mit PIC Mikrocontrollern und der Verwendung der Sprache C umzugehen. Sollten Ihr dennoch Fragen haben zögert nicht diese über die Kommentarfunktion zu stellen!

Leave a Comment