Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Program pod 8051. Zapis do rejestrów.

Gosuto Inu 26 Mar 2005 17:34 2639 19
  • #1
    Gosuto Inu
    Level 11  
    Witam
    Mam liczbe zapisana w 2 rejestrach(14-bitowa) i chcialbym otrzymac jej poszczegolne cyfry w systemie dziesietnym. Np majac 3Fh oraz FFh(16383d) chcialbym zapisac do rerjetrow kolejno 1,6,3,8,3. Jesli ktos ma pomysl jak to zrobic to bede wdzieczny za kazda podpowiedz :wink:
  • Helpful post
    #2
    Caladan
    Level 19  
    Nalezy po kolei dzielic przez 10. wartosc liczby. Za kazdym razem zapisujesz kolejne cyfry liczby.
    Wiec za pierwszym razem dostaniesz liczbe dziesiatek tysiecy, potem liczbe tysiecy, setek, dziesiatek i jednosci.
  • #3
    Gosuto Inu
    Level 11  
    Po pierwsze nie wiem jak to zrobic jak mam ja zapisana w 2 rejestrach, a po drugie to chyba w B(reszcie z dzielenia) bede mial na poczatku jednosci,a potem dziesiatki itd.
  • #4
    Caladan
    Level 19  
    Zgadza sie, troche sie zagalopowalem, zapomnialem, ze to 8bitow a nie 16 :D

    ALe rozwiazanie mam i tak, wlasnie wymyslilem :D

    DT - dziesiatki tysiecy
    T - tysiace
    S - setki
    H - wyzszy bajt
    L - nizszy bajt
    C - flaga przeniesienia
    B - flaga pozyczki

    Przepraszam, ze w C, ale w asmie zajeloby mi to dluzej :D

    DT=0; //liczba dziesiatek tysiecy
    if (((H==0x27)&&(L>=0x10)||(H>0x28))
    {
    DT++;
    H-=27; //odejmij 9984
    L-=16; //i jeszcze 16, dla pelnych 10000
    H-=B; //jesli pozyczka
    }

    T=0;
    while (H>=4)
    {
    H-=4; //-1024
    L+=24; //+24 => by byl odjety dokladnie tysiac
    H+=C; //przeniesienie z dodawania jesli wystapi
    T++
    }

    if ((H==3))&&(L>=232))
    //dla tego ostatniego tysiaca, ktory jest mniejszy niz 1024 :wink:
    {
    T++;
    H=0;
    L-=232;
    }

    S=0; //liczba setek
    while (H)
    {
    S+=2; //w 256 sa dwie setki
    H--; //-256
    L+=56; //+56
    H+=C; //+przeniesienie, jesli nastapilo
    }

    //a teraz juz albo odejmowaniem, albo dzieleniem prosze sobie policzyc
    //reszte - pozostale dane znajduja sie juz tylko w bajcie L
  • #5
    caramba
    Level 13  
    Nawiązując jeszcze do poprzedniego pomysłu: możesz skorzystać z rejestru DPTR (16 bitowego). Można się też do niego odnosić jak do dwóch rejestrów 8-bitowych (DPH i DPL).
  • #6
    Gosuto Inu
    Level 11  
    no tylko ze dptr chyba sie nie przyda jak nie da sie go dzielic :?
    to chyba to odejmowanie zostaje
  • #7
    Gosuto Inu
    Level 11  
    Zrobilem z tym odejmowaniem i dzila wszystko git :D
    dzieki za pomoc :wink:
  • #8
    Caladan
    Level 19  
    A prosze bardzo, milo mi, ze dziala :D
    Najpierw zaprojektowaem metoda, a potem ja jeszcze na kartce policzylem sobie testowo, wiec bym sie zdziwil, gdyby nie dzialala :wink:
  • #9
    Gosuto Inu
    Level 11  
    Chodzi o to ze to moj pierwszy program pod 8051 wiec sie ciesze ze jakos to napisalem 8-) A ile pamieci na program ma 8051??

    Dodano po 3 [godziny] 13 [minuty]:

    a jak da sie uzyskac taki przebieg ""|_,--""|_,-- :)
    do lcd mi to potrzebne
    chyab ma byc tak:na poczatku jako wyjscie stan H, potem jako wejcie L i jeszcze ½napiecia(stan wysokiej impedancji :?: )
    jestem zielony wiec jakby ktos mogl to niech pomoze :wink:
  • #10
    Caladan
    Level 19  
    8051 ma na program 8kB pamieci. Atmelek AT89C4051 bedzie mial dla przykladu 4kB.

    Nie rozumiem, po co potrzebne Ci do LCD przebiegi o trzech stanach, ale ich nie da sie tak latwo uzyskac :D

    Stan wysoki powoduje, ze port zachowuje sie jak zrodlo pradowe. Stan niski, ze moze pochlaniac prad.
    Jesli chcesz odczytac stan portu musisz ustawic go w stanie wysokim. Nastepnie cos zewnetrznego musi albo dac na ten port stan wysoki (nic sie nie dzieje, wiekszosc portow ma wew rezystor podciagajacy), albo stan niski (wtedy port zostanie sciagniety do masy).

    Zdaje mi sie, ze stan wysokiej impedancji to taki, w ktorym port po prostu nie moze pochlaniac pradu. Czy chodzi tez od bycie zrodlem, nie wiem.
  • #11
    marek_Łódź
    Level 36  
    Gosuto Inu wrote:
    a jak da się uzyskac taki przebieg ""|_,--""|_,-- :)
    do lcd mi to potrzebne


    Dobrych parę lat temu składałem taki układ i pisałem program do takiego wyświetlacza.

    Sterowanie jednej linii wyświetlacza było zrealizowane z dwóch wyjść podłączonego do portu procesora bufora 74HCxxxx i alternatywnie z CMOSa serii 4000 przez dzielnik oporowy (R do wyjścia A, R do wyjścia B, wyświetlacz połączony do punktu środkowego) i o ile pamiętam, miałem jeszcze regulację napięcia tego bufora (od 3V w górę). Można też spróbować bezpośrednio z portu podciągając linie rezystorem rzędu kilku kOhm i łącząc dwa piny szeregową parą oporników rzędu 100 kOhm (wyjście na wyświetlacz z punktu połączenia tych oporników). Tyle, że wtedy możesz mieć problemy z ustawieniem kontrastu (brak regulacji napięcia). Można też spróbować zrobić dzielnik na trzech rezystorach łącząc ten trzeci do regulowanego źródła napięcia. Tyle, że trzeba wtedy dobrać rezystory.

    Na linii wyświetlacza
    AB
    00-wyjście 0
    11-wyjście Umax
    10 lub 01 - wyjście Umax/2

    jeśli zastosujesz układ niesymetryczny (różne oporniki, dostaniesz 2 napięcia pośrednie różne dla układu 01 i 10

    Wyświetlacz miał tę nieprzyjemną cechę, że przy niskich temperaturach (powiedzmy w pobliżu 0° C) przestawał pokazywać liczby i do dziś nie wiem, czy była to kwestia napięć, programu, czy tego bufora.

    ps. wielobitowa konwersja do bcd była opisana w temacie https://www.elektroda.pl/rtvforum/topic187210.html" target="_blank" rel="noopener " title="http://
    https://www.elektroda.pl/rtvforum/topic187210.html" class="postlink inline-block ">
    https://www.elektroda.pl/rtvforum/topic187210.html

    Układy .....51 mają 4kB pamięci, układy ....52 osiem KB, różne mutacje tych układów 12 i więcej kilobajtów pamięci,

    Dopisano po 1 godz

    Znalazłem jakieś schematy, ale to była inna wersja - na liniach UART pracującego w trybie synchronicznym (1MHz) mam rejestry przesuwające 4094, dalej mam wyświetlacz LCD 6 cyfr po 7 segmentów w układzie matrycy, co jest o tyle prostsze w obsłudze, że mogę dać +U, 0V i -U na segment. Rejestry sterowane są przez rezystory (niby takie dopasowanie poziomu) i zasilane z potencjometru (regulacja 3-9V). Całość była pędzona z kości 8751 (jeszcze z okienkiem kasowania UV).
  • #12
    Tdv
    Level 34  
    Układów cyfrowych raczej nie steruje się połową napięcia - przypuszczalnie tak narysowano w dokumenatcji (oznaczać to może np. że dane mogą się zmieniać), podaj może typ wyświetlacza albo jeszcze lepiej jakiś linek do tej dokumentacji.
    marek_Łodź: "... przy niskich temperaturach (powiedzmy w pobliżu 0° C) przestawał pokazywać liczby i do dziś nie wiem, czy była to kwestia napięć, programu, czy tego bufora..."
    Ani napięć, ani bufora ani programu - LCD to ciekłe kryształy - a one nie lubią niskich temperatur - po prostu zimno im było i strajkowały.
  • #13
    marek_Łódź
    Level 36  
    Tdv wrote:
    Układów cyfrowych raczej nie steruje się połową napięcia - ...


    Rozumiem że piszemy o różnych rzeczach. Ja piszę o sterowaniu wyświetlacza czyli o napięciach podawanych bezpośrednio na segmenty wyświetlacza. Normalnie takie układy steruje się ze scalonych driverów, które dają właśnie napięcia na poziomach pośrednich, natomiast opisany wyżej układ jest dowodem, że wyświetlacz można sterować niemal bezpośrednio z linii procesora. Podejrzewam, że autor pytania pisząc o napięciu połówkowym myślał właśnie o takim sterowaniu.
    Jesli się mylę - sorry.
  • #14
    Gosuto Inu
    Level 11  
    tu mam ciekawy link http://www.ee.nec.de/_pdf/U14737EE1V0AN00.PDF
    mam wyswietlacz ½duty ½bias, czyli ma 2 wejscia sterujace na ktorych wystepuja 3 rozne napiecia. Sprobuje zrobic z tymi rezystorami szeregowo na 2 piny. Obojetnie na ktorym porcie 8051 takie cos zrobie czy mozna tylko na jakims konkretnym.
  • #15
    Gosuto Inu
    Level 11  
    A ktorych portow i jak uzywac 8051 jako licznik(jak go wykorzystac jako zwykly 14bitowy licznik).
  • #16
    marek_Łódź
    Level 36  
    Gosuto Inu wrote:
    A ktorych portow i jak uzywac 8051 jako licznik(jak go wykorzystac jako zwykly 14bitowy licznik).


    Układy licznikowe w trybie 1 liczą jako 16 bitowe liczniki/timery, po ustawieniu źródła impulsów na zewnętrzne będą Ci zliczać impulsy na wejściu T0 lub T1. W przypadku wolniejszych sekwencji możesz wykorzystać wejścia przerwania zewnętrznego, albo dowolny inny port, odsłuchiwany np w przerwaniach zegara, czy nawet w pętli programu.

    Co do wyświetlacza, to port może być dowolny, jest ew. kwestia wewnętrznych rezystorów podciągających, które musisz doliczyć do dzielnika, nie wiem tylko jak rozwiążesz problem ew ustawiania kontrastu. Bo chyba trzeba regulować napięcia wyświetlacza.

    Rozumiem, że wyświetlacz będzie sterowany sekwencją generowaną w przerwaniach zegarowych.

    ps Link rzeczywiście ciekawy. Może warto z bliska się przyjrzeć procesorom ze zintegrowanym sterownikiem LCD (jeszcze ich nie oglądałem). Ciekawie wyglądają też MSP430 z Texas Instruments
  • #17
    shg
    Level 35  
    8051 ma 0kB (zero) pamięci programu :P
    A poważnie, to ma tyle, ile się do niego podłączy pamięci zewnętrznej, max. 64kB
    To już archaizm - pierwsze procki z rodziny '51 Wtedy słowo Flash kojarzyło się z niejakim Gordonem Flashem :d
    Przed 8051 były jeszcze 8031, a przed nimi był chaos :D


    A chcesz te wyjścia wykorzystać jak wyjścia normalnego licznika?

    Jak tak, to tak:
    ; porty dowolne, na przykład tak:
    ; port 1 - młodsze 8 bitów
    ; port 2 - starsze 6 bitów
    
       .org 0x0000
       SJMP   start
       .org 0x000b ;- procedura (?) umieszczona pod adresem 000B (szesnastkowo), czyli wektor przerwania timera 0
       LJMP   timer0int
    
    start:
      MOV   P1, #0
      MOV   P2, #0
    
      MOV   a,  TMOD  ; trzeba tak, bo rejestru TMOD nie można adresować bitowo
    ANL   a, #0xF0
    ORL   a, #0x02 ; timer0 = timer, taktowany z wewnętrznego sygnału zegarowego, tryb 2, czyli samopowtarzalny, jak automat Kałasznikowa :D
    MOV   TMOD, a
    MOV   TH0, #6 ; przerwanie co 250 (256-6) cykli zegara = 4kHz (dla kwarcu 12MHz)
    MOV   TL0, #6 ; to tak dla zasady, nie musi być, ale dzięki temu timer od samego początku odmierza poprawny czas
    MOV   IE, #0x82 ; uaktywnia przerwanie timera 0
    SETB   TR0 ; start timera 0
    
    ; i tu cala zabawa się kończy, w pętli czekamy na nic :D , bo resztą zajmują się przerwania
    czekaj_na_armagiedon:
      SJMP   czekaj_na_armagiedon
    
    timer0int:
    INC   P1
    JNC   bez_przeniesienia
    INC   P2
    bez_przeniesienia:
    RETI
    

    Ta procedurka (timer0int) wywoływana jest w każdym przerwaniu timera.
    Właściwie to jest licznik 16 bit, ale jeżeli nie wykorzystujesz najstarszych dwóch bitów, to masz licznik 14 bit, tak było prościej :D

    Taki licznik ma jedną wadę - w momencie zmiany stanu protu P1 n 255 na 0 w tej samej chwili wartość na porcie P2 powinna zwiększyć się o 1. Tak się niestety nie dzieje, zmiana następuje po 4mikrosekundach (tak na oko, nie mam pod ręką tabelki z czasami wykonywania instrukcji) (dla kwarcu 12MHz)
    procedurę w przerwaniu można też zrealizować za pomocą instrukcji ADD i ADDC
    ADD P1,#1
    ADDC P2,#0
    nie wiem, czy taki tryb adresowania istnieje (ale wydaje mi się że tak), w każdym razie to nawet lepsze rozwiązanie niż poprzednie, bo opóźnienie będzie tylko 2µs
  • #18
    marek_Łódź
    Level 36  
    shg wrote:
    8051 ma 0kB (zero) pamięci programu :P
    Przed 8051 były jeszcze 8031, a przed nimi był chaos :D


    Tak naprawdę to najpierw był chaos, a potem Z80;-). Jeśli chodzi o 8051 to jest to wersja procesora 8031 z wewnętrzną, programowaną fabrycznie pamięcią ROM. W pięknych czasach złotej wolności takie procesory używano zamiennie z 8031 (EA do masy) i o dziwo czasem były tańsze od swoich słabszych braci.

    Egskjuz mi, ale ten poprzedni przykład to nie licznik, lecz timer, który się kręci w kółko jak głupi.

    Jeśli chcesz mieć 14 bitowy LICZNIK (impulsów) z wyjściami binarnymi (takie prawie 4060 w wersji mikroprocesorowej), to ta procedurka inkrementacji powinna być spięta np z przerwaniem zewnętrznym od pinu INT0 lub INT1.

    Problem przepełnienia dolnego bajtu jest nie do obejścia, chyba, że zastosujesz dodatkowy rejestr, do którego jednym ruchem przepiszesz całe 14/16 bitów.

    Rozkazy ADD i ADDC działają chyba tylko na akumulatorze.
  • #19
    Gosuto Inu
    Level 11  
    A jakie sa ograniczenia podanej na T0/T1 czestotliwosci sygnalu?
    Quote:
    tryb 2, czyli samopowtarzalny, jak automat Kałasznikowa :D
    z tego co wiem to kalasznikow jest maszynowy a nie samopowtarzalny, ale w sumie jak maszynowy to tez samopowtarzalny :D
  • #20
    shg
    Level 35  
    ograniczenie jest takie same, jak dla timera pracującego z wewnętrznym zegarem - 1/24 częstotliwości kwarcu, czyli np. 0.5MHz dla kwarcu 12MHz
    W dół ograniczenie nie istnieje, czyli od 0Hz :D

    To jest ograniczenie fizyczne, wynikające ze sposobu "pobierania" sygnału z wejść T0/T1. Wejścia te nie są połączone bezpośrednio z wejściami zegarowymi timerów, ich stan jest próbkowany "w rytm" oscylatora.


    Faktycznie, niestety ADD i ADDC działają tylko z akumulatorem :(

    Można to jeszcze zrobić z małym opóźnieniem nieco inaczej, ale to trochę toporne rozwiązanie i nie poradzi sobie z sygnałem o częstotliwości bliskiem maksymalnej możliwej:
    timer będzie taktowany zewnętrznym sygnałem, będzie pracował w trybie 16bit, a procesor będzie kopiował w pętli zawartość rejestrów TH0 i TL0 na porty. Głupie to dla tego, że musi się cały czas "kręcić" w pętli i nie robić nic innego, w przeciwnym wypadku (albo w razie podania zbyt dużej częstotliwości) będzie "gubił" wartości na wyjściach.