Kurzanleitung: µVision für MiCoWi Uwe Wittenfeld 2011
Transcrição
Kurzanleitung: µVision für MiCoWi Uwe Wittenfeld 2011
C-Programmierung von MiCoWi mit der Keil-Entwicklungsumgebung µVision4 1. Erstellung eines neuen Projektes Menüpunkt: Project | New µVision Project Es wird ein komplett neues Projekt in einem beliebigen Verzeichnis erzeugt. Zunächst wird dieverwendete CPU spezifiziert. Micowi arbeitet mit dem Prozessor AT89S8253 von Atmel. Bitte bestätigen Sie die Frage, ob der 8051Startup-Code hinzugefügt werden soll mit „Ja“. Das Projekt enthält jetzt im Ordner Source Group 1 die Datei STARTUP.A51, aber noch keine C-Datei. Es müssen noch einige Einstellungen (Options Target) vorgenommen werden: Reiter Device: • Xtal (MHz): 12 • Memory Model: Small • Code Rom Size: Compact Reiter Output: • Create HEX File aktivieren Einfügen einer Datei mit Quellcode: Eine C-Datei mit dem Quellcode muss explizit zum Projekt hinzugefügt werden. Nur das Öffnen der Datei reicht nicht aus. Klicken Sie dazu mit rechts auf den Ordner Source Group 1 und wählen Sie Add files to group. Die Datei sollte sich auch im Projektordner befinden. Dateien, die nicht in das Projekt eingebunden sind, werden ohne Syntax highlight dargestellt. MiCoWi und µVision Seite 1 Uwe Wittenfeld 2011-03 2. Grundstruktur des Quellcodes Es gibt bereits eine Datei, in der alle Register des Mikrocontrollers deklariert sind. Dieses Includefile sollte am Anfang des Quelltextes eingefügt werden: #include "reg52.h" Das Hauptprogramm muss immer eine „ewige Schleife“ enthalten, denn es gibt kein Betriebssystem und der Prozessor muss immer ein definiertes Programm abarbeiten. void main (void) { init(); // Grundinitialisierung für Timer, IRQ, etc. while(1) { } } //main 3. Erweiterungen der C-Syntax für Mikrocontroller Compiler für Mikrocontroller haben spezielle Ergänzungen der normalen ANSI-C-Konventionen. Diese Erweiterungen sind Compilerspezifisch, d.h. die Syntax muss gegebenenfalls bei der Verwendung eines anderen Prozessors angepasst werden. Einzelbits des Mikrocontrollers: Um auf Bits des Mikrocontrollers zugreifen zu können, die einzeln adressierbar sind, kann der Datentyp sbit verwendet werden. sbit testbit = P0^7; // Bit 7 von Port 0 Interrupts: Die Deklaration einer Interruptfunktion hat folgende Syntax: void irq_test(void) interrupt 1 { … } Die Nummer hinter dem Wort Interrupt kennzeichnet den verwendeten Interrupt: MiCoWi und µVision Seite 2 Uwe Wittenfeld 2011-03 4. Logische Einzelbitmanipulationen Bei der Programmierung von Mikrocontrollern spielt die bitweise Manipulation eine große Rolle.: Operator Funktion Beispiel x = x & 0xF0 //Unterstes Nibble von x auf 0 & Und x = x | 0x80 //Oberstes Bit von x setzen | Oder Bit ist 1, wenn genau eins der zugehörigen Bits 1 ist ^ Exclusiv Oder Alle Bits invertieren ~ Nicht x = x << 2 //x um 2 Bit nach links schieben (*4) << Shift left x = x >> 2 //x um ein Bit nach rechts schieben (/2) >> Shift right 5. Datentyp der einem Byte entspricht Es gibt in C keinen Datentyp Byte (8 Bit ohne Vorzeichen). Beim Keil-Compiler dient hierzu der Datenty unsigned char. 6. Interruptfreigabe Um einen Interrupt freizugeben muss im Register IE das dem entsprechenden Interrupt zugeordnete Byte und der Bit EA gesetzt werden. ET0 = 1; EA = 1; // Irq von Timer 0 // Generelle Interruptfeigabe Nach einem RESET sind zunächst alle Interrupts abgeschaltet. MiCoWi und µVision Seite 3 Uwe Wittenfeld 2011-03 7. Timer Alle Prozessoren der 8051/8052-Serie verfügen über mindestens zwei Timer. Die Timer sind prinzipiell identisch, d.h. es ist dem Programmierer überlassen, ob er eine Aufgabe mit Timer 0 oder mit Timer 1 löst. Es soll hier vorläufig mit folgenden Einschränkungen gearbeitet werden: • Es wird entweder der 16-Bit-Modus ohne Autoreload oder der 8-BitModus mit Autoreload verwendet. • Es wird nur mit einem intern erzeugten Takt . • Das An- und Ausschalten der Zähler wird nur durch das Programm und nicht durch eine externe Hardware durchgeführt. Folgende Eigenschaften des Zählers sind zu berücksichtigen: • Der Zähler zählt vorwärts. • Ein Überlauf des Zählers löst einen Interrupt aus. • Der Zähltakt entspricht dem Prozessortakt, also 1/12 der Quarzfrequenz (Hier: 1 MHz). • Im 16-Bit-Modus muss der Wert nach jedem Überlauf neu nachgeladen werden. Für eine genaue Beschreibung der Timer sei auf die Hardwarebeschreibung hingewiesen. Beispiel 1: 10ms-Timer Gewählt: Timer 0 im 16-Bit-Modus) tm = tm = TMOD= TH0 = TL0 = ET0 = EA = TR0 = TMOD; tm & 0xF0; tm | 1; 0xD8 ; 0xEF; 1; 1; 1; //Timermodusregister einlesen //Zustand Timer 1 ausmaskieren //Timer 0: 16 Bit (Modus 1), Timer 1 unverändert //High-Byte des Zählers //Low-Byte des Zählers //Interrupt für Timer 0 freigeben //Generelle Interruptfreigabe; //Timer 0 starten Timerwert für 10ms (10000µs): 65535-10000=55535 = 0xD8EF Der Timer muss im Interrupt nachgeladen werden, damit er nicht mit einer Zykluszeit von 65,535 ms weiterläuft. MiCoWi und µVision Seite 4 Uwe Wittenfeld 2011-03 8. Beispielprogramm: Lauflichtprogramm //============================================================== // Lauflicht mit Timer und Interrupt // An LEDPORT wird ein Lauflicht ausgegebeb // Timer 0 erzeugt einen 10ms-Interrupt (12 MHz) // Uwe Wittenfeld 2008-01 //============================================================== #include "reg52.h" #define #define #define #define #define LEDPORT STARTWERT IRQANZ THBYTE TLBYTE P0 0x7 10 0xD8; 0xEF; unsigned int wert; unsigned int irqcnt; // // // // P0 als Ausgabeport Startwert des Lauflichts Alle 10 Interrupts wird Lauflicht geändert 10 ms bie 12 MHz --> 65535-10000=55535=D8EFh //Aktueller Wert des Lauflichts //Interuptzähler // Init ========================================================= void init (void) { unsigned char tm; //Zwischenwert TMOD-Register wert = STARTWERT; //Startwert für Schieberegister irqcnt = 0; //Interruptzähler auf 0 tm = TMOD; //Timermodusregister einlesen tm = tm & 0xF0; //Zustand Timer 1 ausmaskieren TMOD= tm | 1; //Timer 0: 16 Bit (Modus 1), Timer 1 unverändert TH0 = THBYTE; //High-Byte des Zählers TL0 = TLBYTE; //Low-Byte des Zählers ET0 = 1; //Interrupt für Timer 0 freigeben EA = 1; //Generelle Interruptfreigabe; TR0 = 1; //Timer 0 starten } //init // Bearbeitung des Lauflichts =================================== void tuwas (void) { unsigned char carry; //Übertrag LEDPORT = wert; //Ausgabe carry = wert&0x80; //Oberstes Bit merken wert = wert<<1; //Wert nach links schieben if (carry>0) //Bit herausgeschoben? {wert = wert|1;}; //Unten wieder einfügen } //tuwas // Timer-0 Interrupt ============================================ void timer0 (void) interrupt 1 { TR0 = 0; //Timer 0 abstellen TH0 = THBYTE; //High-Byte des Zählers TL0 = TLBYTE; //Low-Byte des Zählers TR0 = 1; //Timer 0 starten irqcnt++; //Zähler erhöhen if (irqcnt >= IRQANZ) { tuwas(); //Lauflicht bearbeiten irqcnt=0; //Zähler wieder auf 0 } // if irqcnt } //timer 0 // Hauptprogramm ================================================ void main (void) { init(); //Timer- und Interruptinitialisierung while(1) //Unendliche Schleife {} } //main MiCoWi und µVision Seite 5 Uwe Wittenfeld 2011-03