Skocz do zawartości
mystery

program pod dsm8051

Rekomendowane odpowiedzi

witam, jest to moj pierwszy post, czyli jestem tu nowym noobkiem :P

dopiero zaczynam zapoznawać się z tym forum, więc nie jestem pewien czy w odpowiednim miekscu umieściłem ten temat, jeśli w złym to niech admin przeniesie tam gdzie trzeba, byle nie do kosza :)

mam mały problem i w związku z tym szukam małej pomocy. nie chcę żeby ktoś za mnie pisał program a jedynie mi doradził co nieco jeśli oczywiście jest to możliwe. do rzeczy

muszę napisać program pod mikrokontroler 8051, język programy pisze się w assemblerze, ale trzeba znać odpowiednią listę rozkazów, zresztą ten kto miał styczność z tym sprzeten kiedykolwiek wie o co come on :)

treść programu:

po uruchomieniu program ma zmierzyć czas reakcji jaki upłynią od zapalenia diody do wciśnięcia przycisku podłączonego z zewnątrz (wejście INT0 lub INT1) i czas wyśletlić na ekranie LCD lub siedmiosegmentowym. trzeba wykorzystać oczywiście przerwania i układ czasowo licznikowy. mój problem tkwi w tym jak poprawnie zaprogramować przerwanie oraz sam licznik.

jak widać program nie jest aż tak trudny, ale jestem poczatkujący więc jeszcze nie kumam wszystkiego.

korzystałem z opcji szukania, ale nic nie znalazłem konkretnego :P

jeśli ktoś jest w stanie mi pomóc to byłbym bardzo wdzięczny :)

pozdro :)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

To ja może spróbuje pomóc, chociaż sam niedawno zaczołem programowanie w Assemblerze.

Żeby obsłużyć przerwanie trzeba pierw zezwolić na przerwanie programując odpowiedni rejestr. Tym rejestrem jest IE. Opis najczęściej używanych rejestrów mam nadzieje masz pod ręką bo bez tego ani rusz. Żeby zezwolić na przerwanie INT1 do IE trza wysłać #84H czyli MOV IE,#84H żeby INT0 zezwolić trza wysłać MOV IE,#81H. Jeśli wystąpi dane przerwanie to procek szuka obsługi przerwania pod odpowiednim adrsem (tabelka przerwań i ich adresów także powinna być pod reką). INT0 ma adres 0003H, a INT1 0013H. Czyli żeby obsłużyć przerwanie trza umieścić instrukcje pod danym adresem. Musisz jeszcze wiedzieć od jakiego adresu możesz zacząć pisać instrukcej. Najczęsciej jest to 2000H i teraz przykładzik:

 

CSEG AT 2000H;adresowanie od 2000HSJMP USTAW   ;skok bezwarunkowy do etykiety ustaw gdzie programuje procka, liczniki itdORG 2003H    ;obsluga przerwania INT0SJMP PRZERW  ;skok bezwarunkowy do etykiety przerw, moga ty byc instrukcje ale za duzo ich nie moze byc bo mozna wejsc na adres nastepnego przerwaniaUSTAW:MOV TMOD, #01H ;programowanie licznikówMOV IE,#81H        ;zezwolenie na przerwanie INT0

o licznikach zaraz napisze

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

URL=http://www.ime.uz.zgora.pl/dydaktyka/materialy/oprogramowanie_aparatury_up/regb_mcs51.pdf]To[/url] powinineneś mieć pod ręką.

 

Zapomniałem napisać że trzeba jeszcze "wyjść" z obsługi przerwania instrukcją RETI.

 

A teraz o licznikach. W tej broszurce co podałem linka wyżej masz schemat blokowy działania liczników w odpowiednich trybach. Pierw musisz wiedzieć jaką czestotliwością jest taktowany procek. ZAkladam że jest to 12MHz bo tak jest zreguły jeśli chcemy coś zliczać. Licznik programujemy wysyłając do rejestru TMOD odpowiednia liczbe (opis rejestru w broszurce). Jeśli licznik uzywamy do zliczania to najczęściej częstotliwość dzilimy na 12 żeby otrzymać 1MHz. (dzielimy przez 12 ustawiając C/T na 0 przy programowaniu). 1MHz czyli licznik jest zwiększany co 1us (mikrosekundę) 1s=1000000us. Do zliczania licznik ustawia się najczęściej na tryb 1 ponieważ ma największą pojemność (4 bajty czyli 65535us czyli 0,065s czyli dużo za mało dla danego przykładu ale o tym póżniej).

 

