logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATtiny2313][asm] - zegarek i wyświetlacze 7-segmentowe

grysek 23 Sie 2009 20:54 5818 26
REKLAMA
  • #1 6926623
    grysek
    Poziom 19  
    Witam

    Napisałem program zegarka na ATiny2313, wyświetlacze sterowane są pokolei. Wyświetlacze mają wspólną anodę a katodami podpięte są do portu B, natomiast anody kolejnych wyswietlaczy przez tranzystory do kolejnych pinów portu D. (tak jak na schemacie). Wszytko działa poprawnie ale kiedy na ostatnim (6) wyświetlaczu pojawi się cyfra 1 lub 7 to wszystkie wyświetlacze świecą jaśniej - zupełnie nie wiem czemu. Jest to denerwujące ponieważ co kilka sekund widać jak zegarek świeci jaśniej a potem znowu ciemno. Fragment programu poniżej. Proszę o pomoc w rozwiązaniu problemu.

    [ATtiny2313][asm] - zegarek i wyświetlacze 7-segmentowe

    petla:
    
    ldi acc, 0x00
    out PORTD, acc
    mov stan, acc
    sec
    rol stan                ;wyswietl dziesiatki godzin
    add adr, hour_h
    mov r26, adr
    ld acc,  x
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60
    
    rol stan                ;wyswietl godziny
    add adr, hour_l
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc        
    ldi adr, 0x60 
    
    rol stan                 ;wyswietl dziesiątki minut
    add adr, min_h          
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rol stan
    add adr, min_l           ;wyswietl minuty
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rol stan                 ;wyswietl sekundy
    add adr, sec_h
    mov r26, adr            
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rol stan
    add adr, sec_l
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rjmp petla
  • REKLAMA
  • #2 6926749
    Konto nie istnieje
    Poziom 1  
  • #3 6926757
    kwesoly
    Poziom 15  
    Jeśli to jest pełny a nie symboliczny schemat to zapewne brakuje rezystorów ograniczających prąd segmentów - ogranicza go biedny uC i źródło zasilania. 1 lub 7 to 2 lub 3 segmenty z 7 więc dostają więcej prądu -> świecą jaśniej.
  • #4 6926771
    crazy_phisic
    VIP Zasłużony dla elektroda
    atom1477 napisał:
    Litości.
    A o rezystorach kiedyś słyszałeś?
    A o opóźnieniach w pętli programu?

    Akurat nie wyjaśnia to takiego zachowania się układu, ale od tego bym zaczął.


    Wyjaśnia ;) tylko autor musi sam to sprawdzić.
  • #5 6928118
    grysek
    Poziom 19  
    Nie wyjaśnia. Rezystory w rzeczywistości są a schemat narysowałem po to aby wiadomo było gdzie co jest podpięte.

    kwesoly - tez tak myślałem ale później doszedłem do wniosku że przecież gdyby tak było to:
    1. tylko ostatnia cyfra powinna świecić jaśniej a nie wszystkie wyświetlacze
    2. działo by się to kiedy na innych wyświetlaczach też by była 1 lub 7. A teraz jest tak że tylko wtedy kiedy na ostatnim wyświetlaczu jest 1 lub 7. Kiedy jest na pozostałych to działa ok.

    Po tym wywnioskowałem ze problem musi być gdzieś w pętli programu tylko nie mam pojęcia gdzie?

    atom1477 - po co opóźnienia?
  • #6 6928875
    zumek
    Poziom 39  
    grysek napisał:
    ...Po tym wywnioskowałem że problem musi być gdzieś w pętli programu tylko nie mam pojęcia gdzie?


    Z tego kawałeczka kodu co nam pokazałeś, też trudno wywnioskować przyczyny Twoich ... kłopotów :|
  • REKLAMA
  • #7 6928998
    Konto nie istnieje
    Poziom 1  
  • #8 6930554
    grysek
    Poziom 19  
    Rzeczywiście masz rację poświata występuje. Myślisz ze opóźnienie wystarczy?
    Próbowałem też zrobić tak:
    PORTB = cyfra1 -> PORTB = 0xFF -> zapal kolejny wyśw. -> PORTB = cyfra2 .. itd.
    Tak aby podczas zmiany wyświetlaczy nie była wyświetlana żadna cyfra, i w rzeczywistości wyświetlało dobrze, lecz gdy Timer1 zgłosił przerwanie i nastąpił skok do obsługi przerwania wszystkie wyświetlacze przygasały :/

    Ale nadal nie rozwiązuje to probemu głównego :| Ma ktoś jeszcze jakiś pomysł?

    Oto listing całego programu (bez definicji):

    .dseg
    .org 0x60
    data: .byte 10
    
    .cseg
    .org 0 
    rjmp init
    .org OVF1addr
    rjmp Timer1
    
    init:
    ldi acc, RAMEND
    out SPL, acc
    
    ldi adr, 0x60
    ldi acc, 0b01111100 ;przepisz znaki do pamieci RAM
    sts 0x61, acc
    ldi acc, 0b00010010
    sts 0x62, acc
    ldi acc, 0b00011000
    sts 0x63, acc
    ldi acc, 0b00101100
    sts 0x64, acc
    ldi acc, 0b00001001
    sts 0x65, acc
    ldi acc, 0b00000001
    sts 0x66, acc
    ldi acc, 0b01011100
    sts 0x67, acc
    ldi acc, 0b00000000
    sts 0x68, acc
    ldi acc, 0b00001000
    sts 0x69, acc
    ldi acc, 0b01000000
    sts 0x60, acc
    ;Konfiguracja portów i timera
    ldi acc, 0b01111111
    out DDRB, acc
    ldi acc, 0b00111111
    out DDRD, acc
    ldi acc, 0b01000000
    out PORTD, acc
    ldi acc, 0xFF
    out PORTB, acc
    ldi acc, Timsk_data
    out TIMSK, acc
    sei
    ldi acc, Timer_control
    out TCCR1B, acc
    ldi acc, low(Timer_data)
    out TCNT1L, acc
    ldi acc, high(Timer_data)
    out TCNT1H, acc
    
    petla:
    
    ldi acc, 0x00
    out PORTD, acc
    mov stan, acc
    sec
    rol stan                ;wyswietl dziesiatki godzin
    add adr, hour_h
    mov r26, adr
    ld acc,  x
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60
    
    rol stan                ;wyswietl godziny
    add adr, hour_l
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc        
    ldi adr, 0x60 
    
    rol stan                 ;wyswietl dziesiątki minut
    add adr, min_h          
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rol stan
    add adr, min_l           ;wyswietl minuty
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rol stan                 ;wyswietl sekundy
    add adr, sec_h
    mov r26, adr            
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rol stan
    add adr, sec_l
    mov r26, adr
    ld acc, X
    out PORTD, stan
    out PORTB, acc
    ldi adr, 0x60 
    
    
    rjmp petla
    
    
    Timer1:
    push zl
    push zh
    ldi acc, low(Timer_data)
    out TCNT1L, acc
    ldi acc, high(Timer_data)
    out TCNT1H, acc
    sbis PINB, 7
    inc min_l
    sbis PIND, 6
    inc hour_l
    inc sec_l
    cpi sec_l, 10
    brne T1_0
    clr sec_l
    inc sec_h
    T1_0:
    cpi sec_h, 6
    brne T1_1
    clr sec_h
    inc min_l
    T1_1:
    cpi min_l, 10
    brne T1_2
    clr min_l
    inc min_h
    T1_2:
    cpi min_h, 6
    brne T1_3
    clr min_h
    inc hour_l
    T1_3:
    cpi hour_l, 4
    brne T1_4
    cpi hour_h, 2
    brne T1_4
    clr hour_l
    inc hour_h
    T1_4:
    cpi hour_l, 10
    brne T1_5
    clr hour_l
    inc hour_h
    T1_5:
    cpi hour_h, 3
    brne end
    clr hour_h
    end:
    pop zl
    pop zh
    reti
    
  • #9 6930676
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #10 6943229
    grysek
    Poziom 19  
    Jakie opóźnienie powinienem dać pomiędzy kolejnymi wyświetlaczami? Coś rzędu 200us czy może wystarczy kilka "nop"? Jaka częstotliwość bedzie najlepsza?
  • #11 6943423
    Konto nie istnieje
    Poziom 1  
  • #12 6950637
    grysek
    Poziom 19  
    Rzeczywiście atom1477 masz racje opóźnienia rozwiązały problem poświaty na poszczególnych wyświetlaczach:D

    Niestety dalej nie pomogło w problemie głównym i jeszcze doszedł 2 problem. Nie mam pojecia dlaczego w sekundach omija mi liczbę 4 :| jest 3 a zaraz potym 5, dziwne, przeciez oprócz opoźnien program wogóle się nie zmienił.

    Co może być nie tak?
  • #13 6950851
    Konto nie istnieje
    Poziom 1  
  • #14 6951577
    grysek
    Poziom 19  
    Ten fragment kodu odpowiedzialny jest za ustawianie godzin i minut.
    > jeśli stan PINB.7 jest równy 0 to zwiększ godzinę o jeden.
    > jeśli stan PIND.6 jest równy 0 to zwiększ minuty o jeden.

    Natomiast jeśli obydwa bity są ustawione to instrukcje zwiększania są omijane.

    Ale naszczeście głowny problem już rozwiązałem :D Tkwił on w kondensatorze filtrującym zasilanie - był on za mały ale dałem większy i działa ok :D

    Chciałbym jeszcze zrobić aby godzina była zapisywana do EEPROM, tak aby podczas kiedy zabraknie zasilania była zapisana godzina o której zabrakło energii. I tutaj rodzi sie kolejny problem bo z tego co wiem to EEPROM jest strasznie wolny przy zapisie. Ma ktoś propozycje jak to zrealizować aby nie było widać mrugnięcia? A może zrobić jakieś podtrzymanie zasilania?
  • #15 6953484
    kwesoly
    Poziom 15  
    Podtrzymanie zasilania na bateryjce zrabialne, trzeba by tylko wyłączać wyświetlacze bo te LEDy ci zjedzą baterię. Z tego co tutaj już przeczytałem (na forum) wynika że problemem są jeszcze resety procka związane np z zakłóceniami - a to już większy problem.

    Odnośnie EEPROMu to jeszcze dojdzie problem ilości zapisów.

    grysek napisał:

    Ale naszczeście głowny problem już rozwiązałem :D Tkwił on w kondensatorze filtrującym zasilanie - był on za mały ale dałem większy i działa ok :D

    Gdybyś poświęcił się z normalnym schematem dowiedziałbyś się tego wcześniej :)
  • REKLAMA
  • #16 6953598
    Konto nie istnieje
    Poziom 1  
  • #17 6955023
    grysek
    Poziom 19  
    Ale jak to do przerwania? Przeciez przerwanie generowane jest co 1 sek a wyświetlanie musi być cały czas. Wyjaśnij co dokładnie masz na myśli? :|
  • #18 6955399
    Konto nie istnieje
    Poziom 1  
  • #19 6956832
    grysek
    Poziom 19  
    Rzeczywiście pomysł jest dobry, ale skoro przerwanie było by generowane co 400us a zapis do EEPROM moze trwać nawet kilka ms, to znacznie za długo bo procesor nie zdąży zapisac danych kiedy wystąpi przerwanie? Tak że zapis bedzie cały czas przerywany nie?
    A i musiałbym zliczać przerwania az do jednej sekundy. Czyli przy przerwaniu co 400us musiałbym zliczać aż do 2500 i wtedy bedzie jedna sekunda. Trochę to kłopotliwe.
    Niestety po dłużesz obserwacji zegarka zauważyłem jeszcze jeden problem - znacznie się spóźnia. Na 8 godzinach spoźnia się 3 minuty

    Wg moich obliczen wynika że: 8000000Hz (taktowanie) \ 256 (preskaler) = 31250 taktów musi zliczyć Timer aby trwało to sekundę. 65536 - 31250 = 34286 a taką wartość wpisuje do Timera1. Czy dobrze to wyliczyłem?

    A i do tego dochodzi jeszcze czas jaki zajmuje zgłoszenie przerwania, skok do jego obsługi, i jego przeładowanie czyli 14 cykli, tak więc przy zegarze 8Mhz tyle cyki trwa zaledwie około 2us więc chyba nie możliwe aby z tego powodu było aż takie opóźnienie prawda? :|
  • Pomocny post
    #20 6957535
    Konto nie istnieje
    Poziom 1  
  • #21 6957635
    grysek
    Poziom 19  
    Attiny tyka na wewnętrznym kwarcu 8Mhz bez dzielnika przez 8. No ale te 2us to jest czas w którym Timer nie zlicza (znaczy zlicza ale od zera, akiedy wpisze mu nową wartość to liczy tak jakby od nowa) no więc te 2us jest dodawane do każdej sekundy co nie?
    No niby jest sprzetowo ale zeby wszystkie dane móc zapisac na raz to trzeba trochę czasu, chyba zebym zapisywał dane po zmianie (czyli np godziny nie cały czas tylko jak przeskoczy z 18 na 19). Ok pomyślę na tym teraz najważniejsze jest żeby dobrze chodził, z tym EEPROM to dalsza bajka.
  • #22 6957692
    Konto nie istnieje
    Poziom 1  
  • #23 6958327
    grysek
    Poziom 19  
    No masz rację złego słowa użyłem :p Ale jak dam rezonator zewnętrzny to wtedy timer bedzie dokładniejszy? To rozwiąże problem?

    Już rozumiem o co Ci chodzi z tym preskalerem :D rzeczywiście nie spojrzałem na to z tej strony, czyli w tym czasie moge miec duzo wiecej instrukcji żeby tylko trwały mniej niż 255 cykli nie?

    A co do datasheetu to juz studiowałem go milion razy a na zegar systemowy nigdy nie zwróciłem uwagi ;p
  • #24 6958726
    Konto nie istnieje
    Poziom 1  
  • #25 6967439
    grysek
    Poziom 19  
    Tak też postanowiłem zrobić że dam kwarc 12MHz. Lecz mam programator ISP czyli jeśli ustawie fusebit A897 na 0000 External Clock to nie bede mógł zaprogramować procesora moim programatorem. Ale wymyśliłem że zrobię generator i podłącze go do XTAL1 i rzeczywiście podziałało a procesor zaprogramował się.
    Ale niestety procesor w rzeczywistoście nie działa co moze byc nie tak?

    Rezonator podpiąłem do XTAL1 i XTAL0 i przez kondensatorki 47pF do masy
  • Pomocny post
    #26 6967772
    szelus
    Poziom 34  
    Eh, może byś bardziej dokładnie czytał DS?
    Nie "External Clock" (chyba, że chcesz zostawic ten generator na stałe ;)), tylko "External Crystal"; plus tabelka 4, co daje wynik "1111".
    47p to trochę za dużo, też tabelka 4.
  • #27 6972874
    grysek
    Poziom 19  
    Rzeczywiście masz racje :D Dzieki za pomoc, wszystko juz działa ok - no poza pojedyńczymi zapaleniami się na wyświetlaczach przypadkowych segmentów, ale z tym rozprawię się już sam :D

    Dzieki wszystkim za pomoc !!
REKLAMA