-
        

Ergebnis 1 bis 8 von 8

Thema: Problem bei Binäruhr

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    18.05.2008
    Ort
    Aschaffenburg
    Alter
    27
    Beiträge
    25

    Problem bei Binäruhr

    Anzeige

    Hallo,

    ich habe vor kurzen angefangen, eine Binäruhr mit LED-Anzeige zu bauen. Mittlerweile habe ich die Platine fertig gelötet und habe mi9ch an den Code gemacht. Nun stehe ich allerdings vor dem Problem, dass der Atmega samt seiner schaltung nicht so wollen wie ich.

    Code:
    $regfile "m8def.dat"
    $crystal = 16000000
    
    Dim Sec As Byte
    Dim Minu As Byte
    Dim Hour As Byte
    Dim Flag As Bit
    Dim X As Byte
    Dim Y As Byte
    'Dim Tag As Integer
    Sec = 0
    Minu = 0
    Hour = 0
    
    Config Portd = Output
    Config Portc = Output
    Config Portb = Output
    
    Config Timer1 = Timer , Prescale = 256
    Load Timer1 , 3036
    
    Enable Timer1
    
    On Timer1 Timer_interrupt
    Enable Interrupts
    
    ' Portd.0 = 0
    'Tag = 0
    Do
    '(
    If Tag > 976 Then
    Incr Sec
    Tag = 0
    If Portd.0 = 1 Then Portd.0 = 0
    Else
    Portd.0 = 1
    End If
    ')
    
    For X = 0 To 2
    Y = X + 3
    Portb.y = Sec.x
    Next
    
    X = 0
    Y = 0
    
    For X = 3 To 5
    Y = X - 3
    Portc.y = Sec.x
    Next
    
    X = 0
    Y = 0
    
    For X = 3 To 5
    Y = X - 3
    Portb.y = Minu.x
    Next
    
    X = 0
    Y = 0
    
    For X = 0 To 2
    Y = X + 5
    Portd.y = Minu.x
    Next
    
    X = 0
    Y = 0
    
    For X = 0 To 4
    Portd.x = Hour.x
    Next
    
    X = 0
    Y = 0
    
    Flag = 0
    If Flag = 0 Then
     If Sec > 59 Then
     Sec = 0
     Incr Minu
     End If
    
     If Minu > 59 Then
     Minu = 0
     Incr Hour
     End If
    
      If Hour > 23 Then
     Hour = 0
     End If
    
     End If
    
    Loop
    
    
    'Do
    'Loop
    
    Timer_interrupt:
    
    Incr Sec
    
    Flag = 1
    
    
    'Toggle Portd.0
    Load Timer1 , 3036
    Return
    Soweit so gut. Zur Zeit läuft die Schaltung über ein 4,5 V Netzteil, woher vermutlich die Ungenauigkeit des Quarzoszillators stammt. Das aktuelle Problem ist allerdings, dass bis auf 3 LEDs (32, 16, 8 Sekunden) alle nur wild am flakern sind.
    Die Beschaltung der Ports:
    Code:
    PD0 = 1 h
    PD1 = 2 h
    PD2 = 4 h
    PD3 = 8 h
    PD4 = 16 h
    PD5 = 1 min
    PD6 = 2 min
    PD7 = 4 min
    PB0 = 8 min
    PB1 = 16 min
    PB2 = 32 min
    PB3 = 1 sek
    PB4 = 2 sek
    PB5 = 4 sek
    PC0 = 8 sek
    PC1 = 16 sek
    PC2 = 32 sek
    Ich hoffe ihr könnt mir da weiter helfen

    MfG DaRe

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112

    Re: Problem bei Binäruhr

    Zitat Zitat von walkonshit
    Config Timer1 = Timer , Prescale = 256
    Load Timer1 , 3036
    Load Timer1, 3036 setzt den Timer Wert auf 65536-3036=62500, sodass nur noch 3036 Schritte bis zum Überlauf sind.
    16.000.000 / 256 = 62500 Ich denke, du solltest
    Load Timer1, 62500
    setzen. Eigentlich müsste die Uhr dadurch ca. 20 x so schnell laufen wie normal.
    Ob der rest so stimmt kann ich nicht sagen. Da bin ich noch nicht durchgestiegen.

    Gruß

    Rolf

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    18.05.2008
    Ort
    Aschaffenburg
    Alter
    27
    Beiträge
    25
    Oh okay...
    ich habe den Wert geändert und stelle fest, dass soweit alles gut läuft. Allerdings nur eine Minute, danach flakern die Stunden- und Minuten-LEDs wieder wild drauf los.

    Edit: Die Variable Sec behält den Wert 60 und Min steigt pro Zyklus der Do-Loop-Schleife um 1. Ergo: Sec = 0 wird nicht durchgeführt, aber warum?

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791
    Hallo walkonshit,

    deine Bitmanipulationen habe ich mir nicht genauer angesehen.
    Grundsätzlich hast du eine Do-Loop Schleife, die mit Maximalgeschwindigkeit durchläuft. Darein haut dann der Interrupt jede Sekunde und erhöht die Sekunde um 1 und setzt ein Flag.
    Das Flag wird in der Do-Loop-Schleife konstant auf 0 gesetzt.

    Warum diese "wilde" Konstruktion?
    Vorschlag:
    1. Einmalig wird die Binäruhr nach der Uhrzeit gestellt (alle Bits gesetzt).
    2. Dann gehts in die Do-Loop Schleife, die gar nichts macht (leere Schleife) bis ein Interrupt kommt.
    3. Dann wird die Sekundenanzeige neu dargestellt und nur bei Überlauf die Minuten und Stunden geändert.
    4. Danach gehts wieder in die leere Schleife an den Anfang (warten auf nächste Sekunde).

    Dann wird die Anzeige ganz ruhig und völlig entspannt.

    Gruß Dirk

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    18.05.2008
    Ort
    Aschaffenburg
    Alter
    27
    Beiträge
    25
    Ich dachte es is vielleicht geschickter die Routinen ausserhalb des Interupts zu lassen, da sonst der Interrupt zuviele Zyklen verbraucht. Okay ich merke grad selber Blödsinn...Egal dennoch, selbst wenn ich das Programm umschreibe habe ich doch immer noch das Problem, dass die Variable SEC nicht auf 0 gesetzt wird.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791
    ... wenn ich das Programm umschreibe habe ich doch immer noch das Problem, dass die Variable SEC nicht auf 0 gesetzt wird.
    Ich weiß nicht genau, warum das nicht klappt.
    Allerdings kann dein Prog erstaunliche Effekte produzieren:
    Stell dir vor, der Interrupt würde in eine dieser Schleifen ...
    Code:
    For X = 0 To 2 
    Y = X + 3 
    Portb.y = Sec.x 
    Next 
    
    X = 0 
    Y = 0 
    
    For X = 3 To 5 
    Y = X - 3 
    Portc.y = Sec.x 
    Next
    ... reinhauen.
    Der Effekt wäre, dass sehr merkwürdige Dinge angezeigt würden, weil der Sec-Wert in der Schleife geändert (inkrementiert) wird.

    Oder:
    Wenn er hier reinhauen würde...
    Flag = 0
    ==> Interrupt haut HIER rein!
    If Flag = 0 Then
    If Sec > 59 Then
    Sec = 0
    Incr Minu
    End If
    ... dann ist ja Flag = 1 und der Sec-Überlauf fände nicht statt.

    Also: Umschreiben!

    Gruß Dirk

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    18.05.2008
    Ort
    Aschaffenburg
    Alter
    27
    Beiträge
    25
    Okay...da hast du natürlich Recht. Ich habe den Code abgeändert und siehe da...ebenfalls werden die Variablen nicht resettet.

    Code:
    $regfile "m8def.dat"
    $crystal = 16000000
    $sim
    Dim Sec As Byte
    Dim Minu As Byte
    Dim Hour As Byte
    Dim Flag As Bit
    Dim X As Byte
    Dim Y As Byte
    Sec = 0
    Minu = 0
    Hour = 0
    
    Config Portd = Output
    Config Portc = Output
    Config Portb = Output
    
    Config Timer1 = Timer , Prescale = 256
    Load Timer1 , 62500
    
    Enable Timer1
    
    On Timer1 Timer_interrupt
    Enable Interrupts
    
    
    Do
    Loop
    
    Timer_interrupt:
    
    Incr Sec
    
    If Sec > 59 Then
     Minu = Minu + 1
     Sec  = 0
    
    
     If Minu > 59 Then
     Minu = 0
     Hour = Hour + 1
    
    
      If Hour > 23 Then
     Hour = 0
     End If
     End If
     End If
    
    For X = 0 To 2
    Y = X + 3
    Portb.y = Sec.x
    Next
    
    X = 0
    Y = 0
    
    For X = 3 To 5
    Y = X - 3
    Portc.y = Sec.x
    Next
    
    X = 0
    Y = 0
    
    For X = 3 To 5
    Y = X - 3
    Portb.y = Minu.x
    Next
    
    X = 0
    Y = 0
    
    For X = 0 To 2
    Y = X + 5
    Portd.y = Minu.x
    Next
    
    X = 0
    Y = 0
    
    For X = 0 To 4
    Portd.x = Hour.x
    Next
    
    X = 0
    Y = 0
    
    Load Timer1 , 62500
    Return
    Langsam wirds merkwürdig.

    MfG DaRe

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Zitat Zitat von walkonshit
    Ich dachte es is vielleicht geschickter die Routinen ausserhalb des Interupts zu lassen, da sonst der Interrupt zuviele Zyklen verbraucht.
    Nicht aus dem Grund, aber machen würde ich das wirklich genau so.
    Bei mir wird die Variable Sec übrigens in ASM Farbe dargestellt. Daher habe ich die Variable mal auf Seco geändert. Dann funktioniert dein Programm.
    Zusätzlich noch ein wenig aufgeräumt sieht es dann so aus:
    Code:
    $regfile "m8def.dat"
    $crystal = 16000000
    
    Dim Seco As Byte
    Dim Minu As Byte
    Dim Hour As Byte
    Dim Flag As Bit
    Dim X As Byte
    Dim Y As Byte
    'Dim Tag As Integer
    Seco = 0
    Minu = 0
    Hour = 0
    
    Config Portd = Output
    Config Portc = Output
    Config Portb = Output
    Config Timer1 = Timer , Prescale = 256
    Load Timer1 , 62500
    
    Enable Timer1
    
    On Timer1 Timer_interrupt
    Enable Interrupts
    
    ' Portd.0 = 0
    'Tag = 0
    Do
       If Flag = 1 Then
          '(
          If Tag > 976 Then
             Incr Sec
             Tag = 0
             If Portd.0 = 1 Then Portd.0 = 0
          Else
             Portd.0 = 1
          End If
          ')
          Flag = 0
          If Seco > 59 Then
             Seco = 0
             Incr Minu
          End If
          If Minu > 59 Then
             Minu = 0
             Incr Hour
          End If
          If Hour > 23 Then
             Hour = 0
          End If
          Portb.3 = Seco.0
          Portb.4 = Seco.1
          Portb.5 = Seco.2
          Portc.0 = Seco.3
          Portc.1 = Seco.4
          Portc.2 = Seco.5
          Portd.5 = Minu.0
          Portd.6 = Minu.1
          Portd.7 = Minu.2
          Portb.0 = Minu.3
          Portb.1 = Minu.4
          Portb.2 = Minu.5
          Portd.0 = Hour.0
          Portd.1 = Hour.1
          Portd.2 = Hour.2
          Portd.3 = Hour.3
          Portd.4 = Hour.4
       End If
    Loop
    
    
    Timer_interrupt:
       Load Timer1 , 62500
       Incr Seco
       Flag = 1
       'Toggle Portd.0
    Return
    Gruß

    Rolf

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •