36
Softwaredokumentation AT89C51ED2 - Testboard Inhaltsverzeichnis 1.Einführung............................................................................................................... 2 2.Spezielles Library zur Initialisierung............................................................................ 3 3.Hallo Welt................................................................................................................ 4 4.Download des ersten Programms in den Kontroller...................................................... 8 5.Einführung I/O-Ports............................................................................................... 10 6.Port-I/O................................................................................................................. 11 7.Hallo Welt mit Watchdog......................................................................................... 13 8.Zugriff auf den internen EEPROM............................................................................. 15 9.Zugriff auf den I²C-Bus .......................................................................................... 17 10.I²C-Parallel-I/O-Baustein PCF8574.......................................................................... 20 11.I²C- AD/DA-Wandler PCF8591P.............................................................................. 21 12.I²C-Temperatursensor LM75.................................................................................. 22 13.LC-Displays........................................................................................................... 23 14.Interrupts............................................................................................................. 25 15.Timer................................................................................................................... 27 16.Mini-DAQ-System mit ADC0804.............................................................................. 31 17.Von stehenden Bildern oder VT52-Terminal............................................................. 32 18.Die Welt wird bunt oder VT100-Terminal................................................................. 34 19.Pulsweitenmodulation (PWM)................................................................................. 35 SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 1 / 36

Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Inhaltsverzeichnis1.Einführung............................................................................................................... 22.Spezielles Library zur Initialisierung............................................................................ 33.Hallo Welt................................................................................................................ 44.Download des ersten Programms in den Kontroller...................................................... 85.Einführung I/O-Ports............................................................................................... 106.Port-I/O................................................................................................................. 117.Hallo Welt mit Watchdog......................................................................................... 138.Zugriff auf den internen EEPROM............................................................................. 159.Zugriff auf den I²C-Bus .......................................................................................... 1710.I²C-Parallel-I/O-Baustein PCF8574.......................................................................... 2011.I²C- AD/DA-Wandler PCF8591P.............................................................................. 2112.I²C-Temperatursensor LM75.................................................................................. 2213.LC-Displays........................................................................................................... 2314.Interrupts............................................................................................................. 2515.Timer................................................................................................................... 2716.Mini-DAQ-System mit ADC0804.............................................................................. 3117.Von stehenden Bildern oder VT52-Terminal............................................................. 3218.Die Welt wird bunt oder VT100-Terminal................................................................. 3419.Pulsweitenmodulation (PWM)................................................................................. 35

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 1 / 36

Page 2: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

1. Einführung

Zu aller erst gilt natürlich: alle Informationen dieser Dokumentation werden „WIE SIE SIND“ zur Verfügung gestellt und erheben nicht den Anspruch perfekt zu sein. Für Schäden, welcher Art auch immer, die durch die Nutzung dieser Informationen entstehen, kann keine Haftung übernommen werden. Ergänzungen, Fragen und Korrekturen können gerne an [email protected] gerichtet werden.

Die beigefügte Setup-ED2_TB.exe beinhaltet alle benötigten Demos und zugehörige Quellcodes. Die Dateien werden in das Verzeichnis C:\ed2_tb installiert. Dieser Pfad sollte unbedingt verwendet werden, da einige Dateien mit absoluter Pfadangabe arbeiten und dieses Verzeichnis voraussetzen.

Zusätzlich zu den Quellcodes wird noch der C-Compiler „uc51“ der Fa. Wickenhäuser benötigt. Dieser Compiler mit einfacher IDE und einigen Tools kann kostenlos unter www.wickenhaeuser.de heruntergeladen werden. Die dort bereitgestellte Version mit einer Begrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus.

Für die Programmierung des verwendeten Controllers ist die Software „FLIP“ , welche von Atmel unter www.atmel.com kostenlos zur Verfügung gestellt wird, vorgesehen. Andere Programmer funktionieren mit Sicherheit, werden hier jedoch weder berücksichtigt noch behandelt.

Die Lizenzvereinbarungen der jeweiligen Hersteller sind zu beachten und wirken sich nicht auf diese Dokumentation und/oder umgekehrt aus.

Unter c:\ed2_tb\doc werden diverse Verzeichnisse mit verschiedenen Dokumentationen (u.a. Schaltplan / Layout des Testboards, Datenblätter usw.) angelegt.

An dieser Stelle sollte sich der Leser, nach der Installation von uc51, anhand der mitgelieferten Dokumentation („Start -> Programme -> uc51 -> Docu->a_uC51Docu.pdf“) einen Überblick über den Compiler sowie die Entwicklungsumgebung verschaffen. Eine Empfehlung an dieser Stelle : In der Dokumentation sind einige Beispiele (Hello World / menue / menue2) für Singlechip-Controller angegeben. Der Leser sollte nach Durchsicht der Compiler-Dokumentation in der Lage sein, die benötigten Make-Dateien zu erzeugen und diese natürlich auch einigermaßen verstanden haben. Wichtig hierbei: die Beispiele laufen nicht ohne weiteres auf unserem Board, relevant für die Lernkurve ist jedoch nur, daß diese erfolgreich kompiliert werden können.

In erster Linie soll diese Dokumentation dazu dienen, das AT89C51ED2-Testboard möglichst schnell und effizient nutzen zu können. Einige Eigenschaften und bemerkens-werte Umstände die evtl. den Compiler und dessen Anwendung betreffen, werden hier trotzdem kurz aufgegriffen. Die Details sind dann aber der Doku des Compilers zu entnehmen.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 2 / 36

Page 3: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

2. Spezielles Library zur Initialisierung

Um immer wieder anfallende Standardinitialisierungen wie z.B die Timerkonfiguration für die serielle Schnittstelle, Watchdog-Initialisierung usw. nicht jedes mal neu ein klopfen zu müssen, wurden diese unter „init_ed2“ zusammengefasst. Im Verzeichnis C:\ed2_tb\ed2_sup befindet sich ein Unterverzeichnis „html“ in dem die zu Verfügung stehenden Funktionen dokumentiert sind (index.html). Auf die einzelnen Funktionen wird in den diversen Demos noch näher eingegangen.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 3 / 36

Page 4: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

3. Hallo Welt

Das Demo befindet sich unter c:\ed2_tb\ed2_hello. Vorgestellt wird eine einfache Initialisierung mit serieller Ausgabe.

Das JFE-Workspace-File ist bereits vorbereitet und kann über „File - Open Workspace“ geladen werden.

Doch zunächst zu den Grundeinstellungen. Wie jedes Projekt benötigt auch dieses ein bereits vorbereitetes Makefile zum kompilieren (ed2_hello.mak) :

L51FLAGS = -r$0,$0SIOTYPE = PMODEL = largeB2HFLAGS = -sA51FLAGS = -gC51FLAGS = -dCPU_NSEC=272 -dFG3

Hier sind die wichtigsten Parameter im Makefile erklärt:

L51FLAGS = -r$0,$0

Definiert die Startadressen für den Linker, in unserem Fall immer -r$0,$0. Andere Werte sind nur für Systeme nötig, die ein Monitorprogramm benötigen/verwenden.

SIOTYPE = P

Typ des verwendeten SIO-Treibers für die serielle Schnittstelle. Wir verwenden immer den P-Typ, da keine weitere Debug-Info benötigt wird (fehlendes Monitorprogramm) und wir uns diesen „Overhead“ sparen können.

MODEL = large

Großes Speichermodell, wir verfügen über mehr als 128Byte RAM

C51FLAGS = -dCPU_NSEC=272 -dFG3

-dCPU_NSEC=272

Unsere CPU arbeitet mit einer Zykluszeit von 272nS. Diese Informationen werden von diversen, zeitkritischen Routinen verwendet um genaue Zeitschleifen zu ermöglichen.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 4 / 36

Page 5: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

-dFG3

Der Compiler unterstützt intern speziell den verwendeten Controller und benötigt diesen Wert zur Anpassung. Zum Projekt muss neben dem eigentlichen Programm (ed2_hello.c) noch init_ed2.c mit gelinkt werden um die Standardinitialisierungen verwenden zu können.

Doch nun zum eigentlichen Programm:Es werden diverse Standardheader (u.a. für printf() usw.) eingebunden. Im einzelnen sind dies:

#include <stdio.h>

Diverse Standardfunktionen wie z.B. Konvertierungen (ASCII-> Integer), Eingabeoperationen, Ausgabeoperationen und Zeitfunktionen. Der Umfang ist in der Dokumentation zum Compiler ausführlich beschrieben.

#include <string.h>

Verschiedene Hilfsfunktionen zur Stringverarbeitung.

#include <reg51.h>

Registerdefinition aller „Standard“-Register eines 8051. Hier werden auch die Adressen und Symbole z.B. für den Zugriff auf die Funktionsregister und Ports definiert.

#include <irq52.h>

Der hier verwendete Controller basiert auf der 8052-Architektur und verfügt daher noch über einige Erweiterungen (Interrupts usw.) die in diesem Header definiert werden.

#include <89C51RD2.H>

In diesem Header befinden sich Register und zugehörige Symbole, die nur auf dem von uns verwendeten Controller zur Verfügung stehen.

#include "../../ed2_sup/init_ed2.h"

Hier befinden sich die Funktionsdeklarationen für die Standardinitialisierungen.

Das eigentliche Programm sieht dann eher langweilig aus, im Hintergrund passiert jedochnoch so einiges. Besonders wichtig sind die Codeschnipsel, die am Anfang der Dateiinit_ed2.c zu finden sind. Diese, in Assembler geschriebene Initialisierung erzeugt einelokale Version von „startup_first“. Dies ist die allererste Routine die vom Programm angesprungen wird und wird für grundlegende Initialisierungen vor dem eigentlichenProgrammstart benötigt. Wird keine eigene (lokale) Version angegeben, erzeugt der

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 5 / 36

Page 6: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Compiler eine Version mit default-Werten. In unserer lokalen Version aktivieren wir sofortden gesamten Speicherbereich, deaktivieren ALE und stellen die maximale Geschwin-digkeit für den Speicherzugriff ein.

Das eigentliche Programm läuft dann in der Funktion „main“ ab:

