- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 4 von 4

Thema: DCF ist bei drittem Mal korrekt

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478

    DCF ist bei drittem Mal korrekt

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Moin,

    Vorweg: ich erwarte nicht, dass sich jemand meinen Code im Detail reinfuchst, ich hoffe, dass es villeicht etwas ist, wo ich einfach nur nicht drauf komme.

    Ich hab mir nen schönen Code zum Auswerten von nem DCF Signal gebaut. Das seltsame ist, die Zeitauswertung ist erst im zweiten oder dritten Anlauf korrekt.

    Das läuft so, dass erst alles etwa 3 min lang ignoriert wird, dann auf die lange Pause nach Sekunde 59 gewatet wird und erst dann das Signal berücksichtigt wird.

    Eine Funktion wird nach jedem Ouls aufgerufen und entscheidet ob es 1 oder 0 war. Ist das 59 mal passiert, wir das Bitmuster ausgewertet.

    Klappt aber eben erst beim zweiten,dritten mal wirklich.

    Hat da jemand einen Vorschlag?

    Danke


    Code:
    .include "m8def.inc"
    
    .def tmp = r16
    .def tmp2 = r17
    .def status_reg = r18
    ;BIT 0 zeigt an, ob PINB,1 während der ISR LOW war, dann = 1
    ;BIT 1 warten auf dcf Anfang =1 => freigabe
    ;Bit 2 Fehlerbit
    .def pw = r19
    .def pw2 = r20
    .def pw_alt = r21
    
    .def dcf_shift_reg = r24
    .def sreg_save = r25
    
    .equ dcf_BIT_counter = 104
    .equ eins = 1
    .equ zwei = 2
    .equ vier = 4
    .equ acht = 8
    .equ zehn = 10
    .equ zwanzig = 20
    .equ vierzig = 40
    
    .org 0x000
      rjmp reset
    .org OC1Aaddr
         rjmp timer1_int
    
    ;*****************************************	
    ;*****************************************	
    ;         Pointer Z
    ; 
    ;              ms = RAM 100
    ;              sc = RAM 101
    ;             min = RAM 102
    ;          stunde = RAM 103
    ; dcf_BIT_counter = RAM 104
    ;     
    ;******************************************
    
    ;******************************************
    ;        Pointer Y
    
    ;     dcf BIT 0-7 = RAM 105
    ;    dcf BIT 8-15 = RAM 106
    ;   dcf BIT 16-23 = RAM 107
    ;   dcf BIT 24-31 = RAM 107
    ;   dcf BIT 32-39 = RAM 108
    ;   dcf BIT 40-47 = RAM 109     
    ;   dcf BIT 48-55 = RAM 110
    ;   dcf BIT 56-59 = RAM 111
    
    reset:
       ;Stack wird bei Interrupts benötigt! 
       ldi tmp,HIGH(RAMEND) 
       out SPH,tmp 
       ldi tmp,LOW(RAMEND) 
       out SPL,tmp
       ldi tmp,0xFF
       out DDRD,tmp
       ldi tmp,0
    
       ldi r28,105
       ldi r29,0
    
       ldi r31,0
       ldi r30,100
       st Z+,tmp
       st Z+,tmp
       st Z+,tmp 
       st Z+,tmp 
       st Z,tmp
       ldi r30,100
       
       ldi tmp,0
       out DDRC,tmp
       ldi tmp,0b00110000
       out PORTC,tmp
       ldi tmp,0
       out DDRB,tmp
       ldi tmp,0
       out PORTB,tmp
       ldi tmp,0b00110000
       out TIMSK,tmp
       
    ldi tmp,0b00000010
       out OCR1AH,tmp
       ldi r17,0b01110001
       out OCR1AL,r17
    
       ldi tmp,0b00000000
       out TCCR1A,tmp
       ldi tmp,0b00001011
       out TCCR1B,tmp
       ldi r17,0
       ldi status_reg,0
       
       ldi r28,105
       
    ldi dcf_shift_reg,0
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y,dcf_shift_reg
    ldi r28,105
    sbi PORTD,7
    ldi pw_alt,0
       sei
    
       main:
    ;**********************************
    ; Funktion dcf_einholen wird aufgerufen, wenn
    ; pw > 9  und am ISR Anfang keinSignal da war
    ; pw wird in dcf_einholen gelöscht
    ;pw kann nur erhöht werden, wenn 
    ;lange Pause da war => keine Abfrage von 
    ;Bit 1 im status_reg nötig
       cpi pw,5
       brlo dcf_nicht_einholen
       sbrc status_reg,0b00000000; 
       rjmp dcf_nicht_einholen
       rcall dcf_einholen
       
    ;**********************************
    ;   out PORTD,r28
    
    
      sbrc status_reg,0b00000100
       rcall dcf_auswerten
       dcf_nicht_einholen:
       
     sbis PINC,5
     ori status_reg,0b00100000
    
      
    
       
       
       
       rjmp main
    
    
    fehlerroutine:
    ldi status_reg,0 
    ldi r28,105
    st Y,status_reg
    ldi r30,104
    st Z,status_reg
    ldi r30,100
    ldi pw,0
    ldi pw2,0
    ret
    
    
    
    dcf_einholen:
    /*
    1.) prüft Pulsweite auf >< 150 ms
    2.) erhöht Y Pointer, wenn ein Byte voll ist
    3.) speichert bei "überlauf" von bit_counter=8 bit_counter = 0 ab
    24 CK´s inclusive rcall
    */
    
    	 
         ldi r30,dcf_BIT_counter
    	 ld tmp,Z
    	 ld dcf_shift_reg,Y;
    	 lsr dcf_shift_reg
    	 
    	 cpi pw,16
    	 brlo log_null
    	 ori dcf_shift_reg,0b10000000
    	 log_null:
    	 
         st Y,dcf_shift_reg    
    	 sbrs tmp,0b00000011
    	 rjmp vollmachen
    	 ldi tmp,0
    	 st Z,tmp
    	 inc r28
    	 
    	 ldi dcf_shift_reg,0
    	 vollmachen:
    	
    
         
    ldi pw,0
    ldi r30,100
    inc pw_alt
    cpi pw_alt,59
    brne mehr1
    ori status_reg,0b00010000
    mehr1:
    ret
    
    
    dcf_auswerten:
    
    ldi r30,dcf_BIT_counter
    ldi tmp,0
    st Z,tmp
    
    andi status_reg,0b11101101; löschen der Freigabe von Pause_war_da
                              ; und Aufruf von dcf_auswerten
    
    ldi pw_alt,0
    
    /*
    wertet die Bitmuster in RAM 107 bis 109 in Minuten und Stunden aus
    81 CK´s inclusive rcall
    */
      
    ;***************************
    ;       Minuten
    
    
    ldi r28,107
    
    ld tmp,Y
    
    inc r28;lädt von 107 dann inc zu 108
    ldi r22,0
    
    ldi tmp2,1
    sbrc tmp,0b00000101
    add r22,tmp2
    
    ldi tmp2,2
    sbrc tmp,0b00000110
    add r22,tmp2
    
    ldi tmp2,4
    sbrc tmp,0b00000111
    add r22,tmp2
    
    
    ld tmp,Y
    inc r28;lädt von 108 dann inc zu 109
    
    ldi tmp2,8
    sbrc tmp,0b00000000
    add r22,tmp2
    
    ldi tmp2,10
    sbrc tmp,0b00000001
    add r22,tmp2
    
    ldi tmp2,20
    sbrc tmp,0b00000010
    add r22,tmp2
    
    ldi tmp2,40
    sbrc tmp,0b00000011
    add r22,tmp2
    ;out PORTD,r22
    ;***************************
    
    ;***************************
    ;     Stunde
    
    ldi tmp2,eins
    sbrc tmp,0b00000101
    add r23,tmp2
    
    ldi tmp2,2
    sbrc tmp,0b00000110
    add r23,tmp2
    
    ldi tmp2,4
    sbrc tmp,0b00000111
    add r23,tmp2
    
    ld tmp,Y ;lädt von 109
    ldi tmp2,8
    sbrc tmp,0b00000000
    add r23,tmp2
    
    ldi tmp2,10
    sbrc tmp,0b00000001
    add r23,tmp2
    
    ldi tmp2,20
    sbrc tmp,0b00000010
    add r23,tmp2
    
    ldi r22,0
    ldi r23,0
    ;***************************
    ldi r28,105
    ldi dcf_shift_reg,0
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y+,dcf_shift_reg
    st Y,dcf_shift_reg
    ldi r28,105
    
    out PORTD,status_reg
    sbi PORTD,6
    ret
    
    
     
    
     timer1_int:
     in sreg_save,SREG
     sbrs status_reg,0b00000101
     rjmp ignore
      ;****************************
      ; setzt Bit 0 in status_reg, wenn Signal da (PINB_0 HIGH)  ist
      ; setzte Bit 3 in status_reg auf rising edge 
      sbis PINB,0
      rjmp kein_signal_an_pinb0 
       sbrs status_reg,0b00000000
       ori status_reg,0b00001000
        ori status_reg,0b00000001
    	rjmp signal_da
      kein_signal_an_pinb0:
      andi status_reg,0b11111110
      signal_da:
    ;**************************
    
    ;***************************
    ; ausführen wenn kein Signal 
    
      sbrc status_reg,0b00000000
      rjmp warten_auf_pause
    
     
        inc pw2
        cpi pw2,100
        brlo warten_auf_pause
    	ldi r22,0
        sbrc status_reg,0b00000001
        rjmp fehlerbit_setzten
           ori status_reg,0b00000010
           ldi pw2,0
    	  
        rjmp warten_auf_pause
        fehlerbit_setzten:
            ori status_reg,0b00000100    
    
        ldi pw2,0
    	   
    	   
    
        rjmp war_keins_da 
     
     warten_auf_pause:
    
     war_keins_da: 
     
    ;***************************
    
    ;***************************
    ;ausführen, wenn zu ISR Anfang Signal da war und
    ;lange Pause da war
     sbrs status_reg,0b00000000
     rjmp warten_auf_signal
     sbrs status_reg,0b00000001
     rjmp warten_auf_signal
     
     inc pw
     ldi pw2,0
     
     warten_auf_signal:
    
    
    
    
    
     sbrc status_reg,0b00000000
     ldi pw2,0
     
     sbrs status_reg,0b00000011
     rjmp fix
     ldi r30,dcf_BIT_counter
     ld tmp,Z
     inc tmp
     
     st Z,tmp
     andi status_reg,0b11110111
     fix: 
     ;out PORTD,status_reg
    ignore:
    
    ;****************** Zählen der ms RAM 100
      ldi r30,100
      ld tmp,Z
      inc tmp
      st Z,tmp
      cpi tmp,100 
      brlo mehr
      ldi tmp,0
      st Z+,tmp
    ;******************
    
    ;****************** Zählen der sec RAM 101
    
      ld tmp,Z
      inc tmp
      st Z,tmp
    
      cpi tmp,60
      brlo mehr 
      ldi tmp,0
      
      st Z,tmp
      inc r30
    ;****************** 
    
    ;****************** Zählen der min RAM 102
    
     ld tmp,Z
     inc tmp
     st Z,tmp
    
     cpi tmp,5
     brne ignore2
     sbr status_reg,0b00100000
     cbi PORTD,7
     ignore2:
    
     cpi tmp,60
     brlo mehr
     ldi tmp,0
     st Z,tmp
     inc r30
    ;******************
    
    ;****************** Zählen der Stunde RAM 103
     ld tmp,Z
     inc tmp
     st Z,tmp
     cpi tmp,25
     ldi tmp,0
     st Z,tmp
    ;******************
     mehr:
    ldi r30,100
     out SREG,sreg_save
    reti
    Chuck Norris kann Windows Vista auf einem Atmel in Assembler implementieren!
    Chuck Norris coded mit 3 Tasten:"1","0" und "compile"

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von Tido
    Registriert seit
    14.11.2006
    Ort
    OWL
    Alter
    48
    Beiträge
    622
    Hm,

    bei kommerziellen Produkten (bei allen meine Funkuhren) ist es genauso, obwohl da ja nicht "dein" Code drin läuft...
    MfG
    Tido

    ---------------------------------------------------
    Have you tried turning it off and on again???
    ---------------------------------------------------

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Bei den kommerziellen Uhren kommt die extra verzögerung zum Teil daher, das auf 2 gültige Signale gewartet wird um Fehler besser zu unterdrücken. Trotzdem macht einer meiner Wecker (und auch andere ähnliche) immer noch mal Fehler bei den Stunden.

    Es könnte sein das der Empfang nicht gut ist und daher das Bitmuster gelegentlich fehlerhaft ist. Leider können Röhren-Fernseher in der Nähe den Empfang leicht stören ( 5 x 15,75 kHz sind recht dicht bei 77 kHz).

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    Mir fällt grade auf, dass ich hätte präziser sein müssen.
    Auch wenn der <Empfänger schon länger lief und ich nur
    den µC resete passiert das gleiche, deswegen Suche ich den
    Fehler noch bei mir.

    mfg

Berechtigungen

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

Solar Speicher und Akkus Tests