Universita t Koblenz/Landau Studienarbeit



Ähnliche Dokumente
Dokumentation IBIS Monitor

Elektrische Logigsystem mit Rückführung

Einführung in die Welt der Microcontroller

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Interrupt-Programmierung

Microcontroller Kurs Microcontroller Kurs/Johannes Fuchs 1

Synchronisierung. Kommunikationstechnik, SS 08, Prof. Dr. Stefan Brunthaler 73

CU-R-CONTROL. Beschreibung zur Schaltung ATMega16-32+ISP MC-Controller Steuerung auf Basis ATMEL Mega16/32. Autor: Christian Ulrich

Wie halte ich Ordnung auf meiner Festplatte?

10. Elektrische Logiksysteme mit

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

WLAN Konfiguration. Michael Bukreus Seite 1

CMS.R. Bedienungsanleitung. Modul Cron. Copyright CMS.R Revision 1

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Software-Beschreibung Elektronische Identifikations-Systeme BIS Softwarekopplung PROFIBUS DP mit BIS C-60_2-...an S7

RS-Flip Flop, D-Flip Flop, J-K-Flip Flop, Zählschaltungen

Aufgaben Leiten Sie die Formeln (9) und (10) her! Vorbetrachtungen. Der High-Fall

Enigmail Konfiguration

S7-Hantierungsbausteine für R355, R6000 und R2700

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine

MSXFORUM - Exchange Server 2003 > SMTP Konfiguration von Exchange 2003

Technische Informatik Basispraktikum Sommersemester 2001

Primzahlen und RSA-Verschlüsselung

Simulation LIF5000. Abbildung 1

Wenn wir also versuchen auf einen anderen PC zuzugreifen, dann können wir sowohl per Name als auch mit der Adresse suchen.

DIGITALVARIO. Anleitung Bootloader. Ausgabe 0.1 deutsch für Direkt-Digital-Vario. Firmware ab Hardware 01 Seriennummer ab 0003

BELIEBIG GROßE TAPETEN

Erweiterung AE WWS Lite Win: AES Security Verschlüsselung

Umwandelung einer Physikalischen Größe in eine Elektrische

Informationen zum neuen Studmail häufige Fragen

MC-Hx 006. Einbindung des MC-Hx Modul als MODBus TCP Slave. MB DataTec GmbH. Stand:

Ablaufsteuerung Sequenzer, als Schaltstufen für den Amateurfunk.

Anleitung TempCW 2011

Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13. Teil IV: Programmieren an Beispielen

10.0 Quick Start mit AT89LP2052 Elliptecmotor Kit

Local Control Network

Befehlssatz zum High Speed Interface-88-USB (HSI-88-USB) (ab Firmware 0.71) (Version 1.2)

Anleitung über den Umgang mit Schildern

V o r w o r t. A n l e i t u n g

9 Multiplexer und Code-Umsetzer

Tag 2 Eingabe und Interrupts

Bekannte Effekte bei Soft- und Hardware der ESTEC Datenlogger sowie der PC Auswertesoftware

Zwischenablage (Bilder, Texte,...)

1 topologisches Sortieren

Aufbau und Bestückung der UHU-Servocontrollerplatine

Lieferschein Dorfstrasse 143 CH Kilchberg Telefon 01 / Telefax 01 / info@hp-engineering.com

3.14 Die Programmieroberfläche Programmierung

DSO. Abtastrate und Speichertiefe

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

KabelKiosk NDS CI+ Modul Fehlercode-Liste

Stepperfocuser 2.0 mit Bootloader

Erstellen einer Collage. Zuerst ein leeres Dokument erzeugen, auf dem alle anderen Bilder zusammengefügt werden sollen (über [Datei] > [Neu])

EFR Smart Control EEG EINSPEISEMANAGEMENT PER FUNK

Projekt 2HEA 2005/06 Formelzettel Elektrotechnik

Grundlagen verteilter Systeme

1 Einleitung. Lernziele. automatische Antworten bei Abwesenheit senden. Einstellungen für automatische Antworten Lerndauer. 4 Minuten.

easyident Türöffner easyident Türöffner Art. Nr. FS-0007 FS Fertigungsservice

Übung - Konfigurieren einer Windows 7-Firewall

Professionelle Seminare im Bereich MS-Office

Virtuelle COM-Schnittstelle umbenennen

Atmel AVR für Dummies

1. Aktionen-Palette durch "Fenster /Aktionen ALT+F9" öffnen. 2. Anlegen eines neuen Set über "Neues Set..." (über das kleine Dreieck zu erreichen)

Nutzung von GiS BasePac 8 im Netzwerk

Einfache Computersteuerung für Modellbahnen

FuxMedia Programm im Netzwerk einrichten am Beispiel von Windows 7

Thermoguard. Thermoguard CIM Custom Integration Module Version 2.70

Windows Vista Security

Makros sind Textersetzungen, welche vom Präprozessor aufgelöst werden. Dies Passiert bevor der Compiler die Datein verarbeitet.

Informationsblatt Induktionsbeweis

Local Control Network Technische Dokumentation

Facharbeit Informatik. Thema:

Wir arbeiten mit Zufallszahlen

Technical Note Nr. 101

GEVITAS Farben-Reaktionstest

Beispiel: Siemens AG 900E03 9 Seiten Update:

Eigene Dokumente, Fotos, Bilder etc. sichern

Autoradio On Off Schaltung

Tutorial -

1 Aufgaben zu Wie funktioniert ein Computer?

Installationsanleitung Sander und Doll Mobilaufmaß. Stand

C.M.I. Control and Monitoring Interface. Zusatzanleitung: Datentransfer mit CAN over Ethernet (COE) Version 1.08

Protokoll des Versuches 7: Umwandlung von elektrischer Energie in Wärmeenergie

Anleitung zur Nutzung des SharePort Utility

GeoPilot (Android) die App

Bedienungsanleitung. Mailboxsystem

Tutorial about how to use USBView.exe and Connection Optimization for VNWA.

Installation OMNIKEY 3121 USB

Anleitung zur Inbetriebnahme einer FHZ2000 mit der homeputer CL-Software

Integrated Services Realtime Remote Network

SRH - Kurzinformation

Anwendertreffen 20./21. Juni

Die Arbeitsweise von Flash

Verschlüsseln von Dateien mit Hilfe einer TCOS-Smartcard per Truecrypt. T-Systems International GmbH. Version 1.0 Stand

AUSBILDUNG eines OBEDIENCE HUNDES

Mandant in den einzelnen Anwendungen löschen

Einführung in. Logische Schaltungen

Pflichtenheft. Projektteam. Rexford Osei - Frey Michael Weichert Thomas Thutewohl. Pflichtenheft Seite 1 von 7

Anwendungsbeispiele Buchhaltung

Transkript:

Universita t Koblenz/Landau Studienarbeit Michael Fogel mikfogel@uni-koblenz.de 1.8.2005 Abbildung 1: Bild des fertigen Gera tes 1

INHALTSVERZEICHNIS INHALTSVERZEICHNIS Inhaltsverzeichnis 1 Aufgabenstellung 3 2 Die Hardware 3 2.1 ADXL202............................. 3 2.2 AT90S2313PI........................... 5 2.2.1 Die Register........................ 6 2.2.2 Die Ports......................... 6 2.2.3 Die Timer......................... 7 2.2.4 UART........................... 8 2.2.5 Externe Interrupts.................... 9 2.3 Das serielle EEPROM...................... 10 2.3.1 Der I 2 C Bus........................ 12 3 Die Software 13 3.1 Hello World............................ 14 3.2 Die Tools.asm.......................... 16 4 Das Projekt 24 4.1 Messertermittlung......................... 25 4.2 Zwischenspeichern im EEPROM................. 27 4.2.1 Die Makros........................ 31 4.3 Die PC Verbindung........................ 34 4.4 Die Messung............................ 36 4.5 Programmstart.......................... 38 4.6 Erweiterungen........................... 40 4.7 Der Programmablauf....................... 41 5 Die Platine 48 5.1 Schaltplan Gerät......................... 49 5.2 Schaltplan Mainboard...................... 49 5.3 Die Stromversorgung....................... 50 6 Beispielprogramm 51 6.1 Bedienungsanleitung....................... 52 6.1.1 Vorwort.......................... 52 6.1.2 Inbetriebnahme...................... 52 6.1.3 Messung.......................... 52 6.1.4 Übertragung an den PC................. 53 7 Ausblick 53 2

