Zmienne bitowe w AVR

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
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Zmienne bitowe w AVR

Post autor: Aro » 18 lut 2007, 10:57

Czy da się zmniejszyc rozmiar instrukcji wpisującej i odczytującej zmienne bitowe w C? Bo instrukcje typu
uint8_t zmienna ;
.........
zmienna |=(1<<2);

......
if(zmienna&(1<<2)).....


zajmują więcej pamięci flash niż ze zmiennymi bajtowymi, a znowu bajtowe więcej RAMu. Jest na to złoty środek?

michalko12
-
Posty: 2
Rejestracja: 14 sty 2007, 0:57

Re: Zmienne bitowe w AVR

Post autor: michalko12 » 19 lut 2007, 21:53

Wybierając język w którym chce sie pisać program trzeba liczyć się z pewnymi kompromisami, albo łatwość i szybkość pisania programu albo zwiezły, oszczędny i szybki kod wynikowy. Od języka wysokiego poziomu nie mozna wymagac wszystkiego, w tych czasach zasoby w procesorach są tak duże ża na takie kwestie nie zwraca sie uwagi, jesli jest cos krytycznego to trzeba zejść na język niższego poziomu i robić np wstawki asemblerowe.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 20 lut 2007, 9:06

Zawsze myślałem że kompilatory C najlepiej przeprowadzają optymalizacje kodu. Jeśli w asemblerze są jakieś rozkazy porównania zmiennych bitowych to mógłbyś pokazac jak taki kod będzie wyglądac w asemblerze , byłbym wdzięczny. Przypominam jeszcze że nie chodzi o program komputerowy tylko o procesor AVR , bo obniosłem takie wrażenie czytając twój post. Nie zależy mi też na małym pliku źródłowym tylko na jak najmniejszym kodzie wynikowym i jak najmniejszej zajętości RAMu.

Awatar użytkownika
marcing
Użytkownik
Posty: 868
Rejestracja: 14 lut 2006, 14:13
Lokalizacja: z pociągu...
Kontakt:

Post autor: marcing » 20 lut 2007, 13:22

Aro - w asemblerze AVRków są polecenia związane z bitem T w rejestrze SREG...
Wykorzystać je można dość łatwo - wpierw ładujesz interesujący Ciebie bit ze zmiennej do T, sprawdzasz jaki ma stan, i wykonujesz skok do odpowiedniego miejsca w programie...

Kod: Zaznacz cały

BST rejestr, numerbitu  ;przepisanie bitu "numerbitu" z rejestru przechowującego zmienną
BRBS 6, adresskoku     ;jeśli bit ma być ustawiony
BRBC 6, adresskoku2   ;jeśli bit ma być wyzerowany

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 20 lut 2007, 21:38

I to mi sie podoba :grin: Musze sie jeszcze upewnic czy w połączeniu z moim programem to będzie wyglądac tak?

Kod: Zaznacz cały

//nie robiłem nigdy wstawek asemblerowych w C
//więc kod...   to chyba nie jest poprawnie ale to tak tylko żeby było jakoś napisane

//uint8_t zmienna  
LDI R19 , 0x00  //deklaracja zmiennej

OUT R19 , 2     //ustawienie drugiego bitu w zmiennej

BST  R19 , 2   //przepisanie bitu do bitu T rejestru SREG 
BRBS  6 , gdzieś  // ->pod adres
....
Mam jeszcze pytanie czy tylko bit T można wykorzystac czy inne bity tego rejestru też można?
I jeszcze jak zrobic taką instrukcję: if(!((PINx &(1<<x)) || (instrukcja sprawdzająca bit)) ?

Awatar użytkownika
marcing
Użytkownik
Posty: 868
Rejestracja: 14 lut 2006, 14:13
Lokalizacja: z pociągu...
Kontakt:

Post autor: marcing » 20 lut 2007, 21:47

Inne NIE! Ten jeden jest przewidziany dla dowolnego wykorzystania...
Pozostałe odpowiadają za stan uP (bit I za włączenie przerwań).

Korzystając z C pamiętaj o zapamiętaniu rejestru przed obsługą wstawki asemblerowej, i przywróceniu po zakończeniu obsługi...

Co do samego "mieszania" C i asemblera - tu pomoże Tobie ktoś bardziej doświadczony (np: Tasza, Koppel, ZbeeGin)

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 21 lut 2007, 12:08

A o jakim kompilatorze mowa? Bo wstawki asemblerowe trochę inaczej wyglądają w GCC, inaczej w Keilu... czy innych kompilatorach.

Czy taka wstawka na pewno będzie bardziej optymalna? Pominąwszy MCS51 bardzo mało współczesnych procesorów ma specjalny obszar obsługiwany bitowo. W asemblerze AVR istnieją operacje ustawiające / zerujące bity w przestrzeni wejścia wyjścia. Na przykład operacja:
PORTB |= 1<<3;
Zostanie zamieniona na jedną instrukcję. Natomiast czy działanie zostanie wykonane tak:
1. Wczytanie zmiennej do rejestru
2. Skopiowanie wybranego bitu do flagi T
3. Skok względem T
czy tak:
1. Wczytanie zmiennej do rejestru
2. Operacja AND ze stałą
3. Skok względem flagi zera
To będzie tyle samo kodu i tyle samo cykli. Ogólnie obsługa zmiennych bitowych w AVR zawsze będzie wolniejsza niż obsługa zmiennych bajtowych. Ale zwykle jest to kwestia jednej instrukcji więcej.
marcing pisze:Korzystając z C pamiętaj o zapamiętaniu rejestru przed obsługą wstawki asemblerowej, i przywróceniu po zakończeniu obsługi...
Niekoniecznie. W GCC podaje się we wstawce listę rejestrów traconych. Kompilator sam je zapisze i odzyska jeśli uzna, że mogą one zawierać potrzebne dane. Jest to o tyle fajna sprawa, że może się okazać, że reszta programu z naszego rejestru nie korzysta i nie trzeba go odzyskiwać :)

Awatar użytkownika
marcing
Użytkownik
Posty: 868
Rejestracja: 14 lut 2006, 14:13
Lokalizacja: z pociągu...
Kontakt:

Post autor: marcing » 21 lut 2007, 12:28

Koppel pisze:W GCC podaje się we wstawce listę rejestrów traconych. Kompilator sam je zapisze i odzyska jeśli uzna, że mogą one zawierać potrzebne dane.
Jak zwykle nie napisałem - jakiego rejestru... chodziło mi o SREG.
Chociaż nie wiem jak to w AVR-GCC wygląda...


Ale co do sprawdzania stanu bitu za pomocą AND - jak najbardziej się z tym zgadzam.

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 21 lut 2007, 12:34

marcing pisze:chodziło mi o SREG
Nie wiem czy w jakimkolwiek kompilatorze C trzeba pamiętać jego stan. W obsłudze przerwania jest on zapisywany automatycznie, a w kodzie jego stan nie ma znaczenia pomiędzy poszczególnymi instrukcjami. Wstawki asemblerowej i tak nie umieszczamy przecież między jedną a drugą częścią dodawania dwóch liczb 16 bitowych :P
Ale piszę to jedynie po swoich doświadczeniach z GCC i niewielkich doświadczeniach z Keil'em.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 22 lut 2007, 10:48

To teraz przynajmniej wiem że prościej się nie da. Wyjde troche poza temat. Czy da się uprościc jednorazowe sprawdzenie naciśnięcia przycisku bez zatrzymywania programu?
Ja to robie w taki sposób:

Kod: Zaznacz cały

uint8_t sprawdz;
if(!((PINx &(1<<x)) || (sprawdz)))
{
   sprawdz=1;
   instrukcje
   .....
}
if(PINx &(1<<x)) sprawdz=0;
jest to dośc pamięciożerne zarówno FLASH jak i RAM. Jakby "sprawdz" kożystac z bitów to zajętośc RAM sie zmniejszy ale FLASH wzrośnie i to sporo.

ODPOWIEDZ