MOV TMOD,#01H ;tryb 1 i dzielenie przez 12, licznik 0

 

to co licznik zliczył jest w rejestrach TL0 i TH0 (lub TH1 i TL1 w zalerzności który licznik używamy).

Żeby powiększyć zakres licznika trza wprowadzić dodatkowy rejestr do zliczania. Możemy zezwolić na przerwanie jesli licznik sie przepelni i zwiekszać dodatkowy resjestr (któryś z R0-R7), wtedy mamy juz 6 bajtów czyli możemy zliczyć do ok 16.sekund.

Muszę już kończyć jakby cosbylo niejasnego a napewno było to pisz jak znajde czas to odpisze.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

dzięki cici, ale ja wiem jak zorganizowane są przerwania w tym układzie, wiem tez jak ustawic liczniki w dany tryb pracy. częstotliwosc się zgadza (a dokladnie jest to 11,059Mhz)

mój problem tkwi w tym aby odpowiednio zaprogramować licznik, aby liczył czas z dokladnością do setnej sekundy. na potrzeby programu 16 sekund na pewno wystarczy, bo w końcu ma mierzyc czas reakcji.

program nie muszę zaczynać az od bitu 2000H. dsm-51 ma inaczej zorganizowaną pamięć. przerwania zaczynają się od adresu 03H - dla INT0, a dla INT1 - 13H, sam program zaś należy zacząć pisać od adresu 100H. myślę jednak że z samym przerwaniem nie będzie większego kłopotu. muszę zastanowić się tylko nad tym jak wyświetlic zawartosć licznikow na wyświetlaczu. gdy juz bedę mial odpowiednio ustawione liczniki to z tym sobie jakos poradzę.

jeszcze troche pracy przede mną :)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Licznik najlepiej ustawic na tryb 1, czyli

MOV TMOD, #01H

Z tymi 11MHz będziesz miał mały problem, ale to szczegół. Lepszą częstotliwością byłoby 12MHz bo licznik by zliczał dokładnie co 1us, a tak zlicza co 1,085us, ale to sie da obejsc. Napisz jeszcze z jaką dokładnością musisz wyświetlić czas reakcji, bo moża to zrobić troche w inny sposób. Można zliczać na przykład co 0,1s. Wartość początkową liczników ustawiasz na wartość żeby przepełnienie licznika nastąpiło co 0,1s i wtedy jak się licznik przepelni inkermentujesz któryś z rejestrów.

A jak wyświetlić wartości liczników na wyswietlaczu, to trza wiedzieć w jaki sposób jest podłączony wyświetlacz do mikroprocka. wyświetlacze LED są podłączone albo przez multiplekser, albo są podłączone do lini adresowej i wtedy wartość do wyświetleniana na danym segmencie wysyła się pod odpowiedni adres.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

niestety nie mam wpływu na wybór układu. musze zadowolić się tym zegarem :).

co do dokładności to myślę, że do jedej setnej sekundy ( 0.01s) będzie dobrze.

jeśli chodzi o wyświetlenie wyniku to z tym nie będzie większego problemu. poza tym mam do wyboru wyświetlacz LED albo siedmiosegmentowy. wyświetlenie na LED będzie łatwiejsze, ale tym już sam się zajmę :)

pozostaje mi teraz napisać algorytm i potem program. ale nie jestem jeszcze do konca wszystkiego pewny :)

 

dzięki za pomoc cici, jak będziesz jeszcze chciał to napisz coś więcej :D

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Robiłem całkiem niedawno podbne zadanko, tylko że ja miałem zrobić zegarek odświerzany co sekundę. Ustawienie licznika więc będzie podobne.

Jak wcześniej napisałeś dokładność ma być 0,01s więc co taki czas powinno być wywołane przerwanie przepełnienia licznika. Trzeba więc ustawić wartości początkowe licznika. Licznik musi być ustawiony w tryb 1, ponieważ w tym trybie licznik ma największą pojemność.

Musimy odmierzyć 0,01s czyli 10000us

kwarc jest 11,085MHz do licznika dochodzi częstotliwość podzielona przez 12, czyli licznik jest inkrementowany co 1,0825us.

Żeby odmierzyc 0,01s licznik musi się zwiększyć 9238 razy

w trybie szesnastkowym to będzie 2416h

czyli tą liczbę trzeba odjąć od FFFFh

