AVR Uhr

So, hier ist mein erstes µC Projekt. Es handelt sich dabei um eine Uhr. Die Hardware basiert auf dem AT90S2313, einem 20poligen IC mit 15 I/O Pins. Die Software wurde mit Bascom-AVR geschrieben, einem Basic Dialekt für Atmel AVR Controller.

Feature:

Software

Das Programm ist ausführlich kommentiert und sollte somit gut verständlich sein.

'*******************************************************************************
' Uhr V2.3.3
' 22.06.2004
' Wolfgang Schwarz
' http://www.black-strom.de.vu/
'
'
' Feature:
' - mit Interner Zeitbasis (Timer1)
' - Multiplexausgabe auf Siebensegmentanzeige (Timer0)
' - Uhr ist über zwei Taster einstellbar.
'
' To Do:
' -
'
' Feature for the future:
' - anderer µC  evnt. ATMega8, da der 902312 für den rest nicht reichen wird
' - Uhr stellen über RC5, braucht Timer0
' - Wecker
' - DCF77 empfang
' - Datum zusätzliche über Alphanumerische anzeigen
'
'
' History:
' - V2.3.3 wird ein taster zum uhr stellen länger betätigt> schnellvorlauf
' - V2.3.2 beim uhr stellen die sekunden auf null setzen
' - V2.3.1 Uhren Code aus dem Inetrupt Label ind die Hauptschleife verschoben.
' - V2.3   Uhren Code umgeschrieben; jede Ziffer wir jetzt einzelnt gezählt,
'          Function Bcdzahl und Label Multiplex wir überflüssig.
'          Die Uhr ist jetzt einstellbar.
' - V2.2   Bugy  <ö#+Q@
' - V2.1   Uhr geeicht auf 4MHz > Load_timer1 = 62755
' - V2.0   erster Hardware test
' - V1.0   nur am PC getestet
'
' HW Stack: 40 ; SW Stack 20 ; Framesize: 16
'
'*******************************************************************************


' µC Deklarationen
$regfile = "2313def.dat"                'AT90S2313-Deklarationen
$crystal = 4000000


' Variablen
Dim Temp_ziffer As Byte                 'welche ziffer soll bearbeitet werden
Dim Bcd_aus As Byte                     'enthält den Wert der dez zahl die ausgegeben werden soll

Dim Ausgang As Byte                     'Segmentfolge die Ausgegeben wird aus Segmentcode - Tabelle
Dim Sek_blink As Bit                    'Blinkt im Sekunden Takt

Dim Zl_sekunde As Byte                  'Zeit Variablen
Dim Zl_minute As Byte                   'enthalten die Uhrzeit
Dim Zl_stunde As Byte                   'Zl-... => Low Wert der Zeit
Dim Zh_sekunde As Byte                  'Zh-... => High Wert der Zeit
Dim Zh_minute As Byte
Dim Zh_stunde As Byte


' Ein-/Ausgänge
Config Portb = Output                    'Port B als Ausgang
Ddrd = &B0111100                         '1 Ausgang, 0 Eingang
Portd = &B1000011                        '1 = PullUp aktiviert Eingang (Taster gegen Masse)

'Ausgänge:
Segment_a Alias Portb.0
Segment_b Alias Portb.1
Segment_c Alias Portb.2
Segment_d Alias Portb.3
Segment_e Alias Portb.4
Segment_f Alias Portb.5
Segment_g Alias Portb.6
Dezimalpunkt Alias Portb.7
Ziffer_1 Alias Portd.2
Ziffer_2 Alias Portd.3
Ziffer_3 Alias Portd.4
Ziffer_4 Alias Portd.5

'Eingänge:
T_min_stellen Alias Pind.0
T_h_stellen Alias Pind.1


' Sonstiges
Const Load_timer1 = 62755                 'Konstande auf die der Timer1 geladen wird
'4MHz = 62755 | 62760 etwas zu langsam <> 62750 etwas zu schnell



'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Timer0 für Multiplexausgabe
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

On Timer0 7segment                      'Interrupt-Routine für Timer0-Overflow
Config Timer0 = Timer , Prescale = 64   'Takt: Quarz/Prescale  (möglich: 1, 8, 64, 256, 1024)
Enable Timer0                           'Timer0-Overflow-Interrupt einschalten


'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Timer 1 als Zeitbasis
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

On Timer1 Sekunde_plus                   'Interrupt-Routine für Timer1-Overflow
Config Timer1 = Timer , Prescale = 64    'Takt: Quarz/Prescale  (möglich: 1, 8, 64, 256, 1024)
Enable Timer1                            'Timer0-Overflow-Interrupt einschalten
Enable Interrupts                        'Interrupts global zulassen
Load Timer1 , Load_timer1                'Lädt den Timer auf einen wert vor


