Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Ds89C430 + Ds1307 = problem

07 Maj 2005 20:13 1431 4
  • Poziom 15  
    Witam
    Robie budzik na bazie ukladow jak w temacie. Na razie jest to wstepna wersja, w ktorej odczytuje tylko rejestry z sekundami i minutami, a nastepnie wyswietlam je (po odpowiedniej konwersji) na czterech mulipleksowanych wyswietlaczach siedmiosegmetnowych. Ale niestety czasami (srednio raz na 15 minut) wyswietlaja sie niekompletne cyfry - cyfra niby jest wlasciwa ale niektore segmenty nie zaswiecaja sie. Wyswietlacze sprzetowo powinny byc ok. - jesli w programie nie odczytuje danych z rtc a tylko wyswietlam wpisane na stale wartosci to nic sie nie krzaczy. Gdzie moze byc problem?

    Z gory dzieki za pomoc
    Pozdrawiam

    Code:

    wysw          equ P2         ;katody wyswietlaczy
    w1          equ P1.0      ;anody wyswielaczy
    w2          equ P1.1
    w3          equ P1.2
    w4          equ P1.3

    sw0         equ P3.6
    sw1         equ P3.7      ;przyciski
    sw2         equ P1.6
    sw3         equ P1.7

    SDA         equ P3.5      ;do obslugi i2c
    SCL         equ P3.4
    ram         equ 20h
    I2C_fault      equ ram.0
    I2C_busy      equ ram.1
    I2C_no_ack       equ ram.2
    I2C_ostatni_bajt   equ ram.3
    licznik_bitow_I2C   equ 41h


    opoz_w       equ 30h         ;zmienna do funkcji opozniajacej dla wyswietlaczy


    cyfra_1      equ 35h
    cyfra_2      equ 36h
    cyfra_3      equ 37h
    cyfra_4      equ 38h

    il_minut   equ 39h
    il_godz      equ 40h

    stos       equ 50h

    ;-------------------------------------------------------------------

    TH0_SET      EQU   238
    TL0_SET      EQU   0

    ;-------------------------------------------------------------------
       ORG   00h

       LJMP   RESET            ;przeskoczenie wektora przerwan

    ;-------------------------------------------------------------------
    ; Przerwanie Timer 0
       ORG   0BH

       mov TH0, #TH0_SET

       push psw
       push acc

       acall odczytaj_z_rtc

       acall przeksztalc

       acall wyswietl


       pop acc
       pop psw

    reti

    ;-------------------------------------------------------------------
    ; Przerwanie Timer 1   
       ORG   1BH

    ;-------------------------------------------------------------------
    ; Przerwanie Timer 2
       ORG    02Bh

    ;-------------------------------------------------------------------
    ; Program glowny
       ORG   100H
    RESET:

       mov sp, #stos         ;ustawienie wskaznika stosu

       mov wysw, #0         ;wstepne wygaszenie wyswietlacza
       mov dptr, #cyfry      ;adres tablicy ze wzorami cyfr

       mov cyfra_1, #0
       mov cyfra_2, #0
       mov cyfra_3, #0
       mov cyfra_4, #0

       mov il_minut, #0
       mov il_godz, #0


       mov TMOD, #11h         ; oba timery jako 16 bitowe,kontrolowane wewnetrznie
       mov TH0, #TH0_SET      
       setb ET0         ; zezwolenie na przerwanie od timer'a 1
       setb TR0         ; uruchomienie timer'a 1
       setb EA;


       jb sw0, loop         ;pominiecie zerowania - normalna praca

       acall zeruj   
       
       
    ;poczatek petli nieskonczonej

    loop:


    jmp loop



    ;-------------------------------------------------------------------
    ; funkcja opozniajaca dla wyswietlaczy
    czekaj_wysw:            
          
       mov r7, #100
       qqq:
       mov opoz_w, #30
       djnz opoz_w, $
       djnz r7, qqq

    ret
          

    ;-------------------------------------------------------------------
    wyswietl:

       setb w4            ;cyfra tysiecy                                                                                                                                                                                                                                                                                                                                                                                
       nop
       mov a, cyfra_4
       movc a, @a+dptr
       mov wysw, a
       clr w1
       acall czekaj_wysw

       setb w1            ;cyfra setek                                                                                                                                                                                                                                                                                                                                                                                     
             nop
       mov a, cyfra_3
       movc a, @a+dptr
       mov wysw, a
       clr w2
       acall czekaj_wysw


              setb w2            ;cyfra dziesiatek                                                                                                                                                                                                                                                                                                                                                                                  
             nop
       mov a, cyfra_2
       movc a, @a+dptr
       mov wysw, a
       clr w3
       acall czekaj_wysw


              setb w3            ;cyfra jednosci                                                                                                                                                                                                                                                                                                                                                                                   
             nop
       mov a, cyfra_1
       movc a, @a+dptr
       mov wysw, a
       clr w4
       acall czekaj_wysw

    ret

    ;-------------------------------------------------------------------
    ;odczyt danych z RTC
    odczytaj_z_rtc:

       ACALL I2C_START            
       jb I2C_fault, www

       MOV A, #11010000b         ;adres ukladu RTC w trybie do zapisu
       ACALL I2C_WRITE
       jb I2C_no_ack, www

       MOV A, #00h            ;wskaznik rej RTC na poczatek
       ACALL I2C_WRITE
       jb I2C_no_ack, www

       ACALL I2C_STOP   



       ACALL I2C_START   
       jb I2C_fault, www
          
       MOV A, #11010001b         ;adres ukladu RTC w trybie do odczytu
       ACALL I2C_WRITE
       jb I2C_no_ack, www

       MOV A,#0
       clr I2C_ostatni_bajt
       ACALL I2C_READ            ;odczyt sekund
       mov il_minut, a

       MOV A,#0
       setb I2C_ostatni_bajt
       ACALL I2C_READ            ;odczyt minut
       mov il_godz, a   
       
    www:

       ACALL I2C_STOP   

       
    ret

    ;-------------------------------------------------------------------
    ;przeksztalcenie odczytanych bajtow na liczby
    przeksztalc:

       mov a, il_minut      ;przeksztalcenie minut
       push acc
       
       anl a, #11110000b

       rr a
       rr a
       rr a
       rr a

       mov cyfra_2, a

       pop acc

       anl a, #00001111b

       mov cyfra_1, a      

    ;;;;;;;;;;

       mov a, il_godz         ;przeksztalcenie godzin
       push acc

       anl a, #11110000b

       rr a
       rr a
       rr a
       rr a

       mov cyfra_4, a

       pop acc

       anl a, #00001111b

       mov cyfra_3, a      
    ret

    ;-------------------------------------------------------------------
    ;procedura zerowania RTC po wymianie baterii
    zeruj:

       ACALL I2C_START            
       jb I2C_fault, zeruj

       MOV A, #11010000b         ;adres ukladu RTC + tryb zapisu
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;wskaznik rejestrow RTC na poczatek
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj


       MOV A, #0            ;start oscylatora (7bit) + sekundy
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;minuty
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;godziny (6bit-> 12/24godz)
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;dzien tygodznia
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;dzien miesiaca
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;miesiac
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;rok
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj

       MOV A, #0            ;rej sterujacy wyj SQWE
       ACALL I2C_WRITE
       jb I2C_no_ack, zeruj                                                                     

       ACALL I2C_STOP   
    ret

    ;-------------------------------------------------------------------
    ;tablica ze wzorami cyfr do wyswietlaenia, kolejnosc: 0-9, '1' zaswieca wybrany segment
    cyfry:
       db 00111111b
       db 00000110b
       db 01011011b
       db 01001111b
       db 01100110b
       db 01101101b
       db 01111101b
       db 00000111b
       db 01111111b
       db 01101111b


    $INCLUDE (I2C.A51)            ;plik z procedurami i2c

    end                  ;koniec programu


    Code:


    ;EXTERN SDA, SCL       ; linie portow pelniace funkcje szyny I2C

    ;EXTERN I2C_fault, I2C_busy, I2C_no_ack, I2C_ostatni_bajt   
                ; wskazniki stanu i bledow szyny

    ;EXTERN licznik_bitow_I2C   

    ;PUBLIC I2C_WRITE, I2C_READ, I2C_START, I2C_STOP


    ;===========================================================
    ; procedura pomocnicza - ustawia linie SCL w stan wysoki
    ; i czeka na zakonczenie ewentualnego przeciagania stanu
    ; niskiego przez urzadzenie podrzedne

    SCL_high:   
       SETB SCL      ; probuje wymusic wysoki stan linii SCL
            JNB SCL, $     ; i czeka na faktyczne przejscie SCL w stan wysoki
            RET


    ;===========================================================
    ; procedura wysylania sygnalu START szyny I2C

    I2C_START: 
       SETB I2C_busy   ; ustawienie wskaznika aktywnej transmisji I2C
            CLR I2C_no_ack  ; zerowanie wskaznikow bledow: braku potwierdzenia
            CLR I2C_fault   ; oraz                         blednego stanu szyny
            JNB SCL, fault  ; sprawdza poprawnosc stanu szyny i sygnalizuje
            JNB SDA, fault   ; ewentualny blad
            CLR SDA         ; poczatek sygnalu START
            CALL wait_5us
            CLR SCL
            CALL wait_5us   ; koniec sygnalu START
            RET
    fault: 
       SETB I2C_fault  ; ustawienie wskaznika bledu szyny
    RET             

       
    ;===========================================================
    ; procedura pomocnicza - wysyla sygnal STOP i zwalnia szyne

    I2C_STOP: 
       CLR SDA         ; wymusza stan niski na SDA
            CALL SCL_high   ; przygotowanie SCL (SCL w stan wysoki)
            CALL wait_5us   ; minimalne opoznienie
            SETB SDA        ; wlasciwe zbocze sygnalu STOP
            CALL wait_5us
            CLR I2C_busy    ; wyzerowanie wskaznika zajetosci szyny
    RET                 

    ;===========================================================
    ; procedura wysylania bajtu do urzadzen podrzednych
    ; bajt do wyslania w ACC
    ;    niszczy CY

    I2C_WRITE: 
       MOV licznik_bitow_I2C, #8   
    wr_loop:   
       RLC A           ; bit do wyslania do CY
            MOV SDA, C      ; i na linie SDA
            CALL SCL_high   ; zbocze narastajace SCL
            CALL wait_5us   ; odmierzenie minimalnego czasu wysokiego SCL
            CLR SCL      ; i zbocze opadajace SCL
            CALL wait_5us   ; zmow minimalny odstep czasowy
            DJNZ licznik_bitow_I2C, wr_loop
             ; powtarza petle, az wysle wszystkie bity
            SETB SDA        ; przygotowanie do odbioru bitu potwierdzenia
            CALL SCL_high   ; poczatek impulsu zegarowego dla bitu potwierdzenia
            CALL wait_5us
            JNB SDA, no_wr_ACK ; sprawdzenie, czy jest potwierdzenie, jesli nie
            SETB I2C_no_ack    ; to ustawiany jest odpowiedni znacznik
    no_wr_ACK:   
       CLR SCL         ; koniec impulsu zegarowego dla bitu potwierdzenia
            CALL wait_5us   
    RET


    ;===========================================================
    ; procedura odbierania bajtu od urzadzenia podrzednego
    ;
    ;    odebrany bajt zwracany jest w ACC
    ;
    ; UWAGA! wskaznik I2C_ostatni_bajt jest wykorzystywany do
    ; sygnalizacji konca odbioru danych brakiem potwierdzenia
    ; i musi zawierac "1", jesli odbierany bajt ma byc ostatnim
    ; odbieranym bajtem lub "0" w przeciwnym przypadku
    ;
    ;    niszczy CY

    I2C_READ:   
       MOV licznik_bitow_I2C, #8   ; trzeba odebrac 8 bitow
    rd_loop:   
       CALL SCL_high           ; zbocze zegara dla odbieranego bitu
            CALL wait_5us
            MOV C, SDA          ; odbierany bit z linii SDA do CY
            RLC A                 ; i jego wsuniecie do ACC
            CLR SCL         ; koncowe zbocze zegara odebranego bitu
            CALL wait_5us      ; minimalny odstep przed kolejnym bitem
            DJNZ licznik_bitow_I2C, rd_loop   
                ; jesli nie wszystkie bity, to skok
       MOV C, I2C_ostatni_bajt
       MOV SDA, C      ; stan bitu potwierdzenia na linie SDA
       CALL SCL_high           ; poczatek bitu potwierdzenia
            CALL wait_5us
            CLR SCL
            SETB SDA            ; koniec bitu potwierdzenia
            CALL wait_5us
    RET

    ;===========================================================
    ; procedura pomocnicza - generuje opoznienie ok. 5 us
    ;
    ; UWAGA! dopasowana do zegara 12 MHz, przy wiekszej lub
    ; wyraznie mniejszej fosc nalezy ja odpowiednio zmodyfikowac

    wait_5us:   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP     
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP     
       NOP   
       NOP   
       NOP   
       NOP     
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP     
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
       NOP   
    RET
  • Poziom 39  
    Nie będę się wiele rozwodził , ale Twój program - mówiąc delikatnie - jest niepoprawnie napisany , ponieważ jest to jedno wielkie przerwanie Timera0 zajmujące 100% "mocy" uC.
    Code:

    ; Przerwanie Timer 0
       ORG   0BH

       mov TH0, #TH0_SET         ;~4600 cykli do kolejnego przepełnienia.

       push psw
       push acc

       acall odczytaj_z_rtc           ;1258 cykli

       acall przeksztalc                ;30 cykli

       acall wyswietl                    ;~25650 cykli !!!!

       pop acc
       pop psw

    reti                                     ;licznik T0=578Fh



    Powinieneś przebudować program.

    Piotrek

    PS
    Tyle powiedział symulator dla proców rodziny MCS-51 :wink:
  • Poziom 15  
    A jak w takim razie ten program powinien ogolnie wygladac? Tzn. zeby dzialalo multiplesowanie wyswietlaczy + komunikacja z rtc i konwersja danych + docelowo sprawdzanie stanu przyciskow.

    Pozdrawiam
    Piotrek
  • Specjalista - oświetlenie sceniczne
    przyciski i multiplexowanie w przerwaniu, reszta w pętli głównej programu, niektóre operacje w pętli głownej mogą być wykonywane tylko po ustawieniu bitu w oibsłudze przerwania (np wykonanie tylko raz na sekunde)

    taki zabieg zdecydowanie odciąży procesor
  • Poziom 15  
    Witam

    Zmiana czasu dlugosci wykonania procedury obslugi przerwania niestety nie wystarczyla i uklad dalej co jakis czas sie wysypywal.
    Zastosowalem wiec "zwykly" atmelowski 89s52 i dostosowalem do niego opoznienie przy komunikacji i2c i uklad o dziwo dziala do dzis.
    Wszystkim ktorzy mieli jakies pomysly dziekuje.

    Pozdrawiam
    Piotrek