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.

Adresowanie pamięci programu AVR - kilka pytań

prokopcio 25 Lut 2007 21:50 1925 9
  • #1 25 Lut 2007 21:50
    prokopcio
    Poziom 29  

    Witam.

    Z tą pamięcią programu mam kilka pytań bo się zakręciłem.

    Tak czytam sobie w książeczce R.Baranowskiego że rozkazowi np. lpm należy podać wskaźnik 16bit z czego

    Cytat:
    Wszystkie prócz najmłodszego bity rejestru indeksowego "Z" służą do adresowania 16-bitowej komórki pamięci programy, która ma zostać odczytana......do wyboru 8-bitowej części odczytywanej komórki wykorzystuje się najmłodszy bit rejestru "Z". Jeśli bit jest ten wyzerowany, odczytywana jest część LSB słowa, jeśli ustawiony - MSB
    czy to nie jest całkowicie normalne adresowanie całym rejestrem "Z" ale pojedyńczych komórek 8bit? Tylko nie rozumię dlaczego w przykładzie programu jest przesunięcie w prawo (mnożenie przez 2) :
    Code:

    Tab: .dw 0x12AB

         ldi ZH,high(Tab<<1)
         ldi ZL,low(Tab<<1)
         lpm R16,Z+
         lpm R17,Z


    wydawało mi się, że skoro adresujemy słowo16bit ale za pomocą 15bitów a ostatni jest do wyboru "półsłowa" czyli bajtu to po co mnożyć adres przez 2?

    i pytanie drugie: Czemu służyć ma takie dziwne zorganizowanie pamięci że pierwszy jest bajt LSB a po nim MSB? przez to zapis słów16bit:
    .dw 0x1234,0x5678
    zapisuje do pamięci rzeczywiście bajty:
    .db 0x34,0x12,0x78,0x56
    ale ktoś to dziwnie wymyślił utrudniając życie programistą (i tu napewno się mylę)...

    Czy ktoś mi rozjaśni umysł co do tych pytań?

    Dodano po 4 [minuty]:

    ok. pierwsze pytanko zajarzyłem... translator dla etykiet przyporządkowuje adres słów a nie bajtów, ten adres jest 2 razy mniejszy od adresu bajtu więc trzeba go przemnożyć. Dość jasne.

    0 9
  • #2 11 Cze 2007 21:23
    y0yster
    Poziom 19  

    Co do tego całego przesunięcia o 1 w lewo to, żebyś wiedział lepiej o co chodzi, to przytoczę taką sytuację:

    .db 'PLOT'
    .db 'KON'

    W pamięci to wygląda tak (pamięć jest adresowana za pomocą WORD, słowa)

    adres w WORD zawartosc adres bajtowy
    001 'PL' 2
    002 'OT' 4
    003 'KO' 6
    004 'N\0' 8

    Jak sam widzisz, żeby uzyskać adres bajtowy należy to pomnożyć razy 2.

    001 * 2 = 2

    Prawda.

    A o co chodzi z przesunięciem? Zauważ takie coś

    2 = 0b10

    0b001 << 1 = 0b010

    A 0b010 to przecież 2. Więc przesunięcie bitowe o 1, a mnożenie dziesiętne razy 2 to to samo.

    Mama nadzieję, że trochę rozjaśniłem tą sytuację.

    --edit

    Co do drugiego pytania to nie wiem, czy ułatwił, czy utrudnił. To według mnie zależy od architektury. Poczytaj sobie o organizacji bajtów w adresach. Jaśniej mówiąc możesz poczytać o little endian i big endian. Możesz przeczytać o tym w jednym z artykułów na mojej stronie w dziale asembler, lub na stronie wikipedia.pl

    0
  • #3 23 Lut 2008 19:19
    dj_max84
    Poziom 13  

    a moze ktos bardziej szczgolowo napisac jak korzystac z tej opcji .db ??
    walcze z wyswietlaczem graficznym i nie moge sobiez tym poradzic
    wyswietlacz dziala ok, moge wysylac na niego pojedyncze bajty, zdefiniowalem tez z jakich bajtow po kolei sklada sie dana cyfra np
    .DB $0F,$0F,$30,$30,$30,$30,$30,$30,$0F,$0F,$00,$00
    ale nie wiem jak przeslac te poszczegolne bajty

    0
  • #4 24 Lut 2008 09:12
    y0yster
    Poziom 19  

    Zazwyczaj przed podaniem dyrektywy w asemblerze .db podajesz jeszcze .org 0x0000, która do umieszcza dane pod tym adresem (0x0000). Innymi słowy, wszystkie dane, które zostały zamieszczone po .org 0x0000, są dostępne od adresu 0x0000. Zauważ, że jeśli korzystasz z pamięci flash w uC np. Atmega8 masz tam organizację pamięci 2 bajtową (WORD), a wszystko to zostało wyjaśnione przeze mnie w wcześniejszym poście.

    Pozdrawiam.

    0
  • #5 24 Lut 2008 09:50
    Pituś Bajtuś
    Poziom 28  

    y0yster napisał:
    Zazwyczaj przed podaniem dyrektywy w asemblerze .db podajesz jeszcze .org 0x0000, która do umieszcza dane pod tym adresem (0x0000). Innymi słowy, wszystkie dane, które zostały zamieszczone po .org 0x0000, są dostępne od adresu 0x0000.

    I program idzie w krzoki bo wektor resetu tez ma adres 0x0000. Wystarczy przed definicjami stałych umieścić etykietę i dostęp do danych będzie możliwy poprzez tą etykietę, po co se głowe zawracać sztywnymi adresami?

    0
  • #6 24 Lut 2008 12:57
    dj_max84
    Poziom 13  

    no dobrze a jesli wrzuce pod jedna etykieta caly alfabet to jak moge wyciagnac z niej tylko 1 litere??
    widzialem takie cos w pewnym programie ale byl bardzo pogmatwany i bez opisow. program w kazdym razie dziala podobno..

    0
  • #7 24 Lut 2008 13:24
    y0yster
    Poziom 19  

    Pituś Bajtuś masz rację, po prostu myślałem, że nie trzeba pisać przed adresem "np.", a jednak. Jest to oczywiste, że 0x000 to adres przerwania resetu. Mój błąd.

    Co do twojego pytani adj_max84, to tak jak powiedział Pituś Bajtuś. Możesz do tego celu użyć etykiety, dawno pod asemblerem nie pisałe i jakoś takie rozwiązanie wyszło mi z głowy ;P.

    Odnośnie odczytywania 1 literki spod danego adresu wystarczy pomnożyć adres etykiety razy 2, lub przesunąć bitowo w lewo, tak jak wyżej pisałem. A następnie zaangażować jakąś dodatkową zmienną, która by pełniła rolę indexu w tablicy.

    Przykład:

    napis:
    .db 'abcd'

    ;mnożysz adres etykiety "napis"

    ;chcesz wyciągnąć np. 'a'

    ;index = 0
    ;pod adresem "napis"+index znajduje się 'a' itd.

    Instrukcje jakie możesz użyć do operacji odczytu danych spod pamięci flash to:

    lpm ;odczytujemy jeden bajt spod adresu Z, jest on ładowany do rejestrze R0
    adiw ZH:ZL, 1 ;zwieksza adres o 1

    Jeśli pomogłem naciśnij Pomógł :P.

    Pozdrawiam.

    0
  • #8 24 Lut 2008 13:37
    don diego
    Poziom 32  

    Może zrozumiesz na przykładzie.

    Code:
    wyswietl: 
    
    push R17
    ldi ZH, high(cyfry<<1);ładuj rejestr Z adresem, pod którym umieszczono
    ldi ZL, low(cyfry<<1) ;początek tablicy cyfr
    clr R17
    add ZL, temp ;dodaj zawartość rejestru temp do wskaźnika Z
    add ZH, R17 ;R17=0
    lpm temp, Z
    out PORTB,temp
    pop R17
    ret

    cyfry: .db ~0xB7, ~0x24, ~0x73, ~0x76, ~0xE4, ~0xD6, ~0xD7, ~0x34, ~0xF7, ~0xF6, ~0x40, ~0x00
    ;            0      1      2      3      4      5      6      7      8      9      -     nic   

    Podany fragment odpowiada za wyświetlanie cyfr na wyświetlaczu 7-segmentowym. Najpierw w rejestrze Z jest umieszczany adres etykiety "cyfry". Następnie do adresu jest dodawana wartość przesunięcia. W tym przykładzie przesunięcie odpowiada cyfrze. Czyli na przykład, jeśli w rejestrze temp jest wartość 4, to nastąpi odczytanie wartości komórki przesuniętej o 4 względem adresu etykiety "cyfry".
    Mam nadzieję, że to co napisałem jest w miarę zrozumiałe:)
    Pozdrawiam
    Adam

    0
  • #9 10 Mar 2008 21:43
    dj_max84
    Poziom 13  

    ok to juz kapuje jak wyciagnac pojedyncza cyfre
    teraz jak mniej wiecej moze wygladac procedura przeksztalcenia liczby np 4 cyfrowej na pojedyncze cyfry? dzielic to po kolei przez 1000, 100, 10 a pozniej zapisywac ilosc tysiecy, ilosc setek, itd?
    to w miare zrozumiale ale jak zrobic zeby wyciagnac konkretne litery z tablicy majac podany wyraz? uzyc do tego ascii?? czy moge takze cofac (odejmowac) ZH i ZL?? chcac np wyswietlic najpierw cyfre 6 a pozniej 1??

    0
  • #10 10 Mar 2008 21:48
    Freddie Chopin
    Specjalista - Mikrokontrolery

    dj_max84 napisał:
    ok to juz kapuje jak wyciagnac pojedyncza cyfre
    teraz jak mniej wiecej moze wygladac procedura przeksztalcenia liczby np 4 cyfrowej na pojedyncze cyfry? dzielic to po kolei przez 1000, 100, 10 a pozniej zapisywac ilosc tysiecy, ilosc setek, itd?

    dzielenie jest 'ciezkie' - lepiej zrobic petle z wykorzystaniem odejmowania. przynajmniej takie jest moje zdanie. zalezy czy AVR ktorego uzywasz ma jakies sensowne wsparcie do dzielenia. bo jesli nie, to lepiej zrobic odejmowanie. jakis czas temu pisalem jak to dokladnie zrobic - jak przejrzysz moje ostatnie posty to na to trafisz, albo jak nie trafisz, to daj znac - znajde ci tego posta.

    0x41 0x56 0x45!!

    0