'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Hauptprogramm
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Do                                                'Start Hauptschleife


' ### Uhren Code ###
' Es wird für jede Ziffer einzelnd gezählt, das ermöglicht eine einfacher ausgabe
' auf den 7segmentanzeigen. Der Zählvorgang funktioniert ím prinzip wie z.B.
' bei einem normalen Logik Zähler-IC

If Zl_sekunde = 10 Then            'Wenn der Sekunden Low Wert = 10
Zl_sekunde = 0                     'wird er auf 0 gesetzt
Incr Zh_sekunde                    'und der High Wert um eins erhöht
   If Zh_sekunde = 6 Then          'Ist der High Wert 6 (entspricht 60 Sekunden)
   Zh_sekunde = 0                  'wird er auf 0 gesetzt
   Incr Zl_minute                  'und der Minuten Low Wert um eins erhöht
   End If
End If


If Zl_minute = 10 Then
   Zl_minute = 0
   Incr Zh_minute
End If
If Zh_minute = 6 Then
   Zh_minute = 0
   Incr Zl_stunde
End If


If Zl_stunde = 10 Then
   Zl_stunde = 0
   Incr Zh_stunde
End If
If Zh_stunde = 2 And Zl_stunde = 4 Then
   Zl_stunde = 0
   Zh_stunde = 0
End If



' ### Uhr stellen ###
' Wird der Taster "T_min_stellen" betätigt werden die Minuten um eins erhöht.
' Wird der Taster "T_h_stellen" betätigt werden die Stunden um eins erhöht.
' Werden beide gleichzeitig betätigt werden Stunden und Minuten auf Null gesetzt.
' Wird einer der Taster länger betätigt (> 150ms) gibt es einen schnellvorlauf

If T_min_stellen = 0 Then                   'Wird "T_min_stellen" betätigt
   Waitms 150                               'Entprellen
   If T_min_stellen = 0 Then                'Ist der Taster immer noch betätigt
   Incr Zl_minute                           'wird Minute um eins erhöht
   Zl_sekunde = 0                           'Sekunden auf Null setzen
   Zh_sekunde = 0
   End If
End If


If T_h_stellen = 0 Then
    Waitms 150
    If T_h_stellen = 0 Then
    Incr Zl_stunde
    Zl_sekunde = 0
    Zh_sekunde = 0
    End If
End If


If T_min_stellen = 0 And T_h_stellen = 0 Then     'Wenn "T_Min_stellen" und "T_H_stellen" gleichzeitig betätigt
    Zl_minute = 0                                 'dann werden Minuten und Stunden auf 0 gestzt
    Zh_minute = 0
    Zl_stunde = 0
    Zh_stunde = 0
End If



Loop                                              'Ende Hauptschleife

End                                               'Programm Ende


'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Interrupt-Routine für Ziffer ausgabe im 7 Segmentcode
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Bei jedem Aufruf wir nur eine Ziffer ausgegeben, d.h nur eine Anzeige wird
' angesteuert. Die anderen bleiben dunkel. Bei jedem Aufruf wird eine Anzeige
' weitergeschaltet.
'
' Anzeigen anordnung
'
' 1111  2222   3333  4444
' 1  1  2  2   3  3  4  4
' 1111  2222   3333  4444
' 1  1  2  2   3  3  4  4
' 1111o 2222o  3333o 4444o
'
'                        ^-- Dezimalpunkt
'                      ^---- 4. Ziffer | Minute Low Wert  | Variable Zl_minute
'                ^---------- 3. Ziffer | Minute High Wert | Variable Zh_minute
'         ^----------------- 2. Ziffer | Stunde Low Wert  | Variable Zl_stunde
'   ^----------------------- 1. Ziffer | Stunde High Wert | Variable Zh_stunde


7segment:

If Temp_ziffer = 4 Then Temp_ziffer = 0           'bestimmt die auszugebende Ziffer (1 bis 4)
Incr Temp_ziffer                                  'bei jedem aufruf des Lable wir eine andere Ziffer ausgegeben


Portb = &B11111111                                'Alle Ziffern aus, ansonsten gibt es "Geister" Anzeigen


