Zamiana kolejności bitów

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Zamiana kolejności bitów

Post autor: M@ciej » 09 lip 2008, 11:12

Witam wszystkich :)

Mam pytanie: jak w prosty sposób zamienić kolejność bitów zmiennej typu BYTE w Bascomie?
Żeby MSB stał się LSB i odwrotnie. Wpadłem na taki pomysł:

Kod: Zaznacz cały

 Dim Q as Byte   'Zmienna pomocnicza
 Dim Bta as Byte 'zmienna do zamiany

  Q.0 = Bta.7
  Q.1 = Bta.6
  Q.2 = Bta.5
  Q.3 = Bta.4
  Q.4 = Bta.3
  Q.5 = Bta.2
  Q.6 = Bta.1
  Q.7 = Bta.0
  Swap Q , Bta
...ale jest on mało elegancki. Przetrzepałem kilka przykładowych zmiennych na papierze metodą Rotate w obie strony,ale nie otrzymałem docelowego rezultatu.

Zna ktoś może lepszy sposób?

adi-niunio
Użytkownik
Posty: 308
Rejestracja: 04 mar 2004, 9:21
Lokalizacja: Zabrze
Kontakt:

Post autor: adi-niunio » 09 lip 2008, 12:43

SHIFT RIGHT ZMIENNA 7 albo ROTATE RIGHT ZMIENNA 7 , niestety nigdy nie jestem w stanie zapamietac, ktory nie wpisuje zer, tylko dziala w kolko , w sensie to co wychodzi wchoni na druga strone.

Awatar użytkownika
RcTomek
Moderator
Posty: 243
Rejestracja: 27 wrz 2007, 21:15
Lokalizacja: Głogów / Wrocław

Post autor: RcTomek » 09 lip 2008, 16:27

adi-niunio pisze:SHIFT RIGHT ZMIENNA 7 albo ROTATE RIGHT ZMIENNA 7 , niestety nigdy nie jestem w stanie zapamietac, ktory nie wpisuje zer, tylko dziala w kolko , w sensie to co wychodzi wchoni na druga strone.
ROTATE (ang. obracać) działa w kółko - zawartość znacznika C jest wpychana spowrotem.

-> M@ciej
A może być wstawka asemblerowa? Działa dużo szybciej niż polecenia bascomowe (większość instrukcji jest wykonywana w 1 takcie zegara). Kod:

Kod: Zaznacz cały

Dim Zmienna As Byte At &H60       'poczatek obszaru SRAM
(...)
Zmienna = &B11100011  'początkowa wartość zmiennej (0xE3)

$asm
lds R16, &h60   'laduj do R16 zawartosc zmiennej 'zmienna'
clr R17   'zeruj pomocniczy rejestr R17
ldi R18, 8   'zaladuj licznik petli
Petla:
lsl R16   'przesun w lewo zawartosc R16 (zmiennej)
ror R17   'przesuwaj w prawo zaw. R17 ladujac bity wchodzace zaw. znacznika C
dec R18   'dekrementuj licznik petli
brne PETLA   'jesli R18 != 0, zapetl
sts &h60, R17   'zapisz do SRAM nowa (odwrocona) wartosc zmiennej
$end Asm

'teraz zmienna ma wartosc &B11000111 (0xC7)

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 09 lip 2008, 17:10

Wow, dzięki :)

Nie spodziewałem się aż takiej procedury? Ja się na asemblerze znam trzy-po-trzy i miałbym w związku z tym (programem) kilka pytań:

1. Dlaczego ładujemy zmienną do R16, a nie np. do R12 albo R5? To samo dotyczy zmiennej R17
2. Co to jest znacznik C?

Sorki,za te pytania,ale chcę zrozumieć procedurę, która mam zastosować. Inna sprawa, że w tym programie nie jest potrzebna wielka szybkość, ale procedura przyda się kiedyś do innych zastosowań.

