Aaaaaaaaaaah, hilfä, leute, was macht Ihr da
Das ist ja Spaghetti-Code in Reinform
Also, wenns denn dann so funktioniert könnt Ihrs wegen mir so lassen aber ich kommt nicht drum herum meinen Senf hierzu abzugeben denn das was ich gerade gesehen habe tuzt mir echt weh. Doch schauen wir uns zunächst die Einzelthemen im einzelnen an.
Konfiguration von PIN's:
Unter Bascom ist es möglich mittels einfachem Befehl
einen gesamten Port als Ausgang zu setzen. Ihr könnt Euch auf diesem Weg 7 Zeilen Code sparen.
Die Megas haben zur Konfiguation ob Eingang oder Ausgang ein Data-Direction-Register das man in BASCOM auch direkt ansprechen kann. Schauen wir uns das an Eurem beispiel bei Port B mit gemischten I/O's mal an.
Hier gibt es prinzipiell zwei Mögichkeiten. Entweder Ihr beschreibt das Register direkt (1) oder Ihr holt Euch vorher den Inhalt und modifiziert die Stellen welche Ihr braucht (2).
Bit = 0 im DDR sagt Eingang, Bit = 1 im DDR sagt Ausgang. In Eurem Beispiel soll Bit 0 Eingang sein und Bit 1- 4 Ausgang. Das sieht binär so aus &Bxxx11110.
Zu (1):
konfiguriert den Port wie gewünscht wobei mit dieser Methode die Bits 5-7 auch noch überschrieben werden. Mit dieser Methode spart Ihr 4 Zeilen Code!
Zu(2):
DIM helpbyte AS Byte
helpbyte = DDRB AND &B11100000 ' verwendete Bits erst mal ausmaskieren
DDRB = helpbyte OR &B11110 ' Konfiguration schreiben
Die Lösung ist eleganter und schneller!
Der Zähler:
Die Möglichkeit die die Steuerung über einen Zähler mit debounce Abfrage zu machen ist möglich und nicht schlecht.
Sollten jedoch im Programm noch weitere Aufgaben dazu kommen so könnte man sich auch überlegen die Abfrage des externen Tasters über Interrupt zu machen. Das ist aber wirklich reine Geschmackssache.
Ansteuerung:
Ich würde nie und nimmer bei solch einer schönen Problemstellung die Ausgabe auf die Ports in sequentieller Spaghetti-Form machen.
Mit einem BASCOM Befehl wie z.B.
kann mit einem Befehl ein komplettes Bitmuster auf den Port geschrieben werden. Damit spart Ihr Euch wieder 7 Zeilen Code.
Weiter würde ich nicht die einzelnen Bits im Case oder im Code jeweils einzeln setzen sondern ich würde mir eine Tabelle zur Ansteuerung der 7-Segment-Anzeige erstellen, zur Laufzeit über den Zähler gesteuert in die Tabelle greifen, mir den entsprechenden Wert rausholen und auf die Ports schreiben. Dabei reicht ein Byte-Wert nicht sondern ich würde ein Word verwenden. Das Word könnt ihr genauso mit Bits befüllen wie alle anderen Variablen.
Beispiel:
Code:
Dim word_var As Word
word_var = &B0101010101010101 ' Achtung: word hat 16 Bit!
Ähnliche wie bei der Initialisierung kann man ganze Bytes auf Ports schreiben oder aber mit Operationen wie OR, AND, SHIFT Bitmanipulationen durchführen.
Ich würde nie und nimmer für 16 verschiedene Zählerstände 16 Ausgaben implementieren. Es reicht wie gesagt eine Ausgaberoutine zu programmieren die dann mit Daten aus der Tabelle befüttert wird.
Wie man mit Tabellen arbeitet könnt Ihr Euch unetr dem Thread
http://www.avr-praxis.de/forum/showthread.php?t=62
mal ansehen.
Dann noch ein Wort zur BCD-Problemstellung. Die BCD-Codierung ergibt sich 1:1 aus dem Wert des Zähler, da dieser nur Werte zwischen 0 und 15 (16) Zahlen annehmen kan (&B0000 bis &B1111, Achtung &B1111 ist 15!!!)
In Euerem Programmbeispiel ist ein Denkfehler. Ihr startet mit B_kanal = 0, soweit OK! Aber die Abfrage auf 16 muss unmittelbar danach erfolgen da 16 bereits schon ein Überlauf des Wertebereich zur folge hat. Also bitte:
Code:
B_kanal = B_kanal + 1 ' Zählwert für Kanal wird um eins erhöht
If B_kanal = 16 Then B_kanal = 0 ' Zählwert für Kanal wird auf 0 gesetzt
Wenn Ihr das IF-Statement in einer Zeile schreibt dann kann man End If verzichten.
So, nun ist sichergestellt, das die Variable, bevor Ihr in den Case reinlauft wirklich nur 0-15 (16 Zustände) hat, sonst hättet Ihr nämlich einen 17 und damit undefinierten Zustand.
Noch ein paar Sätze zur Ausgabe:
Ihr wollt die Daten auf PortB.1 bis PortB.4 ausgeben. OK, was haltet Ihr von der folgenden Lösung (der Zähler ist Basis!):
Code:
Dim Helpbyte1 As Byte
Dim Helpbyte2 As Byte
Helpbyte1 = PortB AND &B11100001 ' Inhalt PortB auslesen und maskieren
Helpbyte2 = B_kanal ' Zähler in Arbeitsvariable
Shift Helpbyte2, Left, 1 ' Zähler auf richtige Bitposition
Helpbyte1 = Helpbyte1 + Helpbyte2 ' Zähler auf Port-Variable addieren
PortB = Helpbyte1 ' Port mit neuem Inhalt setzen.
Mit dieser Methode spart Ihr Euch 16x die Ausgabe einzelner Bits auf den Ports und das Programm wird überschaubar, strukturierter und übersichlicher.
Fazit:
Schaut Euch einfach mal die von mir dargestellten Themen an und probiert sie aus. Mittels der von mir vorgestellten Methoden könnt Ihr komplett auf einen aufwändigen Case-Verteiler verzichten und alles schon "runterprogrammieren"
Soll keine Kritik sondern nur eine Hilfestellung sein denn der Spass entsteht durch neue Herausforderungen und man wächst schließlich mit seinen Aufgaben.
Vielleicht könnt Ihr das ein oder andere verwenden oder wollt es einfach mal ausprobieren. Wenn ja freut es mich ansonsten könnt ihr auch bei der italienischen Variante bleiben.
Grüße,
Markus