2 DIE HARDWARE 1 Aufgabenstellung Benötigt wird ein kleines Modul, welches die Werte des Beschleunigungssensors ADXL202 auswertet und zur Weiterverarbeitung an den PC sendet. Hauptsächlich wird das Modul in der Physik eingesetzt um Versuche auf einer Beschleunigungsbahn durchzuführen. Da Kabel bei diesen Versuchen stören, müssen die Werte entweder zwischengespeichert oder über Funk versendet werden. Die gemessenen Werte sollen dann am PC dargestellt werden. Umfang ist Entwicklung und Bau des Gerätes sowie der dafür benötigten Software für das Gerät. Eine Beispielanwendung für den PC soll die gemessenen Werte graphisch darstellen. 2 Die Hardware 2.1 ADXL202 Der Beschleunigungssensor ADXL202 oder ADXL210[DEV] der Firma Analog Devices, ist ein Sensor der neuen Generation. Meist wurden Beschleunigungssensoren durch den Einsatz von Piezo Kristallen realisiert. Diese Kristalle sind in vielen Feuerzeugen oder Druckern zu finden. Bei mechanischen Belastungen wie z.b. Stößen, erzeugen diese Kristalle einen elektrischen Strom, dessen Stärke der Stärke des Stoßes proportional ist. Sensoren auf Basis dieser Kristalle, können aber nur dynamische, also sich verändernde Beschleunigungen erfassen. Die neue Generation dieser Sensoren ist aber in der Lage, auch statische, also konstante Beschleunigungen zu messen, wie etwa die Erdbeschleunigung. Diese Bausteine sind unter dem Stichwort imems ( integrated Micro Electro Mechanical System) bekannt. Eine federnd gelagerte Last im inneren des Chips, wird durch die Beschleunigungen bewegt und verändert dabei die Kapazität eines veränderlichen Kondensators, der ähnlich des Frequenzabgleiches älterer Radios aufgebaut ist. Wird die Masse bewegt, so schieben sich Kondensator platten auseinander oder zusammen. Diese Änderung wird von einem Decoder registriert und in eine analoge Spannung umgewandelt. Diese kann nun direkt gemessen werden, oder über den eingebauten DCM (Duty Cycle Modulator), der die Spannung digitalisiert ausgibt. Beide Sensoren bieten die Möglichkeit die Beschleunigung auf 2 orthogonalen Achsen zu erfassen. Der einzige unterschied beider ist die Auflösung. Der ADXL202 kann Beschleunigungen zwischen +2 und -2 G erfassen. Der 3

2.1 ADXL202 2 DIE HARDWARE ADXL210 kann Beschleunigungen zwischen +10 und -10 G erfassen. Beide Sensoren sind pinkompatibel und können daher ohne Änderungen an der Schaltung oder Software getauscht werden. Ausgabe beider Sensoren und Richtungen, ist ein PWM Signal an den Ausgängen. Erzeugt werden diese Signale durch einen PWM Generator innerhalb des Sensors der die analogen Signale der eigentlichen Messvorrichtung Quantisiert und digital ausgibt. Das PWM Signal selbst besteht aus der Periode T2, in der das Signal T1 lang High Pegel annimmt und danach T2-T1 lang Low Pegel. Dieses Signal ist bestens geeignet, von einem Mikrocontroller ausgewertet zu werden. Analog Devices selbst stellt für diesen Zweck einen Assembler Code zur Verfügung.[Wei] Der Code ist jedoch ungeeignet da er mehrere Schwächen hat. Besonders schlecht ist die Dokumentation. Oft wird nicht ganz klar, was der Code überhaupt bewirkt. Zudem ist es von vielen Faktoren abhängig. Die Frequenz des Controllers muss wohl 1 MHz betragen, da pro NOP Befehl 1 µs angenommen wird. Die T2 Periode muss 1000, 2000 oder 4000 µs betragen. Andere Werte sind nicht möglich. Bei diesem Algorithmus wird nur die T1-Zeit gemessen. Dazu wird auf eine steigende Flanke gewartet, dann ein Timer gestartet und dieser wieder bei fallender Flanke gestoppt und ausgelesen. Der T2-Zeit Vergleich für die Duty wird dabei durch einen shift vorgenommen. Daher muss die T2-Zeit Periodenlänge schon bei Compilieren des Codes bekannt sein. Eine weitere oft angewandte Möglichkeit funktioniert mittels Interrupts. Angeschlossen an die Interrupt Leitungen des Controllers, ist es möglich fallende Flanken, steigende Flanken oder Low Level zu erfassen. Will man einen Wert erfassen, so stellt man den entsprechenden Interrupt auf steigende Flanke ein. Bei Beginn der T1-Zeit wird nun der Interrupt ausgelöst. In der Interruptroutine startet man nun einen Timer und stellt den Interrupt auf fallende Flanke ein. Beim nächsten Interrupt stellt man wieder auf steigende Flanke um, liest den Timer aus und startet ihn erneut. Der letzte Interrupt beendet die Messung von T2-T1. Diese Methode kann aber nur dann angewandt werden, wenn die Interrupts nicht durch andere Interruptroutinen gesperrt werden können. Eine dritte Möglichkeit ist eine Abwandlung der Ersten. Statt des Timers können auch Register verwendet werden. Dies bietet den Vorteil, dass mehrere dieser Speicher zur Verfügung stehen und nicht nach Ende der Messung der Timer ausgelesen werden muss und so einen Teil des nächsten Messwertes verpasst wird. Dazu wird einfach auf die steigende Flanke gewartet. Solange der Pegel High, 4

2.2 AT90S2313PI 2 DIE HARDWARE ist addiert man 1 zum ersten Register. Nach der fallenden Flanke addiert man 1 zum zweiten Register solange der Pegel Low ist. Mit dieser Methode stehen alle benötigten Werte zur Verfügung, ohne statische Parameter zu benötigen. Aus den beiden Werten T1 und T2 lässt sich dann über eine einfache Formel die Beschleunigung ermitteln. A(g) = (T1 / T2-0,5 ) / 12.5% bzw. A(g) = (T1/T2-0,5)/0,4% Die Ausgabe der Sensoren bewegt sich dabei zwischen 25% - 75% Duty. 50% Duty bedeuten bei beiden Sensoren eine Beschleunigung von 0g. Die beiden Grenzwerte entsprechend der maximal messbaren Beschleunigung in beide Richtungen. Aufgrund der wenigen Bauteile, die für den Betrieb des Sensors erforderlich sind, den geringen Stromverbrauch und der einfachen Auswertung der Messwerte, gibt es eine Vielzahl von Anwendungen. Angefangen von der Überwachung von zerbrechlichen Gütern beim Transport, oder des Schock Ausgleichs bei CD Laufwerken, der Sensor ist für fast alles verwendbar. 2.2 AT90S2313PI Der Atmel AVR RISC Mikrocontroller AT90S2313PI ist ein sehr Leistungsstarker Mikroprozessor, mit echter RISC Architektur [ATM]. Anders als bei vielen anderen Controllern, wird hier die Quarzfrequenz nicht intern geteilt, wodurch der Befehlsdurchsatz bei einem 10MHz Quarz 10 Millionen Befehle pro Sekunde beträgt. Unterstützt wird seine Leistungsfähigkeit durch den gelungenen internen Aufbau des Controllers, der es zulässt fast jeden Befehl auch wirklich in einem Takt abzuarbeiten. Erreicht wird dies durch den Code Lademechanismus der noch während ein Befehl abgearbeitet wird, den nächsten Befehl vorbereitet. Sehr mächtige Befehle und 32 Register, die direkt an den internen Bus angeschlossen sind, machen es dem Entwickler besonders einfach, ein sehr kleines, jedoch Effizientes und schnelles Programm zu erstellen. Der geringe Preis macht den Atmel dabei besonders für Hobbybastler interessant. Die Ausstattung des Controllers 5