Mam natomiast o wiele gorszy problem. Chcę dogadać Atmegę8 z programem napisanym w Bascomie z Delphi6 przez port RS-232.Używam w Delphi dodatku TComPort. Programy robią sobie samowolkę, jeden "nie widzi" drugiego. Muszę ponawiać kilka razy w pętli (czy to w bascomie czy Delphi) zapis lub odczyt, żeby wyłapać potrzebne mi dane wśród zer i innych krzaków.
Wstyd, bo chcę wysłać do procka tylko dwa bajty i odebrać inne dwa bajty i nawet z tym mam problem. Nie chcę zakładać nowego tematu, gdyż oba niejako się wiążą (dotyczą tego samego projektu).

Pomóżcie!

Awatar użytkownika
RcTomek
Moderator
Posty: 243
Rejestracja: 27 wrz 2007, 21:15
Lokalizacja: Głogów / Wrocław

Post autor: RcTomek » 09 lip 2008, 19:44

1. Do R16 dlatego, że ta część rejestrów roboczych jest 'najbardziej' ogólnego przeznaczenia. W procesorach AVR nie ma jednakowego dostępu do wszystkich rejestrów roboczych. Przykładowo instrukcja ldi może operować wyłącznie na górnej połówce rejestrów, z kolei instrukcj mnożące operują tylko na fragmencie górnej połówki rejestrów. R16 i R17 to para rejestrów, która jest używana jako 'akumulatory' ogólnego przeznaczenia , na których wykonuje się wszelkie operacje ładowania danych, liczenia etc. Każda instrukcja ma dostęp do tych rejestrów.
2. Znacznik C z rejestru SREG to znacznik przeniesienia. Przykładowo jego znaczenie jest ważne przy dodawaniu liczb 16-bitowych. Dodając do siebie młodsze bajty owej liczby może nastąpić przepełnienie rejestru 8-bitowego (np. dodając do siebie 192 i 225) i wtedy ustawiany jest znacznik C. Można go potraktować jako przedłużenie rejestru z 8 do 9 bitów. Następnie dodając starsze bajty danej liczby 16-bitowej, dodajemy zawartość znacznika C, co w konsekwencji daje poprawny 16-bitowy wynik dodawania (wynika to z natury liczb binarnych). Tak samo przy wykonywaniu instrukcji przesuwania bity wypychane ładowane są kolejno do znacznika przeniesienia.
W podanym przeze mnie programie lsl R16 wysuwa kolejne bity zmiennej od MSB do LSB, które następnie instrukcją ror R17 ładowane są do uprzednio wyzerowanego R17. R18 to licznik zapętleń, przesuwanie trzeba wykonać 8x. Szczegółów możesz poszukać w kartach katalogowych AVR (lista instrukcji).

Gratuluję, jeśli zrozumiałeś o co mi chodzi ;)

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 09 lip 2008, 20:55

Muszę przyznać, że o wiele jaśniej teraz. Jeśli przyjdzie mi kiedyś samodzielnie, lub półsanmodzielnie napisać jakąś wstawkę assemblerową, to już będę wiedział jakich rejestrów użyć. Dzięki zatem za wyjaśnienie :)

Awatar użytkownika
gwozdex
Użytkownik
Posty: 879
Rejestracja: 24 lut 2006, 10:04
Lokalizacja: Czechowice-Dziedzice
Kontakt:

Post autor: gwozdex » 09 lip 2008, 21:30

Mnie bez problemu udaje się przesyłać dane pomiędzy PC a AVR! Urzywam równeż komponentu TComPort- uważam ze działa wyśmienicie! Podeślę Ci mój programik jak wrócę do domu- wtedy bedziesz wiedział czy masz z PC coś nie tak czy z AVR.

A nie zapomniałeś czasem o opóźnieniu po wysłaniu każdego bajtu?

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 09 lip 2008, 22:02

Z moich męczarni z transferem RS232↔AVR wynikało, że nie da się wysłać z Delphi znaku i zaraz odebrać innego.Odbierał znaki puste,lub krzaki,a także znaki #10 i/lub #13.

