Bascom-AVR

Kleiner Bascom AVR Kurs -
Label, Unterprozeduren und Funktionen

Hallo!

Bevor ich weitere Möglichkeiten zeigen kann, wie man Signale an Eingängen erkennt, muss ich noch auf die Strukturierung von Programmen eingehen, ohne die ich in weiteren Beispielen nicht auskomme.

Es ist ziemlich schlechter Stil, einfach alle Befehle in einer Wurst untereinander zu schreiben. So etwas nennt man unter Programmierern Spagetticode. Der Nachteil von Spagetticode ist, dass er nicht wartbar ist. Fehler lassen sich kaum finden und spätestens nach ein paar Wochen ist man oft schneller wenn man ein Programm neu schreibt anstatt dieses an geänderte Anforderungen anzupassen.

Natürlich ist man bei der Programmierung von µControllern sehr eingeschränkt und kann nicht mit Klassen oder anderen Strukturierungsmöglichkeiten arbeiten, die in der Anwendungsprogrammierung ganz normal sind.

Trotz der Speichereinschränkungen mancher µController, gibt es in Bascom Möglichkeiten, ein wenig Struktur in das Programm zu bringen. Es gibt so genannte "Label", die man von beliebigen Codestellen aus anspringen kann, Unterprozeduren (Sub) und Funktionen.

Ein Label ist eine "benannte" Stelle im Code. Diese Stelle kann mit dem Befehl GOTO angesprungen werden. Das Programm springt dann zu dieser benannten Stelle und arbeitet den Code ab dieser Stelle ab. GOTO ist die niederste Anweisung für so etwas. Springt man mit GOTO ein Label an, dann gibt es keine dynamische Möglichkeit, zur ursprünglichen Codezeile zurück zu kehren. Damit meine ich, dass sich der µC nicht merkt, von wo aus zum Label gesprungen wurde um danach wieder zurück zu springen. Dafür braucht GOTO keinen zusätzlichen Speicher um sich diese Information zu merken.

Basom Hilfe zu GOTO: http://avrhelp.mcselec.com/index.html?goto.htm

Dim A As Byte


Start:

A = A + 1
If A < 10 Then
  Goto Start
End If

Print "Fertig"


End

GOTO ist ein alter und sehr umstrittener Befehl. GOTO gilt allgemein als das größte Problem von BASIC. Je öfter mit GOTO irgendwohin gesprungen wird, desto schwieriger wird es dem Programmierer gemacht, dem Programmverlauf zu folgen. Meide GOTO wenn ein Problem auch anders gelöst werden kann! Verwende GOTO wenn dadurch das Programm einfacher wird (und das wird nur sehr selten der Fall sein).

Man kann ein Label auch mit dem Befehl GOSUB anspringen. GOSUB ist schon einen Level höher als GOTO. Bevor ein Label mit GOSUB angesprungen wird, wird im HWSTACK (=Stapelspeicher) die Adresse des aktuell ausgeführten Befehls (=Programmzeiger) abgespeichert. Diese Information wird benötigt, um nach einem RETURN wieder zu dieser Stelle zurückkehren zu können. Der Befehl RETURN veranlasst die Rückkehr zur Stelle, von der aus das Label mit GOSUB angesprungen wurde.

Du wirst dich vielleicht schon gewundert haben, was dieses $hwstack = 100 am Anfang jedes Programmes soll. Damit wird die Größe dieses Stapelspeichers festgelegt. Je mehr hin und her gesprungen wird, desto größer muss dieser Speicherbereich sein.

Basom Hilfe zu GOSUB: http://avrhelp.mcselec.com/index.html?gosub.htm

Dieses Beispiel geht davon aus, dass an PD5, PD6 und PD7 LEDs angeschlossen sind. Im Beispiel sieht man recht gut, dass mit GOSUB zum Label gesprungen wird und mit RETURN zum Aufrufpunkt zurückgekehrt wird.

$regfile = "M8def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100