2.2 AT90S2313PI 2 DIE HARDWARE 32 x 8 Bit Register mit Verbindung zur ALU 2 KByte Flash Speicher für das Programm 128 Byte EEPROM Speicher für nicht flüchtige Werte 128 Byte SRAM für Variablen 1 8 Bit Digitalport 1 7 Bit Digitalport 1 8 Bit Timer 1 16 Bit Timer Full Duplex UART Analog Komparator Watchdog 2 Externe Interrupts 2.2.1 Die Register Die Register haben eine direkte Verbindung zur ALU und können so ohne Umwege über einen ACCU für Additionen genutzt werden. Dies macht die Befehlsabarbeitung beim Atmel besonders Effizient. Gegenüber gängiger Prozessoren und Mikrocontrollern, bei welchen der Wert vor einer Operation in den ACCU geladen werden muss, entfällt hier die Notwendige Ausführungszeit, die dieses Verfahren in Anspruch nimmt. So ist es möglich Additionen, Subtraktionen, oder etwa Vergleiche innerhalb eines Systemtaktes auszuführen. Leider sind die Register nicht völlig gleich. So können z.b. Nur die Register 17-32 für alle 8 Bit Operationen genutzt werden. Es sind jedoch nur einige Ausnahmen SBCI, SUBI, ANDI, ORI, CPI, LDI, SER, SBR und CBR, die nicht auf die Register 1-16 angewandt werden können. Zusätzlich können die Register 26,27 zu X, 28,29 zu Y und 30,31 zu Z Zusammengefasst werden um auch 16 Bit Befehle wie Addition und Subtraktion ausführen zu können. 2.2.2 Die Ports Der AT90S2313PI hat 2 Ports. Benannt sind diese mit PortB und PortD. PortB hat 8 Bit und PortD 7 Bit. Ansonsten sind beide gleich und können auch gleich verwendet werden. Kontrolliert werden beide Ports über je drei IO-Register. Das Data Direction Register kurz DDR definiert, ob das jeweilige Bit ein Eingang oder ein Ausgang ist. Über das Port Data Register kann dem Port ein Zustand zugewiesen werden. Das Port Input Pin Register 6

2.2 AT90S2313PI 2 DIE HARDWARE kann nur gelesen werden und ist in Verbindung mit den Skip Befehlen ein leistungsfähiges Hilfsmittel. Den einzelnen Bits der Ports kann durch den Controller 4 Zustände zugeteilt werden. Tristate, HIGH, LOW und Pullup. Eingestellt wird dies durch das DDR und das Port Data Register. DDR Register Data Register Zustand 0 0 Tristate der normale Eingangszustand 0 1 Pullup Eingang jedoch ist Leitung HIGH 1 0 LOW Ausgang definiert LOW 1 1 HIGH Ausgang definiert HIGH Die Ports werden durch die IN, OUT Befehle Verwendet. Eine Ausnahme sind die Input Pin Register. Diese können direkt durch Tests ausgewertet werden um den Programmablauf extrem einfach zu gestalten. 2.2.3 Die Timer Der AT90S2313PI verfügt über zwei Timer. Einer ist ein 8 Bit der andere ein 16 Bit Timer. Grundsätzlich sind beide Timer gleich, jedoch verfügt der 16 Bit Timer noch über einige weitere Funktionen die jedoch bei meinem Projekt nicht gebraucht wurden. Diese sind z.b die Ausgabe eines pulsweiternmodulierte Ausgabe von Signalen oder generieren eines selbst definierten Signals. Der 8 Bit Timer im Datenblatt[ATM] Timer/Counter 0 genannt, wird über 3 Register gesteuert, ein 4tes für Interrupt Flags gibt dem Anwender Kontrolle über die eigentlichen Interrupts. Das 8 Bit Register TCNT0 dient dem Timer als Zählerregister. Es wird pro Takt um eins erhöht. Dieser Takt muss aber nicht der Systemtakt sein, sondern wird intern erzeugt. Bei Übergang von FF nach 00 wird das Timer Overflow Interrupt Flag 0 kurz TOV0 im Timer Interrupt Flag Register kurz TIFR gesetzt. Dieser wird ausgewertet wenn das Timer Overflow Interrupt Enable 0 Flag gesetzt wurde. Das TCNT0 Register kann zu einem beliebigen Zeitpunkt geschrieben und gelesen werden. Somit sind Anwendungen von Zeiterfassung bis hin zu Zählungen von Einzelimpulsen möglich. Um den Timern ein möglichst breites Anwendungsfeld zu geben, ist der Takt am Timer nicht fest eingestellt sondern kann durch einen Multiplexer eingestellt werden. Dies geschieht über das Timer/Counter Control Register 0 kurz TC- 7

2.2 AT90S2313PI 2 DIE HARDWARE CR0. Die Schalter dazu sind CS00,CS01 und CS02. CS02 CS01 CS00 Takt 0 0 0 Timer deaktiviert 0 0 1 Clock 0 1 0 Clock / 8 0 1 1 Clock / 64 1 0 0 Clock / 256 1 0 1 Clock / 1024 1 1 0 T0 falling edge 1 1 1 T0 rising edge Wie in der Tabelle angegeben kann die Quelle für den Zähler auch ein externer Taktgenerator angeschlossen an T0 oder sonstiger Sensor sein. Der Timer/Counter 1 besitzt die gleichen Grundfunktionen wie der Timer/Counter 0. Erweitert wurde er zusätzlich um einen PWM Output und Standardanwendungen zur Regelungselektronik. Gesteuert wird der Timer daher durch 8 Register. TIFR und TIMSK werden von beiden Timern benutzt. Kontrolliert wird der Timer durch die Register TCCR1A und TCCR1B. Für die Grundfunktionen muss IO-Register TCCR1A 0 sein und in IO-Register TCCR1B muss entsprechend der Multiplexer Wert eingestellt werden. Das Counter Register hat hier entsprechend 16 Bit. Der Controller hat jedoch nur einen 8 Bit Bus. Daher muss bei einschreiben sowie auslesen des Counter Wertes eines Beachtet werden. Um beide 8 Bit Werte gleichzeitig bearbeiten zu können, wird das TCNT1H Register in einem Hardware Temp Register Zwischengespeichert. Ein Lesezugriff auf das TCNT1L IO-Register bewirkt die Übertragung des TCNT1H Wertes in das Temp Register. Dies kann dann direkt danach gelesen werden. Der Schreibzugriff muss entsprechend anders herum geschehen. Zuerst wird der Wert in das IO-Register TCNT1H geschrieben. Der Wert befindet sich danach Im Temp Register. Der Schreibzugriff auf das TCNT1L IO-Register bewirkt nun die Übertragung beider Werte in den Counter. 2.2.4 UART Der AT90S2313PI verfügt über eine in Hardware realisierte, eingebaute UART, die über die Pins PD0 und PD1 auch RXD und TXD mit der Umwelt verbunden ist. Die UART kann komplett von den Pins abgekoppelt werden wenn diese als normale digitale Ein oder Ausgänge verwendet werden. Gesteuert wird die UART über die IO-Register UDR (UART Data Register ), USR ( 8

2.2 AT90S2313PI 2 DIE HARDWARE UART Status Register), UCR ( UART Control Register) und UBRR ( UART Baudrate Register). Realisiert ist die UART intern durch zwei Schieberegister. Eines dient als Sender und das andere als Empfänger. Das Taktsignal für die Schieberegister stammt aus dem Systemtakt. Dazu wird die Baudrate durch das UBRR Register als Teiler des Systemtaktes angegeben. Ermitteln lässt sich der Wert durch die Formel UBRR = CLOCK / (BAUDRATE*16) -1. Das UDR IO Register besteht aus 2 Register. Einem im Empfänger aus dem nur gelesen werden kann und einem im Sender in das nur geschrieben werden kann. Die passende Aktion wird durch die Hardware sichergestellt und ist für den Anwender unsichtbar. Aktiviert wird die UART im UCR Register. Durch beeinflussen der Bits RXEN und TXEN können Sender und Empfänger unabhängig voneinander aktiviert und deaktiviert werden. Der Sender bleibt jedoch solange aktiviert, bis das letzte Byte gesendet wurde. Über RXIE, TXIE und UDRIE können die Interrupts für Empfangen, Gesendet oder Sendepuffer leer. CHR9, TBR9 und TXB9 dienen dem Senden und Empfangen eines 9. Bits. Dies wird allerdings nur selten gebraucht. Über das USR können die Flags auch im Programm abgefragt und gesetzt werden um evtl. eine Flusskontrolle zu realisieren. Auftretende Fehler die nicht korrigiert werden konnten werden hier ebenfalls angezeigt. 2.2.5 Externe Interrupts Der AT90S2313PI verfügt über 2 externe Interrupt Eingänge. Diese teilen jeweils einen Pin mit PD2 und PD3. Über diese Interrupts ist es möglich den Atmel zeitnah auf äußere Ereignisse reagieren zu lassen. Kontrolliert werden die Eingänge durch die Register GIMSK ( Global Interrupt Mask Register), GIFR ( Global Interrupt Flag Register) und MCUCR ( MCU Control Register). Über die Bit ISC00 ISC01 bzw ISC10 ISC11 lassen sich die Interrupt Einstellen. GIMSK dient nur der Aktivierung der Eingänge und GIFR zeigt eine Auslösung an. Die Eingänge besitzen dazu 3 Modi, die in der Tabelle abzulesen sind. ISC11 ISC10 Bedeutung 0 0 Interrupt 1 reagiert auf LOW Level 0 1 Reserviert darf nicht benutzt werden 1 0 Interrupt 1 reagiert auf fallende Flanke 1 1 Interrupt 1 reagiert auf steigende Flanke 9

