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