i dostaniemy wartość początkową licznika DBE9 czyli

TH0 powinno mieć wartość DBh

a TL0 E9h

 

przerwanie od licznika T0 będzie wywoływane co 0,01s.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

czyli muszę jeszcze zorganizować drugie przerwanie. z twojej wypowiedzi wynika, że co 0.01s będzie wywoływane przerwanie z licznika, gdy się on przepełni, czyli muszę to zapisać w jakimś rejestrze, np R7. co każde przerwanie zwiększałby się o jeden, tylko że rejstr ma ograniczoną pojemność, tj. tylko 8 bitów, czyli największa liczba jaką mogę w nim zapisać to 255, czyli odpada. ale jest jeszcze 16-bitowy rejestr DPTR, w którym mogę zapisać juz 65355 - czyli jak dla moich potrzeb wystarczająco. lecz nie jestem pewien czy mogę użyć tego rejestru, ale chyba tak. wynika z tego, że w rejestrze miałbym czas w ms poczynając od 10ms, bo tak ustawiony jest zegar. zastanawiam się tylko czy nauczyciel mi na to pozwoli, bo jeśli ktoś nie wciśnie w ciągu np po minucie, ale można programowo założyć że czas tej reakcji nie powinien przekraczać np. 5 sekund, wtedy wszystko będzie wporządku. przed wyświetleniem należy jeszcze przed trzecim znakiem postawić kropkę, ale tym zajmę się później.

najważniejsze w programie jest odpowiednie ustawienie zegara, bo przerwania juz są łatwiejsze.

i tak przerwanie od przycisku będzie tylko zatrzymywało licznik i wyświetli stan rejestru na LCD. procedura na wyświetlanie na LCD jest gotowa w pamici EPROM układu, więc wystarczy go tylko przywołać w odpowiednim miejscu(mam nadzieję że będę mogł tego użyć, bo jak nie to wyświetle na 7-seg :P), tylko że podprogram ten wyświetla zawartość akumulatora na LCD :/. muszę pomyśleć jak to rozwiązać, ewentualnie zapytam opiekuna pracy.

btw, we wtorek juz mam pierwsząkontrolę prac dyplomowych :/. lipa bo miałem nadzieje ze po świętach dopiero to będzie, ale cóz, wystarczy że będę miał algorytm i trochę programu na kartce :D

jeszcze pytanie. dsm-51 ma zegar 11.059MHz, a nie 11.085MHz, więc czy ustawienia, które podałeś będą się zgadzały? moim zdaniem różnica jest znikoma, ale pytam dla pewności :)

i jeszcze jedno, po przepełnieniu licznik będzie mierzył spowrotem od zadanej wartości, czy muszę ją jeszcze raz przypisać, np w przerwaniu?

pozdrawiam

mystery[/code]

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Problem z przepelnieniem rejestru (np. R7) mozesz rozwiazac podczas obslugiwania przerwania. Sprawdzasz czy R7 ma wartosc 255, jeśli tak to to zwiększasz rejestr R6 a R7 zerujesz. I wtedy mamy 16 bitów. Mozna jeszcze sprawdzac rejestr R6 czy się nie przepelnia i zwiększac R5 itd. DPTRa raczej się nie używa do przechowywania danych. Zmiana zegara dużo nie zmieni, ale zapewne w sprawozdaniu będziesz musiał wyliczyć dlaczego takie a nie inne są wartości początkowe rejestrów licznika.

Po przepełnieniu licznika musisz na nowo wprowadzić wartości początkowe liczników. Czyli w obsłudze przerwaniu musi się to znaleźć.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

witam ponownie, sporo czasu upłynęło do mojej ostatniej wizyty. ale mam już program, tzn napisałem juz program. Dlaczego tak długo? bo wcześniej mi się nie chciało :P w sumie to w godzine go napisałem. oto program:

      LJMP            START                  ORG            03H                  SJMP           PRZERW1                  ORG            0BH                  MOV            TH0,#0DBH                  MOV            TL0,#0FFH                  INC             R7                  CJNE           R7,#100,P1                  INC             R6    P1:                  RETI                  ORG            100H    START:                  MOV            IE,#10000011B    ;ustawienie przerwań                  MOV            TMOD,#01H        ;tryb pracy licznika                  MOV            TH0,#0DBH                  MOV            TL0,#0FFH                  MOV            R7,#0                  MOV            R6,#0                  CLR             P1.7      ;zapalenie diody                  SETB           TR0       ;włączenie licznika                  SJMP           $    PRZERW1:                  SETB           P1.7                  CLR            TR0                  MOV            A,R6                  ACALL         POD                  MOV            A,#'.'                  LCALL         WRITE_HEX    ;write_hex wyświetla na LCD znak, ktorego kod zapisany jest w A                  MOV            A,R7                  ACALL         POD                  RETI      POD:                                            ;jest to podprogram, który przedstawia wymik dzielenia                  MOV            B,#100           ;na LCD w postaci dziesiętnej                  DIV             AB                  LCALL         WRITE_HEX                  MOV            A,B                  MOV            B,#10                  DIV             AB                  ADD            A,B                  LCALL         WRITE_HEX                  RET