2.3 Das serielle EEPROM 2 DIE HARDWARE ISC01 ISC00 Bedeutung 0 0 Interrupt 0 reagiert auf LOW Level 0 1 Reserviert darf nicht benutzt werden 1 0 Interrupt 0 reagiert auf fallende Flanke 1 1 Interrupt 0 reagiert auf steigende Flanke Werden diese Interrupts verwendet, so muss auf einen definierten Zustand geachtet werden. Angeschlossen an einen Taster, können Nebeneffekte zu unkontrollierbaren Reaktionen führen. Die Aktivierung des Pin Pullup, ist ausreichend um diese Nebeneffekte bis auf das Prellen der Taster zu verhindern. Sofern die Taster mit Masse verbunden werden. 2.3 Das serielle EEPROM Das Serielle EEPROM 24C65[Mic] der Firma Xicor, verfügt über 65 KBit Speicher und wird über den Serielle I 2 C Bus gesteuert. Intern besteht das ser. EEPROM aus Control Logik Bausteinen, mehreren Registern, Adressdecoder und einem parallelen EEPROM. Fr die Schreiboperationen ist zusätzlich ein Cache eingebaut. Organisiert ist der Speicher in jeweils 8 Byte große Pages. Dies ist für die Leseopertionen uninteressant. Jedoch bei Schreiboperationen kann es ohne Beachtung dieses Designaspektes zu Fehlern kommen. Der Schreibcache kann bis zu 8 pages fassen. Beginnt das Scheiben innerhalb einer Page so wird der Cache nicht von beginn an gefüllt, sondern erst ab der richtigen Position innerhalb der Page. Werden nun alle 64 Bytes an das EEPROM gesendet, so springt der Zeiger im cache wieder an den Anfang und füllt die noch freien Bytes der ersten Page. Beim Schreiben des Cache in das EEPROM wird immer am Anfang einer Page begonnen. Die zuletzt eingetragenen Daten, überschreiben also die Daten vor der Startposition( siehe Abbildung 2). Belässt man es bei weniger als 56 Bytes pro Schreibzyklus oder beginnt immer an einem Page Anfang, so kommt es zu keinen Problemen. Alle Kommandos erreichen oder verlassen den Baustein über den I 2 C Bus. Die eingebaute Logik sorgt immer für ein protokollkonformes Verhalten. Das EEPROM kann immer nur die Rolle des Slave einnehmen. Kopieroperationen zwischen mehreren Bausteinen sind also nicht möglich. Jedoch können mehrere EEPROM an einem gemeinsamen Bus betrieben werden. Das erste übertragene Byte, das Kontrollbyte macht dies möglich. Die ersten 4 Bit sind fest mit 1010 Kodiert. Diese sind Firmenspezifisch und können nicht 10

2.3 Das serielle EEPROM 2 DIE HARDWARE Abbildung 2: Quelle: Datenblatt des EEPROM[Mic] verändert werden. Die nächsten 3 Bit können jedoch frei gewählt werden. Über die 3 Eingänge A0, A1, A2, werden diese Definiert. Das letzte Bit des Byte teilt dem Baustein mit welche Operation folgt, lesen 1 und schreiben 0 War die gewählte Operation eine Schreiboperation, so erwartet das EE- PROM nun eine Adresse. Da das EEPROM nur einen 13 Bit Adressraum besitzt, sind die ersten 3 Bit nicht belegt. Diese 3 Bit werden dazu verwendet weiter Funktionen zu Steuern. Diese sind z.b Security und Block Endurance Einstellungen. Alles weitere zu diesen Funktionen sollte dem Datenblatt[Mic] entnommen werden. Zum lesen und schreiben in das EEPROM müssen diese Bits auf 0 gesetzt sein. Wollte man also schreiben so überträgt man die 13 Bit Adresse mit den führenden 3 Nullen in Form von 2 8 Bit Paketen. Nach jedem Paket muss ein Ack durch das EEPROM erfolgen. Anschließen können die Daten in Byte Blöcken übertragen werden. Wollte nun gelesen werden so erfolgt das senden sofort nach den Ack. Die Adresse von der gelesen wird definiert der interne Zeiger. Dieser kann nur durch eine Schreiboperation gesetzt werden. Nach jedem Lesevorgang wird dieser um 1 inkrementiert sodass ein sequenzielles lesen möglich ist. Nach jedem Paket muss nun ein Ack durch den Master erfolgen. Wird dies nicht gegeben so bricht die Verbindung ab. Um eine bestimmte Adresse lesen zu können muss man also eine Schreiboperation vortäuschen. Nach erfolgter Übertragung der Adresse mit positivem Ack, erzeugt der Master eine Stopp Condition und wieder eine Start Condition. Der Zeiger ist nun auf die gewünschte Adresse gesetzt und das lesen kann erfolgen. 11

2.3 Das serielle EEPROM 2 DIE HARDWARE Nachfolgend ist noch einmal das Protokoll des Busses erläutert. 2.3.1 Der I 2 C Bus Der I 2 C Bus wurde für die Kommunikation zwischen 2 Mikrocontrollern entwickelt und geht dabei speziell auf die technischen Eigenschaften der Prozessoren ein. Das Medium über das die Controller Kommunizieren besteht dabei aus 2 Leitungen die beide mittels Pullup Widerstandes auf HIGH gezogen werden. Die Leitungen sind SDA die Datenleitung und SCL die Taktleitung über die die Kommunikation synchronisiert wird. Zugriff auf die Leitungen wird nur auf 2 Arten durchgeführt. Soll die entsprechende Leitung HIGH Liefern, so nimmt der Controller keinen Zugriff auf die Leitung, schaltet also in den Tristate Zustand. Der Pullup übernimmt dann den Rest. Soll jedoch LOW auf der Leitung liegen, so wird die Leitung durch Ausgabe einer NULL auf LOW gezogen. Um dabei den Port nicht zu überlasten sollte der Pullup Widerstand nicht zu klein gewählt werden. Dieses Verfahren hat besonders bezogen auf die Arbitrierung des Busses große Vorteile. Der Bus verbindet mehrere Controller miteinander, jedoch können immer nur 2 Controller diesen auch nutzen. Erst wenn der Bus wieder freigegeben wurde, können die nächsten 2 Kommunizieren.[Wol03] Das verwendete Protokoll unterstreicht dabei noch einmal die Vorteile dieses Busses. Liegen beide Leitungen auf HIGH, so bedeutet dies dass der Bus für den nächsten Zugriff frei ist. Der Start einer Verbindung ist immer die so genannte Start Kondition. Dabei wird einfach die SDA Leitung auf LOW gezogen. Nach Beendigung der Verbindung erfolgt die so genannte stopp Kondition. Dabei wird während die SCL Leitung auf HIGH ist die SDA Leitung auf HIGH geschaltet. Nach der Durchführung sind beide Leitungen wieder auf HIGH, also im IDLE Zustand. Die eigentliche Datenkommunikation ist genauso einfach wie Auf und Abbau der Verbindung. Die eigentliche Kommunikation erfolgt dabei serialisiert. Nach der Start Kondition wird auch die SCL Leitung auf LOW gezogen. Jetzt wird die Adresse des Slaves übertragen. Dazu wird während SCL auf LOW ist das erste Bit auf die SDA Leitung gelegt. Damit der Slave das Bit übernimmt wird für kurze Zeit die SCL Leitung auf HIGH gelegt. Danach erfolgt die Übertragung der restlichen 7 Bit. Nach der Übertragung des 8 Bits durch den Master, erfolgt in einem 9. Takt das ACK durch den Slave. Dazu schaltet der Master die SDA Leitung auf Tristate und wartet damit der Slave sei ACK geben kann. Während nun die SCL Leitung das 9. mal auf HIGH liegt ist die SDA Leitung entweder auf LOW das ACK des Slave oder auf HIGH Übertragung war Fehlerhaft. Alle weiteren Daten werden auf die Gleiche weise übertragen. Jede Übertragung ist in 8 Bit Blöcke eingeteilt und zu jedem Block gehört ein ACK. Wird 12

3 DIE SOFTWARE ein Fehler erkannt muss die komplette Verbindung erneut vorgenommen werden. Das ACK wird dabei immer vom Empfänger des Blocks erzeugt. Werden also Daten von Slave zum Master übertragen, bricht die Verbindung ab falls der Master kein ACK erzeugt. Die Arbitrierung des Busses ist dabei sehr genial gelöst worden. Wird der Bus als IDLE erkannt kann der Master auf den Bus zugreifen. Greifen gleichzeitig mehrere Master auf den Bus zu, so entscheidet es sich während der Übertragung welcher den Bus freigeben muss. Da ja nur zum schreiben eines LOW auf die Leitung zugegriffen wird, ist das Datum auf dem Bus immer konsistent. Dadurch erhält der Master den Bus, der die meisten LOW Pegel Überträgt. Schreibt ein Master einen HIGH Pegel, es liegt jedoch ein LOW Pegel an, so stoppt er seine Übertragungen und zieht sich vom Bus zurück. In diesem Projekt gibt es jedoch nur einen Master und so wurde auf den zusätzlichen Code für die Arbitrierung verzichtet. 3 Die Software Nicht nur die Hardware muss stimmen sondern auch die Software. Es geht nun darum die Aufgabenstellung nun auch zu realisieren. Auf dem AT90S2313PI wie auch den anderen Controllern der Atmel Familie bestehen die einzelnen Befehle aus 16 oder 32 Bit werten, die während des Programmablaufes aus dem internen Flash gelesen und im Prozessor verarbeitet werden. Da es sehr verwirrend, bis hin zu fast unmöglich ist das Programm in diesem Binärcode zu schreiben benutzt man dazu mehr oder weniger komfortable Hochsprachen. Für den Atmel gibt es eine Reihe von Compilern für verschiedenste Hochsprachen. Die wohl bekanntesten Hochsprachen für den Atmel sind C, Bascom Basic und Assembler. Atmel selbst stellt einen Compiler für C und Assembler zur Verfügung. Leider sind die Produkte nur unter Windows funktionsfähig. Open Source Applikationen sind avr-gcc für C und avra für Assembler. Die Basic Variante ist leider Eigentum von Bascom und so gibt es keine Alternativen. Für welche der Sprachen man sich nun entscheidet ist jedem selbst überlassen. Meine Entscheidung wurde vom Platzbedarf des Programms und dessen Geschwindigkeit bestimmt. 13

3.1 Hello World 3 DIE SOFTWARE C ist sehr schnell da die einzelnen Befehle der Sprache sehr nahe am eigentlichen OP-Code liegen. Leider sind die damit erzeugtem Programme für den Atmel unverhältnismäßig groß Selbst ein leerer Programmrumpf benötigt fast 100 Byte. Dies liegt wohl an verschiedensten Bibliotheken, die für bestimmte Befehle wie z.b. Multiplikation und Division benötigt werden. Auch wenn diese nie benutzt werden, sind sie enthalten.[avrb] Die Bascom Basic Variante ist sehr einfach und Komfortabel. Selbst schwierige Algorithmen sind schnell und einfach erstellt. Leider bietet diese Sprachen damit die geringste Kontrolle über den Atmel. Viele verfahren sind durch Standardcode realisiert und nur schwer zu ändern. Auch ein direkter Zugriff auf die Hardware ist nicht möglich. Die erzeugten Programme sind auch hier sehr groß und damit entsprechend langsamer. Zudem lässt sich hier nichts optimieren.[bas] Assembler ist im engeren Sinne nicht als Hochsprache zu Bezeichnen. Es handelt sich vielmehr um eine menschenlesbare Form des Codes, die fast 1:1 vom Compiler in den eigentlichen OP-Code übersetzt wird. Lediglich bei Sprüngen und schleifen wird man durch den Compiler unterstützt der die entsprechenden Adressen berechnet und den Code auf syntaktische Fehler hin prüft. Will man ein Programm erstellen das schnell läuft und zudem auch in den kleinsten Speicher passt, kommt man an Assembler nicht vorbei. Atmel stellt dafür in seiner Dokumentation[ATM] zu den Controllern ca. 120 Befehle vor.[avra] 3.1 Hello World Bewegt man sich zum ersten mal in einer neuen Sprache so fängt man erst einmal klein an. Viele kennen es. Das erste Beispiel mit dem bestimmt jeder anfängt ist Hello World. Es geht einfach darum eine Ausgabe zu erreichen um überprüfen zu können ob das Programm korrekt funktioniert. Die dabei meist genutzt Ausgabe geschieht üblicherweise durch die Konsole und den Text Hello World. Beim Atmel gestaltet sich das ganze etwas anders. Hier gibt es keine Konsole und auch keinen Bildschirm, an dem man es ausgeben kann. Nur die Ports stehen zur Verfügung. Die einfachste Ausgabe über die Ports ist HIGH und LOW. Eine daran ange- 14

3.1 Hello World 3 DIE SOFTWARE schlossenen LED ermöglicht es, den Pegel auch zu sehen. Die meisten erhältlichen Experimentierboards sind auch nach diesem Prinzip aufgebaut. Die Rückmeldung ist das wichtigste überhaupt, da sonst nicht erkannt werden kann ob alles richtig funktioniert oder im schlimmsten Fall defekt ist. Der Code ist dabei recht einfach. Der entsprechende Pin muss per DDR Register auf Ausgang konfiguriert werden und der Port muss muss auf 1 gelegt werden. Dies ist noch einfach und daher immer erfolgreich. Eine weitere Herausforderung ist ist danach die LED blinken zu lassen. Bei jedem Takt den Pegel am Pin zu ändern führt hier leider nicht zum Ziel, da die Frequenz einfach zu schnell ist, um es sehen zu können. Einfügen von delay Schleifen ist dabei eine Lösung. Diese Aufgabe führte mich jedoch zu den Interrupts. Genauer zu den Timer Overflow Interrupts. Diese ermöglichen es die LED in immer gleichen Zeitintervallen Blinken zu lassen. Als dies Funktionierte ging es weiter den Atmel auf externe Reize reagieren zu lassen. Um gleichzeitig eine Rückmeldung zu haben, versuchte ich die LED nun über einen Taster zu steuern. Um gleichzeitig mehr über die Interrupts zu lernen sollte der Taster über einen Interrupt abgefangen werden. Die Interrupt Eingänge 0 und 1 lassen sich dazu in drei Modi konfigurieren. Interrupt bei LOW Level, Falling edge und rising edge. Um einen definierten zustand zu erhalten sollte dabei der interne Pullup eingeschaltet sein. Nach setzen des Enable Flag ist der Interrupt schon einsatzbereit. Also wird die LED per Taster ein und ausgeschaltet. Da die LEDs nicht zu debug Zwecken ausreichen, ist es Notwendig eine Verbindung zum Rechner herzustellen. Sehr gut geeignet dazu ist der interne UART. Zu Anfang soll dazu nur ein Zeichen übertragen werden. Um die UART zu aktivieren muss entsprechend des installierten Quarzes das UBRR Register und das TX Enable Flag gesetzt werden. Der nächste Versuch sollte nun alle diese Funktionen in einem Programm vereinen. Das blinken der LED kann nun durch die Tasten gesteuerte werden. Die eine Taste aktiviert es und die andere deaktiviert es wieder. Gleichzeitig wird auch die UART aktiviert und deaktiviert. Wird ein Zeichen an den Atmel gesendet, so wird es wie bei einem ECHO zurückgesendet. Aus all den Versuchen entstand nun eine Sammlung von kleinen, Hardware nahen Routinen um den Atmel zu Steuern. Diese sind in der Tools.asm zusammengefasst. Die Routinen werden dabei durch Parameter die durch die Variablendefinitionen angegeben werden parametrisiert. So ist es möglich diese ohne Eingriff zu nutzen oder auch zu verändern. Leider sind diese Parameter ab der Compilezeit fest eingestellt. Änderungen während des Programmablaufes sind damit leider nicht möglich. Dies muss dann durch kopieren 15

