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

wyłącznik czasowy taki jak na klatce schodowej w AVR

emenemsbis 25 Sty 2005 13:09 2846 9
  • #1 25 Sty 2005 13:09
    emenemsbis
    Poziom 10  

    Potrzebny mi wylacznik czasowy, takie cos jak do swiatla na klatce schodowej. Czy ktos moze wie jak napisac taki program?? Mialby on byc na procesor atmel at90s8515, juz mam jeden program, ale napisany 'przestarzala' metoda. Zamieszczam go ponizej, moze wiecej wam to wyjasni. Potrzebuje miec to napisane w formie funkcji...hmmm...chyba nie jestem dobra w tlumaczeniu o co mi chodzi:P dobra, zamieszczam program i prosze o pomoc!!
    ;***************************************************************************
    ;
    ; wlacznik czasowy na klatce (port A)
    ; wlacznik ustawiony jest na 5 sekund
    ; w porcie A znajduje sie wlacznik
    ;
    ;***************************************************************************
    .include "8515def.inc"

    .def tmp =r16 ;rejestr ogolnego przeznaczenia

    ;***** Uzyte rejestry

    .def maska =r17 ;
    .def rs1 =r18 ;
    .def rs2 =r19 ; w wypisanych obok rejestrach bede trzymal
    .def rm1 =r20 ; minuty , godziny , sekundy
    .def rm2 =r21
    .def rg1 =r22
    .def rg2 =r23
    .def swiatlo =r24 ; jesli w rejestrze jest 1 swiatlo jest zapalone
    ; jesli 0 zgaszone

    .cseg ; segment kodu
    .org 0
    rjmp reset ;Reset
    reti ;nie uzywane przerwania

    .org $0002
    reti ;nie uzywane przerwania

    .org $0005
    rjmp irq_tim1 ;internal TIM1 interrupt handler

    ;** przewanie od zegara TIM1
    irq_tim1:
    sei
    ldi tmp,$80
    out TCNT1H,tmp ; wpisz 80
    set ; T=1
    reti

    ;** nastwa parametrow zegara TIM1
    tim1_init: nop
    ldi tmp,$00 ; wart. poczatkowa F0
    out TCNT1H,tmp
    ldi tmp,$03 ; 1/2/3/4 - 1/8/64/256/1024
    out TCCR1B,tmp ; przy zegarze 4MHz okolo 1 s
    ldi tmp,$80 ; aktywne przerwanie TIM1
    out TIMSK,tmp ; 80
    ret


    ;*** Reset

    reset:
    clr rs1 ;czyszcze rejestry
    clr rs2
    clr rm1
    clr rm2
    clr rg1
    clr rg2
    clr maska
    clr swiatlo

    sbi ACSR,ACD ;wylacz komparator analogowy
    ldi tmp,low(RAMEND) ; adres stosu SPL
    out SPL,tmp ;
    ldi tmp,high(RAMEND) ; adres stosu SPH
    out SPH,tmp ;
    rcall tim1_init ; TIMER 1 - ustawienia
    cli ;zeruj pzrerwania
    ldi tmp,0xFF ;inicjacja port B jako wyjscie
    out DDRB,tmp
    clr tmp ; zeruj rejestr r16
    out PORTB,tmp ; wysli 0 na port B
    clr maska




    clr tmp
    out PORTA,tmp ;wyslij 0 na port A
    set ; ustaw T w 1 kroku
    sei ; uaktywnij przerwanie

    wroc:
    ldi swiatlo,0x00 ; swiatlo wylacz
    sbis PINA,0x00 ; jesli wcisniety przycisk 1
    brne wroc ; to idz dalej
    powtorz:
    brts idz ; T=1 - idz dalej
    rjmp powtorz ; opoznienie od TIM 1
    idz: clt ; zeruj T

    inc rs1
    licz:
    ldi swiatlo,0x01 ; wlacz swiatlo
    cpi rs1,0x0a ; w ponizszych operacjach testuje wartosci
    breq dodaj_s2 ; odpowiednich rejestrow
    cpi rs2,0x06 ; jesli np wartosc rejestra jednostek
    breq dodaj_m1 ; sekund przekroczy wartosc 9 to
    cpi rm1,0x0a ; wtedy zwieksza sie wartosc dziesiatek
    breq dodaj_m2 ; sekund a zeruje sie wartosc jednostek

    rcall ustaw_1
    out PORTB,rs1
    or rs1,maska
    out PORTB,rs1
    andi rs1,0x0F
    nop
    out PORTB,rs1

    rcall ustaw_2
    out PORTB,rs2
    or rs2,maska
    out PORTB,rs2
    andi rs2,0x0F
    nop
    out PORTB,rs2

    rcall ustaw_3
    out PORTB,rm1
    or rm1,maska
    out PORTB,rm1
    andi rm1,0x0F
    nop
    out PORTB,rm1

    rcall ustaw_4
    out PORTB,rm2
    or rm2,maska
    out PORTB,rm2
    andi rm2,0x0F
    nop
    out PORTB,rm2

    cpi rs1,0x05 ;jesli minie 5 sekund wylacz swiatlo
    breq wroc

    rjmp powtorz ;powrot do poczatku programu

    ; **********************
    delay1:
    ldi r19,4 ;
    de1: dec r19
    brne de1
    ret ;funkcje ustawiajace maske ktore sa
    ;wielokrotnie wywolywane
    ustaw_1:
    ldi maska,0x80
    ret

    ustaw_2:
    ldi maska,0x40
    ret

    ustaw_3:
    ldi maska,0x20
    ret

    ustaw_4:
    ldi maska,0x10
    ret

    dodaj_s2: ;tu sa funkcje zerujace i zwiekszajace
    clr rs1 ;dane w odpowiednich rejestrach
    out DDRA , tmp
    clr tmp ;w tej pierwszej petli jest tez funkcja
    ldi tmp,0xff ;wysylajaca dane na portA
    out PORTA , tmp ;dane sa wysylane co 10 sekund
    inc rs2
    rjmp licz
    dodaj_m1:
    clr rs2
    inc rm1
    rjmp licz
    dodaj_m2:
    clr rm1
    inc rm2
    rjmp licz

    0 9
  • #2 25 Sty 2005 13:31
    GienekS
    Poziom 32  

    Jeżeli ma to być Twoje rozwiązanie to musisz wiedzieć co i gdzie ma być podłączone i jak to ma działać, wtedy można się zabierać za pisanie programu.
    Czyli reasumująć schemat + algorytm i już można pisać program bo tak w powietrzu to trochę niebardzo.

    0
  • #3 25 Sty 2005 13:38
    emenemsbis
    Poziom 10  

    ale wlasnie ja nie bardzo wiem jak sie za to zabrac;] a jesli chodzi o to co ten program ma robic, to ma byc takim wylacznikiem czasowym, np ustawic czas na 5 sec, wlaczyc i po 5 sec sie wylacza. No i zeby to bylo mozna ten czas regulowac. Ale to akurat jest najmniejszy problem, tak mi sie przynajmniej wydaje :? no i ma byc napisane w AVR na procesro at90s8515, ale o tym to chyba juz pisalam. Jak juz wspomnialam ten program ktory zamiescilam jest dobry, ale niestety nie zostal dopuszczony do zaliczenia, poniewaz wykladowca stwierdzil ze jest robiony przestarzala metoda...i ma to byc zrobione w formie funkcji

    0
  • #4 25 Sty 2005 15:50
    Zbych_
    Poziom 24  

    Kiedyś zrobiłem coś takiego dla s1200, 2313 itp. Jak chcesz to sobie przerób. Program odmierza czas, a po jego upłynięciu zaczyna migać żarówką (np wyłącza ją na 1s, potem zapala na 10s i tak 3 razy), a na koniec gasi żarówkę. Program nie jest jakoś super napisany, ale z tego co pamiętam działał. Do asemblacji radziłbym użyć oryginalnego assemblera ze strony atmela.

    Code:

    ;*********************************************************************************
    ;                Program do obslugi wylacznika klatkowego
    ;
    ;Sprzet:
    ;   1) wlacznik - aktywny stanem niskim Port D.0
    ;   2) zarowka  - wlaczana stanem niskim na porcie D.1
    ;
    ;Sposob dzialania:
    ;   1) lampa jest uruchamiana nacisnieciem przycisku
    ;   2) w kazdej chwili czas swiecenia mozna wydluzyc
    ;   3) po uplynieciu czasu swiecenia swiatlo zaczyna ostrzegawczo migac
    ;      tzn gasnie na 1s i zapala sie na 10s, cykl ten powtarza sie 3 razy
    ;   4) jesli w czasie trwania ostrzezenie przycisk nie zostanie nacisniety
    ;      swiatlo jest gaszone
    ;   5) stan przycisku jest probkowany wielokrotnie (min 5 razy), aby uniknac zaklocen
    ;
    ;Wymagania:
    ;   procesor min. 90S1200 - trzeba recznie usunac ustawianie stosu - ten @#$%#%$@ asembler nie ma kompilacji warunkowej
    ;
    ;*********************************************************************************

    .include "2313def.inc"


    ; ******* NASTAWY CZASÓW ***************
    .equ LongTime   = 10*60*20            ; czas swiecenia lampy w jedn. 50ms - 10 minut
    .equ ShortTime   = 10*20               ; krotki czas swiecenia jedn. 50ms - 10 sekund
    .equ OffTime   = 1*20               ; czas przerwy w jedn 50ms   - 1 sekunda
    .equ NumOfWarn   = 3                  ; liczba powtorzen ostrzezenia


    ;----- Stale ---------------------------
    .equ IntDelay   = 256-1               ; czas ~50ms przy zegarze 1MHz i preskalerze 1024
    .equ Presc      = 5                  ; preskaler 1024
    .equ MinPrTime   = 2                  ; minimalny czas trzymania przycisku (w jedn. 50ms)
    ;----- Definicje linii -----------------
    .equ SwPort      =   PIND
    .equ SwPin      =   0               ; port i numer linii przelacznika
    .equ LampPort   =   PORTD
    .equ LampPin   =   1               ; port i numer linii zarowki
    ;----- Rejestry ------------------------
    .def Counter   =    r14
    .def SwTime      =    r15               ; licznik czasu wlaczenia przycisku
    .def itemp2      =   r16
    .def temp      =   r17               ; rejestr pomocniczy
    .def itemp      =   r18               ; tmp dla przerwania
    .def History   =   r19
    ;rejestry 16 bitowy do odmierzania czasu
    .def Time      =   r30 ; rejestr Z      ; licznik czasu
    .def TimeH      =   r31
    .def TimeL      =    r30

    ;***************************************
    ;   Makra

    .Macro   LampOn                     ; Wlaczanie zarowki
          cbi LampPort,LampPin
    .endm

    .Macro   LampOff                     ; Wylaczanie zarowki
          sbi LampPort,LampPin
    .endm

    .Macro IsTimeZero                  ; sprawdz czy liczba 16 jest zerem
          mov temp,TimeH
          or  temp,TimeL
    .endm

    .Macro LoadTime
          ldi TimeH,high(@0)
          ldi TimeL,low(@0)
    .endm
    ;***************************************
    .cseg
    ;---------------------------------------
    Reset:
          rjmp Start
    .db "Zbych 2003"
    ;---------------------------------------
    .org OVF0addr                     ; ~50ms przerwanie
          in itemp,SREG               ; zapamietaj rejestr stanu
    ; przeladuj timer
          ldi itemp2,IntDelay
          out TCNT0,itemp2            ;; zaladuj timer
    ; Obsluga odmierzania czasu
          mov itemp2,TimeH
          or  itemp2,TimeL
          breq NoDelay
          sbiw Time,1                  ; jesli !=0 to zmniejsz
    NoDelay:
    ; Obsluga przycisku
          sbic SwPort,SwPin            
          rjmp SwRel                  ; skocz jesli przycisk jest puszczony
          tst History                  ; sprawdz czy przycisk byl juz wcisniety wczesniej
          brne SwEnd
          tst SwTime                  ; czy minal minimalny czas ?
          breq MinTimeOut
          dec SwTime                  ;; jesli nie minal czas to zmniejsz licznik
          rjmp SwEnd
    MinTimeOut:
          ori itemp,$40               ; jesli minal czas to ustaw flage - przycisk wcisniety
          ori history,1               ; ustaw flage
          rjmp SwEnd
    SwRel:   
          ldi itemp2,MinPrTime         ;; jesli przycisk puszczony to ustaw czas
          mov SwTime,itemp2
          andi itemp,~($40)            ;; zeruj bit oznaczajacy wcisniecie przycisku
          clr History
    SwEnd:
          out SREG,itemp               ;; odtworz rejestr stanu
          reti
    ;========================================
    Start:
    ; inicjacja peryferiów
          ldi temp,RAMEND               ;; !!!! usunac te 2 linie jesli CPU==90S1200
          out SPL,temp               ;; ustaw stos na koniec      
    ; WatchDog
          ldi temp,$0E               ;; wlacz watchdoga, przepelnienie co 0.97s..3s
          out WDTCR,temp
    ; Porty
          ldi temp,$FF               ;; wyjscia w stanie wysokim, wejscia z podciaganiem
          out PORTD,temp
          ldi temp,0b00000010            ;; bit 1 wyjscie, bit 0 wejscie
          out DDRD,temp               ;; ustaw kierunek linii
    ; Timer 0
          ldi temp,IntDelay
          out TCNT0,temp               ;; zaladuj timer
          ldi temp,Presc
          out TCCR0,temp               ;; ustaw preskaler
          ldi temp,1<<TOIE0
          out TIMSK,temp               ;; odpal przerwanie z timera 0
          sei                        ;; odpal przerwania
    ; Tryb oszczedzania energii
          ldi temp,1<<SE
          out MCUCR,temp               ;; pozwól na tryb idle
    ; ========== Program glowny ============
    Idle:
          wdr                        ;; Azor ! jestes tam ?
          sleep                     ;; uspij procesor
          LampOff                     ;; wylacz lampe
          brtc Idle
    SwOn:
          clt                        ;; zgas flage zapalenia przycisku
          LampOn                     ;; wlacz lampe
          LoadTime LongTime            ;; zaladuj czas swiecenia, synchronizacja wpisu poprzednim sleepem
          
    OnLoop:
          wdr                        ;; zobacz co robi Azor
          sleep                      ;; uspij procesor
          brts SwOn                  ;; jesli przycisk wcisniety to przedluz czas
          IsTimeZero                  ;; czy koniec czasu ?
          brne OnLoop                  ;; czy skonczyl sie czas ?
    ; Ostrzezenia przy gaszeniu swiatla
    Warnings:
          ldi temp,NumOfWarn
          mov Counter,temp            ;; zaladuj licznik iloscia ostrzezen
    WarnMainLoop:      
          LampOff                     ;; wylacz swiatlo
          LoadTime OffTime            ;; zaladuj czas zgaszonego swiatla, synchronizacja wpisu z przerwanie jest zapewniona przez poprzedniego sleepa
    WarnOffLoop:
          wdr                        ;; daj jesc Azorowi
          sleep                      ;; spac !!
          brts SwOn                  ;; czy przypaletal sie jakis czlek ?
          IsTimeZero                  ;; czy koniec czasu ?
          brne WarnOffLoop      

          LampOn                     ;; wlacz swiatlo
          LoadTime ShortTime            ;; synchronizacja zmiany za pomoca poprzedniego sleepa
    WarnOnLoop:
          wdr                      ;; pobaw sie z Azorem
          sleep                     ;; uspij procesor
          brts SwOn                  ;; jesli przycisk nacisniety to zapal skok
          IsTimeZero
          brne WarnOnLoop

          dec Counter                  ;; zmniejsz licznik ostrzezen
          brne WarnMainLoop            ;; jesli !=0 to powrot do petli
          rjmp Idle                  ;; wroc na poczatek programu
    ;***************************************

    0
  • #5 26 Sty 2005 14:01
    emenemsbis
    Poziom 10  

    Wow, dzieki, ale chyba nie jestem na tyle genialna :wink: Ja nawet nie wiem o jaka metode temu facetowi chodzi ze mam to napisac w postaci funkcji...na cw zawsze robilismy takim sposobem programy i mu zawsze pasowalo, a tu nagle nie chce przyjac programu bo mowi ze to przestarzala metoda wyskakuje z tekstem ze ma to byc w formie funkcji :( ...i co ja mam biedna zrobic??

    0
  • #6 26 Sty 2005 15:50
    mcy
    Poziom 15  

    W formie funkcji oznacza jak najmniej rjmp a jak najwięcej rcall lub call:)
    A tak poważnie to facetowi chodzi o podział funkcjonalny aplikacji, czyli zamknięcie powtarzalnych czynności w bliki, które można dowolnie często wywoływać. Ogólnie zasada programowania jest taka, że jeżli dany kod (kilka instrukcji) powtarza się więcej niż 2 razy w całości programu to zamyka się go w fuknkcję. Dotyczy to programowania nie tylko na uK ale dla dowolnego środowiska.

    Pozdrawiam

    0
  • #7 26 Sty 2005 16:01
    emenemsbis
    Poziom 10  

    hmmm...jestem baaardzo poczatkujaca jesli chodzi o assemblera...teoretycznie to co napisales to w miare zrozumialam (na szczescie, bo juz zaczelam myslec ze jakas tepa jestem :] )ale jak to zastosowac w praktyce?? Oto jest pytanie :( ....moze jakis przykladzik albo cos w tym stylu??

    0
  • #8 26 Sty 2005 20:40
    cyberdar
    Poziom 31  

    A w jaki sposób podłączony jest układ do sieci ? Czy jest to podłączenie szeregowo z żarówką czy ma zasilanie osobne. Pytam, bo pierwsze rozwiązanie stanowi pewien problem :)

    0
  • #9 26 Sty 2005 20:46
    emenemsbis
    Poziom 10  

    A jaki problem?? Bo tak szczerze to nie wiem, bo u nas na stanowisku nawet zarowki nie ma:] sa tylko diody, wyswietlacz lcd i klawiatura 4x4...i podlaczamy to do com1 albo com2:] ten program ma tylko symulowac...

    0
  • #10 26 Sty 2005 23:47
    mcy
    Poziom 15  

    Jeśli jesteś początkująca, to polecam stronkę:
    www.avrbeginners.net
    opisane wszystkie zasoby uK AVR wraz z przykładami (bardzo dobry opis)
    Co prawda po angielsku, ale jak któś programuje, to musi sie nauczyć tego języka.

    0