eine LED-Laufschrift zu programmieren. Und das interessierte mich auch.
Vor einiger Zeit hatte ich mir mal testhalber zehn dieser 5x8 DotMatrix-Anzeigen von Pollin mit bestellt. Naja, und nun hatte ich mal etwas Zeit fuer eine solche Bastelei.
Sieben 74HC595, einen ATMega32, acht BD140, ein Haufen Widerstaende, Loetstreifenrasterplatinen und ein paar Kleinteile auf den Tisch, die Datenblaetter ausgedruckt, Loetkolben angeheizt und los ging's.
Die ganze Loetarbeit an dieser Laufschrift war doch schon etwas muehselig. Ich hatte aber auch keine Lust mir eine Platine aetzen zu lassen. Das waere mir zu aufwaendig und zu teuer geworden. Zumindest fuer diese (erste) Laufschrift. Es ging mir nur um die Machbarkeit.
Nachdem ich die ganzen Bauteile aufgeloetet hatte und es auch alles messtechnisch soweit funktionierte, ging es an's Programmieren. Und das war schon 'ne Ecke kniffliger.
gibt es die wunderschoene Befehle shiftout und spiout. Damit hatte ich zunaechst gespielt. Es ging auch ansatzweise. Aber hier schiebt man die ganzen Bits byteweise heraus. Und da gab es immer wieder irgendwelche Probleme die Bits auch so zu positionieren das wieder lesbare Zeichen daraus wurden. Daraufhin habe ich mich entschieden die Bits ueber eine eigene Routine einzeln herauszuschieben. Da weiss man wenigstens was da passiert.
Die Daten von einem 6x8 Font fuer ein KS108-Display habe ich so uebernommen. Sie bilden die Grundlage von dem Zeichensatz (nicht vollstaendig im Beispielcode) fuer die Laufschrift. Die einzelnen Bytes werden hier zerlegt und entsprechend den Anforderungen neu zusammengesetzt. Dann werden die Daten bitgenau in die 74HC595-Kette geschoben. Der entsprechende Zeilen-Transistor schaltet die dazugehoerige Zeile. Das zerlegen des Textes, der auf der Laufschrift angezeigt werden soll, geschieht zunaechst "in aller Ruhe". Ist der Datensatz komplett, wird ein Timer gestartet in dessen mit jedem Durchlauf ein Datensatz rausgeschoben und die Zeile umgeschaltet wird. In der Haupt Do-Loop veraendere ich lediglich alle paar Millisekunden den Bereich der angezeigt werden soll. Man schaut also wie durch ein Fenster auf den Ausgabetext. Und durch Veraenderung entsprechender Variablen verschiebe ich das "Fenster".
Das ganze ist sicherlich nicht optimal und es verbraucht auch 'ne Menge an Speicher von dem ATMega32. Aber ich wollte auch erstmal nur ergruenden ob es ueberhaupt moeglich ist. Auch der Ausgabetext ist noch fest im Programm integriert (eine serielle Eingabe waere hier eine Moeglichkeit).
Zumindest hat man wieder eine Menge Erfahrungen mit einer solchen Bastelei gesammelt. Und die Freude ist doch wieder gross, wenn es schlussendlich funktioniert.
Code:
$regfile = "m32def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 30
$framesize = 40
Config Porta = Output
Config Portb = Output
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer_isr
Enable Timer0
Enable Interrupts
Stop Timer0
Dout Alias Portb.2
Ss Alias Portb.1
Clock Alias Portb.0
Zeile Alias Porta
Dim A As Word , B As Word
Dim A1 As Word , A2 As Word , A3 As Word
Dim Beginn_zeichen As Word , Ende_zeichen As Word , Db_zeiger As Word
Dim Bz As Word
Dim Ti As Byte , Tl As Byte , Tl2 As Word , Tl3 As Word
Dim Ez As Byte
Dim Dat(1530) As Byte
Dim Ze(8) As Byte
Dim Text As String * 255
Dim Einzelzeichen As String * 1
Ze(1) = 127
Ze(2) = 191
Ze(3) = 223
Ze(4) = 239
Ze(5) = 247
Ze(6) = 251
Ze(7) = 253
Ze(8) = 254
Text = " LED-Laufschrift mit Bascom, ATMega32 und Pollin Display " 'max. 255 Zeichen
Tl = Len(text)
B = 1
For A = 1 To Tl
Tl2 = Tl * 6
Einzelzeichen = Mid(text , A , 1)
Ez = Asc(einzelzeichen)
Bz = Ez - 32
Beginn_zeichen = Bz * 6
Ende_zeichen = Beginn_zeichen + 5
For Db_zeiger = Beginn_zeichen To Ende_zeichen
Dat(b) = Lookup(db_zeiger , Zeichensatz)
Dat(b) = 255 - Dat(b)
Incr B
Next Db_zeiger
Next A
A2 = 1
Tl3 = Tl2 - 50
Start Timer0
Do
A3 = A2 + 50
Waitms 60
Incr A2
If A2 = Tl3 Then A2 = 1
Loop
End
Timer_isr:
If Ti = 9 Then Ti = 1
Select Case Ti
Case 1:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).0
Clock = 0
Next A1
Ss = 1
Zeile = Ze(1)
Case 2:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).1
Clock = 0
Next A1
Ss = 1
Zeile = Ze(2)
Case 3:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).2
Clock = 0
Next A1
Ss = 1
Zeile = Ze(3)
Case 4:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).3
Clock = 0
Next A1
Ss = 1
Zeile = Ze(4)
Case 5:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).4
Clock = 0
Next A1
Ss = 1
Zeile = Ze(5)
Case 6:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).5
Clock = 0
Next A1
Ss = 1
Zeile = Ze(6)
Case 7:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).6
Clock = 0
Next A1
Ss = 1
Zeile = Ze(7)
Case 8:
Ss = 0
For A1 = A2 To A3
Clock = 1
Dout = Dat(a1).7
Clock = 0
Next A1
Ss = 1
Zeile = Ze(8)
End Select
Incr Ti
Return
Zeichensatz:
Data 0 , 0 , 0 , 0 , 0 , 0 'Leerzeichen
Data 0 , 0 , 6 , 95 , 6 , 0 '!
Data 0 , 7 , 3 , 0 , 7 , 3 '""
Data 0 , 36 , 126 , 36 , 126 , 36 '#
Data 0 , 36 , 43 , 106 , 18 , 0 '$
Data 0 , 6 , 9 , 9 , 6 , 0 '%
Data 0 , 54 , 73 , 86 , 32 , 80 '&
Data 0 , 0 , 7 , 3 , 0 , 0 ''
Data 0 , 0 , 62 , 65 , 0 , 0 '
Data 0 , 0 , 65 , 62 , 0 , 0 '
Data 0 , 8 , 62 , 28 , 62 , 8 '*
Data 0 , 8 , 8 , 62 , 8 , 8 '+
Data 0 , 0 , 224 , 96 , 0 , 0 ',
Data 0 , 8 , 8 , 8 , 8 , 8 '-
Data 0 , 0 , 96 , 96 , 0 , 0 '.
Data 0 , 32 , 16 , 8 , 4 , 2 '/
Data 0 , 62 , 81 , 73 , 69 , 62 '0
Data 0 , 0 , 66 , 127 , 64 , 0 '1
Data 0 , 98 , 81 , 73 , 73 , 70 '2
Data 0 , 34 , 73 , 73 , 73 , 54 '3
Data 0 , 24 , 20 , 18 , 127 , 16 '4
Data 0 , 47 , 73 , 73 , 73 , 49 '5
Data 0 , 60 , 74 , 73 , 73 , 48 '6
Data 0 , 1 , 113 , 9 , 5 , 3 '7
Data 0 , 54 , 73 , 73 , 73 , 54 '8
Data 0 , 6 , 73 , 73 , 41 , 30 '9
Data 0 , 0 , 108 , 108 , 0 , 0 ':
Data 0 , 0 , 236 , 108 , 0 , 0 ';
Data 0 , 8 , 20 , 34 , 65 , 0 '<
Data 0 , 36 , 36 , 36 , 36 , 36 '=
Data 0 , 0 , 65 , 34 , 20 , 8 '>
Data 0 , 2 , 1 , 89 , 9 , 6 '?
Data 0 , 62 , 65 , 93 , 85 , 30 '@
Data 0 , 126 , 9 , 9 , 9 , 126 'A
Data 0 , 127 , 73 , 73 , 73 , 54 'B
Data 0 , 62 , 65 , 65 , 65 , 34 'C
Data 0 , 127 , 65 , 65 , 65 , 62 'D
Data 0 , 127 , 73 , 73 , 73 , 65 'E
Data 0 , 127 , 9 , 9 , 9 , 1 'F
Data 0 , 62 , 65 , 73 , 73 , 122 'G
Data 0 , 127 , 8 , 8 , 8 , 127 'H
Data 0 , 0 , 65 , 127 , 65 , 0 'I
Data 0 , 63 , 64 , 64 , 64 , 48 'J
Data 0 , 127 , 8 , 20 , 34 , 65 'K
Data 0 , 127 , 64 , 64 , 64 , 64 'L
Data 0 , 127 , 2 , 4 , 2 , 127 'M
Data 0 , 127 , 2 , 4 , 8 , 127 'N
Data 0 , 62 , 65 , 65 , 65 , 62 'O
Data 0 , 127 , 9 , 9 , 9 , 6 'P
Data 0 , 62 , 65 , 81 , 33 , 94 'Q
Data 0 , 127 , 9 , 9 , 25 , 102 'R
Data 0 , 38 , 73 , 73 , 73 , 50 'S
Data 0 , 1 , 1 , 127 , 1 , 1 'T
Data 0 , 63 , 64 , 64 , 64 , 63 'U
Data 0 , 31 , 32 , 64 , 32 , 31 'V
Data 0 , 63 , 64 , 60 , 64 , 63 'W
Data 0 , 99 , 20 , 8 , 20 , 99 'X
Data 0 , 7 , 8 , 112 , 8 , 7 'Y
Data 0 , 97 , 81 , 73 , 69 , 67 'Z
Data 0 , 0 , 127 , 65 , 65 , 0 '[
Data 0 , 2 , 4 , 8 , 16 , 32 '\
Data 0 , 0 , 65 , 65 , 127 , 0 ']
Data 0 , 4 , 2 , 1 , 2 , 4 '^
Data 128 , 128 , 128 , 128 , 128 , 128 '
Data 0 , 0 , 3 , 7 , 0 , 0 '`
Data 0 , 32 , 84 , 84 , 84 , 120 'a
Data 0 , 127 , 68 , 68 , 68 , 56 'b
Data 0 , 56 , 68 , 68 , 68 , 40 'c
Data 0 , 56 , 68 , 68 , 68 , 127 'd
Data 0 , 56 , 84 , 84 , 84 , 8 'e
Data 0 , 8 , 126 , 9 , 9 , 0 'f
Data 0 , 24 , 164 , 164 , 164 , 124 'g
Data 0 , 127 , 4 , 4 , 120 , 0 'h
Data 0 , 0 , 0 , 125 , 64 , 0 'i
Data 0 , 64 , 128 , 132 , 125 , 0 'j
Data 0 , 127 , 16 , 40 , 68 , 0 'k
Data 0 , 0 , 0 , 127 , 64 , 0 'l
Data 0 , 124 , 4 , 24 , 4 , 120 'm
Data 0 , 124 , 4 , 4 , 120 , 0 'n
Data 0 , 56 , 68 , 68 , 68 , 56 'o
Data 0 , 252 , 68 , 68 , 68 , 56 'p
Data 0 , 56 , 68 , 68 , 68 , 252 'q
Data 0 , 68 , 120 , 68 , 4 , 8 'r
Data 0 , 8 , 84 , 84 , 84 , 32 's
Data 0 , 4 , 62 , 68 , 36 , 0 't
Data 0 , 60 , 64 , 32 , 124 , 0 'u
Data 0 , 28 , 32 , 64 , 32 , 28 'v
Data 0 , 60 , 96 , 48 , 96 , 60 'w
Data 0 , 108 , 16 , 16 , 108 , 0 'x
Data 0 , 156 , 160 , 96 , 60 , 0 'y
Data 0 , 100 , 84 , 84 , 76 , 0 'z
Data 0 , 8 , 62 , 65 , 65 , 0 '{
Data 0 , 0 , 0 , 119 , 0 , 0 '|
Data 0 , 0 , 0 , 0 , 0 , 0 '}
Data 0 , 2 , 1 , 2 , 1 , 0 '~
Data 0 , 0 , 0 , 0 , 0 , 0 '
Lesezeichen