3.2 Die Tools.asm 3 DIE SOFTWARE und verändern der jeweiligen Routine erfolgen. 3.2 Die Tools.asm ; Einige Funktionen um Standard Aktionen zu kapseln ; ; START TIMER1: ; Initialisiert und aktiviert Timer0 ; REFRESH TIMER1 ; Schreibt den Timer wert wieder in die Register für Timer1 ; START TIMER0: ; Timer0 wird aktiviert Clock und Interrupt gesetzt ; STOP TIMER0: ; Deaktiviert den Timer0 ; REFRESH TIMER0: Schreibt den Timer wert wieder in das Timer Register für Timer0 ; falling edge int0: ; Setzt die Interrupt Auslösung für int 0 auf fallende Flanke ; rising edge int0: ; Setzt die Interrupt Auslösung für int 0 auf steigende Flanke ; low level int0: ; Setzt die Interrupt Auslösung für int 0 auf Level 0 ; falling edge int1: ; Setzt die Interrupt Auslösung für int 1 auf fallende Flanke ; rising edge int1: ; Setzt die Interrupt Auslösung für int 0 auf steigende Flanke ; low level int1: ; Setzt die Interrupt Auslösung für int 0 auf Level 0 ; START IRQ0: ; Setzt das int0 Interrupt enable Flag ; STOP IRQ0: ; Löscht das int0 Interrupt enable Flag ; START IRQ1: ; Setzt das int1 Interrupt Enable Flag ; STOP IRQ1: ; Löschen des int1 Interrupt Enable Flag ; KILL WATCHDOG: ; Deaktiviert den Watchdog Timer ; INIT UART: ; Aktiviert die UART und setzt wichtige Parameter ; START UART: ; Aktiviert den RX Interrupt ; STOP UART: ; Deaktiviert die Interrupts der UART UART bleibt aber völlig einsatzbereit ; SEND DATA: ; Sendet den Registerinhalt von tempdat über die UART raus ; STOP ANALOG: ; Deaktiviert den Analogen Komparator ; ; Damit diese Funktionen genutzt werden können, müssen folgende konstanten verfügbar sein ; ; Konstanten ;.equ CRYSTAL = 4000 ; Quarz Geschwindigkeit in KHz ;.equ BAUDRATE =9660 ; Baudrate für die UART ;.equ Timer1 high value = $0b ; Wert für Register TCNT1H ;.equ Timer1 low value = $bd ; Wert für Register TCNT1L ;.equ Timer0Value = 0x00 ; Zähl wert für den Timer0 ;.equ TCCR0Value = (1<<CS00) (1<<CS02) ;.equ TCCR1BValue = (1<<CS10) ; ;.equ TCCR1AValue = 0x00 ; ; ; Berechnungen ;.equ UBRR INIT = 25 ; CRYSTAL/(BAUDRATE*16) -1 ; ; Leider muss die Gleichung noch selbst gelöscht werden ; ; da ganze Zahlen gebraucht werden ; ; Definitionen ;.def tempdat = r18 ;.CSEG ; START TIMER1: ; Initialisiert und aktiviert Timer0 LDI temp,tccr1bvalue ; Clock OUT TCCR1B, temp ; schreiben in Control Register LDI temp,tccr1avalue ; OUT TCCR1A,temp ; Deaktivieren aller Zusatztools REFRESH TIMER1: LDI temp,timer1 high value OUT TCNT1H,temp LDI temp, Timer1 low value OUT TCNT1L, temp START TIMER0: ; Timer0 wird aktiviert Clock und Interrupt gesetzt LDI temp, TCCR0Value ;Clock/1024 OUT TCCR0, temp ; schreiben in Control Register IN temp,timsk ORI temp,(1<<toie0) OUT TIMSK,temp STOP TIMER0: ; Deaktiviert den Timer0 IN temp,timsk ANDI temp,(1<<ocf1a) (1<<TICIE1) (1<<TOIE1) ; Timer 0 Overflow Interrupt dissable OUT TIMSK,temp 16

3.2 Die Tools.asm 3 DIE SOFTWARE IN temp,tccr0 ANDI temp,0xf8 OUT TCCR0,temp REFRESH TIMER0: ; Schreibt den Timer wert wieder in das Timer Register für Timer0 LDI temp,timer0value OUT TCNT0,temp falling edge int0: ; Setzt die Interrupt Auslösung für int 0 auf fallende Flanke IN temp,mcucr ORI temp,(1<<isc01) (1<<ISC00) OUT MCUCR, temp rising edge int0: ; Setzt die Interrupt Auslösung für int 0 auf steigende Flanke IN temp,mcucr ORI temp,(1<<isc01) ANDI temp,(1<<se) (1<<SM) (1<<ISC11) (1<<ISC10) (1<<ISC01) OUT MCUCR, temp low level int0: ; Setzt die Interrupt Auslösung für int 0 auf Level 0 IN temp,mcucr ANDI temp,(1<<se) (1<<SM) (1<<ISC11) (1<<ISC10) OUT MCUCR, temp falling edge int1: ; Setzt die Interrupt Auslösung für int 1 auf fallende Flanke IN temp,mcucr ORI temp,(1<<isc11) (1<<ISC10) OUT MCUCR, temp rising edge int1: ; Setzt die Interrupt Auslösung für int 0 auf steigende Flanke IN temp,mcucr ORI temp,(1<<isc11) ANDI temp,(1<<se) (1<<SM) (1<<ISC01) (1<<ISC00) (1<<ISC11) OUT MCUCR, temp low level int1: ; Setzt die Interrupt Auslösung für int 0 auf Level 0 IN temp,mcucr ANDI temp,(1<<se) (1<<SM) (1<<ISC01) (1<<ISC00) OUT MCUCR, temp START IRQ0: ; Setzt das int0 Interrupt Enable Flag IN temp,gimsk ; ORI temp,(1<<int0) ; Interrupt 0 an OUT GIMSK,temp ; Setzen des Interrupt Enabled Flag STOP IRQ0: ; Löscht das int0 Interrupt Enable Flag IN temp,gimsk ; ANDI temp,(1<<int1) ; Löschen Interrupt 0 OUT GIMSK,temp ; Löschen des Interrupt Enable Flag - START IRQ1: ; Setzt das int1 Interrupt Enable Flag IN temp,gimsk ; ORI temp,(1<<int1) ; Start Interrupt1 OUT GIMSK,temp ; Setzen des Interrupt Enabled Flag STOP IRQ1: ; Löschen des int1 Interrupt Enable Flag IN temp,gimsk ; ANDI temp,(1<<int0) ; Deaktivieren Interrupt 1 OUT GIMSK,temp ; Löschen des Interrupt enabled Flag KILL WATCHDOG: ; Deaktiviert den Watchdog Timer ldi temp,$1f OUT WDTCR,temp LDI temp,$17 OUT WDTCR,temp ;Killen des Watchdog INIT UART: ; Aktiviert die UART und setzt wichtige Parameter LDI temp,ubrr INIT ; Baudrate Laden OUT UBRR,temp LDI temp,(1<<rxen) (1<<TXEN); (1<<TXB8) ; RX an TX an 9. Bit 1 für Stop Kondition 17

3.2 Die Tools.asm 3 DIE SOFTWARE OUT UCR,temp START UART: ; Aktiviert den RX Interrupt IN temp,ucr ORI temp,(1<<rxcie) ; Aktiviert den RX Interrupt ;ORI temp,(1<<txcie) ; Aktiviert den TX Interrupt OUT UCR,temp STOP UART: ; Deaktiviert die Interrupts der UART, UART bleibt aber völlig ; einsatzbereit IN temp,ucr ANDI temp,(1<<udrie) (1<<RXEN) (1<<TXEN) (1<<CHR9) (RXB8) (1<<TXB8) OUT UCR,temp ; Deaktivieren von RXCIE und TXCIE SEND DATA: uwait: sbis USR,UDRE ; is uart ready to xmit? rjmp uwait OUT UDR,tempdat STOP ANALOG: ldi TEMP,(1<<ACD) ;turn off the analog comparator out ACSR,TEMP Hier nun einige kurze Erläuterungen: START TIMER1:; Initialisiert und aktiviert Timer0 Benötigt:.equ TCCR1BValue.equ TCCR1AValue Diese Routine Startet den Timer 1 durch setzen seiner Kontrollregister. Die zu schreibenden Werte müssen sich dabei in den beiden Variablen befinden. Die genaue Konfiguration dafür muss dem Datenblatt[ATM] entnommen werden. REFRESH TIMER1 ; Schreibt den Timer Wert wieder in die Register für Timer1 Benötigt:.equ Timer1 high value ; Wert für Register TCNT1H.equ Timer1 low value ; Wert für Register TCNT1L Diese Routine setzt die Zählerregister für den Timer1. Hier wird für eine gleichmäßige Periode die Takte eingestellt die der Timer zusätzlich zum erreichen des Überlaufs bei $FF benötigt. Soll die Zeitdauer immer 200 Takte betragen und der Multiplexer des Timer wurde auf Clock eingestellt so ist 18

