Upline: Infos & Dokus Elektronik

Übung ATMEL-µC mit vollgrafischem LCD Teil 2


Timer mit ATMega8515 und DataVision DG12864-12

Dieses Beispiel baut auf der 1. Übung auf und verwendet exakt die gleiche Schaltung. Lediglich die Ports habe ich verändert (statt A/C hier B/C).

Software

Auch dieses Programm ist in Bascom geschrieben worden, ein Teil des Sources aus der 1. Übung ist (leicht verändert) noch enthalten, einiges mußte ich entfernen, da die freie Demoversion sonst bereits an ihre 4kB-Grenze stößt. Eine Möglichkeit zum Stellen der Uhr habe ich nicht programmiert, da dazu ohnehin spätestens nach dem 3. µC-Reset niemand mehr Lust haben dürfte. Wer eine wirklich genaue Zeitanzeige haben möchte, ohne jedes mal alles neu stellen zu müssen, müßte eine völlig andere Schaltung entwerfen, evtl. mit einem 2. µC und Akkus oder seine Zeit z.B. aus dem GPS-Signal beziehen - womit letztendlich eine derart genaue und Prozessorlast erzeugende Zeitberechnung, wie sie hier erfolgt, allerdings nicht mehr nötig wäre.
Ich lasse per Interrupt die Variable Tcount hochzählen. Diese wird im Programm in einer Endlosschleife neben den sonstigen Dingen ausgewertet. Der Parameter hD = 0.264748221 ist hierbei der Faktor, der für meine Schaltung die exakte Umrechnung von Tcount in Sekunden ermöglicht. Da jeder Quarz geringfügig anders schwingt und ich auf ein Ziehen per Kondensatoren verzichten wollte, habe ich diesen Wert in einem 14-stündigen Dauerlauf aus dem Verhältnis der angezeigten Zeiten des Mikrocontrollers und einer Stoppuhr ermittelt. Über ein paar Hilfsvariablen wird dann der Sekundenwert in das Uhrzeit-Format hh:mm:ss umgewandelt. Hierbei kann man schnell über einige Merkwürdigkeiten in Bascom stolpern: Bascom verhält sich nämlich völlig anders, als gängige PC-Programmiersprachen wie Delphi oder C++, wenn es darum geht, Typumwandlungen und typübergreifende Berechnungen zu erledigen ...
Da ich kein Datum mitzählen lasse und auch Longints irgendwann überlaufen, verringere ich nach 24h Tcount um 326431 - diese Zahl ist evtl. nicht exakt und müßte bei Bedarf noch angepaßt werden.
Der Rest des Quelltextextes sollte leicht verständlich sein, um nochmals einige der aus Übung 1 bekannten Funktionen zu verwenden, habe ich noch einige Unterfunktionen, die ich direkt per GOSUB anspringe, integriert.
Hinweis: die Parameter von "Config Graphlcd" müssen alle in einer Zeile stehen, ich habe nur um das vertikale Scrolling in dieser Seite zu verhindern, einen Zeilenumbruch eingefügt.
'Programm nutzt 128x64-Pixel-Display für Ausgaben
$regfile = "m8515.dat"
$crystal = 4000000
$baud = 9600
Config Portd = Input                                        'Taster
Config Graphlcd = 128 * 64 , Dataport = Portc , Controlport = Portb , Wr = 2 ,
Rd = 3 , Ce = 4 , Cd = 5 , Reset = 6 , Fs = 7 , Mode = 6       'PortB/C für LCD
Config Timer0 = Timer , Prescale = 1024
On Timer0 Isr_timer0
Enable Timer0
Enable Interrupts
Dim A as Byte , D as Byte , tCount as Long , ssec as Long , tCount2 as Single , hD as Single
Dim thh as Byte , tmm as Byte , tss as Byte , hL as Long , hL2 as Long
Dim strtime as String * 8

CLS
CURSOR off

DO
 D = 128 * Pind.7
 A = 64 * Pind.6
 D = D + A
 A = 32 * Pind.5
 D = D + A
 A = 16 * Pind.4
 D = D + A
 A = 8 * Pind.3
 D = D + A
 A = 4 * Pind.2
 D = D + A
' A = 2 * Pind.1         'weggelassen, da Taster defekt ;)
' D = D + A
 D = D + Pind.0

 IF D = 1 THEN CLS
 IF D = 4 THEN GOSUB Textout
 IF D = 5 THEN CLS Text
 IF D = 8 THEN GOSUB Lineout
 IF D = 9 THEN CLS Graph
 IF D = 32 THEN
  Pset 0 , 0 , 1
 END IF
 IF D = 64 THEN
  Pset 1 , 0 , 1
 END IF
 IF D = 128 THEN
  Pset 124 , 0 , 1
 END IF
 IF tCount >= 326431 THEN tCount = tCount -326431           'ca. 1d
 tCount2 = tCount
 hD = 0.264748221                                           'Faktor für 1s bei ca. 4MHz
 tCount2 = tCount2 * hD
 ssec = tCount2
 LOCATE 6 , 1 : LCD ssec : LCD "     "
 hL2 = 3600
 hL = ssec / hL2
 thh = hL
 hL = hL * hL2
 ssec = ssec - hL
 hL2 = 60
 hL = ssec / hL2
 tmm = hL
 hL = hL * hL2
 ssec = ssec - hL
 tss = ssec
 strtime = ""
 IF thh < 10 THEN strtime = "0"
 strtime = strtime + str(thh) + ":"
 IF tmm < 10 THEN strtime = strtime + "0"
 strtime = strtime + str(tmm) + ":"
 IF tss < 10 THEN strtime = strtime + "0"
 strtime = strtime + str(tss)

 LOCATE 7 , 1 : LCD strtime                                 'Uhrzeit
 LOCATE 8 , 1 : LCD "PortD=" : LCD D : LCD "  "
 WAITms 50
LOOP

END                                                         'end program

Isr_timer0:
 incr Tcount
Return

Textout:
 LOCATE 1 , 1 : LCD "ATMega8515@4MHz"
 LOCATE 2 , 1 : LCD "gLCD 128x64 T6963c"
RETURN

Lineout:
 LINE(2 , 0) -(2 , 30) , 1
 LINE(2 , 0) -(125 , 0) , 1
 LINE(125 , 0) -(125 , 30) , 1
 LINE(2 , 30) -(125 , 30) , 1
RETURN

Ergebnis

Es ist in dem Foto rechts zwar schlecht zu erkennen, aber da steht in Zeile 6 der Sekundenzähler, darunter die Uhrzeit und in der letzten Zeile der Status vom PortD.