Mimo, że AVR grzecznie czeka przy komendzie WaitKey(),za to z wysłaniem z AVRa do PC jest już gorzej.Tutaj otrzymywałem najwięcej pustych/błędnych znaków. Czy mógłby mi Kolega przybliżyć temat opóźnień?

Awatar użytkownika
gwozdex
Użytkownik
Posty: 879
Rejestracja: 24 lut 2006, 10:04
Lokalizacja: Czechowice-Dziedzice
Kontakt:

Post autor: gwozdex » 10 lip 2008, 14:09

Witam!
Na początek wspomnę o czymś o czym zapomniałem w poprzednim poście, mianowicie: Bray's Terminal. Moim zdaniem wyśmienity program do obsługi RS-232 na licencji open source. Ponieważ swego czasu miałem problem z jego znalezieniem zamieszczam go w załączniku łącznie z moim prostym programikiem.
:arrow: bray's terminal

Sprawa opóźnień!
Po zapisaniu jednego bajtu do EEPROMU czekamy około 7ms co można załatwić w łatwiutko: Waitms 7 i po sprawie.
Skoro tak to wydawało by się, że wysyłając takowe dane z PC również trzeba poczekać te 7ms pomiędzy wysłaniem kolenych bajtów plus dodatkowy czas na inne operacje. Wiele zależy od konstrukcji twojego programu(ów)- ja wysyłałem bloki 32kB i okazało się , że żeby nie zgubić ani jednego bajtu to opóźnienie jakie jest wymagane to 50ms (czyli PC wysyła jeden bajt danych, czeka 50ms i wysyła drugi...). Zapewne można ten czas skrócić stosując choćby bufory wejściowe w AVR, ja jednak nie zdecydowałem się na to.
W załączniku mój programik. Aha jeszcze jedna ważna rzecz- program na AVR został tak napisany, że dana do zapisu do EEPROM jest akceptowana po odebraniu znaku #013.
Załączniki
RS_232_programy.rar
(189.15 KiB) Pobrany 356 razy

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 10 lip 2008, 15:16

Chyba się do końca nie zrozumieliśmy, więc zacznę może od początku.

Projekt, którym się obecnie zajmuję składa się z programu napisanego w Delphi, oraz programu na Atmege8, w Bascomie. Program w Delphi nie służy do samego wysyłania bajtów do RSa,a jest to jedynie jedna z jego funkcji. Z powodzeniem udaje mi się nawiązać łączność pomiędzy AVR a terminalem wbudowanym w Bascoma, jednak nie o to chodzi w moim projekcie. Program w Delphi przygotowuje najpierw dane,by je przesłać do AVR. Na początek chciałem zrobić coś prostego:

Delphi:

Kod: Zaznacz cały

var s:string;
begin 
  ComPort.open; 
  ComPort.WriteStr('test');
  ComPort.ReadStr(s,3); 
  ComPort.Close;
  if s='ack' then ShowMessage('Odebrano ACK');
End;
Programik ma sprawdzić, czy urządzenie połączone jest z komputerem. Niestety funkcja ComPort.Connected zwraca True, nawet jeśli kabel podłączony jest do komputera, ale nie do urządzenia.
Program w Bascomie wygląda natomiast tak:

Kod: Zaznacz cały

dim s as string*3
do
 s=waitkey()
 if s="start" then
  print "ack"
 end if
loop
tak więc Delphi zamiast odebrać słowo "ack", odbiera pusty string.

adi-niunio
Użytkownik
Posty: 308
Rejestracja: 04 mar 2004, 9:21
Lokalizacja: Zabrze
Kontakt:

Post autor: adi-niunio » 16 lip 2008, 11:49

SHIFT RIGHT ZMIENNA 7 albo ROTATE RIGHT ZMIENNA 7 , niestety nigdy nie jestem w stanie zapamietac, ktory nie wpisuje zer, tylko dziala w kolko , w sensie to co wychodzi wchoni na druga strone.
ogolnie, to przepraszam kolegow, bo niepomyslalem (jestem na wakacjach) i napsialem pierwsze co do glowy wpadlo, a odpowiedz nie byla trafna.

ODPOWIEDZ