3.2 Die Tools.asm 3 DIE SOFTWARE hier 255;55 einzutragen, 255;255-000;200. START TIMER0: ; Timer0 wird aktiviert Clock und Interrupt gesetzt Benötigt:.equ TCCR0Value Diese Routine startet den Timer0. Der Wert der Variable wird dabei in das Kontrollregister geschrieben. Zusätzlich wird hier der Interrupt aktiviert STOP TIMER0: ; Deaktiviert den Timer0 Benötigt: Keine Variablen Diese Routine löscht das Interrupt Enable Flag und hält den Timer an. Andere Bits werden dabei nicht verändert REFRESH TIMER0:; Schreibt den Timer wert wieder in das Timer Register für Timer0 Benötigt:.equ Timer0Value Diese Routine schreibt den Wert aus der Variable in das Timer0 Zählerregister. falling edge int0:; Setzt die Interrupt Auslösung für int 0 auf fallende Flanke Benötigt: Keine Variablen 19

3.2 Die Tools.asm 3 DIE SOFTWARE Diese Routine setzt die Interruptauslösung für den Externen Interrupt Input 0 auf fallende Flanke. rising edge int0:; Setzt die Interrupt Auslösung für int 0 auf steigende Flanke Benötigt: Keine Variablen Diese Routine setzt die Interruptauslösung für den Externen Interrupt Input 0 auf steigende Flanke. low level int0:; Setzt die Interruptauslösung für int 0 auf Level 0 Benötigt: Keine Variablen Diese Routine setzt die Interruptauslösung für den Externen Interrupt Input 0 auf Low Level. Dabei muss beachtet werden dass die Auslösung solange geschieht bis der Eingang wieder auf High ist. Es kann also vorkommen dass der Interrupt öfters aktiviert wird. falling edge int1:; Setzt die Interrupt Auslösung für int 1 auf fallende Flanke Benötigt: Keine Variablen Diese Routine setzt die Interrupt Auslösung für den Externen Interrupt Input 1 auf fallende Flanke. rising edge int1:; Setzt die Interruptauslösung für int 1 auf steigende Flanke Benötigt: Keine Variablen 20

3.2 Die Tools.asm 3 DIE SOFTWARE Diese Routine setzt die Interruptauslösung für den Externen Interrupt Input 1 auf steigene Flanke. low level int1: ; Setzt die Interrupt Auslösung für int 1 auf Level 0 Benötigt: Keine Variablen Diese Routine setzt die Interruptauslösung für den Externen Interrupt Input 1 auf Low Level. Dabei muss beachtet werden dass die Auslösung solange geschieht bis der Eingang wieder auf High ist. Es kann also vorkommen dass der Interrupt öfters aktiviert wird. START IRQ0: ; Setzt das int0 Interrupt enable Flag Benötigt: Keine Variablen Diese Routine aktiviert das Interrupt Enable Flag für den externen Interrupt 0. Dies macht den Interrupt erst aktiv. Es sollte darauf geachtet werden zuerst die Interruptauslösung zu initialisieren sonst kann es zu Nebeneffekten kommen. STOP IRQ0: ; Löscht das int0 Interrupt Enable Flag Benötigt: Keine Variablen Diese Routine löscht das Interrupt Enable Flag des externen Interrupt 0. Das Interrupt Flag wird dabei nicht verändert. Ist also noch ein Interrupt vorgemerkt, so wird dieser nach erneutem aktivieren des Interrupts abgearbeitet. 21

3.2 Die Tools.asm 3 DIE SOFTWARE START IRQ1: ; Setzt das int1 Interrupt Enable Flag Benötigt: keine Variablen Diese Routine aktiviert das Interrupt Enable Flag für den externen Interrupt 1. Dies macht den Interrupt erst aktiv. Es sollte darauf geachtet werden zuerst die Interruptauslösung zu initialisieren sonst kann es zu Nebeneffekten kommen. STOP IRQ1: ; Löschen des int1 Interrupt Enable Flag Benötigt: keine Variablen Diese Routine löscht das Interrupt Enable Flag des externen Interrupt 1. Das Interrupt Flag wird dabei nicht verändert. Ist also noch ein Interrupt vorgemerkt, so wird dieser nach erneutem aktivieren des Interrupts abgearbeitet. KILL WATCHDOG: ; Deaktiviert den Watchdog Timer Benötigt: keine Variablen Diese Routine deaktiviert den Watchdog des Atmels. Dieser ist dazu da den Atmel im falle eines Fehlers neu zu starten. Intern ist dieser einfach durch einen Zähler realisiert der im Programm zurückgesetzt werden kann. Ist dieser jedoch abgelaufen kommt es zum Reset Interrupt. Das deaktivieren muss in einer festgelegten Reihenfolge passieren, daher ist eine eigene Routine sehr gut geeignet dies zu erledigen. INIT UART: ; Aktiviert die UART und setzt wichtige Parameter Benötigt:.equ UBRR INIT 22

3.2 Die Tools.asm 3 DIE SOFTWARE Diese Routine aktiviert die UART. Dazu wird im UBRR Register der so genannte Prescaler eingestellt um die Übertragungsrate zu garantieren. Damit die Leitungen der UART auf den Pins liegen, werden die UART Enable Flags gesetzt. Der UBRR Wert errechnet sich wie folgt CRYSTAL/(BAUDRATE*16) -1 Der Wert muss ganzzahlig sein und daher gerundet werden. START UART: ; Aktiviert den RX Interrupt Benötigt: keine Variablen Diese Routine aktiviert den RX und wahlweise auch den TX Interrupt. STOP UART: ; Deaktiviert die Interrupts der UART. Die UART bleibt aber völlig einsatzbereit Benötigt: keine Variablen Diese Routine deaktiviert die UART Interrupts. Die UART bleibt jedoch völlig einsatzbereit. Es können weiterhin Daten gesendet und empfangen werden. SEND DATA: ; Sendet den Registerinhalt von tempdat über die UART raus Benötigt.def tempdat = r18 Diese Routine sendet die Daten Per UART an das angeschlossene Gerät. Dabei werden allerdings die Daten nicht einfach ins UDR Register geschrieben. 23

4 DAS PROJEKT Vorher wird das Register überwacht ob es auch wirklich leer ist. Ist es dies nicht, so wird das Programm quasi so lange angehalten bis es leer ist und dann wird das Datum geschrieben. Es ist also nicht definiert wie lange diese Routine benötigt. STOP ANALOG: ; Deaktiviert den Analogen Komparator Benötigt: keine Variablen Diese Routine deaktiviert den ANALOG Comperator der es ermöglicht, 2 Spannungen zu vergleichen. Wenn dieser nicht gebraucht wird, so wird empfohlen diesen zu deaktivieren. 4 Das Projekt Um den Code trotz des recht komplizierten Befehlssatzes möglichst einfach und strukturiert zu halten, werden die einzelnen Funktionen jeweils in eigenen Routinen gekapselt. Dazu gibt es 3 Arten von Routinen. Eine Mischung wurde dabei möglichst vermieden. Immer war es jedoch nicht möglich. Die erste Gruppe der Routinen dient der Initialisierung. Diese Routinen befinden sich in der Tools.asm Datei. Es handelt sich dabei um Controllerfunktionen, die mit diesen Routinen aktiviert, deaktiviert und konfiguriert werden können. Alle Einstellungen werden durch Variablen vorgegeben die zu beginn des Codes Definiert werden sollten. Um diese Aufgaben zu erfüllen, arbeiten die Routinen unmittelbar mit den Hardware Registern. Die zweite Gruppe der Routinen dient der Bedienung der Hardware. Diese Gruppe dient der Realisierung systemnaher Prozesse, wie die Kommunikation mit dem EEPROM oder die Erfassung der Werte. Die Routinen kennzeichnen sich durch hohe Effektivität und meist leider auch Komplexität. Hier ist meist der zeitliche Faktor zu beachten. Die Dritte Gruppe abstrahiert fast vollständig von der Hardware. Diese Routinen realisieren aus den vorhergegangenen Routinen komplexe Abläufe, ohne dem Code die Lesbarkeit zu nehmen. Dies hat den Preis der Geschwindigkeit. Viele Calls führen zu hohen Leistungsverlusten. Diese sind jedoch hier 24

