Programmierung eines Atmel-MicroControllers mit BASCOM
(Schalten von Ausgängen/Zustandsabfrage von Eingängen)
(Eine Unterseite von http://www.oliver-schlenker.dyndns.org)

Beschreibung:

Mit dieser Seite soll gezeigt werden, wie man mit der Programmiersprache "Bascom" (ein Basic-Dialekt speziell zur Programmierung von MicroControllern) von der Firma MCS-Elektronik einen MicroController von Atmel (in diesem Fall habe ich einen ATMega32 genommen; hatte ich einfach noch vom AVR-NET-IO übrig!) programmiert. Die Fa. MCS-Electronik bietet eine kostenlose Demoversion von "Bascom für AVR" zum Download auf Ihrer Webseite (http://www.mcselec.com) an. Mit dieser Demoversion können hier immerhin 4 KB große Programme geschrieben werden und die Demo eignet sich gut um mal ohne große Investition den Einstieg zu finden.

Als Programmierhardware habe ich mir schon vor einer Weile von der Fa. Pollin das Atmel-Evalutations-Board Version 2.0.1 zugelegt. Bisher habe ich dieses Board zum Programmieren von ATMega8, ATTiny2313, ATMega32, ATMega644 benutzt. Hauptsächlich die Firmwarefiles von Pollin für das AVR-NET-IO-Board und auch von E2000-Projekten habe ich mit diesem Board auf die entsprechenden Atmel-Bausteine geschrieben. Falls Ihr so ein Board nicht kaufen wollt, könnt ich auch das AVR-NET-IO-Board von Pollin als kleine Experimentierhardware hernehmen. Das Evaluationsboard hat z. B. 3 Taster, 2 LEDs und einen Summer eingebaut. Mit diesen Schaltern und Anzeigen kann man wunderbar Programmfunktionen ausprobieren, ohne weitere Hardware zu kaufen. Ich habe mir hier allerdings über einen Portadapter alle Pins des ATMega32-Controllers auf ein Steckbrett rausgelegt. So kann ich nach Herzenslust LEDs, Schalter, Sensoren und Aktoren für Tests anschließen.

Nach den "Spielereien" mit dem AVR-NET-IO-Board und der alternativen E2000-Firmware für dieses Board, was lag nun näher als sich mit der Erzeugung einer eigenen kleinen Firmware für einen MicroController zu beschäftigen, anstatt hier immer auf vorgefertigte Lösungen zurückzugreifen? Abgesehen davon lernt man bei der eigenen Programmierung auch die Funktionsweise der Atmel-MicroController klarer und verständlicher kennen.

Das Evaluations-Board wird mit einem einfachen 9V-Netzteil betrieben, welches ich noch in der Bastelkiste hatte. Dieses Board kann man bei Fa. Pollin entweder fertig aufgebaut (Best-Nr. 810 074) oder als Bausatz (Best.-Nr. 810 038) bekommen. An dieses Board habe ich dann über über einen 40poligen Flachbandleiter einen Adapter-Bausatz für Punktraster/Lochraster für dieses Board (Best.-Nr. 810 057) und ein Laborsteckbrett zum Experimentieren angeschlossen. Dort kann ich dann meine Testschaltungen mit LEDs zur Anzeige von Ausgängen oder Schaltern zum Einstellen von Werten für Eingänge anschließen/aufbauen.

Des Weiteren benötigt man ein serielles Verbindungskabel um eine Datenaustauschverbindung vom Controller zum Rechner herzustellen. Die Anpassung der MicroController-Logik an die Computerlogik wird auf dem Board von einem Baustein mit der Bezeichnung "MAX232" übernommen. Auch dieses Verbindungskabel gibt es bei Fa. Pollin (Best.-Nr. 720 738). Um über den integrierten seriellen Programmer des Atmel-Evalutationsboards den Controller zu programmieren benötigt man ein zweites solches Kabel (oder man muss ständig umstecken). Da diese Programmierverbindung allerdings recht langsam ist, habe ich meinen bereits vorhandenen Parallel-Port-ISP-Programmer (mit welchem ich bisher auch das AVR-NET-IO von Pollin über den ISP-Port programmiert habe) an das Atmel-Evaluationsboard angeschlossen. Auch einen USB-Programmer habe ich schon an das Board problemlos angeschlossen. Generell kann an das Board kann jeder ISP-Programmer mit 10poligem Stecker oder auch ein JTAG-Programmer angeschlossen werden. Auch mein "Selbstbaukabel" zur ISP-Programmierung von Atmel-MicroControllern kann hier ohne Probleme angeschlossen und genutzt werden.

(Um die Grafiken klarer und detaillierter zu sehen, solltet Ihr einen Klick mit der linken Maustaste
auf der entsprechenden Grafik ausführen!)

Hier mal ein Bild meines Testaufbaus für Programmierprojekte, bestehend aus dem
Pollin-Evaluationsboard, einer Flachbandverbindung an einen 40poligen Adapter und
dem Laborsteckbrett zum einfachen und schnellen Aufbauen von Testschaltungen:

Hier mal ein Bild des angeschlossenen/einsatzbereiten Atmel-Evaluationsboards von Pollin
(bestückt mit einem µC von Atmel Typ ATMega32-16PU; der 40pin-Baustein links vom Flachband):

Links unten seht Ihr das 9pol-Serial-Kabel zur Kommunikation mit dem MicroController bzw. dem darauf abgelegten Programm. Darüber befindet sich die 9V-Stromversorgung für das Board. Dann seht Ihr den seriellen Anschluss für den integrierten ISP-Programmer des Boards (welchen ich aber nicht nutze). Statt dessen nutze ich oben links den Flachbandanschluß für einen externen ISP-Programmer. Rechts seht Ihr die Möglichkeit einen JTAG-Programmer an das Board anzuschließen. Und rechts schließlich das 40polige Flachbandkabel zur Verbindung an das Laborsteckbrett/die Experimentierplatine. Im Moment ist auf dem Board ein Microcontroller von Atmel Typ ATMega32-16PU aufgesteckt (siehe links vom Flachbandleiter). Das Board ist universell für verschiedene Atmel-MicroController nutzbar. Auf den leeren Controller-Steckplätzen können z. B. auch ATMega8, ATTiny-Controller, usw. programmiert werden. Des Weiteren befinden sich auf dem Board 3 Taster, 2 LEDs und ein Summer, mit denen man experimentieren kann. Auf der Webseite der Fa. Pollin könnt Ihr Euch auch die Anleitung für das Board runterladen. Dort sind die genauen technischen Daten des Boards detailiert beschrieben.

Hier ein Bild des Laborsteckbretts, welches über einen 40poligen Adapter mit dem
Pollin Evaluationsboard (Bild oben) verbunden ist:

Auf dem Testboard habe ich mal LEDs und entsprechende Vorwiderstände zur Anzeige der Ausgänge platziert und einen Schalter um an einem Eingang einen Schaltzustand einzustellen. Für mein folgendes einfaches Testprogramm benötigen wir zwar nur eine LED und einen Vorwiderstand von ca. 300 Ohm, aber da ich vorhabe mich mit diesem Thema intensiver auseinander zu setzen, habe ich das schon mal entsprechend vorgesehen. Die LEDs sind an jeweils einen Pin angeschlossen und sind über einen Vorwiderstand mit GND verbunden. Bevor ich Euch ein kleines Programm zum Einstieg/Test vorstelle, müssen wir uns mal noch den MicroController, den ich im Folgenden benutzt habe (in diesem Fall einen Atmel ATMega32-16PU) anschauen.

Hier mal die Pinbelegung des ATMega32-16PU MicroControllers:

Wie man sehen kann, hat das Teil 40 Pins. Wenn man hier nun die Versorgungspins bzw. festen Pins zum Betrieb des Controllers abzieht, bleiben noch 32 Pins, die man relativ frei benutzen kann. Es sind die Blöcke PA, PB, PC und PD mit jeweils Pin 1-8. D. h. Pin PA0-PA7, Pin PB0-PB7, Pin PC0-PC7 und PD0-PD7. 4 x 8 Pins = 32 Pins zur Verwendung. Die Pins PD0 (RXD=Serieller Empfang) und PD1 (TXD=Serielle Sendung) werden hier für die Kommunikation mit der RS232 des Rechners benutzt. D. h. es bleiben hier erstmal noch 30 Pins übrig. Je nach dem welche Pins man noch für Datenverkehr mit anderen Devices benutzt (z. B. für einen I²C-Bus oder Anschluß eines LCD-Displays) sind es entsprechend weniger Pins, die man dann frei programmieren kann.
Die Pins PA0-PA7 können auch als analoge Eingangs-Pins genutzt werden. An diesen Pins könnte auch eine Spannung von 0-5V angelegt werden. Der Controller würde das dann in 1024 Einheiten á  0,0048828125 V (=10-Bit-Eingang) unterteilen. Damit könnte man z. B. analoge Temperatursensoren über einen Widerstand im Sinne eines Spannungsteilers abfragen. In diesem Bericht bleiben wir aber komplett in der "digitalen Technik" und haben hier nur 2 Zustände der Pins (0V=Low=Aus; 5V=High=Ein).  Womit wir eigentlich schon bei der Programmierung des Controllers wären.

Im folgenden Beispiel möchte ich Euch einfach mal zeigen, wie man über eine Rechner einen Befehl an einen MicroController schickt, dieser dann irgendwas tut und eine Meldung an den Rechner zurück schickt. Ich habe mir als Ausgangs-Pin zum Schalten einer LED den Pin 0 von Port B (=PB0) ausgesucht. Als Pin für einen Schalteingang werden wir den Pin 0 von Port C (PC0) nehmen. Beide Pins sind oben entsprechend rot markiert.

Hier nun mal ein kleines Testprogramm in BASCOM
um per PC einen Ausgang zu schalten und einen Eingangszustand abzufragen:

$regfile = "m32def.dat" ' Controllertyp ist ein ATMega32
$crystal = 16000000     ' 16 MHz Taktfrequenz (=16000000 Hz)
$hwstack = 100          ' Reserviere Speicher für Hardwarestack
$swstack = 100          ' Reserviere Speicher für Softwarestack
$framesize = 100        ' Reserviere Speicher für Rahmengröße
$baud = 38400           ' Datenübertragsgeschwindigkeit RS232 einstellen
Enable Interrupts       ' Interrupts einschalten (für serielle Eingabe!)

Output_1 Alias Portb.0   ' Pin 0 von Port B wird "Output_1" benannt
Config Output_1 = Output ' Output_1 wird als Ausgang definiert
Output_1 = 0             ' Output_1 wird mit 0 vorbelegt = Low = 0V = LED AUS

Input_1 Alias Pinc.0     ' Pin 0 von Port C wird "Input_1" benannt
Config Input_1 = Input   ' Input_1 wird als Eingang definiert
Pinc.0 = 1               ' Für Pin 0 von Port C den Pullup-Widerstand aktivieren

' RS232 einrichten: UART-Buffer; Einlesen erfolgt automatisch bei CHR(13)
' (=siehe Funktion des Unterprogramms Serial0charmatch())
Config Serialin = Buffered , Size = 50 , Bytematch = 13

Dim Eingabe As String * 50     ' Eingabevariable vor Gebrauch deklarieren

Declare Sub Serial0charmatch() ' Unterprogramm vor Gebrauch deklarieren/benennen

' Hauptschleife (Befehle zwischen "DO" und "LOOP" werden unendlich ausgeführt)
Do

  If Eingabe <> "" Then    ' Wenn Eingabestring nicht leer ist...
 
Eingabe = Ucase(Eingabe) ' Eingabe in Großbuchstaben umwandeln = eindeutig

 
Select Case Eingabe      ' Anhand des Eingabestrings ein Kommando ausführen

    Case "1ON"             ' Wenn der Befehl "Ausgang 1 einschalten" = 1ON war
      Output_1 = 1         ' setze den Ausgang Output_1 auf High=5V=LED EIN
      Print "Ausgang Nr. 1 hat den Zustand: " ; Output_1 ' Meldung an RS232/PC

    Case "1OFF"            ' Wenn der Befehl "Ausgang 1 ausschalten" = 1OFF war
      Output_1 = 0         ' setze den Ausgang Output_1 auf Low=0V=LED AUS
      Print "Ausgang Nr. 1 hat den Zustand: " ; Output_1 ' Meldung an RS232/PC

    Case "1INP"            ' Wenn der Befehl "Eingang 1 abfragen" = 1INP war
     
Print "Eingang Nr. 1 hat den Zustand: " ; Input_1  ' Meldung an RS232/PC

    Case Else              ' Wenn keine der o. g. Eingaben zutrifft...
      Print "Fehler: unbekanntes Kommando"               ' Meldung an RS232/PC

  End Select               ' Ende der "SELECT-CASE"-Überprüfung

 
Eingabe = ""             ' Eingangsvariable vor nächstem Schleifenlauf leeren

  End If                   ' Ende der "IF"-Bedingung

Loop                       ' Ende der Hauptschleife/Endlosschleife

End                        ' Theoretisches Programmende; wird nie erreicht!

' Unterprogramm/Prozedur
' Diese Prozedur wird automatisch ausgeführt, wenn ein CARRIAGE RETURN (CHR(13);
' ENTER) am Zeilenende empfangen wird. Dann wird die Variable "Eingabe" mit
' dem Inhalt der Eingabe gefüllt.
' (Siehe Initialisierung von UART-Buffer unter "Config Serialin...")
Sub Serial0charmatch() ' Unterprogramm-Name
Input Eingabe          ' Schreibe Eingabestring via RS232 in Variable "Eingabe"
End Sub                ' Ende des Unterprogramms

O. g. Programm könnt Ihr Euch direkt aus dem Rahmen in die Demoversion von BASCOM reinkopieren und damit "spielen" und rumprobieren.

Kurze Erklärung zu o. g. Programm bzw. dessen Funktion:

BASCOM-Befehle sind in schwarz geschrieben              ' Kommentare zur Programmzeile in rot

Testaufbau auf dem Laborsteckbrett:

Ausgang:
Für die Anzeige des Ausgangs (Befehl ist "1ON" oder "1OFF")), wird eine LED über eine Vorwiderstand zwischen Port B Pin 0 und GND angeschlossen. Achtung: Bitte die Polung der LED berücksichtigen. Pluspol der LED an den Pin-Port anschließen.  (Sieht man an der LED meist an längerem Beinchen oder nicht abgeflachte Seite der LED an.)

Eingang:
Für das Schalten des Eingangs (Befehl ist "1INP"), wird zwischen Port C Pin 0 und GND ein einfacher Schalter angeschlossen. Da mit dem Befehl Pinc.0=1 der interne Pullup-Widerstand für den Eingang aktiviert wurde, brauchen wir hier außer dem Schalter keine weiteren Bauteile (z. B. Pullup-/Pulldown-Widerstand), deshalb gehe ich hier auch erstmal nicht weiter drauf ein.

Befehle:
Die Erklärung der einzelnen Befehle sind in rot als Kommentar hinter dem eigentlichen Befehl zu sehen. Dort wird auch erläutert, was diese Programmzeile genau macht.

Funktionsweise/Inbetriebnahme:
Nach dem Compilieren des Programmes und Programmierung des Controllers über BASCOM, solltet Ihr eine Verbindung über die RS232-Schnittstelle mit einem Terminal-Emulationsprogramm wie z. B."Hyperterm" oder "PuTTY" aufbauen.

Die Parameter für den Verbindungsaufbau sind:
- Bits pro Sekunde: 38400
- Datenbits : 8
- Parität : keine
- Stoppbits : 1
- Flusssteuerung : keine

Nun könnt Ihr über das Terminal-Emulationsprogramm Befehle an den Controller schicken und erhaltet dann entsprechenden Rückmeldungen über dieses Fenster.

Folgende Befehle stehen zur Verfügung:
1ON   = Schalte Ausgang1/LED ein
1OFF = Schalte Ausgang1/LED aus
1INP  = Frage den Eingangszustand von Eingang1 ab; je nach Schalterstellung des Eingangsschalters

Nach jedem Befehl wird eine entsprechende Rückmeldung auf das Fenster der Terminal-Emulation ausgegeben.

Hier mal ein Snapshot aus PuTTY mit den einzelnen Befehlen und den entsprechenden
Rückmeldungen des µControllers über die RS232-Schnittstelle:

Hier kann man die Befehle und die Rückmeldungen wie folgt sehen:
(Nach jedem Befehl wird die ENTER-Taste als Zeilenabschluss gedrückt)

Der Befehl "1on"
schaltet auf dem Steckbrett die LED ein und gibt dann die Meldung
"Ausgang Nr. 1 hat den Zustand: 1"
aus.

Der Befehl "1off"
schaltet auf dem Steckbrett die LED wieder aus und gibt dann die Meldung
"Ausgang Nr. 1 hat den Zustand: 0"
aus.

Der Befehl "1inp"
zeigt je nach Schalterzustand des Schalters auf dem Steckbrett den Zustand des Eingangs an.
Bei geschlossenem Schalter wird
"Eingang Nr. 1 hat den Zustand: 0"
angezeigt, da ja über den Schalter der Eingangs-Pin auf Masse/GND gelegt wird und damit keine 5V-Spannung mehr führt. Wenn nun der Schalter manuell geöffnet wird führt der Eingangs-Pin wieder 5V. Wenn nun

der Befehl "1inp"
erneut eingegeben wird, gibt das Programm dann die Meldung
"Eingang Nr. 1 hat den Zustand : 1"
aus. Über den im Programm intern aktivieren Pullup-Widerstand führt der Eingangs-Pin 5V im Standard.
Nach Verbindung mit Masse/GND über den Schalter fließt der Strom gegen Masse ab und der Pin hat wieder 0V.
Beim erneuten Öffnen des Schalters wird der Pin nicht mehr auf Masse/0V gelegt, sondern über den intern aktivierten Pullup-Widerstand wieder auf 5V verbunden.

Gerade im Beispiel mit dem Eingang sieht man die Logik sehr deutlich, dass hier nun ein geschlossener Schalter eigentlich 0V = AUS und ein geöffneter Schalter 5V = EIN bedeutet. Hier ist die Signallogik invertiert.
Zu=0 und Auf=1. Im Verhältnis dazu sieht man am Ausgang, dass Zu=5V=LED EIN und Auf=0V=LED AUS bedeutet, was genau umgekehrt zur Eingangslogik ist.

Wenn man nun am Eingang den internen Pullup-Widerstand nicht gesetzt hätte und auf dem Steckbrett einen Widerstand am Eingang auf Masse/GND gelegt hätte, hätte man die gleiche Logik wie beim Ausgang erreicht. Allerdings benötigt man ein Bauteil mehr. Die Thematik "PullUp"-, "PullDown"-Widerstand und auch die Signalpegel "HIGH" und "LOW" möchte ich hier nicht im Detail behandeln, da das Internet voll von Erklärungen diesbezüglich ist. 

Hier ein mal paar Qellenlinks über Wikipedia bzgl. den wichtigen Schlagworten für die AVR-Programmierung:

Infos über Atmel-MicroController allgemein: http://de.wikipedia.org/wiki/Atmel_AVR
Pullup- und PullDown-Widerstand: http://de.wikipedia.org/wiki/Open_circuit
Logikpegel: http://de.wikipedia.org/wiki/Logikpegel
Fusebits: http://de.wikipedia.org/wiki/Fuse-Bit

Generell gilt für uns aber in diesem einfachen Beispiel die folgende Pegel-Logik:
0V = LOW-Signal = AUS; Ausgang=LED Aus; Eingang=Schalter geschlossen
5V = HIGH-Signal = EIN; Ausgang=LED Ein; Eingang=Schalter geöffnet


Mit der Demoversion von BASCOM könnt Ihr o. g. Programm ausprobieren und damit "spielen", erweitern und anpassen. Ihr könnt auch das AVR-NET-IO-Board nehmen, an einen Ausgang eine LED anschließen und auf den Controller über den ISP-Stecker das Programm aufspielen. Auch das AVR-NET-IO-Board kann man sicherlich als Testumgebung nehmen. Allerdings sind hier einige Ports vom EXT-Stecker und dem Controller für den Netzwerkanschluss belegt. In der Anleitung des Boards könnt Ihr aber sehen, welche Pins von welchen Ports noch frei sind und dort z. B. eine LED anschließen und dieses Testprogramm nutzen.

Der nächste Schritt wäre hier nun ein schönes Programm zu basteln, mit dem man bis zu 30 Pins schalten kann, und ein eigenes Platinenlayout für diesen Controller zu basteln (ev. mit Ausgangsrelais oder Optokopplern zum Schalten von Verbrauchern), sowie dann die Platine zu ätzen, zu bestücken und in Betrieb zu nehmen. Über Programme wie z. B. Purebasic kann man dann leicht auf so einen Controller zugreifen und eine Bedienoberfläche zum Schalten der Ausgänge und Abfragen der Eingänge, etc. gestalten. Dies werden dann vielleicht auch mal meine nächsten Schritte in dieser Sache sein. Auf jeden Fall hoffe ich, dass mein kleines Beispiel reges Interesse findet und wünsche Euch viel Spaß bei Nachbauen/Ausprobieren.

Da ich ebenfalls erst am Anfang mit der BASCOM-Programmierung stehe,
habe ich hier z. Zt. keine komplexeren Programme zur Veröffentlichung.
Als genereller Einblick/Einstieg könnte dieses kleine Beispiel aber dem ein
oder anderen User vielleicht recht hilfreich sein und das Interesse wecken.

Wenn ich Eure Neugier geweckt habe, möchte ich Euch an dieser Stelle die Webseite von

Gerold Penz (http://www.halvar.at)

unbedingt empfehlen.

Gerold bietet auf seiner Webseite einen kompletten Einsteigerkurs in BASCOM
(siehe http://www.halvar.at/elektronik/kleiner_bascom_avr_kurs) an,
dessen Komplexität weit über mein o. g. Beispiel hinausgeht, ohne jedoch den Leser
unnötig zu verwirren oder durch technisches Kauderwelsch zu entmutigen.
Er hat alles sehr einfach, verständlich und gut umsetzbar gehalten.
Auch die Beispiele von Gerold kann man leicht erweitern bzw. an
eigene Anforderungen anpassen und sind im Alltag vollkommen einsetzbar.
Durch Gerold habe ich hier einen sehr guten und einfachen Einstieg in die
BASCOM-Programmierung gefunden und möchte Ihm an dieser Stelle
ein herzliches "Dankeschön" für seine Arbeit und seine Mühe aussprechen.

Lieber Gerold: "Bitte weiter so!"

Bei Interesse, Fragen, Wünsche, Anregungen, Lob oder Kritik könnt Ihr mir gerne eine

eMail senden an: Oliver.Schlenker@T-Online.de