PIC16 Programmierung in HITECH-C Operatoren: Arithmetische Operatoren - binäre Operatoren + Addition Subtraktion * Multiplikation / Division % Modulo + - * / sind auf ganzzahlige und reelle Operanden anwendbar. + - können außerdem für Adresswerte benutzt werden. % ist nur für ganzzahlige Operanden einsetzbar. Inkrement- und Dekrement-Operatoren - unäre Operatoren ++ Erhöhung (increment) -Erniedrigung (decrement) Die Operatoren dienen der Erhöhung bzw. der Verringerung des Wertes eines ganzzahligen Operanden um 1. Beide Operatoren können sowohl als Prefix- als auch als Postfix-Operatoren eingesetzt werden. Vorzeichenwechsel - unäre Operatoren + Vorzeichenwechsel Identität Relationale Operatoren - binäre Operatoren < <= > >= == != kleiner als kleiner oder gleich größer als größer oder gleich gleich ungleich Logische Operatoren - binäre Operatoren && logisches AND (Und) || logisches OR (Oder) ! logisches NOT (Negation, Nicht) Bitmanipulation binäre Operatoren & bitweises AND | bitweises OR ^ bitweises XOR (exklusives OR) << bitweises Linksschieben (shift left) >> bitweises Rechtsschieben (shift right) unärer Operator ~ Einerkomplement (Negation) Schleifen: FOR: Die for Anweisung kann man in vier Abschnitte unterteilen: 1. count=1 Das ist die Anfangsinitialisierung 2. count <= 10 Ein Ausdruck. Die for Anweisung wird solange wiederholt, wie dieser Ausdruck wahr (true) ist. 3. count++ Inkrementieren oder dekrementieren einer Zählvariablen 4. printf … Befehl der in der Schleife ausgeführt werden soll for ( count=1 ; count <= 10 ; count++) printf("%d\n", count); WHILE: Mit der while Anweisung wird ein Anweisungsblock solange wiederholt, wie der Ausdruck nach while wahr ist. while(i!= 0) { printf(" i is %d\n", i); i--; } Kommentar: /* alles zwischen diesen Zeichen ist Kommentar unabhängig vom Zeilenumbruch */ // alles ab hier bis zur nächsten Zeile ist Kommentar Programmverzweigung: Die if .. else Anweisung beschreibt eine vollständige Alternative. Die Syntax ist: if ( Ausdruck ) Anweisung1; [else Anweisung2;] Der else Teil kann entfallen, man erhält dann eine bedingte Anweisung. Wenn 'Ausdruck' wahr ist (d.h. Wert ungleich Null ) wird 'Anweisung1' abgearbeitet. Gibt es eine else Anweisung, wird 'Anweisung2' abgearbeitet, wenn 'Ausdruck' gleich Null ist Beispiel: if( a >= b ) /* vollständige Alternative */ larger = a; else larger = b; Variablentypen und deren Länge: Interruptbehandlung: Interrupts aufdrehen: Funktionen: Formaler Aufbau einer Funktion Der formale Aufbau einer Funktion ist recht einfach: <ergebnistyp> <funktionsname> ( <parameterliste> ) { <deklarationen> <anweisungen> } Hierbei ist <ergebnistyp> irgendein vordefinierter oder selbstdefinierter Datentyp, die <parameterliste> eine – eventuell leere – komma-getrennte Aufzählung von Übergabeparametern. Beispiel: void ZeichenSchreiben (unsigned char BefehloderDaten,unsigned char Zeichen) Ergebnistyp kann ein Variablentyp oder void (kein Rückgabewert) sein. Aufruf ohne Ergebnistyp: ZeichenSchreiben (Daten,Ziffer); Aufruf mit Ergebnistyp: Funktionsdefinition: int Funktion (int Parameter) Funktionsaufruf: int Ergebnis, Wert=17; Ergebnis = Funktion (Wert); Hauptprogramm: Auch das Hauptprogramm hat die Form eines Funktionsaufrufs, es unterscheidet sich nur durch den Funktionsnamen . Folgende Formen sind möglich: void main (void) { } int main (void) { return 0; } Das Hauptprogramm hat immer die Form einer Endlosschleife, der Controller kann nicht „stehenbleiben“ oder „nichts tun“. Beispiel: void main (void) { /* Das ist ein Kommentar über mehrere Zeilen. Am Beginn des Hauptprogramms werden die verwendeten Variablen definiert und gegebenenfalls initialisiert. */ unsigned char Z =30; //Definition und Wertzuweisung TRISA = 0x08; //Port A Ausgang bis auf RA3 (MCLR) TRISC = 0x00; //Port C Ausgang //Hier beginnt die Endlosschleife des Hauptprogramms while (1) { ZeichenSchreiben (1,Z); Z+=1; //kurze Schreibweise für Z=Z+1, alternativ Z++; } //Hier endet die Endlosschleife des Hauptprogramms } Am Ende des Hauptprogramms sollte immer ein Zeilenvorschub stehen (nach } noch einmal Return). Verwendung der Peripherie: Alle internen Register sind bei Verwendung der Include – Datei htc.h vordefiniert und können unter dem im Datenblatt verwendeten Namen angesprochen werden. Dafür ist die richtige Definition des Prozessors bei Erstellung des Projektes erforderlich. Die Headerdateien findet man unter dem Pfad: C:\Program Files\HI-TECH Software\PICC\9.83\include\as16FXXX.h Programmbeispiele für die Verwendung der Peripherie (AD-Konverter, Timer,I2C,…) finden sich auf dem Rechner unter folgendem Pfad: C:\Program Files\HI-TECH Software\PICC\9.83\samples Programmbeispiele für PICDem2Plus auf dem Abteilungsserver bei den Lernbehelfen. Beispiel für eine ISR mit 2 Interruptquellen: #include <htc.h> #include <Init.h> /* Das ist die Interruptserviceroutine des PIC16 Prozessors (da nur ein Interruptvektor existiert wird diese Routine bei jedem Interrupt aufgerufen). Zur Feststellung der Interruptquelle muss das IE und das IF Bit aller möglichen Quellen abgefragt werden (das IF Bit alleine genügt nicht weil dieses auch bei ausgeschaltetem Interrupt gesetzt werden kann). Die Kommunikation zwischen Hauptprogramm und ISR sollte über globale Variable erfolgen. Die Rettung und Wiederherstellung aller verwendeten Register wird vom Compiler automatisch eingefügt, dafür sorgt die spezielle Bezeichnung (interrupt) der Funktion. */ void interrupt ISR (void) { extern int Ticker,Sollwert; if (T0IE && T0IF) //Timer0 Interrupt? { TMR0 = 61; //Zähler neu setzen Ticker ++; //Ticker vergrößern if (Ticker == 40) { Ticker = 0; //eine Sekunde um }; T0IF=0; //Interrupt Flag löschen return; }; //Ende ISR Timer2 Interrupt if (TMR2IE && TMR2IF) //Timer2 Interrupt? { TMR2ON = 0; //Timer2 stoppen CCPR2L = Sollwert; //Duty Cycle neu laden TMR2 = 0; TMR2ON = 1; //Timer1 einschalten TMR2IF=0; //Interrupt Flag löschen return; }; //Ende ISR Timer2 Interrupt // weitere Interruptquellen hier behandeln }