4.1 Messertermittlung 4 DAS PROJEKT zu vernachlässigen, da es keine zeitkritischen Prozesse betrifft. 4.1 Messertermittlung Die Messwertermittlung ist das Kernstück dieses Projektes. Daher muss besonders diese Routine effizient und möglichst genau funktionieren. Um diesem Anspruch gerecht zu werden reicht es nicht eine Routine zu schreiben die korrekte Werte ermittelt, vielmehr muss die Funktion in vielen Tests bestätigt werden. Dass bei diesem Prozess mehr als eine Routine entsteht ist verständlich. Daher hier der Vergleich der 2 besten Routinen. Bei der ersten Routine handelt es sich um einen einfachen Poll Algorithmus der den Zustand des Pins überwacht und eine Variable entsprechend hoch zählt. Fr einen definierten Zustand werden die Variablen mit 0 initialisiert. Um sich dann mit dem Sensor zu synchronisieren wird nun gewartet bis der Pin den Low Zustand annimmt. Der nun folgende Wechsel von Low nach High signalisiert den Beginn der Periode. Ab hier muss nun hochgezählt werden. In der folgenden Schleife wird nun die 16 Bit Variable DATAUP inkrementiert, solange der Pin auf High liegt. Die Einteilung in highbyte und lowbyte dient allein der Weiterverarbeitung mit den 8 Bit Befehlen. Beginnt nun der Low Anteil der Periode so wird nun die DATADOWN Variable inkrementiert. Der Wechsel von Low auf High zeigt das ende der Periode an und die Routine springt zurück. Hier nun der Code poll data X:; messen per poll ; erreichte Auslösung 1,25 Micro sek bei 4 MHz ; Varianzen etwa - 1 Micro sek LDI datauplowbyte,0 LDI datauphighbyte,0 LDI datadownlowbyte,0 LDI datadownhighbyte,0 pinhigh1 X: sbic OUTPORT,OUTX ; warte bis Pin2 auf Low RJMP pinhigh1 X pinlow1 X: sbis OUTPORT,OUTX ; warte bis Pin 2 auf High RJMP pinlow1 X pinhigh2 X: adiw datauplowbyte,$01 ; 2 takte sbic OUTPORT,OUTX ; 1 wenn PD2 High, 3 wenn Low (zählt ja nicht) RJMP pinhigh2 X ; 2 takte pinlow2 X: adiw datadownlowbyte,$01 sbis OUTPORT,OUTX RJMP pinlow2 X Die zweite Routine ist der ersten sehr ähnlich. Auch hier wird per Poll gemessen und auch die Schleifen funktionieren gleich. Der Unterschied liegt 25

4.1 Messertermittlung 4 DAS PROJEKT hier in der Erfassung der eigentlichen Werte. Hier wird keine Variable inkrementiert, sondern der Timer ermittelt den eigentlichen Messwert. Dazu wird der 16 Bit Timer entsprechend initialisiert und wegen der hohen Quarzfrequenz mit einem Prescaler von Clock/8 konfiguriert. Der Prescaler darf jedoch noch nicht in das IO-Register geschrieben werden um den Timer noch nicht zu starten. Ist nun der Start der Periode des Sensors erreicht so wird der Prescaler in das IO- Register geschrieben und der Timer beginnt zu laufen. Ist diese Schleife zu ende, wird der Wert aus dem Timer gelesen und in der DATAUP Variable abgelegt. Da der Timer nicht angehalten wurde, läuft er während der Messung in der nächsten Schleife weiter. Nach Abschluss der Periode wird der ermittelte Wert in die DATADOWN Variable übertragen und die eigentliche Messung ist beendet. Die danach folgenden Befehle dienen dem anhalten des Timers und Feintuning der Werte. Hier nun der Code timer poll data X:; messen per poll ; erreichte Auslösung 0,35 micro sek bei 9,216 MHz ; Varianzen etwa - 0.2 Micro sek LDI datauplowbyte,0 LDI datauphighbyte,0 LDI datadownlowbyte,0 LDI datadownhighbyte,0 LDI temp, 0 OUT TCNT1H,temp OUT TCNT1L,temp OUT TCCR1A,temp OUT TCCR1B,temp LDI temp, (1 CS11) ; Teiler auf Clock/8 da sonst Überlauf timer pinhigh1 X: sbic OUTPORT,OUTX ; warte bis Pin2 auf Low RJMP timer pinhigh1 X timer pinlow1 X: sbis OUTPORT,OUTX ; warte bis Pin 2 auf High RJMP timer pinlow1 X OUT TCCR1B,temp timer pinhigh2 X: sbic OUTPORT,OUTX ; 1 wenn PD2 High, 2 wenn Low RJMP timer pinhigh2 X ; 2 takte IN DATAUPLOWBYTE,TCNT1L ; Beide werden gleichzeitig gelesen durch IN DATAUPHIGHBYTE,TCNT1H ; Hardware temp Register timer pinlow2 X: sbis OUTPORT,OUTX RJMP timer pinlow2 X OUT TCCR1B,NULL IN DATADOWNLOWBYTE,TCNT1L IN DATADOWNHIGHBYTE,TCNT1H SBIW DATAUPLOWBYTE, 3 SBIW DATADOWNLOWBYTE,2 Beide Codefragmente sehen sehr ähnlich aus. Letztendlich haben beide auch die gleiche Funktion. Der Hauptunterschied liegt in der Geschwindigkeit der Messung. Der erste Code benötigt 5 Takte für einen Schleifendurchlauf der Zählschleifen und 2 takte beim verlassen. 2 Takte benötigt dabei allein das Inkrementieren der Variablen, 2 der Sprung und 1 Takt die Überwachung des Pin Zustandes. 26

4.2 Zwischenspeichern im EEPROM 4 DAS PROJEKT Der zweite Code hat hier nur den eigentlichen Schleifenrumpf. Durch den durch Hardware realisierten Timer, ist der Prozessor entlastet und die Schleife schneller. So werden nur 3 Takte benötigt. Im Vergleich bedeutet dies eine fast verdoppelte Abtastrate. Die einmalig anfallenden Takte für den Start und das anhalten des Timers werden durch das Feintuning beseitigt. Für das zweite Verfahren ist allerdings die Frequenz von 9,1260MHz ein ernsthaftes Problem. Der Prescaler muss auf ein Verhältnis von Clock/8 eingestellt werden und so wird erst nach 2,6 Schleifendurchläufen der Wert erhöht. Dies ist bei der Messung unerheblich, jedoch schwankt der Wert am ende der Messung so um +-1. Dies macht bei durchschnittlichen Werten von 1000 bis 4000 jedoch nicht viel aus. Bei Tests erwies sich die Zweite Variante als die bessere. Die erste Variante ergab nur leicht schlechtere Werte. Als viel größere Fehlerquelle erwies sich jedoch der Sensor selbst, der leider nicht immer so saubere Signale liefert und vielen Schwankungen unterworfen ist. 4.2 Zwischenspeichern im EEPROM Da die Daten nicht sofort an den PC gesendet werden können, werden diese Während der Messung in einem EEPROM abgelegt und nach Aufforderung an den PC weitergeleitet. Da der Platzbedarf der Bausteine möglichst gering sein sollte und daher ein kleiner Mikroprozessor verwendet wird, stehen nicht genügend Ports zur Verfügung ein EEPROM direkt anzusteuern. So wurde auf ein Serielles EEPROM zurückgegriffen. Dieses benötigt nur 2 Datenleitungen da es zur Übermittlung den I 2 C Bus verwendet. Die Ansteuerung des Busses ist gekapselt und kann somit unabhängig vom eigentlichen Programmcode verwendet und geändert werden. Implementiert wurde wie weiter oben schon beschrieben nur die Kommunikation zwischen 2 Geräten ohne die Arbitrierung mehrerer Master. Hier der Code ; Modul I2C ; Benötigt : (time = r21, dbyt = r22, FLG = r23) ; Signaturen ; Start: dbyt > auf Bus startcondition und init der Verbindung ; ReStart: dbyt > auf Bus idle dann Startcondition und init der Verbindung ; WriteByte: dbyt > legt Byte auf Bus X FLG ; ReadByte: FLG X byte von Bus > dbyt ; Stop: -> legt stopp auf Bus ;Definitionen.def time = r21.def dbyt = r22.def FLG = r23 ; Konstannten.equ Ack = 0 27