'LED1 an PD7
Led1 Alias Portd.7
Config Led1 = Output

'LED2 an PD6
Led2 Alias Portd.6
Config Led2 = Output

'LED3 an PD5
Led3 Alias Portd.5
Config Led3 = Output

Dim Status As Byte


Do
   If Status = 0 Then
      Gosub Set_led1
      Status = 1
   Elseif Status = 1 Then
      Gosub Set_led2
      Status = 2
   Elseif Status = 2 Then
      Gosub Set_led3
      Status = 3
   Elseif Status = 3 Then
      Gosub Set_led3
      Status = 4
   Elseif Status = 4 Then
      Gosub Set_led2
      Status = 5
   Else
      Gosub Set_led1
      Status = 0
   End If

   Waitms 200
Loop

End


Set_led1:
   Led1 = 1
   Led2 = 0
   Led3 = 0
Return


Set_led2:
   Led1 = 0
   Led2 = 1
   Led3 = 0
Return


Set_led3:
   Led1 = 0
   Led2 = 0
   Led3 = 1
Return

An dieser Stelle möchte ich auch die Highlevel-Befehle "SUB" und "FUNCTION" ansprechen.

Je größer das Programm wird das man schreibt, desto wichtiger werden die Befehle SUB und FUNCTION. Damit kann man abgeschlossene Programmbereiche (Unterprozeduren und Funktionen) erstellen, die sogar ihre eigenen "lokalen" Variablen besitzen können. Lokale Variablen sind außerhalb dieser Unterprozeduren und Funktionen nicht sichtbar und können somit den Programmablauf nicht beeinflussen. Und genau das wird immer wichtiger, je größer ein Programm wird. Je weniger ein Programmteil einen anderen Programmteil beeinflussen kann, desto weniger Fehler werden übersehen.

Eine Unterprozedur oder eine Funktion muss Bascom im Kopf des Programms mit DECLARE bekannt gemacht werden. Eine Unterprozedur oder eine Funktion kann Parameter übergeben bekommen. Eine Funktion kann zusätzlich auch noch Werte zurück geben.

$regfile = "M8def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100


'LED1 an PD7
Led1 Alias Portd.7
Config Led1 = Output

'LED2 an PD6
Led2 Alias Portd.6
Config Led2 = Output

'LED2 an PD5
Led3 Alias Portd.5
Config Led3 = Output

'Prozedur deklarieren
Declare Sub Set_led(byval Led_id As Byte)

Dim Status As Byte


Do
   If Status = 0 Then
      Call Set_led(1)
      Status = 1
   Elseif Status = 1 Then
      Call Set_led(2)
      Status = 2
   Elseif Status = 2 Then
      Call Set_led(3)
      Status = 3
   Elseif Status = 3 Then
      Call Set_led(3)
      Status = 4
   Elseif Status = 4 Then
      Call Set_led(2)
      Status = 5
   Else
      Call Set_led(1)
      Status = 0
   End If

   Waitms 200
Loop

End


Sub Set_led(byval Led_id As Byte)
   Led1 = 0
   Led2 = 0
   Led3 = 0

   If Led_id = 1 Then
      Led1 = 1
   Elseif Led_id = 2 Then
      Led2 = 1
   Else
      Led3 = 1
   End If
End Sub

Links zur Bascom-Hilfe:

DECLARE SUB:
http://avrhelp.mcselec.com/index.html?declare_sub.htm
DECLARE FUNCTION:
http://avrhelp.mcselec.com/index.html?declare_function.htm
SUB:
http://avrhelp.mcselec.com/index.html?sub.htm
FUNCTION:
http://avrhelp.mcselec.com/index.html?declare_function.htm
CALL:
http://avrhelp.mcselec.com/index.html?call.htm
GOTO:
http://avrhelp.mcselec.com/index.html?goto.htm
GOSUB:
http://avrhelp.mcselec.com/index.html?gosub.htm

mfg Gerold :-)



Den zugehörigen Original-Beitrag findest du im Loetstelle-Forum.