http://sites.prenninger.com/elektronik/avr-mikrocontroller Wels, am 2014-05-20BITTE nützen Sie doch rechts OBEN das Suchfeld [ ] [ Diese Site durchsuchen]DIN A3 oder DIN A4 quer ausdrucken ********************************************************************************** DIN A4 ausdrucken ********************************************************* AVR-Mikrocontroller AVR http://www.mikrocontroller.net/articles/ARM AVR-Tutorial http://www.mikrocontroller.net/articles/AVR-Tutorial Aufbau des Tutorials
********************************************************* Über AVR-Mikrocontroller http://www.rowalt.de/mc/index.htm Atmel AVR http://de.wikipedia.org/wiki/Atmel_AVR RN-Wissen Tutorial www.roboternetz.de AVR-Einstieg leicht gemachtATmega16 und ATmega32http://www.rn-wissen.de/index.php/AVR-Einstieg_leicht_gemacht ********************************************************* Dr. Claus KühnelProgrammieren der AVR RISC Microcontroller mit BASCOM-AVR3. bearbeitete und erweiterte Auflage,ISBN: 3-907857-14-4, 444 Seiten, € 34,95 http://www.ckuehnel.ch/ckskript/PDF/Inhalt%20BASCOM-AVR%203.pdf Mikrocontroller AVR ARDUINO http://de.wikipedia.org/wiki/Arduino-Plattform http://www.arduino.cc/ Arduino mit BASCOM-AVR programmieren. Hinweise hierzu sind unter http://bascom-forum.de/index.php?topic=4868.0 zu finden. http://www.ckuehnel.ch/ ********************************************************* Arduino Kochbuch Michael Magolis, O'REILLY-Verlag in www.schaltungen.at x704_d_O'REILLY-x_Leseprobe- Arduino Kochbuch – Michael Mangolis (117 Seiten)_2a.doc *********************************************************
AVR Mikrocontroller-Kochbuch
Entwurf und Programmierung praktischer AnwendungenLukas Salzburger,
Irmtraut Meister
ISBN: 3-645-25126-6 , 6,3 MB 336 Seiten, Softcover
Rezept auswählen, Zutaten zusammenstellen - und genießen. Nach genau diesem Konzept finden Sie in diesem Buch alles, um Ihr „Mikrocontroller-Süppchen" zu kochen: Von den ersten Programmierschritten über Messungen unterschiedlichster Größen bis zum Erzeugen von Signalen und zur Kommunikation über diverse Schnittstellen. Entdecken Sie die schier endlosen Möglichkeiten der Mikrocontroller! Mit nur wenig Programmieraufwand verwirklichen Sie im Handumdrehen Ihre Ideen. Schritt für Schritt begleitet dieses Buch Sie von den allgemeinen Grundlagen zur praktischen Umsetzung und erleichtert so auch komplexe Programmierungen. Am Beispiel des AVR®-Mikrocontrollers von Atmel® lernen Sie das Potenzial von Mikrocontrollern kennen und können sich dadurch auch leicht in „fremde" Mikrocontroller einarbeiten. Für Einsteiger bietet das Buch auch Hinweise zur Programmierung von Bitoperationen und einfache Codegerüste - so bleiben keine Fragen offen. http://www.franzis.de/elektronik/simulation-computer/avr-mikrocontroller-kochbuch ********************************************************* Kleiner Bascom AVR Kurs Im Loetstelle-Forum wurde von "passat2001" gefragt, ob man eine einfache analoge Schaltung auch so umsetzen könne, damit man diese später über einen Computer anpassen/programmieren kann. Es hat sich einfach so ergeben. :-) Irgendwie ist aus dieser Frage ein kleiner Kurs geworden, der die AVR Mikrocontroller und deren Programmierung mit Bascom erklären soll. Es handelt sich um den Foren-Thread "Digitale Lösung für Schaltungen / Problem?". Da immer wieder Fragen auftauchten und deren Antworten sich im gleichen
Thread befinden, ist der Thread inzwischen ein wenig unübersichtlich geworden. Deshalb versuche ich hier die wichtigsten Beiträge zusammenzufassen. Hinweis Ich bitte dich, Fragen zu diesem Kurs, direkt im oben genannten
Foren-Thread "Digitale Lösung für Schaltungen / Problem?"
zu stellen, und nicht per Email an mich zu schicken. Die Fragen und deren
Antworten sind auch für Andere interessant. Warum nur einem/einer
helfen, wenn mit gleichem Aufwand viel mehr Menschen etwas davon haben könnten? Zweitens, wird es mir ansonsten einfach zu viel. Viele Fragen können auch von anderen Forenteilnehmern beantwortet werden -- oft auch besser als von mir.
4AP der
4-Teile-AVR-Programmer http://halvar.at/elektronik/kleiner_bascom_avr_kurs/ ********************************************************* Offizielles Bascom Forumhttp://bascom-forum.de/forum.php ********************************************************* BASCOM - Tutorial - Einführung in MikrokontrollerPensionisten-Denkweise: Zur Programmierung reicht ein Kabel (...das man sich
selbst lötet), die Software gibts kostenlos und wenn man mit einer
einfachen Hochsprache wie in meinem Beispiel z.B. mit Bascom-Basic
anfängt, dann hat man meist schon am ersten Abend ein Testprogramm am
laufen. Man braucht also erstmal garnichts anzuschaffen als einen
Controller für ca. € 2,- und mit ein paar vorhandenen Kleinteilen und einem
Lötkolben in der Werkstatt kann man gleich loslegen!
http://www.bunbury.de/Technik/avr/ 1. Vorbereitung ATmega8 1. Vorbereitung1.1 Was kann der Mega8,
was kostet der und wo bekomme ich ihn?
|
Dabei ist der Mega8 recht klein und besitzt die übliche Bauform einfacher Schaltkreise (DIL), die es auch Laien ohne Probleme möglich macht Schaltungen zu löten. Er hat sich mittlerweile quasi als ein Standard durchgesetzt und man kann ihn fast in jedem vernünftigen Elektronikgeschäft für 2 bis 3 Euro kaufen. (bei Conrad zahlt man natürlich das 3fache) | ![]() |
(nach oben)
1.2 Welche Hardware brauche ich um AVRs wie den Mega8 zu programmieren?
Nicht viel. Der Mega8 lässt sich fertig in
eine Schaltung eingebaut programmieren - ohne teures
Programmiergerät, ohne den Chip jedes mal umstecken zu müssen.
Also erst die Schaltung aufbauen und einfach später am
"lebenden" Objekt jeden einzelnen Befehl sofort
ausprobieren!
Grundsätzlich genügt es 5V Betriebsspannung anzuschließen und
ein 5-adriges Kabel zu löten, das am Parallelport des PCs
angeschlossen wird. Sicherheitshalber baut man in einige
Leitungen Widerstände ein um sowohl den Parallelport als auch
den Chip selbst vor Schäden zu schützen.
Es sei darauf hingewiesen, daß es zu Störungen kommen kann,
wenn die Programmieranschlüsse des Mega8 in einer Schaltung
zusätzlich für andere Funktionen vorgesehen sind. D.h. ist z.B.
an einem der für die Programmierung benötigten Pins schon ein
Relais angeschlossen, dann kann dieses während des
Programmierens anziehen oder die Programmierung schlägt fehl.
Soweit möglich ist es günstig die Programmieranschlüsse also
unbeschaltet zu lassen. Benötigt man alle Anschlüsse für die
Schaltung ist es das Sicherste sich eine Extra-Platine zu löten
und den Chip zum Programmieren umzustecken. Ein Programmierboard
sieht am einfachsten so aus:
Diese Schaltung kann als Grundlage genommen werden um Schaltungen
für den Maga8 zu entwerfen, die man jederzeit nachträglich
umprogrammieren kann. Dazu empfiehlt es sich noch einen
beliebigen 5poligen Zwischenstecker auf der Platine vorzusehen,
um das Programmierkabel abzeihen zu können.
Bei anderen AVR-Typen finden sich die Signale MOSI, MISO, SCK und
/Reset ebenfalls und hier sind lediglich die Pinnummern
anzupassen.
Den Quarz und die beiden zugehörigen Kondensatoren können für
einfache Anwendungen auch weggelassen werden, da der Mega 8 einen
internen Oszillator besitzt. Allerdings empfehle ich zumindestens
eine Schaltung zu besitzen, in der der Quarz oder ein
Keramikoszillator enthalten sind. Wird der interne Oszillator
einmal ausgeschaltet und auf extern eingestellt lässt sich der
Mega8 erst wieder ansprechen und auch erst wieder
zurück-umstellen, wenn auch wirklich ein externer Oszillator
angeschlossen ist.
(nach oben)
1.3 Welche Software brauche ich?
Die Software "BASCOM" ist ein
beliebter und sehr einfacher Basic-Compiler für die
Programmierung des Mega8 und anderer AVRs. Er stellt einem sehr
viele komplexe Funktionen zur Verfügung um z.B. die Ansteuerung
von Modellbau-Servos oder die Ausgabe von Text auf LCD-Anzeigen
mit einem einzigen Befehl zu erledigen. Um z.B. den Wert einer
Variablen X über die serielle Schnittstelle auf den
PC-Bildschirm zu senden genügt der Befehl: "Print X" -
fertig!
Selbstverständlich gibt es auch sehr gute und großteils völlig
kostenlose Compiler für C sowie Pascal und natürlich kann man
auch direkt in Assembler programmieren - worauf ich hier jedoch
nicht weiter eingehen will.
BASCOM ist nicht kostenlos - die Demo ist aber zeitlich und in
den verfügbaren Funktionen nicht eingeschränkt. Lediglich die
Programmgröße - also quasi die Länge und Komplexität des
Programmes sind eingeschränkt. Zum Erlernen und für viele
praktische Schaltungen ist diese Limitierung aber noch nicht
störend. Wenn man BASCOM kennen und meist auch schätzen gelernt
hat kann man sich entscheiden ob es einem die gerade mal 80,-Euro
für die Vollversion wert sind oder ob man umsteigt. Der Support
bei registrierter Vollversion funktioniert reibungslos (wenn auch
in Englisch) und meist befinden sich im Anhang einer Email der
Support-Mitarbeiter gleich die gewünschten Updates oder
Dokumente.
Die BASCOM-Demo kann man sich hier von meiner Seite
oder direkt vom Anbieter MCS-electronics
herunterladen. Man achte darauf, daß vor der Installation
irgendein Drucker installiert wurde - BASCOM verweigert sonst
beim ersten Starten den Dienst mit entsprechender Fehlermeldung.
Und es sollte ein beliebiger Parallelport-Drucker(-treiber) sein
- BASCOM akzeptiert USB-Drucker nicht! (Bug)
Da BASCOM Microcontroller direkt über unterschiedlichste
Programmiergeräte beschreiben kann ist es wichtig sorgfältig
darauf zu achten, daß die folgenden Einstellungen korrekt
vorgenommen werden:
Options -> Programmer
Bei Programmer "Universal MCS Interface" und
"WinAVR and SP12" auf der Lasche "Universal"
Das sollte alles sein. Sofern noch nicht geschehen schließt man
einfach das Parallelportkabel und die 5V-Betriebsspannung an den
Mega8 an und es kann los gehen. Man schreibt ein Programm
(nächstes Kapitel) - drückt die Taste F7 um das Programm zu
compilieren (in Chip-Sprache zu übersetzen) und ist dies ohne
Fehlermeldung geschehen drückt man F4 um das Programmerfenster
zu öffnen.
Öffnet sich sofort das folgende Fenster genügt ein Klick auf
"Autoprogram chip" und man kann zusehen wie der Chip
beschrieben wird - fertig!
Bei den meisten erscheint in diesem Moment aber statt des
Programmers erstmal diese Fehlermeldung:
Das bedeutet, daß die Verbindung zum Chip nicht hergestellt
werden konnte. In 90% aller Fälle (meine Erfahrung) liegt das an
fehlerhaft gelöteten Kabeln, falscher Betriebsspannung und
Kurzschlüssen auf Leiterplatten. Also lieber 8mal hingucken, die
5V Betriebsspannung im angeschlossenen Zustand nachmessen und
jede einzelne Verbindung durchklingeln bevor man einen Hilferuf
in die Welt schickt! Gegen falsches Löten kann euch im Internet
keiner helfen!
Ist da 200%ig sicher alles einwandfrei und erscheint trotzdem
immer wieder diese Fehlermeldung, dann kommuniziert BASCOM nicht
korrekt mit dem Parallelport, entweder weil dieser eine andere Adresse als
$378 hat (in der Systemsteuerung überprüfen) -
oder (meistens) weil z.B. WinXP /2k / NT den Direktzugriff auf den Port verweigert.
In diesem Falle ladet euch die Datei "giveio.sys" und speichert sie im Ordner "../Windows/System32/drivers"
Ist das erledigt habt Ihr 2 Möglichkeiten:
- Ihr ladet euch die Datei "LoadDrv.exe" und könnt/müsst den Treiber jedes mal manuell starten und ggF. abschalten
- Ihr installiert den Treiber permanent indem Ihr die Datei "giveio.inf" ladet und ausführt.
Erklärungen, wie dieser Treiber und die Portfreigabe funktioniert findet
Ihr reichlich im Netz. Ich habe den Treiber aus einer mMn seriösen
Quelle
- übernehme aber selbstverständlich keinerlei Garantie das er virenfrei
ist und natürlich auch keine Gewährleistung für mögliche Schäden, die
aus der Installation entstehen können.
Informiert euch selbst und wenn Ihr Zweifel habt, dann lasst die Finger
davon und kauft euch einen USB-Programmer. Ich nutze diesen Treiber
jedenfalls auch und hatte bislang keinerlei Probleme damit.
Dieses Low-Cost-Programmer-Kabel lässt sich nach meiner Erfahrung bis
WinXP wirklich an jedem Rechner zum Laufen bewegen -
Erfahrungen, ob das unter Vista auch noch geht habe ich einstweilen
nicht - falls es jemandem von euch gelingt würde mich eine eine kleine
Info freuen.
Auf alle möglichen Fehlervarianten einzugehen würde den Rahmen dieses
Scripts deutlich sprengen - helfen alle o.a. Maßnahmen nicht weiter,
dann fragt bitte einfach in einem entsprechenden Forum.
(nach oben)
http://www.bunbury.de/Technik/avr/vorbereitung.htm
2. Programmierung BASCOM-AVR - Programmierpraxis
Wichtig: diese Anleitung soll die
hardwarespezifischen Unterschiede der Programmierung zwischen PCs
und Mikrokontrollern vermitteln und richtet sich damit an Leser,
die in irgendeiner Weise bereits Vorkenntnisse in Programmierung
allgemein besitzen. BASCOM besitzt eine ganz brauchbare Hilfe mit
reichlich Beispielcode, mit der sich die genaue Syntax der
Befehle wie If-Abfragen, Schleifen etc. schnell herausfinden
lässt. Einige Teile sind interaktiv und ermöglichen
es z.B. Erklärungen und Beispielrechnungen mit eigenen Werten nachzuvollziehen.
Dazu muß jedoch Javascript aktiviert sein
2. BASCOM - Programmierpraxis
2.1 Zahlen, wie sie ein µC versteht
2.1 prinzipieller Programmaufbau
2.3 digitale Ein- und Ausgänge
2.4 analoge Eingänge (ADCs)
2.5 "analoge" Ausgänge (PWM)
2.6 Hardwareinterrupts
2.7 Timer
2.8 serielle Schnittstelle
2.9 der EEprom
2.1 Zahlen, wie sie ein µC versteht
Um zu verstehen warum ein Microcontroller
manchmal ein unerwartetes Ergebnis präsentiert, sollte man nicht
nur wissen, wie man eine Binärzahl in eine Dezimalzahl
umrechnet, sondern man sollte das Prinzip kennen, wie
Zahlensysteme zusammenhängen, daß alle absolut gleichwertig
sind und das man mit allen nach den selben Regeln identisch
rechnen kann - ohne diese vorher in "normale" Zahlen
umrechnen zu müssen.
Vorweg: Vermeiden Sie bei Mikroprozessorprogrammen wo immer
möglich Fließkommazahlen!
Während es bei der üppigen Rechneleistung eines PCs kaum eine
Rolle spielt wieviele Dezimalbrüche man miteinander verrechnet,
kostet eine einzige Fließkommaoperation beim µC spürbar
Speicher und Geschwindigkeit.
Hier nun erstmal 2 kleine Beispiele, mit denen Sie testen
können, ob Ihr Zahlenverständnis wirklich ausreichend ist um
auch mal einem Programmfehler auf die Schliche kommen zu können:
Die Variable x ist für beide Aufgaben als Byte dimensioniert:
x = 249 + 10 = | |
x = 249 / 10 = |
Für alle die das Zahlenscript
schon gelesen haben, oder auch auch
ohne dies die richtigen Antworten geben konnten habe ich hier
noch ein paar kleine, nicht weiter dokumentierte Hilfsprogramme
abgelegt, die bei den nötigen Berechnungen sehr hilfreich sein
können.
(nach oben)
2.2 prinzipieller Programmaufbau
Ganz kurz vorweg 6 Punkte zur
BASCOM-Syntax, die sich bei unterschiedlichen Hochsprachen
häufiger unterscheiden:
- es ist nicht nötig Befehle oder Zeilen durch ein Semikolon
o.ä. abzuschließen
- Strings bzw. Textkonstanten werden durch Gänsefüßchen
gekapselt
- Kommentare werden durch ein Hochkomma eingeleitet und enden
automatisch mit einem erzwungenen Zeilenumbruch (Enter-Taste)
- Binärzahlen werden durch &B und Hexadezimalzahlen mit
&H eingeläutet. Dezimalzahlen sind natürlich ohne Präfix.
- die Zählweise bei Bits beginnt generell mit Bit 0, während
Arrays stets mit Element 1 beginnen
- das Gleicheitszeichen wird sowohl für Vergleiche als auch für
Wertzuweisungen identisch verwendet
Ein fertig geschriebenes Programm wird durch F7 compiliert und
verläuft dies ohne Fehler kann es mit F4 auf den Chip
"gebrannt" werden. Fehler beim Compilieren können
durch Doppelklick auf die Fehlermeldung (Statuszeile ganz unten)
direkt angesprungen werden.
Ein Bascom-Programm beginnt immer damit dem Compiler mitzuteilen
für welchen Mikrokontrollertyp das Programm vorgesehen ist. Dies
erfolgt indem man die Definitionsdatei benennt, in der alle
prozessorspezifischen Adressen und Eigenheiten abgelegt sind.
Diese Dateien befinden sich im Bascom-Stammverzeichnis und dort
kann man im Zweifelsfalle auch nachschauen, wie die Datei für
den gewünschten Prozessor genau heißt.
$regfile = "M8def.dat" | < Definitionsdatei (hier für ATmega8) |
$crystal = 8000000 | < Quarzfrequenz in HZ angeben (hier 8MHz) |
Dim x As Byte | < Variablen definieren (hier x als Byte 0 - 255) |
(Befehle) | |
Do | < Beginn der Hauptschleife |
(Befehle) | |
Loop | < Ende der Hauptschleife |
End | < Programmende (für Compiler erforderlich) |
Zu Anfang (also vor der Hauptschleife) definiert man Variablen, die Funktionen der Anschlüsse, konfiguriert die Hardware usw. Diesen Teil des Programmes bezeichne ich im Folgenden als Header. Der Header enthält alle Anweisungen, die beim Starten des Prozessors einmalig und vor allen anderen Programmteilen ausgeführt werden sollen.
Welche Zahlentypen verwendbar sind und
welche Werte darin gespeichert werden können entnehmen Sie bitte
der Bascom-Hilfe. Am häufigsten wird man wohl Bit (0 oder 1) ;
Byte ( 8 Bit = 0 -255) und Word (16 Bit = 2 Byte = 0 - 65535)
verwenden.
Nach dem Header folgt üblicherweise für Mikrocontroller eine
Endlosschleife, da das Programm sonst nur einmal durchlaufen
würde.
Vor oder auch nach der Hauptschleife kann man später noch beliebige Funktionsteile anfügen, die später Basic-üblich einfach durch Goto oder Gosub über Ihren Namen (Label) angesprungen werden können. Wird ein Unterprogramm von einem beliebigen Programmpunkt aus per Gosub Unterprogramm1 angesprungen, führt ein Return am Ende des Unterprogrammes dazu, daß das Programm bei erreichen des Return-Befehles wieder direkt nach dem Gosub-Befehl fortgesetzt wird. Das Unterprogramm selbst wird einfach durch seinen Namen, abgeschlossen durch einen Doppelpunkt eingeleitet und der Aufruf erfolgt ohne Doppelpunkt:
Gosub Unterprogramm1
(Befehle)
Unterprogramm1:
Return
Es ist nicht erforderlich Subroutinen bzw.
Funktionen im Header zu definieren (Funktionsprototypen o.ä.)
oder durch einen Befehl der Art Function oder Procedure
einzuläuten - es genügt schlicht das Label (der Name mit
Doppelpunkt).
Call by Value (Variablen- bzw. Pointerübergabe) an Funktionen
geht nicht - also ausschließlich globale Variablen benutzen.
(nach oben)
2.3 digitale Ein- und Ausgänge
Bevor man die Anschlüsse benutzen kann
muss man festlegen, welche Pins als Ein- oder Ausgänge genutzt
werden sollen. Alle Pins sind bidirektional - man kann sich also
aussuchen wo man was anschließt. Die Einstellung sollte also zu
Anfang des Programms (Header) vorgenommen werden - kann aber
später jederzeit wieder geändert werden.
Die Pins sind in mit Buchstaben bezeichnete Ports unterteilt,
denen jeweils Register-Bytes zugeordnet sind, die die Richtung
der Daten speichern (Register DDR), die Eingangswerte zum
Einlesen beinhalten (Register Pin) oder die Ausgabewerte
(Register Port).
![]() |
Der Mega8 besitzt 3
Ports: B; C und D, deren Anschlüsse im Bild ersichtlich
sind. Nochmal der Hinweis: die Zählweise beginnt immer mit 0. Die Angaben in Klammern beziehen sich auf optionale Verwendungen des Pins: Pin23 - 28 lassen sich z.B. auch als Analogeingänge konfigurieren, über Pin 2 und 3 lässt sich eine serielle Verbindung zum Computer aufbauen usw. Die Pins 9 und 10 (PB6 und 7) sind nur frei verfügbar, wenn der Mega8 auf internen Takt eingestellt ist, da sie sonst für den Quarzoszillator verwendet werden. Pin1 ist standardmäßig mit der Reset-Funktion belegt, womit PC6 auch nicht mehr uneingeschränkt verwendbar ist. Die Reset-Funktion lässt sich prinzipiell auch deaktivieren um den Pin nutzbar zu machen - allerdings lässt sich der Chip dann nicht mehr einfach umprogrammieren. Ich rate davon ab und werde auch nicht näher darauf eingehen. |
Man kann jeweils den Zustand aller Pins
eines Ports gleichzeitig verändern/einlesen, indem man ein
ganzes Byte in ein Register schreibt/ausliest.Jedes Bit des Bytes
bezieht sich dann auf einen Pin des Ports. Will man nur den
Zustand eines Bits, also eines einzigen Pins verändern oder
abfragen muß man an den Befehl nur einen Punkt und die Nummer
des zu verändernden Pins anhängen.
Also "RegisterPortbuchstabe.Pinnummer = Wert"
Es empfiehlt sich die Werte direkt binär anzugeben
(&B...) weil man so einfach abzählen kann, welcher Pin
welchen Wert bekommt:
Ein-/Ausgänge festlegen:
DDRD = &B00000101 | schaltet PD0 und PD2 als Ausgang, alle Übrigen werden als Eingänge konfiguriert. |
DDRD.2 = &B0 | setzt nur PD2 auf 0, also auf Eingang und lässt die übrigen Stellen von DDRD unverändert. |
Pins Ein- und Ausschalten:
PortD = &B00000101 | schaltet die Pins PD0 und PD2 auf 1 (+5V) und setzt die Übrigen auf 0V |
PortD.2 = &B1 | schaltet nur PD2 auf 1 (+5V) und lässt die anderen unverändert |
Signal an den Pins einlesen:
Die Eingänge eines AVRs brauchen immer
eindeutige Spannungs-Signale: entweder 0V oder +5V. Ein Schalter
kann aber nicht 2 verschiedene Spannungen ausgeben, sondern nur
einen Stromkreis schließen oder öffnen. Deshalb muss man
zusätzlich wie im Bild unten einen Widerstand vorsehen. Andere
Schaltkreise, Fernsteuerungsempfänger oder Sensoren mit
Digitalausgängen liefern meistens solche Signale und können
ohne zusätzlichen Widerstand angeschlossen werden.
DDRD.2 = 0 x = PinD.2 x ist 1 bei gedrückter Taste |
DDRD.2 = 0 x = PinD.2 x ist 0 bei gedrückter Taste |
![]() |
![]() |
![]() |
Auch Transistoren
machen letztlich nichts anderes als Schalter oder Relais:
Kontakt auf oder zu. Deshalb müssen auch Transistoren
mit Pull-Widerständen versehen werden, wie im Bild
links. Da am Transistorausgang nicht mehr als die 5V vom Pullupwiderstand rauskommen können, ist diese Schaltung auch geeignet um andere Spannungen als 5V einzulesen. Mit dem 10k Basiswiderstand und als Transistor z.B. einem BC550 erhält man bei beliebigen Eingangsspannungen ab ca. 1-2V bis 30V am AVR ein sauberes 0-Signal und mit 0V oder ganz ohne irgendein Signal am Eingang eine logische 1 am AVR. |
Das Eingänge häufig nur mit Tasten oder Transistoren gesteuert werden sollen wussten auch die Entwickler der AVRs und haben die Pullupwiderstände gleich mit eingebaut. Allerdings muss man diese extra einschalten - da sie im Grundzustand nicht aktiv sind. Statt sich noch ein Register merken zu müssen hat man dem Benutzer das Leben leicht gemacht: den Pullupwiderstand eines Pins schaltet man ein, indem man eine 1 ausgibt, obwohl der Pin als Eingang eingestellt wurde:
![]() |
So kann man sich die
extra Pullupwiderstände sparen, wenn man einen Taster
oder Transistor anschließt, der 0V (Masse) schaltet: DDRD.2 = 0 PortD.2 = 1 x = PinD.2 x ist 0 bei gedrückter Taste |
Vielleicht ist es aufgefallen: wenn man einen einzelnen Pin, bzw.
ein einzelnes Bit ein und ausschalten will ist es egal ob man das
&B schreibt, weil die Werte 1 und 0 dezimal identisch sind
mit der binären Zahl. Wenn man mehrere Bits gleichzeitig ändern
will - also ein Byte angibt muß man darauf achten. Der Befehl
DDRC = &B00001001 schaltet C.0 und C.3 als Ausgänge den Rest
als Eingang. Dezimal muss 00001001 umgerechnet werden: DDRC=9
macht also genau das selbe.
Abschließend noch ein zusammengefasstes Beispiel für die
digitalen Ein- und Ausgänge:
DDRB = &B00110000 | schaltet B4 und B5 als Ausgänge und B0-B3 als Eingänge, B6 und B7 gibts beim Mega8 garnicht | |
PortB = &B00010010 | Ausgang B4 wird auf +5V und B5 auf 0V geschaltet und nur der Pullup für den Eingang B1 wird aktiviert - die anderen Eingänge sind "offen" und müssen mit Ausgängen anderer Bausteine verbunden werden. |
Bei Eingängen, an die garnichts
angeschlossen wird sollte man immer den Pullup aktivieren, da sie
sonst zufällige Zustände haben und das Programm anfangen kann
komische Sachen zu machen.
(nach oben)
2.4 analoge Eingänge (ADCs)
Mit dem Mega8 kann man 6 analoge Spannungssignale im Bereich von 0 bis +5V einlesen, z.B. von Sensoren. Standardmäßig werden die Spannungswerte mit 10 Bit binär gewandelt und ergeben damit eine Zahl von 0 (0V) bis 1023 (+5V). Die 6 Analogeingänge ADC0 - ADC5 befinden sich an den selben Pins wie der Digitalport C - also Pin 23 bis 28. Die Werte einzulesen ist vergleichsweise einfach. Der ADC muß nur mit einer Zeile im Header konfiguriert und mit einer weiteren gestartet und ab dann stehen die Werte zur verfügung:
Config Adc = Single , Prescaler = Auto | |
Start Adc |
Ist das einmal im Header geschehen, kann man den aktuellen Wert eines Analog-Kanals jederzeit mit der Funktion Getadc(Kanalnummer) auslesen:
x = Getadc(4) | schreibt den Wert der Spannung an Pin 27 (ADC4) in die Variable x |
Man beachte, daß die Zahl 10 Bit - also
bis 1023 groß sein kann und damit natürlich nicht in einer
Variable der Größe Byte gespeichert werden kann. Deshalb sollte
x zuvor mindestens als Word (16Bit) definiert worden sein. Einen
Variablentyp mit genau 10 Bit gibt es nicht - Word ist das
Nächstgrößere.
(nach oben)
2.5 "analoge" Ausgänge (PWM)
Technisch gehört die Ausgabe von
"analogen" Spannungen hinter die Einführung in die
Timer, thematisch passt es hier aber besser, nach den analogen
Eingängen. Eine Analogspannung kann ein Prozessor eigentlich
nicht ausgeben, mit einem Trick aber etwas Ähnliches:.
Ein Motor würde z.B. an 6V ca. halb so schnell laufen wie bei
12V. Das Selbe - also halbe Drehzahl - erreicht man, wenn man an
den Motor für eine halbe Sekunde die volle 12V-Spannung anlegt
und Ihn dann wieder für eine halbe Sekunde ausschaltet. Die
volle Drehzahl kann er nicht erreichen, das geht nur, wenn die
12V dauerhaft anliegen. Die halbe Drehzahl ergibt sich dadurch,
daß der Motor die halbe Zeit beschleunigt und die andere Hälfte
abbremst.
So ein Signal, bei dem die Ein- und Ausschaltzeit prozentual
eingestellt wird (Puls-Breiten-Modulation) kann ein Controller
erzeugen. Die Ein- und Ausschaltzeiten folgen dabei viel
schneller als im Beispiel mit der halben Sekunde. Praktisch so
schnell, daß eine LED nur schwach zu leuchten schneint und man
garnicht bemerkt, daß diese kurz eingeschaltet und danach
zeitweise ganz ausgeschalten ist. Der Mega8 stellt zwei
PWM-Ausgänge zur Verfügung: OC1A (Pin15) und OC1B (Pin16)
Um diese benutzen zu können muß im Header der Timer1 für die
PWM-Funktion konfiguriert, aktiviert und gestartet werden:
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 |
Enable Timer 1 |
Start Timer 1 |
Eine genaue Beschreibung was welche Angabe
bedeutet findet sich in der Bascom-Hilfe.
Ist der Timer so konfiguriert, kann man den aktuellen Wert eines
PWM-Augangs jederzeit mit der Funktion Pwm(Kanalnummer)
einstellen. Ein PWM Signal wird dann ständig ausgegeben, bis man
den Wert = 0 setzt oder den Timer1 stoppt.
In der Config-Zeile ist der PWM-Ausgang auf 10 Bit Auflösung
eingestellt - also wieder Werte zwischen 0 und 1023. Gibt man dem
PWM-Kanal jetzt den Wert 1023 vor, dann ist der Ausgang für 1023
von 1023 Zeitabschnitten eingeschaltet - also es kommt dauerhaft
+5V aus dem Ausgang. Setzt man den Wert auf 0 (von 1023
Zeitschritten) ist der Ausgang ständig auf 0V. Bei allen anderen
Zahlen ergeben sich Zwischenwerte - gibt man z.B. 10% der
insgesamt 1023 Zählschritte, also 102 als Sollwert vor, dann
bekommt z.B. eine LED am Ausgang auch nur 10% der Zeit Strom und
scheint demnach auch nur mit 10% Ihrer Leuchtkraft zu leuchten.
Pwm1A = 512 | gibt ein Schaltverhältnis von ca. 50% (512 von 1023) auf OC1A (Pin15) aus |
Der PWM Ausgang lässt sich auch auf andere Auflösungen als 1023 Schritte einstellen. Die 10 Bit aus dem Beispiel haben nicht nur den Vorteil, daß sich so sehr feine Abstufungen einstellen lassen, sondern vorallem, daß mit 0-1023 der selbe Zahlenbereich benutzt wird wie bei den Analogeingängen. Theoretisch könnte man also die Spannung von einem Potentiometer an einem Analogkanal (1ADC ) direkt auf einen PWM-Kanal ausgeben und so z.B. die Drehzahl eines Motors einstellen: Pwm1A = Getadc(1) - führt aber leider zu einer Fehlermeldung. Man muß zuerst den Analogwert in eine Variable einlesen und kann dann die Variable auf den PWM-Ausgang schreiben um das zu realisieren:
x = Getadc(1) | steuert mit dem Analogwert von ADC1 (Pin24) den PWM-Ausgang OC1A (Pin15) |
Pwm1A = x |
Man beachte, das x wieder mindestens vom
Typ Word sein muß, um die 10Bit-Werte aufnehmen zu können.
(nach oben)
2.6 Hardwareinterrupts
Normalerweise läuft das Programm des
Mikrocontrollers immer in einer Endlosschleife. Man kann nun z.B.
ständig den Zustand einer Taste abfragen um daraufhin einen
Vorgang auszulösen. Die Programmschleife braucht jedoch eine
gewisse Durchlaufzeit - ist der Tastendruck bzw. das
Eingangssignal sehr kurz, erscheint also erst nach einer Abfrage
des Pin-Zustandes und ist schonwieder vorbei, wenn die
Programmschleife wieder bei der Abfrage angekommen ist, dann
"bemerkt" das Programm garnicht, daß ein Signal da
war.
Dafür gibt es 2 spezielle Anschlüsse: Int0 (Pin4) und Int1
(Pin5).
Diese Pins kann man so konfigurieren, daß sie bei Signalen
sofort das Hauptprogramm anhalten und zuerst einen anderen
Programmteil ausführen, ohne das der Pinzustand in der Schleife
noch abgefragt werden muß. Solche Funktionen, die daß
Hauptprogramm augenblicklich unterbrechen können nennt man
Interrupts und diese sind vor allem für sehr kurze oder
zeitkritische Signale geeignet.
Bei der Einstellung der Parameter kann man auswählen, ob die
Unterbrechung dauerhaft bei 0 Signal (Low Level), oder nur
einmalig beim Umschalten von 0 auf 1 (rising) oder umgekehrt von
1 auf 0 (falling) erfolgen soll:
Config Int0 = Falling | löst eine Unterbrechung des Hauptprogrammes aus, wenn Pin4 von 1 auf 0 umschaltet |
Enable Interrupts | aktiviert allgemein die Interruptfunktionen - muß nur einmal angegeben werden |
Für die Beschaltung mit Pullup- oder
Pulldownwiderständen gilt das selbe wie bei den
"normalen" Digitaleingängen. Ein Interrupt-Anschluss
sollte natürlich auch als digitaler "Eingang"
definiert worden sein.
Nun muß man dem Prozessor noch mitteilen, was er machen soll,
wenn der Interrupt ausgelöst wird. Dazu schreibt man vor oder
nach der Hauptschleife ein Unterprogramm. Der Name
desUnterprogrammes wird zuerst angegeben, abgeschlossen mit einem
Doppelpunkt. Damit weiß Bascom, daß dies ein Label, bzw eine
Sprungmarke ist. Beendet wird die Subroutine durch den Befehl
Return, der dazu führt, daß der Prozessor dort wieder mit dem
Hauptprogramm fortfährt, wo er unterbrochen wurde:
Unterprogramm1: | < Beginn des Unterprogramms |
(Befehle) | |
Return | < Rückkehr zum Hauptprogramm |
Im Header muß noch mitgeteilt werden, daß zu dem Unterprogramm gesprungen werden soll, wenn ein Interrupt ausgelöst wird:
On Int0 Unterprogramm1 | springe bei Interrupt0 zum Unterprogramm1 |
Beim Aufruf eines Unterprogrammes übrigens
nur den dessen Namen angeben, ohne Doppelpunkt. Natürlich kann
ein Unterprogramm, daß automatisch durch einen Interrupt
angesprungen wird auch jederzeit per Programmbefehl mit Gosub
Unterprogrammname angesprungen werden.
Noch ein wichtiger Hinweis, falls die Hardwareinterrupts mit Tasten angesteuert werden:
Das "Prellen" von Kontakten ist ein häufiges Problem in elektronischen
Schaltungen. Das bedeutet, daß bei Betätigung einer
Taste nicht nur ein Impuls gesendet wird, sondern mehrere und häufig
nochmals, beim Loslassen der Taste.
Dieses Problem kann man entweder elektronisch lösen, indem man kleine
Kondensatoren parallel zur Taste anschließt oder per
Software. Die Interrupts im AVR werden meist flankengesteuert genutzt
und werden so mehrmals aufgerufen, auch wenn eine
Taste nur einmal betätigt wurde. Beim Aufruf des ersten Interrupts wird
zwar die Abarbeitung anderer Interruptroutinen
temporär blockiert, aber der AVR "merkt" sich, daß während dessen ein
weiterer Interrupt aufgelaufen ist und führt diesen
unmittelbar nach Beendigung der aktuellen Routine aus. Das Abschalten
bzw. Disablen des Interrupts während der
Abarbeitung hilft leider nichts, da er trotzdem gespeichert wird. Die
Interruptroutine wird dann eben beim Wiedereinschalten des Interrupts
erneut ausgeführt.
Eine mögliche und relativ einfache Lösung für dieses Problem ist, den Interruptspeicher des AVRs vor dem Verlassen der Routine
zu löschen und dies geschieht indem man in das entsprechende Bit des GIFR-Registers eine logische 1 schreibt.
Für den Int0 macht man das z.B. durch den Befehl Gifr.intf0 = 1 . Signalflanken die während der Abarbeitung der
Interruptroutine z.B. durch Prellen entstanden sind führen so nicht mehr zu einem wiederholten Anspringen der Routine.
(nach oben)
2.7 Timer
Der Mega8 besitzt zwei Timer: Timer0 und
Timer1
Timer sind nichts anderes als Zähler, die durch den
Prozessortakt selbstständig vorwärts- oder rückwärtszählen
können. Je nachdem wie hoch die Quarzfrequenz ist und wie der
Timer konfiguriert wird kann man bei bekanntem Timer-Takt anhand
des Zählerstandes sehr genau die Zeit, also z.B. die Dauer eines
Eingangs-Impulses messen. Man kann den internen Takt auch
ausschalten (Modus: Counter) und Impulse von externen
Signalquellen zählen lassen oder man kann Ihn als PWM-Ausgang
konfigurieren.
Timer sind binärer Zähler - Timer0 ist 8 Bit "breit"
und kann demnach nur von 0 bis 255 zählen. Kommt ein 256ter
Zählimpuls geht er wieder auf 0 - das ist so, als ob man ein
Display mit 2 Stellen hat, daß nach 99 auch nur wieder 00
anzeigen kann, statt 100. Timer1 ist 16 Bit breit, kann demnach
bis 65355 zählen und geht beim 65356ten Zählschritt wieder auf
0
Wenn der maximale Zählerstand überschritten wird und sich der Zähler auf 0 zurückstellt, dann wird ein Interrupt ausgelöst. Wie bei den Hardwareinterrupts kann man dem ein eigenes Unterprogramm zuweisen, daß dann automatisch in festen Zeitabständen bei jedem Timerüberlauf aufgerufen wird.
Ein Beispiel:
Sie benutzen
mit 65536 Zählschritten,
einen Quarz mit
MHz
und den Prescaler =
Die Zählschritte des Timers erfolgen mit: Quarzfrequenz /
Prescale = 16 MHz / 256 = 62500 Hz - also alle
0,016 ms. Die
Dauer, die der Timer insgesamt benötigt bis die 65536 Schritte voll gezählt sind beträgt: 0,016 ms x 65536 = 1.048576 Sekunden.
Stellt man den Timer im Unterprogramm gleich auf einen
höheren Startwert als 0 ein, dann zählt er von dort ab
natürlich nicht mehr die vollen 65536 Schritte bis
er wieder auf 0 umschlägt. So kann man die Zeitabstände
zwischen den Interrupts verkürzen und genau
einstellen.
Angenommen man will den Takt statt alle 1.048576 Sekunden genau auf
Sekunden einstellen (aktualisieren), dann darf der Timer nur noch 1,0 Sekunden / 0,016 ms = 62500 Zählschritte zählen. Ergibt diese Rechnung
keine glatte Zahl muß man runden*. Zieht man jetzt diesen
Wert vom Maximalwert 65536 ab, erhält
man den Startwert, auf den der Zähler voreingestellt werden
muss: 3036.
Der Timer zählt jetzt also immer von 3036 bis 65536 und das Unterprogramm wird damit alle 1.0 Sekunden angesprungen, also mit 1 Hz. Das Voreinstellen auf den neuen
Startwert sollte man übrigens gleich als erstes im
Unterprogramm erledigen. Der Timer kann dann im Hintergrund
schon korrekt weiterzählen, während man andere Befehle
ausführen lässt. Ein fertiges Programm, in dem der
Timerinterrupt alle 1.0 Sekunden
aufgerufen wird, könnte also prinzipiell einfach so
aussehen:
$regfile = "M8def.dat" | 'Definitionsdatei für ATmega8 |
$crystal = 16000000 | 'Quarz: 16 MHz |
Config Timer1 = Timer , Prescale = 256 | 'Timer konfigurieren |
On Timer1 Timerroutine | 'Timerinterrupt Subroutine zuweisen |
Enable Timer1 | 'Timer aktivieren |
Start Timer1 | 'Timer starten |
Do | 'Beginn Hauptschleife |
'Programmbefehle einfügen | |
Loop | 'Ende Hauptschleife |
Timerroutine: | 'Beginn Subroutine |
Timer1 = 3036 | 'Timer auf neuen Startwert einstellen |
'Programmbefehle einfügen | |
Return | 'Ende Subroutine |
End |
*Es ist immer sinnvoll, sich vorher etwas Gedanken über
Quarz, Prescale und Timer zu machen, wenn das Ergebnis genau
werden soll. Je mehr Zählschritte dem Timer noch übrig
bleiben, je genauer wird das Ergebnis und je weniger fällt
das Runden auf glatte Zählschritte ins Gewicht. Eine
Timerschleife für Timer0 mit 256 Schritten schon auf 250
Schritte voreinzustellen kann kaum vernünftige Resultate
bringen. Muß man z.B. schon von 0,5 auf einen ganzen Takt
aufrunden, ergäbe sich so auf die letzten 6 verbleibenden
Zählschritte schon ein Fehler von knapp 10%, währen die 0,5
Rundung auf z.B. 200 verbleibende Schritte nur noch 0,025%
ausmacht.
Konfiguriert man den Timer als Counter, dann kann man an die entsprechenden Eingänge: Pin 6 für Timer0 und Pin 11 für Timer1 digitale Signale anschließen, die dann gezählt werden. Man kann einstellen ob der Zählschritt bei der ansteigenden Flanke ( 0 -> 1 Wechsel) oder der abfallenden Flanke des Signals erfolgen soll und selbstverständlich kann man auch hier einen Prescaler vorgeben, so daß z.B. nur jeder 1024te Zählimpuls erfasst wird.
Beispiel:
Config Timer1 = Counter , Edge = Rising, , Prescale = 1024 ' Timer1 zählt jedes 1024te Signal an Pin11 in dem Moment, wo dieses von 0 auf 1 umschaltet.
Die Timer bieten noch weitere
Einstellmöglichkeiten, die ich hier beim besten Willen nicht
aufführen kann. Den Timer1 als PWM-Ausgang zu konfigurieren
wurde oben schon teilweise erklärt, über weitere Möglichkeiten
kann man sich hervorragend in der BASCOM-Hilfe belesen.
(nach oben)
2.8 serielle Schnittstelle
Die meisten älteren Computer besitzen noch
serielle Schnittstellen (z.B. Com1) mit denen AVRs dank Ihrer
eingebauten UART spielend kommunizieren können. Neuere Computer
besitzen diese Anschlüsse häufig nicht mehr, hier kann man sich
aber z.B. mit einem USB Adapter behelfen. Diese Adapter sind
entweder kleine Geräte oder sogar im Stecker eines Kabels
eingebaut und melden sich beim Betriebssystem wie ein Com-Port
an. Alle alten Beispiel- und Terminalprogramme kann man damit über USB
weiterverwenden und meist noch mit höheren
Übertragungsgeschwindigkeiten.
Natürlich kann man die serielle Schnittstelle auch benutzen,
um mehrere AVRs miteinander Daten austauschen zu lassen.
Während man mehrere AVRs einfach zusammenschalten kann muss man
beachten, dass die Spannungen von genormten RS232-Anschlüssen
(wie am PC) zu hoch (+/-12V) und zudem invertiert sind. Will man
nur Daten vom PC empfangen will man aber auch Daten zum PC senden
müsste man sich zuerst die +/-12V erzeugen und das Signal dann
noch invertieren. Dafür gibt es fertige Bausteine wie den Max232, die das alles auf einmal erledigen.
Allerdings ist das Ganze etwas umständlich: USB hat 5V Pegel, für
RS232-Kompatibilität werden die Signale im Wandler invertiert und auf
+/- 12V umgesetzt.
Diese Spannungen muß der Wandler aus den +5V auch erstmal selbst
erzeugen. Auf eurer Platine macht Ihr das ganze mit Max232 o.ä. dann
wieder rückwärts -
keine schicke Lösung. Die +/-12V RS232-Pegel haben nur da Vorteile, wo
das Übertragungskabel sehr lang sein muß - 20m und mehr.
Die Fa. FTDI-Chip bietet ICs an (z.B. FT232R), die sich am USB-Port auch
als Com-Port anmelden - aber direkt 5V-Signale ausgeben die man direkt
an den Controller anschließen kann.
Die ganze Hin- und Herwandlung und Invertierung auf 12V-Signale
entfällt, man spart sich Bauteile und es sind wesentlich höhere
Kommunikationsgeschwindigkeiten möglich.
Meistens kann man so auch gleich die 5V-Versorgungsspannung vom USB-Port
für den Controller benutzen und die FTDI-Chips geben meist sogar einen
12MHz-Takt aus, womit man sich den Quarz am Controller auch noch sparen
kann.
Leider gibt es diese Wandlerchips nur in SMD-Bauformen, die für Laien nicht einfach zu verbauen sind. Bei der Fa. Elmicro
gibt es für weniger als 20,-€ fertige Bausteine mit den Chips von FTDI
die sich einfacher
verbauen lassen und es gibt sogar fertige USB-RS232-Wandlerkabel, die
direkt nichtinvertierte 5V-Signale ausgeben. Diese Kabel kann man direkt
an den Controller anschließen und spart sich die ganze
Zusatzschaltung mit MAX232 o.ä. vollständig.
Daten auszutauschen ist mit Bascom
ausgesprochen simpel. Zunächst gibt man dem AVR im Header eine
Baudrate an und schon kann man mit einem einfachen "Print
X" den Wert einer Variablen an den Rechner senden.
Natürlich können über so eine Datenleitung nur Binärzahlen
(Bytes) gesendet werden. Jeder Zahl ist deshalb ein
Buchstabe/Sonderzeichen (Ascii-Tabelle) zugeordnet, den
PC-Programme anzeigen, wenn der entsprechende Zahlenwert
empfangen wird.
Bascom kümmert sich von selbst um die Umwandlung des
Zahlenwertes in ASCII-Zeichen und sorgt auch dafür, daß nach
der Zahl in die nächste Zeile gesprungen wird, indem es das
Sonderzeichen mit der Ascii-Nummer 13 (CR) als Zeilenumbruch anhängt.
Man kann aber
natürlich auch direkt Binärwerte oder Buchstaben/Texte senden:
$baud = 9600 | 'aktiviert die Schnittstelle und setzt die Baudrate auf 9600 |
Aber Achtung! Vorsicht!! Obacht!!!
Schreibt man das Baud-Statement in den Header wird nicht nur die UART
initialisiert, sondern es werden außerdem gleich die endsprechenden RXD /
TXD-Pins konfiguriert! D.h. Praktisch: Pin 2 wird als Eingang und Pin 3
als Ausgang gesetzt und die Digital-IOs PD0 und PD1 sind damit nicht
mehr verfügbar!
Wenn man die serielle Schnittstelle nicht benutzt sollte also auch auf
das $baud-Statement im Header verzichtet werden.
Ein Beispiel für die Ausgabe von Werten über die serielle Schnittstelle:
x = 107
y = 110
Bascom-Befehl | gesendete Werte | Bildschirmanzeige |
Print "x" Print "y" |
sendet binär die Werte 120 und 121 für
die Buchstaben x und y und anschließend den Wert 13 für Zeilenwechsel |
x y |
Print x Print y |
zerlegt die Zahl 107 in 3
Ascii-Zeichen und sendet diese nacheinander + Zeilenwechsel |
107 110 |
Print x ; Print y ; |
das Semikolon verhindert den Zeilenwechsel | 107110 |
Printbin x Printbin y |
sendet direkt die Variablenwerte
ohne Umwandlung (das Empfangsprogramm wandelt nach Ascii um) |
k n |
Print "x = "; Print x Print "y " Printbin 61; Print y |
Beispiel für Kombinationen (Ascii Code 61 entspricht Gleichheitszeichen; Semikolon nach "y" wurde vergessen, Print ohne weitere Angabe sendet nur einen Zeilenumbruch) |
x = 107 y =110 |
Tip: Will man zwischen anderen ASCII-Zeichen ein Sonderzeichen
versenden, daß BASCOM nicht kennt, dann kann man den ASCII-Code des
Sonderzeichens einfach in geschweiften Klammern in den String
hineinschreiben, den man senden will.
Beispiel: Print "Hallo Welt!" sendet genau das selbe wie Print
"Hallo{032}Welt{033}" weil die {032} dem Ascii-Code des Leerzeichens und
{033} dem Ausrufungszeichen entspricht.
Wichtig: der Ascii-Code in den geschweiften Klammern muß immer dreistellig als Dezimalwert angegeben werden.
Wenn man Daten empfangen will ist das Ganze etwas aufwendiger.
Trifft ein Byte beim AVR ein muß dieses möglichst schnell
ausgelesen werden, weil erst dann der Speicher (Udr) frei ist um
den nächsten Wert zu empfangen. Weil soetwas zeitkritisch ist
ist im AVR wieder ein Interrupt vorgesehen (Urxc), mit dem
automatisch beim Eintreffen eines Bytes ein Unterprogramm
anspringen kann, um das Auslesen sofort zu erledigen.
Den RS232-Empfang im Header vorbereiten:
On Urxc Datenempfang | ' Unterprogramm für RS232 Empfang angeben |
Enable Urxc | ' Interrupt aktivieren |
Dim x As Byte | 'beliebige Variable zum Auslesen des Wertes |
und dann später im Programm:
Datenempfang: | ' Label für Unterprogramm |
x = Udr | ' empfangenen Wert (Udr) in die Variable x auslesen |
' weitere Befehle | |
Return | ' Rückkehr zum Ursprungsprogramm |
In der Variablen x steht jetzt der Wert, der zuletzt empfangen wurde. Trifft ein neues Byte ein wird der letzte Wert von x natürlich überschrieben. Deshalb sollte man - wenn mehrere Bytes nacheinander zu erwarten sind - x möglichst sofort im Unterprogramm weiterverarbeiten, oder in einem Array ablegen. Drückt man auf dem PC eine Taste, dann wird der zur Taste gehörige Ascii-Wert empfangen. Diesen kann man entweder direkt auswerten (If-Abfrage o.ä.) oder mit dem Befehl y = chr(x) einer anderen Variablen (String) wieder das Zeichen/den Buchstaben zuweisen. Häufig ist es aber für einzelne Zeichen (Steuertasten) sinvoll sich das zu sparen. Tragen sie in eines beider Felder einen Wert ein und klicken Sie ins andere um das Ergebnis zu erhalten:
Ascii-Zeichen: | (Buchstabe, Ziffer, Sonderzeichen) | |
Ascii-Wert: | (Dezimalzahl) |
Für den Empfang bzw. zum Senden von Daten im Ascii-Format
genügt auf dem PC grundsätzlich jedes Terminalprogramm. Wie die
grunsätzlichen Einstellungen vorzunehmen sind habe ich
exemplarisch für HyperTerminal beschrieben. Sicher gibt es sehr viel
bessere Terminalprogramme (in Bascom ist auch eines enthalten),
allerdings hat Hyperterminal den großen Vorteil, daß es auf vielen
Windowsrechnern bereits vorinstalliert ist, da es zum Programmpaket gehört.
D.h. ohne extra Programminstallation kann man so Daten seiner AVR-Schaltung
an fast jedem Windowsrechner anzeigen lassen und auch senden.
Die Anleitung findet Ihr hier: Hyperterminaleinrichtung
Sofern man eine PC-Programmiersprache beherrscht ist es
natürlich schöner sich eigene Programme zu schreiben, mit denen
man dann auch nicht nur einzelne Buchstaben oder Zahlen, sondern
auch direkt die binären Werte verarbeiten kann.
Und noch etwas: der AVR generiert seine Baudrate indem er den Quarztakt teilt. Wie bei
allen binären Teilen kann es da zu Rundungsfehlern kommen, die zumindest bei höheren
Baudraten, also schnellem Datentransfer, zu Übertragungsfehlern führen können. Deshalb ist es sinnvoll hierbei
keine "glatten" Taktfrequenzen zu verwenden, sondern "krumme" Quarze mit Frequenzen wie 3,6864 7,3728 oder 9,216 MHz,
weil hier die AVR-Interne Taktteilung ohne Fehler aufgeht. Genauere Erklärungen dazu findet Ihr auf der Seite
www.rowalt.de bzw. im AVR-Lehrbuch von Roland Walter.
(nach oben)
2.9 der EEprom
Der EEprom ist ein Speicher, in dem man Daten wie Variablen und Texte fest abspeichern kann, so, daß sie auch nach dem Abschalten der Betriebsspannung nicht verloren gehen und beim nächsten Einschalten des Gerätes wieder ausgelesen werden können. Wichtig zum Thema EEprom zu wissen ist, daß man nur einzelne Bytes abspeichern kann. D.h. um einen Text zu speichern muß man z.B. Buchstabe für Buchstabe die jeweiligen Ascii-Zahlen speichern und beim nächsten Programmstart wieder zu einem Text zusammensetzen. Das speichern und auslesen ist denkbar simpel und erfordert keinerlei Konfiguration oder Aktivierung im Header:
Writeeeprom x , 1 | ' Speichert den Wert der Variablen x in Speicherzelle 1 |
Readeeprom x , 1 | ' liest Speicherzelle 1 aus und weist den Wert der Variablen x zu |
Es können nur Varablen des Typs Byte direkt abgespeichert werden, bei Variablentypen die mehrere Bytes benötigen (z.B. Word) muß man den Wert zunächst in einzelne Bytes zerlegen, diese einzeln abspeichern und später, beim Auslesen, wieder zusammensetzen:
Dim x As Byte | ' x als Byte definieren |
Dim y As Word | ' y als Word definieren |
y = 899 | ' y beliebigen Wert zuweisen (z.B. ADC Wert o.ä.) |
In einer als Byte vorbereiteten Variablen x
kann man kurzzeitig die einzelnen Bytes vom Word y
zwischenspeichern. Das Kombinieren des Teilens und Speicherns in
einer Befehls-Zeile ist bei Bascom nicht möglich:
x = High(y) | ' weist x das MSB (High-Byte) des Words y zu |
Writeeeprom x , 1 | ' speichert x in Zelle 1 |
x = Low(y) | ' weist x das LSB (Low-Byte) des Words y zu |
Writeeeprom x , 2 | ' speichert x in Zelle 2 |
Das Word y ist so auf die EEprom-Speicherzellen 1 und 2 aufgeteilt. Wenn man verstanden hat, wie Binäre Zahlen funktionieren (Zahlenscript gelsen?) dann ist es simpel diese 2 Bytes später wieder zu einem Wert des Typs Word zusammenzusetzen:
Readeeprom x , 1 | ' Speicherzelle 1 (High-Byte) in die Variable x auslesen |
y = x * 256 | ' bitte selbst nachdenken... |
Readeeprom x , 2 | ' Speicherzelle 2 (Low-Byte) in die Variable x auslesen |
y = y + x |
y hat jetzt wieder den ursprünglichen
Wert, der vorher zerlegt abgespeichert wurde. Natürlich muß man
die Adressen der Speicherzellen nicht unbedingt direkt angeben,
sondern kann auch hierfür Variablen verwenden.
Wichtig zu wissen ist, daß das Lesen und Beschreiben des EEproms
für µC-Verhältnisse recht lange benötigt und vorallem, daß
der EEprom nicht beliebig of beschrieben werden kann. Es
empfiehlt sich also das Lesen/Schreiben nicht innerhalb einer
Schleife ständig zu wiederholen, sondern die Daten nur wenn es
nötig ist einmal zu speichern (z.B. auf Tastendruck im
Unterprogramm) und die Daten z.B. nur einmal beim Starten vor der
Hauptschleife auszulesen.
(nach oben)
http://www.bunbury.de/Technik/avr/bascom.htm
3. Beschaltung Sensorwerte messen
Wenn man einen Mikrocontroller programmiert
hat ist das natürlich nur die halbe Miete. TTL-ICs und Mikrocontroller wie der Mega8 können meist nur 5V-Signale
einlesen und ausgeben und der Ausgangsstrom ist auf wenige mA
beschränkt.
Was ist zu tun, um einen Motor mit 12V Spannung und 1A Strom zu
steuern?
...um ein Sensorsignal mit 0-10V einzulesen?
...um zu kleine Signale von wenigen mV zu verstärken?
...um einen PC anzuschließen?
...um einen Modellbau-Empfänger oder ein Modellbauservo anzuschließen?
Dazu finden Sie am Ende der Seite einen Link, indem die Beschaltung von
TTL-Schaltkreisen im Allgemeinen erklärt wird und diese Schaltungen
funktionieren natürlich auch am Mega8.
Vorab sollten Sie sich aber folgende Betriebsdaten des Mega8 einprägen oder besser notieren!
Sie werden diese beim Basteln oder Berechnen von Bauteilen immer wieder benötigen:
Betriebsspannung: +5V
max. Eingangs-/Ausgangsspannungen von Signalen: +5V
max. Ausgangsstrom pro Pin: 40mA
max. Gesamtstrom aller aktiven Ausgangspins: 200mA
Auch wenn einem Ausgangsströme von 40mA erstmal als nicht sehr viel
erscheinen mögen ist der Mega8 im Vergleich zu seiner
Schaltkreis-Verwandschaft geradezu üppig ausgestattet, viele
Schaltkreise sind nichtmal in der Lage den Strom für eine LED am Ausgang
zu liefern.
http://www.bunbury.de/Technik/avr/beschaltung.htm
http://www.bunbury.de/Technik/avr/bascom.htm
*********************************************************
4TAP 4-Teile-AVR-Programmer am COMx-PORT
bestehend aus 3 Widerständen und einem Transistor.
Ich wollte endlich auch mal Mikrocontroller
programmieren, aber mit möglichst geringem
Anfangswiderstand. Ohne Bootloader, ohne
Entwicklungsplatine, sondern etwa so wie im
"Lernpaket Mikrocontroller" von Franzis. Das
Programmieren und Flashen sollte aber komfortabler
sein, am liebsten in Basic. Der Mega8-ISP-Programmer
vom selben Autor wie das Lernpaket (Burkhard
Kainka), kam der Sache schon ziemlich nahe.
Allerdings musste für den Einsatz von AVRdude
dessen Konfigurationsdatei editiert werden.
Außerdem muss immer die serielle Schnittstelle
geöffnet sein, weil ohne einen HIGH-Pegel an RTS der
Controller in den Reset-Zustand geht. Herausgekommen
ist der "4-Teile-AVR-Programmer", kurz 4TAP.
http://www.franksteinberg.de/4TAP.htm
DIN A4 ausdrucken
Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:schaltungen@schaltungen.at
ENDE