oto i cały program, ale jeszcze nie wiem czy działa, bo nie miałem do tej pory możliwości aby sprawdzić go. jeżeli widzisz jakieś blędy cici, to krzycz. jeżeli masz jakieś wątpliwości co do użytych rozkazów bądź podprogramów to pytaj.

pozdrawiam

mystery

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Witam

Przeglądnołem twój programik i wydaje się być poprawnie zrobiony poza jednym wyjątkiem

 

INC             R7                 CJNE           R7,#100,P1                 INC             R6   P1:                 RETI                 ORG            100H

Jeśli chciałeś tu zrobić to o czym myśle to powinno być jeszcze zerowanie rejestru R7, jeśli rejestr ten osiągnie wartość 100

 

                CJNE           R7,#100,P1                 INC             R6                 MOV            R7,#0 ;tego brakuje  P1:

Jak rozumiem inicjalizacji LCD i funkcji wyświetlającej znaki na wyświetlaczu nie musisz pisać?? Czy po prostu przyjdzie na to czas??

pozdro

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

dzięki cici, to był poważny błąd :)

co do LCD, to system dsm-51 ma wbudowane pewne gotowe procedury, np. na obsługę wyświetlacza, są też podprogramy opóźnień, itp. lepiej jest sobie ułatwiać pracę wykorzystując gotowe już programy. profesor też mi tak powiedział, że to ma być jak najprostszy program, więc wszystko gra B)

nie jestem jeszcze na etapie, aby konfigurować wyświetlanie na LCD, na wyświetlaczu siedmiosegmentowym już umiem, na LCd przyjdzie jeszcze czas :)

pozdrawiam

mystery

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

witam

wszystko byłoby ok, gdyby nie to, że w tym akurat systemie nie wyprowadzonych bezpośrednio wejść INT0 i INT1. fakt ten komplikuje nieco sytuację, ale jak sie okazało wystarczy dodac do programu kilkanaście linijek i wszystko będzie ok. w układzie znajduje sie sterownik przerwań, którego wyjścia podłączone są do wejść mikrokontrolera INT0 i INT1. INT0 połączony jest z portem COM2, wieć odpada jego użycie, natomiast mogę użyć wejścia INT1. NAleży wykorzystać wejście IX na szynie systemowej i odpowiednio zaprogramować steronik przerwań. Nie jest to trudne. Dziś już uporałem się z pracą programu działa on znakomicie.

należy dodać tylko kilka linijek do obsługi przerwania i do programu głównego

do prgramu głównego nalezy dodać:

                   MOV          R1,#CSIC     ;PROGRAMOWANIE               MOV          A,#3          ;STEROWNIKA PRZERWAŃ               MOVX        @R1,A               MOV          IE,#10000110B               LCALL        LCD_CLR    ;WYCZYSZCZENIE EKRANU LCD
do przerwania od INT1 nalezy dodać:

                 MOVX         A,@R1  ;SPRAWDZENIE I WYZEROWANIE               ANL            A,#03H ;PRZERWANIA W STEROWNIKU               MOVX         @R1,A               CJNE          A,#3,END               LCALL         LCD_CLR               (...)               RETIEND:                               ;WYZEROWANIE INNYCH PRZERWAŃ               PUSH          ACC               MOV           R1,#CSAD               MOVX         A,@R1               POP            ACC               MOV           R1,#CSIC               MOVX         @R1,A               RETI
sprawdzilem i dziala

juz niedlugo kontrola prac dyplomowych :)

jezeli ktos chcialby całyprogram to niech napisze to wysle mu na meila :)

pozdrawiam

mystery

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie


×
×
  • Dodaj nową pozycję...