void main(void){ initSerial(); _wait_ms(500); putsl("Hallo Welt...\n");}

Als allererstes wird hier initSerial() aus „init_ed2.c“ aufgerufen. Hier wird der X2-Modedes Controllers aktiviert und anschließend die serielle Schnittstelle konfiguriert.

Die Schnittstelle verwendet folgende Einstellungen:

115200KBaud / 8 Datenbits / kein Paritätsbit / ein Stop-Bit oder kurz 115200Baud, 8,N,1

Die Einstellungen der Schnittstelle sind natürlich über entsprechende Werte in init_ed2.c/initSerial() anpassbar, näheres findet sich im Datenblatt des Controllers.

Die Funktion _wait_ms() erlaubt Wartezeiten im ms Bereich, in unserem Fall also 500ms.Die Funktion putsl() (Put Serial Line) schreibt den übergebenen String auf die serielle Schnittstelle.

Eine Besonderheit sei hier noch erwähnt: der Programmablauf in „main“ wird, nach demdas Programm vollständig durchlaufen wurde, selbstständig wiederholt, also in einerEndlosschleife ausgeführt. Im Gegensatz dazu würde das Programm auf einem PC am Ende von „main“ beendet.Daraus ergibt sich folgendes Problem: die Initialisierung der Schnittstelle wird in diesemBeispiel ebenfalls jedes mal wiederholt. In unserem Fall spielt das keine große Rolle (außer das es natürlich unnötig ist), in der Praxis ist es aber durchaus üblich, daßbestimmte Routinen nur zum Programmstart einmalig ausgeführt werden dürfen. Vorläufig können wir diese „schwäche“ jedoch noch ignorieren, im Demo „Port-I/O“ wird dann später eine einfache Lösung vorgeschlagen.Doch jetzt wollen wir endlich das Programm übersetzen und schauen, ob alles wie gewünscht funktioniert.

Der verwendete Freeware-Editor „jfe“ bietet die Möglichkeit, externe Programme über die Menüleiste einzubinden. Der Aufruf von „Make“ (Compiler / Linker) ist bereitsvorbereitet und direkt im Menü erreichbar. „Remake“ wird verwendet, wenn das komplette Projekt neu erzeugt werden soll (im Gegensatz dazu kompiliert „Make“ lediglich diegeänderten Dateien und linkt das Projekt neu).

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 6 / 36

Page 7: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Nach dem wir „Make“ ausgeführt haben, sollten die Ausgaben im unteren grauen Feld des Editors zu sehen sein. Die Ausgabe sollte etwa so aussehen:

Binary 'ed2_hello.bin': start: $0, end: $117, total size: $118/(dec.)280 bytes, used (dec.)280 bytesSclass 'text': start: $0, end: $117 size: $118/(dec.)280 BytesSclass 'xram': start: $0, end: $3 size: $4/(dec.)4 BytesUmake: 'C:\uC51\bin\bin2hex ed2_hello.bin ed2_hello.hex -s -e'...

Umake: *** OK ***

Relevant ist für uns im Moment lediglich die letzte Zeile „Umake *** OK ***“.Damit wird uns mitgeteilt, daß beim kompilieren des Programms kein Fehler auftrat.Im Fehlerfall versucht der Compiler hier eine möglichst genaue Fehlerbeschreibung auszugeben.

Damit wäre unser erstes Programm übersetzt und es wird Zeit, dieses in den Controller zu laden.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 7 / 36

Page 8: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

4. Download des ersten Programms in den Controller

Zum Download des Programms in den Controller wird das Programm „Flip“ von Atmelverwendet. Dieses Tool steht mit grafischer Oberfläche sowie als Kommandozeilen-version zur Verfügung. Die Kommandozeilenversion lässt sich ideal über eine Batch-Dateiin den „jfe“ einbinden und ist in den Demos bereits vorbereitet. Die Download-Dateiist über den Menüpunkt „DL.BAT“ im Editor erreichbar.

Die Batch-Datei ruft als erstes „Flip“ mit einigen Parametern auf um den Controllerzu löschen und anschließend neu zu programmieren.

Flip führt diverse Tests durch und versucht dann den Download zu starten. Die ver-schiedenen Zeilen in der Ausgabe geben Aufschluss über den aktuellen Programmverlauf.Hier noch ein Hinweis am Rande: gelegentlich kommt es vor, daß es zu Kommunikations-problemen insbesondere bei der Synchronisation („Synchronizing target“) kommt. Keinegroße Affäre, dass Ganze einfach nochmals wiederholen. Sollte das Öffnen des Portsscheitern („Opening port“), ist meistens noch ein Terminalprogramm (Hyperterm, Flashmon usw.) geöffnet und blockiert den Port.

Sobald Flip fertig ist, wird sofort „Flashmon“ (vgl. Doku uc51) aufgerufen. Flashmon ist bereits so eingestellt, das der Controller automatisch gestartet wird und wir die Ausgaben des Programms über die serielle Schnittstelle sehen können. In unserem Fall sieht die Ausgabe also in etwa so aus:

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 8 / 36

Page 9: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 9 / 36

Page 10: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

5. Einführung I/O-Ports

Bevor wir uns softwareseitig mit den I/O-Ports und deren Ansteuerung beschäftigen, sollten wir uns mit den Eigenschaften und Eigenheiten der Ports beschäftigen. In der Regel verfügt ein 8051-Derivat an den Ports P1-P3 über interne Pull-Ups. Das bedeutet:Wird eine logische „1“ auf einen Port-Pin geschrieben, liegt am betreffenden Pin auch tatsächlich eine Spannung an. Bei einer logischen „0“ wird der Port gegen Masse geschaltet. Intern wird der Pull-Up in der Regel durch einen FET realisiert wird. Diese Ports werden auch als „quasi-bidirektional“ bezeichnet, da der selbe Pin „scheinbar“ gegenVCC und Masse schaltet, in der Realität aber nur gegen Masse treiben kann. Hier muß meistens beachtet werden, daß der interne Pull-Up nur einen recht geringen Strom zur Verfügung stellen kann. Details sind je nach Derivat im Datenblatt zu finden. Der von uns verwendete 89C8051ED2 unterliegt ebenfalls dieser Einschränkung. Müssen also größere Verbraucher betrieben werden, sollte also auf jeden Fall ein Treiber-IC nachgeschaltet werden. Weniger kritisch ist das Schalten gegen Masse, dort verträgt unser Controller an den Ports 1-3 je Pin ca. 10mA jedoch darf pro Port ein Gesamtstrom von 15mA nicht überschritten werden. P0 verträgt ebenfalls pro Pin ca 10mA , die Gesamtlast liegt jedoch mit 26mA etwas höher.

P0 stellt hier noch eine Besonderheit dar: im „normalen“ Betrieb als Parallel-I/O-Port verfügt dieser Port intern über KEINE Pull-Ups. Dies bedeutet, daß demzufolge natürlich auch bei einer logischen 1 an einem Pin keine Spannung anliegt. Die Pins dieses Ports verfügen lediglich über eine Pull-Down-Funktion. Dies ermöglicht es, den Port als sehr hochohmigen Eingang zu verwenden, da das Signal mangels Pull-Up nur minimal belastet wird. Soll der Port wie seine Nachbarn P1-P3 betrieben werden, muß extern ein Pull-Up-Widerstand zugeschaltet werden.

Anmerkung am Rande :P0 wird in Systemen mit externen Speicher für das Adress-Low-Byte verwendet. In dieser Anwendung verfügt der Port über interne Pull-Ups. Diese werden jedoch nur zugeschaltet, solange der Port die Adresse abbildet, sobald die Adresse nicht mehr benötigt wird, werden die Pull-Ups wieder deaktiviert. Im Parallel-I/O-Betrieb können diese Pull-Ups leider nicht manuell aktiviert werden.

Um einen Port als Ausgang zu verwenden, genügt es den gewünschten Datenwert auf den Port zuschreiben. Soll der Port als Eingang dienen, muß vorher der gesamte Port auf logisch „1“ gesetzt werden. Dadurch wird der Ausgangstreiber deaktiviert, es wirken nur noch die Pull-Up-Widerstände (bzw. P0 ist dann natürlich hochohmig). Diesen Umstand sollte immer Rechnung getragen werden, ein Ausgangstreiber der noch gegen Masse zieht und von außen „hart“ auf die Versorgungsspannung geschaltet wird, lebt nicht lange!

Der Zustand der Ports nach dem Reset ist definiert logisch „1“, ein Port kann also direkt als Eingang genutzt werden.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 10 / 36

Page 11: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

6. Port-I/O

Das Projektverzeichnis ist c:\ed2_tb\ed2_pio.

Das JFE-Workspace-File sowie die Make-Datei sind bereits vorbereitet.

Da unser Testboard über keine Anzeigen zur Ausgabe bzw. Taster zur Eingabe verfügt, empfiehlt es sich evtl. die unter c:\ed2_tb\doc\hw zu findende Testleiterplatte „AT89C51ED2-DIO_Schaltplan.pdf“ aufzubauen. Diese ist recht unkompliziert gehalten und kann durchaus von Hand nach gebaut werden.

Wir wenden uns jetzt dem direkten Zugriff auf die I/O-Ports des Controllers zu. Im Header„reg51.h“ sind bereits die Symbole für den Portzugriff vordefiniert. Dazu an dieser Stelle noch einige Hintergrundinformationen: Bei der Kontrollerarchitekturdes 8051 ist es üblich, über so genannte „Special-Function-Register“ (SFR) auf die Portszu zugreifen. In der Regel verfügt ein 8051-Controller noch über viele weitere SFR zurKonfiguration verschiedenster Hardware-Einstellungen. Diese Register können aberdurchaus auf verschiedenen Kontrollertypen variieren. Dies ist einer der großen Vorteileder 8051-Architektur. Wird eine neue oder erweiterte Funktionalität in einen Controllerintegriert (z.B. On-Chip AD/DA-Wandler, USB-Schnittstellen, CAN-Schnittstellen ...),wird lediglich der Satz an zur Verfügung stehenden SFR erweitert und die neue Hardware wird über diese zugänglich gemacht.

Wenden wir uns jetzt aber den SFR zu, die auf beinahe allen 8051-Derivaten gleich sind:Den I/O-Ports. Die Ports stehen im Controller an den SFR-Adressen 0x80 für PORT0,0x90 für PORT1, 0xA0 für PORT2 und 0xB0 für PORT3 zur Verfügung. Um sich nicht jedes mal mit den Adressen herumschlagen zu müssen, binden wir den Header „reg51.h“ ein. Dort werden den SFR Symbole zugeordnet. So wird aus der Adresse 0x80 (SFR PORT0) das Symbol P0. In unserem Programm wird also eine Wertzuweisung von 0xFF an PORT0 des Controllers lediglich mit „P0 = 0xFF“ beschrieben.

Ein einfaches Blinklicht an P2 (abwechselnd alle Ein / alle Aus) könnte in etwa so aus-sehen :

while(1){ P2 = 0xFF; _wait_ms(1000); P2 = 0x00; _wait_ms(1000);}

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 11 / 36

Page 12: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Im Header reg51.h werden neben den Symbolen zum Byte weisen Zugriff auf die SFR auch Symbole für die einzelnen Bits der Register zur Verfügung gestellt. Die einzelnen Bits der Ports werden lediglich mit dem Zusatz „_B0“ (z.B. P0_B1, P1_B3,P2_B0 usw.) versehen Ein weiteres Blinklicht: Wir lassen abwechselnd P2_B0 und P2_B1 blinken:

while (1){ P2_B0 = 1; P2_B1=0; _wait_ms(1000); P2_B0=0; P2_B1=1: _wait_ms(1000);}

Ein Port kann auch sehr unkompliziert eingelesen werden, hier einige Beispiele:

In diesem Beispiel lesen wir Port 0 ein und geben den Zustand gleich wieder an P2 aus.

while (1){ P2 = P0;}

Der Zustand des Ports kann unkompliziert auf der seriellen Schnittstelle ausgegeben werden:

printf("Zustand Port 0 : %u",P0);

Natürlich kann der Wert eines Ports auch in Variablen zur weiteren Verarbeitung abgelegtwerden:

unsigned char inData = 0;inData = P0;P2 = inData & 0x0F;

An dieser Stelle wäre jetzt der richtige Zeitpunkt, sich intensiv mit dem Demo zu beschäftigen ! Viel Spaß beim experimentieren!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 12 / 36

Page 13: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

7. Hallo Welt mit Watchdog

Wie bereits in der Hardwarebeschreibung erwähnt, verfügt der AT89C51ED2 über einen internen Watchdog. Dieser wird verwendet um sicherzustellen, dass der Controller, falls das Programm „hängen“ bleibt, durch einen Reset wieder zum Leben erweckt wird. Bei der Verwendung des Watchdogs ist ist zu beachten: einmal vom Programm aus aktiviert, kann der Watchdog nicht mehr ausgeschaltet werden. Insbesondere in Warteschleifen und bei Eingaben über die serielle Schnittstelle kann die Verwendung des Watchdogs proble-matisch werden. Trotzdem soll der Watchdog hier näher vorgestellt werden.

Der Watchdog besteht im wesentlichen aus einem 14-Bit-Zähler, der aus dem Taktsignal des Controllers gespeist wird. Sobald der Zähler überläuft, wird ein Reset ausgelöst. Um den Reset zu verhindern, muß der Zähler vor dem Überlauf wieder zurückgesetzt werden. Der Zähler wird zurückgesetzt in dem in das WDTRST-SFR hintereinander 0x1Eund 0xE1 geschrieben wird.

Die Timeout-Zeit des Watchdogs ist über das SFR WDTPRG in acht Schritten einstellbar.

Unter c:\ed2_tb\ed2_sup\init_ed2.h und c:\ed2_tb\ed2_sup\init_ed2.c stehen bereits fertige Routinen für den Watchdog zur Verfügung. Um den Watchdog zu aktivieren wird die Funktion

enableWatchdog(unsigned char value);

aufgerufen. Der Funktion muß noch eine der acht bereits vordefinierten Timeout-Konstanten übergeben werden.

Die Timeout-Konstanten sind als Makros in init_ed2.h mit folgenden Werten vordefiniert :

#define WDT_8MS 0 //!< Zeitkonstante Watchdogtimer ~8ms bei 24MHz#define WDT_16MS 1 //!< Zeitkonstante Watchdogtimer ~16ms bei 24MHz#define WDT_33MS 2 //!< Zeitkonstante Watchdogtimer ~33ms bei 24MHz#define WDT_65MS 3 //!< Zeitkonstante Watchdogtimer ~65ms bei 24MHz#define WDT_136MS 4 //!< Zeitkonstante Watchdogtimer ~136ms bei 24MHz#define WDT_260MS 5 //!< Zeitkonstante Watchdogtimer ~260ms bei 24MHz#define WDT_500MS 6 //!< Zeitkonstante Watchdogtimer ~500ms bei 24MHz#define WDT_1S 7 //!< Zeitkonstante Watchdogtimer ~1s bei 24MHz

Wie an den Kommentaren ersichtlich, sind die Zeitkonstanten für eine externe Quarzfrequenz von ca. 24MHz ausgelegt. Wird eine andere Frequenz für den Quarz verwendet, müssen die Zeitintervalle neu berechnet werden. Details dazu finden sich im Datenblatt des Controllers.

Sobald der Watchdog mit der Funktion enableWatchdog() aktiviert wurde, muß der Zählerregelmäßig mit der Funktion WDSERV() zurückgesetzt werden.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 13 / 36

Page 14: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Die Funktionen enableWatchdog() und WDSERV() sind mit der Compilervariable USE_WDverknüpft. Wird diese Variable im Makefile nicht angegeben, werden beim kompilieren des Quellcodes leere Funktionen angelegt. Das bedeutet, der Aufruf der Funktionen hat keine Auswirkung, der Watchdog wird nicht aktiviert und das WDTRST-Register wird auch nicht zurückgesetzt. Sobald die Compilervariable angegeben wird, werden die Funktionen tatsächlich mit dem benötigtem Code gefüllt. Diese Vorgehensweise erlaubt es, während des Entwicklungs- und Testprozesses den Watchdog bereits passend einzubauen, jedoch erst beim übersetzen der finalen Version zu aktivieren.

Im Makefile muss also zum tatsächlichen aktivieren des Watchdogs die Zeile

C51FLAGS = -dUSE_WD

eingetragen werden.

Um leere Funktionen für den Watchdog zu erzeugen, genügt es die Zeile mit

#C51FLAGS = -dUSE_WD

zu deaktivieren.

Ein Hauptprogramm mit Watchdog könnte in etwa so aussehen:

void main(void){ initSerial(); enableWatchdog(WDT_260ms); // Watchdog mit 260ms-Timeout aktivieren

while(1) { doSomething(); // wir erfüllen eine Aufgabe WDSERV(); // zwischendurch (vor Ablauf der 260ms) wird der

// Zähler zurückgesetzt doSomething(); }}

Ein praktisches Beispiel für den Watchdog findet sich unter c:\ed2_tb\ed2_wd. Im Makefileist der Watchdog bereits aktiviert, daß Workspace-File ist ebenfalls bereits vorhanden.

Viel Vergnügen beim ausprobieren!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 14 / 36

Page 15: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

8. Zugriff auf den internen EEPROM

Unser Controller verfügt über einen internen EEPROM mit einer Größe von 2kB (2048 Bytes). Der EEPROM ist ideal geeignet um z.B. Konfigurationsdaten zu hinterlegen. Logischerweise gehen die Daten, die in dem EEPROM hinterlegt werden durch einen Spannungsverlust oder beim ausschalten eines Gerätes nicht verloren. Leider sind die Zugriffe auf den internen EEPROM nicht ganz unkompliziert und auch nicht besonders schnell (ein Schreibzugriff dauert etwa 2,5ms).

Um die Zugriffe auf den internen EEPROM einfach realisieren zu können, wurde eine Schreib- sowie eine Leseroutine zur Abarbeitung einzelner Bytes implementiert (vgl. Header/C-File eeprom_ed2 im Verzeichnis c:\ed2_tb\ed2_sup). Hier die beiden Funktionen:

unsigned char readEEPROM(unsigned int adr);void writeEEPROM(unsigned int adr, unsigned char dat);

- - - Jetzt wird es etwas „tricky“ :-) - - -

Um die Funktionen in einer Hochsprache wie C zu realisieren, sind einige Dinge zu beachten: Der Zugriff auf das interne EEPROM wird zur Verfügung gestellt, sobald im EECON-Register das Bit EEE (Bit 2) gesetzt wird. Der EEPROM wird dann in den erweiterten Speicherbereich (xdata) gemappt und ist über „normale“ Schreibfunktionen erreichbar. Dummerweise ist dann natürlich der xdata-Space (hier werden bei uns die Variablen hinterlegt) nicht mehr erreichbar. Das bedeutet im Klartext: sobald das EEPROM-Mapping aktiviert ist, haben wir keinen Zugriff mehr auf die Variablen, die wir unseren Funktionen mitgeben (Übergabe der Adressen und Daten). Um dieses Problem zu umschiffen, sind im C-File die globalen Variablen EEPROM_ADRESS und EEPROM_DATA definiert. Diese Globalen Variablen sind mit dem Zusatz „near“ versehen:

near unsigned int EEPROM_ADRESS; near unsigned char EEPROM_DATA;

Durch „near“ wird der Compiler angewiesen, die Daten in den Variablen nicht im xdata-Speicher sondern im „near“-Speicher anzulegen (die ersten 128 Byte im internen RAM des Controllers). Da der near-Speicher anders angesprochen wird als der xdata-Speicher bleibt der Zugriff auf die near-Variablen auch dann erhalten, wenn der xdata-Speicher vom EEPROM überlagert wird. Die beiden Schreib-/Lese-Routinen müssen also, bevor dass EEPROM-Mapping aktiviert wird, die übergebenen Variablen in die globalen near-Variablen kopieren. Als weiteren Punkt müssen wir beachten, dass die Interrupts gesichert und deaktiviert werden müssen. Würde ein Interrupt ausgelöst, während noch der EEPROM in den Speicher gemappt ist, könnten die Interrupt-Routinen nicht mehr auf den xdata-Speicher zugreifen. In diesem Fall würden bestimmt ganz tolle Dinge passieren, mit Sicherheit jedoch nichts, was wir uns wünschen.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 15 / 36

Page 16: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Um den Zugriff auf den EEPROM einfach gewährleisten zu können, wird im C-File das Charakter-Array EEPROM mit 2048 Bytes größe an der Adresse 0x0000 definiert. Diese Deklaration erzeugt keinen Code, hilft dem Compiler jedoch auf die Sprünge. Durch die Deklaration des EEPROMS wird ein einfacher Zugriff ermöglicht: Um z.B Adresse 0x100 auszulesen, genügt folgende Quellcodezeile:

EEPROM_DATA = EEPROM[0x100];

Der Compiler erzeugt beim übersetzen nun den passenden Code, der auf die Stelle 0x100 im vom Compiler angenommenen xdata-Speicher zugreift. Tatsächlich erhalten wir aber das Byte an Adresse 0x100 des EEPROMS zurück.

Nach dem der EEPROM nicht mehr benötigt wird, wird das Mapping durch zurücksetzen des EEE-Bits im EECON-Register deaktiviert.

Nun gibt es eigentlich nur noch eines zu beachten: Bevor auf das EEPROM zugegriffen werden darf, muß überprüft werden, ob das EEE-Busy-Flag (Bit 1) im EECON-Register vom Controller gelöscht wurde. Dieses Flag bleibt so lange gesetzt, bis der letzte Schreibzugriff auf den EEPROM vollständig abgeschlossen wurde. Das Bit kann nicht von der Software aus überschrieben werden. Einzig die Programmierlogik des EEPROM kann dieses Bit setzen oder löschen. Ein erneuter Zugriff auf den EEPROM, während dieser den vorherigen Schreibzugriff noch nicht abgeschlossen hat, kann zu korrupten Daten im EEPROM führen und muss unbedingt vermieden werden. Diesem Umstand wird bereits in der Implemen-tation der Funktionen Rechnung getragen.

Unter c:\ed2_tb\ed2_eeprom befindet sich ein einfaches Beispiel für Zugriffe auf denEEPROM unter Verwendung der bereits vorgefertigten Funktionen aus den Headern/C-Dateien c:\ed2_tb\ed2_sup\eeprom_ed2.c und eeprom_ed2.h

Ein weiteres Beispiel (einfaches Codeschloss) befindet sich unter c:\ed2_tb\ed2_code.

Viel Spaß beim austesten!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 16 / 36

Page 17: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

9. Zugriff auf den I²C-Bus

Beim I²C-Bus handelt es sich um einen seriellen Datenbus der lediglich zwei Leitungen für die Kommunikation benötigt. Bei diesem System übernimmt eine Leitung den Bus-Clock (SCL), die zweite Leitung den Datencarrier (SDA). Ein wesentlicher Vorteil dieses Busses ist die weite Verbreitung und einfache Beschaffbarkeit von Bausteinen. Die einzelnen Bausteine verfügen jeweils über eine eigene Adresse und werden von einem Master (in unserem Fall der Controller) angesprochen. Die maximale Taktrate des Busses beträgt in der Regel 100kHz, neuere Bausteine am Markt können sogar mit bis zu 400kHz betrieben werden. Die vergleichsweise niedrige Taktrate macht den I²C-Bus natürlich für High-Speed -Anwendungen wie schnelle Datenerfassungssysteme und der gleichen zwar Teilweise unbrauchbar, jedoch eignet er sich sehr gut für verschiedenste Steuer- Ein-/Ausgabe- und einfache Speichersysteme. Da nur zwei Leitungen als Kommunikationskanal zwischen den verschiedenen Baugruppen verwendet werden müssen, fallen insbesondere Leiterplatten-layouts in der Regel wesentlich einfacher aus als bei Parallel-Bus-Systemen. Auf Grund der einfach gehaltenen Busstruktur und der niedrigen Taktrate zeigt sich der Bus recht robust gegenüber Störungen.

Detaillierte Informationen zum I²C-Bus sind im Verzeichnis C:\ed2_tb\doc\i2c unter„philips_i2c_handbook.pdf“ und „design_con_2003_tecforum_i2c_bus_overview.pdf“ zu finden (Quelle : jeweils www.philips.com). Dort finden sich auch die Datenblätter der im folgenden verwendeten I²C-ICs.

Wir beschäftigen uns mit drei sehr weit verbreiteten Bausteinen, die in verschiedensten Anwendungen eingesetzt werden können. Dies Umfasst: Parallel-I/O, AD/DA-Wandler sowie einen Temperatursensor.

Beim verwendeten Testboard ist der I²C-Bus an X3 herausgeführt und kann von dort aus über ein Flachbandkabel auf Erweiterungsboards geführt werden.

Eigentlich war von den Machern des I²C-Bus angedacht, dass Systeme die lediglich über Parallel-I/O's verfügen, über spezielle Wandlerbausteine „Bus-fähig“ gemacht werden. Der relativ langsame I²C-Bus lässt sich jedoch auf modernen Mikrocontrollern problemlos auch in Software nachbilden. Externe Wandlerbausteine können entfallen, anstatt 8-10 Parallel-Leitungen werden nur zwei belegt. Die für den Bus abgestellten Leitungen müssen lediglich mit jeweils einem 3,3kOhm Pull-Up-Widerstand versehen werden um die Busspezifikation einzuhalten. Bei der Implementierung der benötigten Funktionen muss darauf geachtet werden, dass die Signallänge etwa 4,7µs entspricht. Dies bedeutet, dass die Geschwindigkeit des Controllers also insbesondere Maschinenzykluszeit und verwendete Quarzfrequenz beachtet werden müssen. Im Lieferumfang des Compilers befindet sich bereits eine sehr umfangreiche Softwareimplementierung des I²C-Busses.Das von Wickenhäuser mitgelieferte Library wird freundlicherweise im Quellcode zur freien Weiterentwicklung weitergegeben. Um das ED2-Testboard optimal unterstützen zu können, wurde eine eigene Version des Libraries erstellt. Dieses basiert jedoch nahezu

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 17 / 36

Page 18: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

vollständig auf dem mitgelieferten Quellen und wurde lediglich an die Hardware angepasst. Hinzu kam noch die direkte Unterstützung des AD/DA-Wandlers und des Temperatursensors. Ebenfalls wurde das neu aufgebaute Library um eine Dokumentation erweitert. (vgl. Verzeichnis c:\ed2_tb\i2clib\html\index.html). Um vernünftig mit dem I²C-Library arbeiten zu können, muss zu jedem Projekt wieder init_ed2.h eingebunden und init_ed2.c gelinkt werden. In dieser Datei befindet sich die Assemblerroutine

_i2c_wait:

Diese Funktion überschreibt die Version, die im I²C-Library für Standard-8051-Systeme mit 11,0592MHz Quarztakt vordefiniert ist. Mit der lokalen Version von I²C-Wait passen wir das Timing des Busses an unsere Controller an. Näheres zur Umsetzung ist in der Doku zum I²C-Library unter c:\ed2_tb\i2clib\html\index.html zu finden. Dort sind auch alle zur Verfügung stehenden Funktionen des i2clib dokumentiert.

Im i2clib werden diverse Quellcode-Dateien zusammengefasst. Bei der Verwendung des Libraries werden also nicht die einzelnen Quellcodedateien in das Projekt eingebunden, sondern lediglich die benötigten Header, zusätzlich muss dem Compiler mitgeteilt werden,welches Library beim übersetzen eingebunden werden soll. Doch der Reihe nach: bevor das Library verwendet werden kann, muss dieses in einem separaten Schritt erzeugt werden. Dies kann bequem mittels der im Verzeichnis c:\ed2_tb\i2clib vorbereiteten Batch-Datei „build_i2clib.bat“ erfolgen. Nach dem der Compiler die einzelnen Dateien übersetzt hat, linkt er die Dateien zum kompletten Library „i2clib.lib“. Im nächsten Schritt muss dann das fertige Library dem Projekt hinzugefügt werden. Dies geschieht unter Verwendung des „Makewiz“ im Feld „Additional Libraries and Objects“ im Tab „Linker“ :

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 18 / 36

Page 19: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Direkt in der Make-Datei wird das Library wie folgt eingebunden:

L51LIBS = -l../i2clib/i2c_lib.lib

Doch warum jetzt der Aufwand mit dem Library ???Ganz einfach: In Libraries werden in der Regel Funktionen und Funktionsblöcke zusammen gefasst, die direkt voneinander abhängig sind und sich in der praktischen Anwendung eher selten ändern. Zum Beispiel kann der Quellcode von pcf8591.c nie ohne die verwendeten Low-Level-Funktionen aus i2c_ll.s51 verwendet werden. Das Library ändert sich eigentlich nur, wenn ein neues IC aufgenommen wird. Jedes neue IC kann direkt mit den Low-Level-Funktionen implementiert werden, es gibt keinen Grund die I²C-Pins am Controller direkt anzusteuern. Ähnliche Konzepte sind z.B. auf Windows-PCs in Form von DLLs zu finden.

Nun aber an die Software: unter c:\ed2_tb\ed2_i2c_test steht ein kleines Testprogramm zur Verfügung, welches den I²C-Bus nach verfügbaren Bausteinen durch scannt. Dabei macht es sich die Eigenheiten des I²C-Busses sowie der hervorragenden Implementierung des Busses durch Wickenhäuser zu nutze. Das Library spricht nicht nur die Bausteine an, es wird gleichzeitig eine Überprüfung und Rückmeldung der Kommunikation durchgeführt. Dafür wird von jedem Funktionsaufruf ein integer zurückgeliefert, in dessen High-Byte ein möglicher Fehlercode ein codiert ist. Eine Liste der Codes ist unter c:\ed2_tb\i2clib\html\index.html zu finden. Das Testprogramm macht sich den Fehlercode zunutze und versucht auf allen Adressen von 2..254 einen Baustein anzusprechen. Durch Auswertung des Fehlercodes kann einfach erkannt werden, ob ein Baustein an der aktuell getesteten Adresse vorhanden ist. In Verbindung mit dem Board aus c:\ed2_tb\doc\hw\AT_I2C sollten Bausteine an drei Adressen gefunden werden.

Viel Spaß mit ed2_i2c_test!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 19 / 36

Page 20: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

10.I²C-Parallel-I/O-Baustein PCF8574

Für Parallel-I/O-Erweiterungen am I²C-Bus ist der PCF8574 eine sehr gute Wahl. Dieser Baustein verfügt über insgesamt vier mögliche Basisadressen. Dadurch können bis zu vier gleiche Bausteine, jeweils mit einer eigenen Adresse versehen, am I²C-Bus betrieben werden. Zusätzlich wird dieser Baustein vom Hersteller in den Ausführungen PCF8574P und PCF8574AP geliefert. Der P-Typ verfügt über die Basisadressen 64dez. - 70dez., derAP-Typ über die Adressen 112dez – 118dez. Dadurch wird es möglich sogar bis zu acht dieser Bausteine an einem Bus zu betrieben. Es ergibt sich ein maximaler Ausbau von bis zu 64 Parallel-I/O-Pins. Jeder Baustein kann entweder als 8-Bit Eingangs- oder 8-Bit Ausgangsport betrieben werden. Die Umschaltung, ob eine Baustein als Ein- oder Ausgangbetrieben wird, ist lediglich von der Art der Abfrage abhängig. Wird ein Lesezugriff auf den Baustein ausgeführt, wird der Zustand an den Port-Pins zurückgeliefert. Wird ein Schreibzugriff ausgeführt, werden die Daten an die Port-Pins geschrieben. Dabei ist zu beachten, dass am Baustein, wenn er als Eingang verwendet wird, zuerst alle Port-Pins mit logisch eins beschrieben werden müssen. Wird ein Baustein ausschließlich als Eingang betrieben (also von der Software nie neu beschrieben) kann dies entfallen, der Zustand aller Port-Pins nach dem Einschaltreset ist definiert logisch eins. Zu beachten gilt noch, dass der Baustein, ähnlich wie die Port-Pins im Controller, intern nur über einen Pull-Up- Widerstand verfügt und lediglich gegen Masse tatsächlich schalten kann. Sollen z.B. LEDs direkt an den Baustein angeschlossen werden, kann der PCF8574 nur vernünftig eingesetzt werden, wenn dieser die LEDs gegen Masse schaltet. In der Praxis empfiehlt es sich aber sowieso einen geeigneten Leistungstreiber (z.B. ULN2803A) nach zuschalten.

Nun zur Software :Der PCF8574 ist einer der einfachsten ICs der überhaupt für den I²C-Bus erhältlich ist.Daher kann dieser Baustein direkt mit den Low-Level-Routinen des I²C-Libraries angesprochen werden. Einige Funktionen und deren Anwendung werden im Beispiel unter C:\ed2_tb\ed2_i2c_pio vorgestellt. An dieser Stelle sei nochmals auf die Dokumentation unter C:\ed2_tb\i2clib\html\index.html verwiesen. Dort findet sich eine sehr ausführliche Beschreibung aller Funktionen des Libraries.

Viel Spaß beim testen!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 20 / 36

Page 21: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

11.I²C- AD/DA-Wandler PCF8591P

Beim PCF8591P handelt es sich um einen kleinen aber leistungsfähigen Baustein,der über vier Analogeingänge und einen Analogausgang verfügt. Die Analogeingänge lassen sich als Single-Ended (massebezogen) oder als differenzielle Eingänge betreiben. Die genauen Kombinationen sind im Datenblatt unter c:\ed2_tb\doc\i2c zu finden. Für den Baustein steht der Header pcf8591.h zur Verfügung. Dem Projekt muss die Datei pcf8591.c aus dem i2clib-Verzeichnis hinzugefügt werden. Es empfiehlt sich, die Quellen etwas genauer unter die Lupe zu nehmen. Die Implementation des PCF8591 zeigt, wie ein komplexeres Bauteil mit Hilfe der Low-Level-Funktionen eingebunden werden kann.

In der Dokumentation des i2clib ist auch eine ausführliche Beschreibung der Funktionen für den PCF8591 enthalten.

Die Ansteuerung wird unter c:\ed2_tb\ed2_i2c_adda demonstriert.

Viel Spaß beim testen!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 21 / 36

Page 22: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

12.I²C-Temperatursensor LM75

Ein weiteres, recht verbreitetes Bauteil ist der Temperatursensor LM75. Dieser Baustein ist in diversen Ausführungen erhältlich und deckt einen Temperaturbereich von -25°C bis +100°C bei einer Toleranz von +- 2°C bzw. -55°C bis +125°C bei +- 3°C ab. Geeignet ist der Baustein jedoch nur zur Systemüberwachung oder für einfache Innentemperatur-messungen, da er nur im SMD-SOT8 Gehäuse erhältlich ist. Am Markt sind teilweise auch noch Bausteine im DIP8-(THT)-Gehäuse erhältlich, beim Hersteller ist diese Gehäuse-variante mittlerweile jedoch ab gekündigt. Weit verbreitet sind dies ICs teilweise auf PC-Motherboards sowie in industriellen Steuerungssystemen zu Überwachung der Betriebs-temperaturen der Elektronik sowie als thermischer Schutz. Trotz der eingeschränkten Anwendbarkeit des ICs steht unter c:\ed2_tb\ed2_i2c_temp ein Beispiel zur Verfügung.

Viel Spaß beim testen!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 22 / 36

Page 23: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

13.LC-Displays

Im Lieferumfang des Compilers befindet sich ein hervorragend implementierter Treiber für die weit verbreiteten LC-Displays auf Basis des HD44078A-Displaytreiber-ICs. Diese Displays sind in verschiedensten Ausführungen am Markt erhältlich und verfügen über zwei verschiedene Betriebsarten. Zum einen ist dies der 8-Bit-Parallel-Mode, hier werden die einzelnen Datenbytes Byte-Weise übertragen. Zusammen mit den drei zur Kommu-nikation benötigten Steuerleitungen werden also 11 I/O-Leitungen am Controller belegt. Die zweite Betriebsart ermöglicht es, die Datenbytes zerlegt in je ein HIGH-Nibble (die oberen vier Bit) und ein LOW-Nibble (die unteren vier Bit) über vier Datenleitungen zu übertragen. Zusammen mit den drei Steuerleitungen werden also nur 7 I/O-Leitungen am Controller belegt. Einzigster Nachteil dieser Variante ist die langsamere Datenübertragung zwischen Controller und LC-Display. Dies ist jedoch in der Praxis nicht störend, sichtbar ist die Verzögerung aufgrund der Trägheit des Displays ohnehin nicht. Der mitgelieferte Treiber unterstützt Displays mit vier Zeilen und 20 Zeichen pro Zeile. Zwar ist der Treiber im Quellcode sehr leicht anpassbar, jedoch ist es nicht besonders effizient, wenn für jedes Display (1,2 oder 4 Zeilen, verschiedenste Zeichenanzahl usw.)jedes mal der Quellcode umgearbeitet werden muss. Deshalb wurde der Treiber überarbeitet und unterstützt in der vorliegenden Version beliebig viele Zeilen und Zeichen. Die Anpassung auf das aktuell verwendete Display erfolgt einfach über Compilerschalter in der Make-Datei. Zusätzlich unterstützt der Treiber jetzt auch Displaycontroller des Typs KS0066 (Funktionskompatibel mit dem HD44078A, jedoch langsameres Timing) sowie KS0073 (andere Initialisierung nötig).Die Quellen für den Displaytreiber befinden sich unter c:\ed2_tb\ed2_sup in den Dateien lcd_4bp.c und lcd_drv.c. Diese beiden Dateien müssen dem Projekt hinzugefügt und mit kompiliert werden.

In den Quellcode muss lediglich der Header lcd_drv.h eingebunden werden. Als Port für das LC-Display wird P0 angenommen. Dieser Port kann jedoch in lcd_4bp.c unter

#define LCD_PORT

problemlos verändert werden.

Die Anpassung an das Display wird in der Makedatei über die Compilerschalter „DISPLAY_LINES=x“ und „DISPLAY_CHARS=x“ festgelegt. Zusätzlich kann mit dem Compilerschalter „KS0073“ die Unterstützung für diesen Controllertyp aktiviert werden.

Ohne Angabe der Compilerschalter wird ein Display mit HD44078A/KS0066-Controller und 2 Zeilen x 16 Zeichen angenommen.

Eine Dokumentation der Funktionen zum Betrieb des Displays ist unter C:\ed2_tb\ed2_sup\html\index.html zu finden.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 23 / 36

Page 24: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Unter c:\ed2_tb\doc\hw\AT_LCD befindet sich ein Bauvorschlag für eine Anzeigeleiter-platte die an die 25polige SUB-D-Buchse am Testboard angeschlossen werden kann.

Ein Code-Beispiel befindet sich unter c:\ed2_tb\ed2_lcd, im Makefile wird die Verwendung der Compilerschalter aufgezeigt.

Viel Spaß beim testen!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 24 / 36

Page 25: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

14.Interrupts

Interrupts werden verwendet, um hardwaregesteuert eine Unterbrechung des Haupt-programms anzufordern (IRQ -> Interrupt-Request -> Unterbrechungsanforderung). Wird am Controller ein IRQ ausgelöst, wird der aktuell bearbeitete Befehl noch vom Controller verarbeitet, anschließend wird der Zustand des Programms gespeichert und die ISR (Interrupt-Service-Routine) zum zugehörigen Interrupt angesprungen. Sobald die ISR abgeschlossen ist, wird der Zustand des Programms restauriert und an dieser Stelle fortgesetzt. Je nach Controllervariante können verschiedene Interruptquellen existieren. Die Funktionsweise ist jedoch immer die selbe: Beim Programmstart wird die Interruptvektortabelle des Controllers mit den Sprungadressen zur zugehörigen ISR initialisiert. Wird ein Interrupt ausgelöst, ließt der Controller die Sprungadresse aus der Vektortabelle und springt in den Speicherbereich, in dem die ISR abgelegt ist. Interrupts werden z.B. von externer Hardware verwendet um zu signalisieren, daß neue Daten vorhanden sind oder eine externe Aufgabe erledigt wurde (AD/DA-Wandler usw.).

Der hier verwendete AT89C51ED2 verfügt insgesamt über 9 mögliche Interruptquellen.Im einzelnen sind dies :

– INT0 externes Interruptsignal an P3.2– INT1 externes Interruptsignal an P3.3– TF0 internes Interruptsignal von Timer / Counter 0– TF1 internes Interruptsignal von Timer / Counter 1– TF2 internes Interruptsignal von Timer / Counter 2– UART Interruptsignal von der seriellen Schnittstelle– PCA internes Interruptsignal vom Counter-Array– Keyboard Interruptsignal vom Keyboard-Interface– SPI Interruptsignal vom SPI-Interface

Die Interrupts INT0,INT1, TF0, TF1 und UART sind „Grundausstattung“ der 8051-Architektur und auf nahezu jedem Derivat dieser Familie zu finden. Sollen die externen Interrupts INT0 und INT1 verwendet werden, können diese Pins nicht mehr für andere Aufgaben herangezogen werden (außer man gibt sich etwas Mühe).Interrupts, auf die reagiert werden soll, können einzeln im Register IEN0 aktiviert bzw. deaktiviert werden. Zusätzlich kann in diesem Register über das Bit EA die Interrupt-verarbeitung generell deaktiviert werden. Ausführliche Details zum Aufbau der Interruptmaschine und der Register können dem Datenblatt des Controllers entnommen werden.

Die Verwendung von Interrupts in eigenen Programmen stellt sich beim verwendeten Compiler denkbar einfach dar: über ein Makro im Quellcode wird der Compiler veranlasst, den zugehörigen Interruptvektor zu initialisieren. Die ISR, die vom Controller aufgerufen werden soll, wird als normale Funktion im Quellcode geschrieben. Einzigster Unterschied dieser Funktion zu den anderen ist, dass zusätzlich das Schlüsselwort „interrupt“ hinter der

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 25 / 36

Page 26: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Funktionsdeklaration angegeben wird. Die ISR-Funktion wird nicht vom Hauptprogramm aufgerufen.

// Makro zum Registrieren der Interrupts :

IRQ_VECTOR(showInt0,IRQ_INT0) // Interrupt 0 registrieren, // Funktion showInt0() an Interrupt binden

Dem Makro IRQ_VECTOR wird lediglich der Funktionsname der ISR sowie die Einsprungadresse des Interrupts in der Interruptvektortabelle übergeben. Die Adresse ist hier in der Konstanten IRQ_INT0 aus irq52.h definiert.

// ISR für den Interrupt void showInt0(void) interrupt{ printf("Int 0 ausgeloest\n"); while(!P3_B2); printf("Taste (INT0) losgelassen ..\n");}

Die externen Interrupts reagieren generell auf ein LOW-Signal am betreffenden Pin. Über die Bits IT0 und IT1 des TCON-Registers kann beeinflusst werden, ob die Interrupts beiLOW-Level oder bei einer Flanke von HIGH nach LOW ausgelöst werden. Werden die IT0/IT1-Bits mit 1 beschrieben, reagiert die Interruptlogik auf Flanken, bei 0 auf LOW-Level.

Ein Beispiel für die Interruptverarbeitung ist unter c:\ed2_tb\ed2_int zu finden.

Viel Spaß beim experimentieren!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 26 / 36

Page 27: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

15.Timer

Der 8051 verfügt über zwei interne Timer / Counter die als Zeitgeber oder Ereigniszähler verwendet werden können. Die Verwendungsmöglichkeiten sind recht vielseitig, daher ist die Konfiguration auch etwas umfangreicher. In diesem Kapitel beschäftigen wir uns ausschließlich mit der Timerfunktion, die Counterfunktion wird in einem Späteren Kapitel näher besprochen.

Die Timer sind als 2x8-Bit Schieberegister ausgeführt, an die ein aus dem Systemtakt abgeleitetes Taktsignal angelegt wird. Bei einem Überlauf des Zählers wird ein Flag gesetzt. Dieses Flag kann direkt vom Programm ausgewertet werden. In der Regel ist es jedoch üblich (und in den meisten Anwendungsfällen sogar besser) bei einem Überlauf einen Interrupt auslösen zu lassen.

Die beiden Timer 0 und Timer 1 sind nahezu identisch aufgebaut und verfügen jeweils über vier verschiedene Betriebsarten, die in der Regel als „Modes“ (Mode 0 .. Mode 3) bezeichnet werden.

Im Mode 0 arbeiten beide Timer als 13-Bit Schieberegister. Sobald das Register überläuft, wird das Timer-Flag (TF0 bei Timer0 oder TF1 bei Timer1) im TCON-Register gesetzt. Sind die Timer-Interrupts aktiviert, wird durch die Timer-Flags der entsprechende Interrupt ausgelöst.

Der Mode 1 ist mit Mode 0 vergleichbar, jedoch werden alle 16 Bits der Schieberegister verwendet.

Der Mode 2 arbeitet als 8-Bit-Zähler im unteren Byte (TL0 oder TL1) und lädt bei einem Überlauf den Wert aus dem oberen Zählerbyte (TH0 oder TH1) automatisch wieder als Startwert nach. Damit ist es möglich, den Zähler im unteren Byte mit einem bestimmten Wert zu laden, von dem aus bis zum Überlauf gezählt wird. Dieser Mode wird häufig zum erzeugen der Baudrate für die serielle Schnittstelle verwendet.

Beim Mode 3 verhalten sich die Timer unterschiedlich: Timer 1 bleibt im Mode 3 einfach stehen. Timer 0 teilt sich in zwei unabhängige 8-Bit-Zähler (einer im TL0-Register und einer im TH0-Register) auf. Zur Steuerung von TL0 werden weiterhin die Control-Flags von Timer 0 verwendet, der Timer in TH0 verwendet jetzt jedoch die Flags von Timer 1. Dies bedeutet, das Timer 1 keine Interrupts mehr auslösen kann. Timer 1 kann jedoch problemlos noch für Aufgaben herangezogen werden, die keinen Überlaufinterrupt mehr benötigen wie z.B als Baudrategenerator im Mode 2.

In den beigefügten Beispielen wird grundsätzlich über die initSerial()-Routine aus ed2_sup.c Timer 1 im Mode 2 als Baudrategenerator betrieben. Deshalb fällt dieser Timer für die weitere Verwendung weg.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 27 / 36

Page 28: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Timer 0 im Mode 0:

Mode 0 möchte ich an dieser Stelle nur grob umreißen, da er sich nur in der Anzahl der Zählerbits (hier 13) von Mode 1 (mit 16 Bits) unterscheidet. Erwähnenswert bleibt lediglich der Aufbau des Zählerregisters: die oberen 8 Bit des Registers (TH0) werden als „normales“ 8-Bit Schieberegister verwendet. Die unteren 5 Bit des TL0-Registers implementieren die restlichen Bits des 13-Bit Schieberegisters. Die oberen drei Bit des TL0-Registers werden nicht verwendet.

Timer 0 Mode 1:

Um Timer 0 im Mode 1 betreiben zu können, muss das niederwertigste Bit des TMOD-Registers gesetzt werden. Dabei ist jedoch zu beachten: beim ändern der Einträge im TMOD-Register muss stets darauf geachtet werden, daß die oberen vier Bits, die Timer 1 kontrollieren, nicht verändert werden. Diese wurden bereits durch initSerial() korrekt als Baudrategenerator initialisiert. Werden die oberen vier Bits unkontrolliert überschrieben, wird die serielle Schnittstelle nicht mehr arbeiten. Um die oberen Bits des TMOD-Registers sicher zu erhalten, kann z.B mit folgender Anweisung initialisiert werden :

TMOD = (TMOD & 0xF0)+1; // High-Nibble wird erhalten, // LOW-Nibble auf 1 gesetzt

Als nächstes wird der Interrupt (sofern gewünscht) von T0 aktiviert:

ET0 = 1; // Interrupt bei Überlauf von T0 aktivieren

Die globale Interruptverarbeitung muss natürlich ebenfalls aktiviert werden:

EA=1; // Interrupts aktivieren

Der Timer ist jetzt initialisiert und die Interruptverarbeitung bei einem Überlauf aktiviert.Nun muss der Timer noch gestartet werden:

TR0 = 1; // Timer 0 RUN

Mit TR0 = 0; // Timer 0 STOP

kann der Timer jederzeit angehalten werden.

So, der Timer läuft jetzt und löst bei jedem Überlauf einen Interrupt aus, so viel haben wir bereits erreicht. Doch in welchen Intervallen läuft der Timer jetzt über?

Das Schieberegister unseres Timers wird bei jedem Maschinenzyklus um eine Stelle inkrementiert. Wir erinnern uns, daß unser Controller im X2-Mode sechs Systemtakte für einen Maschinenzyklus benötigt. Dies gilt prinzipiell natürlich auch für unsere Timer. Um die Funktion der Timer jedoch mit den Standard-8051 per default kompatibel zu halten,

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 28 / 36

Page 29: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

wird die den Zählern zugeführte Frequenz nochmals durch zwei geteilt. Wir kommen damit also wieder auf 12 Systemtakte pro Zählerschritt, was dem Verhalten eines 8051 entspricht. (Anmerkung: an geeigneter Stelle kann der „Vorteiler“ im X2-Mode auch deaktiviert werden, dann wird das Register alle 6 Systemtakte inkrementiert. Der interessierte Leser findet dazu mehr im Datenblatt des Controllers)

Die dem Schieberegister zugeführte Frequenz beträgt Systemclock / 12, in unseremFall also 22118400Hz / 12 = 1843200Hz. Da wir im Mode 1 ein 16-Bit großes Schieberegister verwenden, wird das Register mit einer Frequenz von 184300Hz / 216 Bits = 28,125Hz überlaufen.

Im vorbereiteten Beispiel zu den Timern wird bei einem Überlauf die ISR für Timer 0 aufgerufen. Dort wird jedes mal Bit 0 an P1 getoggelt. Wir können also an diesem Port eine Frequenz von 28,125Hz / 2 = 14,0625Hz messen.

Hier die Berechnung nochmals Zusammengefasst:

Schieberegistertakt = Systemtakt / 12Überlauffrequenz = Schieberegistertakt / 216 Bits

Das Ganze lässt sich jetzt natürlich auch in „Zeit“ ausdrücken:

Der Zähler wird alle ~543ns inkrementiert ( 1/Schieberegistertakt ) und läuft demzufolge alle ~543ns * 216 = ~35,6ms über.

Dies ist exakt die HIGH bzw. LOW-Zeit die im Beispiel an P1_B0 messbar ist.

Höhere Frequenzen lassen sich erreichen, in dem in der ISR das Schieberegister mit einem Wert ab dem gezählt werden soll initialisiert wird. Konkret: wir lassen den Timer bisher frei über alle 16 Bit zählen. Wenn wir jetzt in den Registern TL0 und TH0 einen Wert voreinstellen, zählt der Zähler nicht mehr von 0x0000 bis 0xFFFF sondern ab dem voreingestellten Wert. Damit sind wir in der Lage, daß Schieberegister schneller überlaufen zu lassen.

Ein Beispiel :Das Schieberegister soll alle 10ms überlaufen. Die Sollzeit wird durch den Schieberegistertakt geteilt: 10ms / 543ns = ~18416Nun wird vom Maximalwert des Zählers der errechnete Wert 18416 abgezogen:65535 – 18416 = 47119 -> 0xB80FUm den Timer jetzt mit unserem Wert zu initialisieren muss das Highbyte in TH0 und das Lowbyte in TL0 geschrieben werden. Damit läuft der Timer, wie gewünscht, alle ~10ms über. Der Quellcode der ISR sieht dann etwa so aus :

P1_B0 = ~P1_B0; // P1_B0 toggelnTH0 = 0xB8; // Highbyte ins ZählerregisterTL0 = 0x0F; // Lowbyte ins Zählerregister

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 29 / 36

Page 30: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Noch ein Hinweis am Rande : bei sehr kurzen Überlaufzeiten (z.B TH0 = 0xFF und TL0 = 0xF0) können die Zeiten nicht mehr optimal bestimmt werden, da der Quellcode der ISRselbst einige Maschinenzyklen „verbrät“. Hinzu kommt, daß während die ISR noch nicht beendet ist, ein erneuter Überlauf des Timers nicht beachtet wird. Insbesondere bei umfangreichen Funktionen in der ISR kann sich dies negativ auswirken.

Timer 0 im Mode 2:

Wie bereits erwähnt steht im Mode 2 ein 8-Bit Schieberegister in TL0 zur Verfügung welches bei einem Überlauf mit dem in TH0 hinterlegt Wert neu geladen wird. Dies erspart die im Mode 1 nötige Neuinitialisierung des Schieberegisters in der ISR. Nachteil des Mode 2 können die deutlich kürzeren Überlaufzeiten des Registers sein. Sollen niedrige Frequenzen erreicht werden, muss in der ISR evtl. ein Zähler implementiert werden. Die kürzeste Überlaufzeit des Registers liegt bei etwa ~543ns * 28 = ~139µs, was einerFrequenz von ca. 7200Hz entspricht. Im Beispiel ist ein 1Hz-Blinker an P1_B0 demonstriert.

Zuletzt bleibt noch der Hinweis auf die GATE-Bits des TCON-Registers. Sobald diese Bits gesetzt sind, fungieren die Interrupt-Eingänge (INT0 für T0 und INT1 für T1) als Freigabeleitungen für die Timer. Über die Gate-Funktion kann der Timer über ein externes Signal gestartet und gestoppt werden. Damit sind sehr einfach Zeitmessungen an externen Signalen möglich.

Das Beispiel zu den Timern befindet sich unter c:\ed2_tb\ed2_timer

Viel Spaß beim experimentieren!

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 30 / 36

Page 31: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

16.Mini-DAQ-System mit ADC0804

Beim ADC0804 handelt es sich um einen 8 Bit AD-Wandler mit Parallel-Interface. Der Wandler arbeitet nach dem Näherungsprinzip (successive Approximation). Die Taktrate des Wandlers beträgt ca. 600KHz, die Wandlungszeit liegt bei etwa 100µs. Der Analogeingang kann bis zu 5V ohne zusätzliche Beschaltung verarbeiten. Die Verwendung des Wandlers gestaltet sich recht einfach: Der Wandler muß lediglich mit einigen passiven Bauteilen beschaltet werden (haupt-sächlich für den internen Taktgenerator). Zur Anbindung an den Mikrocontroller werden die acht Datenleitungen des Wandlers direkt mit einem Port des Controllers verbunden. Zusätzlich werden noch die CS, RD, WR und INT-Leitungen mit einem weiteren Port des Controllers verbunden.

Die Ansteuerung des Wandlers geschieht wie folgt: Mit dem CS-Eingang kann der Wandler selektiert werden. Solange CS auf logisch HIGH liegt, befinden sich die Datenleitungen des Wandlers im hochohmigen Zustand. Dadurch ist es möglich, mehrere verschiedene Bausteine am selben Datenport, an dem sich auch der Wandler befindet zu betreiben. Durch ein LOW am CS wird der Wandler aktiviert, die Datenleitungen sind aktiv.

Mit einem gleichzeitigen LOW-Pegel an den CS- und WR-Eingängen des Wandlers wird dieser zurückgesetzt. Anschließend wird durch ein HIGH an einem der beiden Eingänge die Wandlung gestartet.

Sobald die Wandlung abgeschlossen ist und der digitalisierte Wert zur Verfügung steht, wird der INT-Ausgang des Wandlers auf LOW gezogen um das Ende der Wandlung zu signalisieren.

Die Daten werden vom Wandler auf den Port geschrieben, sobald CS und WR auf LOW gezogen werden. Gleichzeitig wird das INT-Signal vom Wandler wieder zurückgesetzt.Sobald CS und WR wieder auf HIGH gelegt wurden, kann die Wandlung von neuem gestartet werden.

Für den hier beschriebenen AD-Wandler steht bereits eine vollständig implementierte Funktionssammlung unter c:\ed2_tb\ad_da\adc0804.h/c zur Verfügung. Die zugehörige Dokumentation ist im Unterverzeichnis „html“ zu finden.Ein einfaches Erweiterungsboard ist unter c:\ed2_tb\doc\hw\AT_ADC0804 zu finden.

Ein Code-Beispiel für den AD-Wandler befindet sich unter c:\ed2_tb\ed2_ad0804.

Noch ein kurzer Hinweis: Da der Wandler in der vorgestellten Schaltung seine Referenz-spannung aus der Versorgungsspannung bezieht, ist es nötig den Wandler zu kalibrieren. Dies geschieht, in dem im Programm mit der Kalibrierroutine einfach die an Pin 20 des Wandlers anliegende Versorgungsspannung eingegeben wird.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 31 / 36

Page 32: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

17.Von stehenden Bildern oder VT52-Terminal

Bisher wurden die Ausgaben über die serielle Schnittstelle lediglich als ASCII-Zeichenstrom ohne weitere Formatierung oder gar Positionierung ausgegeben. Ausgaben auf das Terminalprogramm (bisher Flashmon) füllen den Bildschirm und scrollen Weg, sobald alle Zeilen beschrieben sind. Für Anzeigen oder Überwachungsfunktionen ist jedoch häufig ein „stehendes“ Bild von Vorteil. Ein Anwendungsbeispiel wäre z.B. eine permanente Darstellung von Portzuständen oder Messwerte eines A/D-Wandlers. Relativ einfach lassen sich „stehende“ Darstellungen unter Verwendung der bereits mehrere Jahrzehnte alten „Escape-Sequenzen“ realisieren. Die Escape-Sequenzen wurden zur Steuerung von Druckern und später auch zur Steuerung von Video-Terminals entwickelt. Das Verfahren stammt noch aus der „grauen Vorzeit“ der Computertechnik, finden jedoch auch heute noch weite Verbreitung. Die Video-Terminals waren ursprünglich nicht mehr als „Datensichtgeräte und Daten-eingabegeräte“ ohne eigene „Intelligenz“. Diese Video-Terminals zeigten lediglich Informationen an, die von einem Großrechner gesendet wurden und sendeten Tastatur Eingaben vom Terminal zum Großrechner. Eingegebene Kommandos wurden also nicht „lokal“ auf dem Terminal ausgeführt, sondern zum Großrechner übertragen und von diesem ausgeführt. Für die Kommunikation zwischen Rechner und Terminal wurden im Laufe der Zeit verschiedene Protokolle entwickelt, die sich zwar in Ihrem Befehlsumfang und Befehlssatz unterscheiden, jedoch immer gleich „eingebettet“ werden. Eingebettet ist hier durchaus der richtige Begriff. Die „Escapesequenzen“ sind Steuerkommandos, die im ASCII-Zeichenstrom mit übertragen werden, jedoch nicht sichtbar sind. Die Sequenzen werden vom Terminal ausgewertet und entsprechend interpretiert. Frühe Protokolle unterstützen hauptsächlich Funktionen zur Cursormanipulation (Positionierung des Cursors). Mit einem der ältesten Protokolle, dem sog. VT-52-Terminal, beschäftigen wir uns im folgenden.

Doch was ist nun eine Escapesequenz genau? - Nichts anderes als simple ASCII-Zeichen, die lediglich mit dem ESC-Zeichen beginnen. Hier ein einfaches Beispiel:Um den Cursor von der aktuellen Position aus um eine Zeile nach unten zu verschieben,wird lediglich die Zeichenfolge „ESC A“ (Hexadezimal „0x1B 0x41“) an das Terminal geschickt. Das Escape-Zeichen dient als Kennung, daß eines oder mehrere der folgenden Zeichen eine Escapesequenz darstellen. Das Terminal reagiert entsprechend darauf und setzt das Kommando um.

Um die Escapesequenzen komfortabel nutzen zu können wurden diese in den Dateien VT52_Terminal.h und VT52_Terminal.c (Verzeichnis c:\ed2_tb\terminals) bereits vollständig gekapselt. Dort ist im Unterverzeichnis „html“ auch eine Dokumentation der Funktionen zu finden.

Ein einfaches Beispiel zur Ausgabe unter Verwendung von Escapesequenzen befindet sich im Verzeichnis c:\ed2_tb\ed2_vt52.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 32 / 36

Page 33: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

An dieser Stelle aber noch wichtiger Hinweis: Das von uns verwendete Terminalprogramm (Flashmon) unterstützt leider keine Escapesequenzen, diese werden von Flashmon lediglich als „Zeichensalat“ dargestellt. Für die korrekte Darstellung müssen wir daher den etwas weiter entwickelten „Hyperterminal“, der zum Standardlieferumfang aller gängigen M$-Windows-Versionen gehört, verwenden. Der Hyperterminal sollte sich unter Start->Programme ->Zubehör-> Kommunikation->Hyperterminal befinden.Hyperterminal muß nach dem starten unter „Eigenschaften“->„Einstellungen“->„Emulation“ noch auf „VT52“ eingestellt werden. Sonst erhalten wir auch hier einen tollen Zeichensalat.

Der Ablauf beim Testen von Programmen mit VT-52-Escape-Sequenzen ist nun folgender:Die Software wird wie gehabt in den Controller geladen und anschließend Flashmon gestartet. Flashmon kann nun beendet werden und die Verbindung mit Hyperterminal zum Testboard aufgebaut werden. Flashmon muß nach dem Programm download unbedingt gestartet werden, da der Controller sonst im Reset-Zustand verbleibt! Bevor der Controller erneut programmiert werden kann, muß die serielle Verbindung am Hyperterminal geschlossen werden, da sonst die Schnittstelle blockiert ist und „FLIP“ den Controller nicht ansprechen kann.

Noch ein Hinweis am Rande: Sollte die beschriebene Vorgehensweise (Programmierung, Flashmon beenden, Hyperterminal verbinden) nicht Funktionieren, hilft nur noch das Umschalten der beiden DIP-Schalter vor und nach jedem Programmierdurchlauf.

Wenn das Übersetzen, der Download und die Einstellung von Hyperterminal korrekt funktioniert hat, sollte die Darstellung im Hyperterminal in etwa so aussehen:

Noch ein Hinweis für die Kenner der Materie: Die Implementation der VT52-Escape-sequenzen ist nicht vollständig, insbesondere Eingabesequenzen werden überhaupt nicht berücksichtigt.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 33 / 36

Page 34: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

18.Die Welt wird bunt oder VT100-Terminal

Die technische Weiterentwicklung machte natürlich auch bei den Terminals nicht halt, bald nach dem VT52-Terminal wurde ein erweitertes Terminal namens VT100 verfügbar. Dieses Terminal ist weitestgehend abwärts kompatibel, verfügt jedoch über weitere Kommandos/Escapesequenzen. Insbesondere die Möglichkeit der farbigen Darstellung von Text sowie die Möglichkeit von Fett- und Kursivdarstellung sind sehr interessant für die formatierte Darstellung von Informationen.

Auch hier ist bereits eine umfangreiche (wenn auch nicht vollständige) Implementation im Verzeichnis „c:\ed2_tb\terminals“ in den Dateien vt100_teminal.h und vt100_terminal.h vorbereitet. Eine erweiterte Version des Programm aus dem vorigen Kapitel mit farbiger Ausgabe ist unter „c:\ed2_tb\ed2_vt100“ zu finden.

Die Vorgehensweise ist die selbe wie beim VT52-Terminal, lediglich die Einstellungen des Hyperterminal unter „Eigenschaften“->„Einstellungen“->„Emulation“ müssen auf „VT100“ geändert werden.

Wenn alles wie vorgesehen funktioniert, sieht die Ausgabe des Hyperterminal etwa so aus:

Wer mehr zum Thema VT100-Terminal erfahren möchte sollte mal bei www.vt100.netvorbei schauen, dort gibt es jede Menge Infos rund um Video-Terminals.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 34 / 36

Page 35: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

19.Pulsweitenmodulation (PWM)

Bei der Pulsweitenmodulation handelt es sich um ein Verfahren, bei dem das Verhältnis zwischen der Ein- und der Auszeit eines Zustandes verändert wird. Im einfachsten Fall ist dies z.B. der Zustand eines PORT-Pins der unterschiedlich lange Ein- und Ausgeschaltet ist. Dieses Verfahren wird häufig für die Helligkeitssteuerung z.B. von Lampen, LEDs usw. verwendet. Andere Anwendungen sind auch in der Leistungselektronik (Leistungs-steuerung) sowie in der Automatisierungstechnik zu finden. Wir werden uns im folgenden mit der Helligkeitssteuerung einer einfachen LED an einem Port-Pin beschäftigen.

Um eine PWM zu realisieren, benötigen wir als erstes einen festen Zeitrahmen. Dieser Zeitrahmen startet immer wieder erneut. Innerhalb dieses Zeitrahmens wird nun das Verhältnis von Ein- und Auszeit eingestellt. In der Praxis lässt sich dies sehr einfach realisieren, in dem wir einen Timer im Mode 2 verwenden. Wir erinnern uns, der Timer wird bei Überlauf in diesem Mode selbstständig mit einem voreingestellten Wert neu geladen. Zusätzlich wird für der Interrupt des Timers aktiviert und eine passende Serviceroutine für den Interrupt geschrieben. Damit haben wir bereits einen festen Zeitrahmen,bei dessen Ablauf ein Interrupt ausgelöst und eine Funktion aufgerufen wird. Innerhalb der ISR wird nun ein Zähler verwendet der in jedem Schleifendurchlauf inkrementiert wird. Im Beispiel verwenden wir für den Zähler einen „unsigned char“, wir sind also in der Lage von 0 bis 255 zu zählen. Das Verhältnis zwischen Ein- und Auszeit lässt sich jetzt sehr einfach verändern, indem der verwendete PORT-Pin gesetzt wird, so lange der Zähler kleiner als ein bestimmter Wert ist. Überschreitet der Zähler den gewünschten Wert wird der Port-Pin zurückgesetzt.

Ein Beispiel:

/** * ISR für Timer 0 */void timer0ISR (void) interrupt // Es handelt sich um eine ISR{ if (cnt > level) // Wenn der Zähler größer als der ausgewählte Level ist P1_B0=1; // wird der Port gesetzt else P1_B0=0; // Sonst wird der Port zurückgesetzt cnt++; // Zähler bei jedem Timerüberlauf inkrementieren}

Im Hauptprogramm wird jetzt je nach Anforderung lediglich der Wert von „level“ ver-ändert – damit ist die PWM prinzipiell bereits am laufen.

Es gilt dabei aber, insbesondere bei der Helligkeitssteuerung, noch einiges zu beachten.Zum einen muß der Reload-Wert des Timers beachtet werden. Ist dieser Wert zu klein, kann es aufgrund des Zählers innerhalb der ISR des Timers zu einer „flackernden“ LED kommen. Wir müssen hier beachten, daß die Überlaufzeit des Timers durch unseren

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 35 / 36

Page 36: Inhaltsverzeichnisdominik-bollivo.de/packages/SW_Doku_AT89C51ED2-Testboard.pdfBegrenzung auf 8kB Binärcode reicht für dieses Tutorial und Projekte weit darüber hinaus. Für die

Softwaredokumentation AT89C51ED2 - Testboard

Zähler nochmals durch 255 geteilt wird! Andererseits sollte der Reload-Wert auch nicht zu groß werden, da sonst die ISR sehr häufig aufgerufen wird und damit den Ablauf anderer Programmteile deutlich verlangsamen kann. Mit einem Reload-Wert von TH0 = 0 ist z.B ein deutliches Flackern zu erkennen. Im folgenden Beispiel verwenden wir einen Reload-Wert von 128.Einen weiteren Punkt den es zu beachten gilt: Leider verhalten sich verschiedene Leuchtmittel (LEDs, Lampen usw.) nicht linear. Bedeutet: Bei einem Pulsverhältnis von 1:1 ist noch lange nicht gesagt, daß das Leuchtmittel auch tatsächlich mit halber Leuchtkraft leuchtet. Ganz im Gegenteil, die Leuchtmittel zeigen eher ein „logarithmisches“ Verhalten. Leider unterscheiden sich die Leuchtmittel auch sehr stark untereinander. Dies macht eine Anpassung mit einer Art „Kennlinie“ nötig. Im folgenden Softwarebeispiel wird dies erreicht, in dem ein Array mit der Kennlinie der LED angelegt wird.

unsigned char brightnes[]={ 255, 254, 253, 252, 251, 249, 247, 244, 239, 232, 223, 210, 191, 165, 128, 75, 0}; // 17 log. Werte (1x AUS, 16x Stufen ON)

Im Hauptprogramm wird jetzt nicht mehr der reale Wert abgefragt, sondern einer der 17Pegel. Je nach Pegel wird der zugehörige Wert aus dem Array gesucht. Damit ist es recht einfach möglich über die Tabelle die PWM an des tatsächliche Verhalten des jeweilige Leuchtmittels anzupassen. Die Abstufung in diesem Beispiel ist etwas grob, beim umschalten der Pegel ist der Helligkeitssprung deutlich zu sehen. Wer es etwas „smoother“ braucht, kann die Tabelle mit einem größeren Datentyp anlegen und eine entsprechend feinere Abstufung erreichen. Dann muß jedoch auch die Zählervariable in der Timer-ISR entsprechend angepasst werden.

Ein Beispiel ist unter c:\ed2_tb\ed2_pwm zu finden.Im Beispiel wird eine LED an Port1.0 angenommen.

SW_Doku_AT89C51ED2-Testboard.odt 23.07.06 Seite 36 / 36