Select Case Temp_ziffer                           'welche Ziffer soll angesteuert werden
   Case 1 : Ziffer_1 = 1                          '1. Ziffer
            Ziffer_2 = 0
            Ziffer_3 = 0
            Ziffer_4 = 0
            Bcd_aus = Zh_stunde
   Case 2 : Ziffer_1 = 0                          '2. Ziffer
            Ziffer_2 = 1
            Ziffer_3 = 0
            Ziffer_4 = 0
            Dezimalpunkt = Sek_blink              'Dezimalpunkt
            Bcd_aus = Zl_stunde
   Case 3 : Ziffer_1 = 0                          '3. Ziffer
            Ziffer_2 = 0
            Ziffer_3 = 1
            Ziffer_4 = 0
            Bcd_aus = Zh_minute
   Case 4 : Ziffer_1 = 0                          '4. Ziffer
            Ziffer_2 = 0
            Ziffer_3 = 0
            Ziffer_4 = 1
            Bcd_aus = Zl_minute
End Select


'Ermittelt aus der Segmentfolge-Tabelle den 7 Segmentcode für die auszugebende Zahl
Select Case Bcd_aus
    Case 1 : Ausgang = Lookup(1 , Segmentfolge)
    Case 2 : Ausgang = Lookup(2 , Segmentfolge)
    Case 3 : Ausgang = Lookup(3 , Segmentfolge)
    Case 4 : Ausgang = Lookup(4 , Segmentfolge)
    Case 5 : Ausgang = Lookup(5 , Segmentfolge)
    Case 6 : Ausgang = Lookup(6 , Segmentfolge)
    Case 7 : Ausgang = Lookup(7 , Segmentfolge)
    Case 8 : Ausgang = Lookup(8 , Segmentfolge)
    Case 9 : Ausgang = Lookup(9 , Segmentfolge)
    Case 0 And Temp_ziffer = 1 : Ausgang = Lookup(10 , Segmentfolge)   'Nullstellenunterdrückung  bei der ersten Ziffer
    Case 0 And Temp_ziffer > 1 : Ausgang = Lookup(0 , Segmentfolge)    'wenn nicht erste Ziffer Null anzeigen
End Select


'Ausgabe des 7 Segmentcodes (Invertierend [Not] bei Anz. mit gem. Anode)
Segment_a = Not Ausgang.0                         'Segment A
Segment_b = Not Ausgang.1                         'Segment B
Segment_c = Not Ausgang.2                         'Segment C
Segment_d = Not Ausgang.3                         'Segment D
Segment_e = Not Ausgang.4                         'Segment E
Segment_f = Not Ausgang.5                         'Segment F
Segment_g = Not Ausgang.6                         'Segment G


Return


'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Interrupt-Routine für Timer1 / Zeitbasis
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sekunde_plus:


Load Timer1 , Load_timer1            'Lädt den Timer auf einen wert vor

Incr Zl_sekunde                      'Erhöht den Low Wert der Sekunde um eins

Toggle Sek_blink                     'Ändert sich jede Sek., 1sec an 1sec aus


Return



'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' 7 Segmentcode - Tabelle
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'
' --A--
' |   |
' F   B
' |   |
' --G--
' |   |
' E   C
' |   |
' --D--


Segmentfolge:                'GFEDCBA / "1" Segment AN
Data &B0111111               '0
Data &B0000110               '1
Data &B1011011               '2
Data &B1001111               '3
Data &B1100110               '4
Data &B1101101               '5
Data &B1111101               '6
Data &B0000111               '7
Data &B1111111               '8
Data &B1101111               '9
Data &B0000000               'leeres Feld (zur Nullstellenunterdrückung)

Hardware

Die Hardware ist recht simpel gehalten. Die Kathoden der 7segmentanzeigen sind alle parallel geschaltet, über die ISP-Schnittstelle wird er µC programmiert, der Rest sollte soweit klar sein.

Download

Schaltplan, Stückliste, Bascom Source Code, Intel Hex File

Bilder

AVR Uhr auf einem Steckbrett aufgebaut
Derzeit nur auf einem Steckbrett aufgebaut
Nachbau von Christian Seifert - mit Sekunden Anzeige
Nachbau von Christian Seifert - mit Sekunden Anzeige
Nachbau von Christian Seifert - mit Sekunden Anzeige
Nachbau von Christian Seifert - mit Sekunden Anzeige
Nachbau von Florian Epple - mit Sekunden und goßen 7segment Anzeigen
Nachbau von Florian Epple - mit Sekunden
und goßen 7segment Anzeigen
Nachbau von Florian Epple - mit Sekunden und goßen 7segment Anzeigen
Nachbau von Florian Epple - mit Sekunden
und goßen 7segment Anzeigen
Nachbau von Andreas Wenzel
Nachbau von Andreas Wenzel
Nachbau von Andreas Wenzel
Nachbau von Andreas Wenzel - der dritte Taster
dient dazu die Sekunden anzuzeigen
Nachbau von Mike Köppl
Nachbau von Mike Köppl
www.black-strom.de.vu
Stoppt die Vorratsdatenspeicherung! Jetzt klicken &handeln! Willst du auch an der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien: