Moje boje z AVRGCC.

Apr 23, 2004 38 Replies

Ehlo.



Siedze i oblatuje sie w subj. Nie powiem, rezultaty calkiem znosne, ale poleglem w pewnym miejscu, mianowicie stringi. Chcialbym napisac sobie procedurke wysylajaca stringa na LCD. I teraz nie bardzo wiem jak to zrobic, bo w GCC chyba nie ma takiego typu zmiennej, co prawda po glowie mi sie kolacze ze string 19 znakowy to nic innego jak np. char a[20] zakonczony zerem. Rzuccie jakims przykladem jak przekazac do procedurki stringa... bo jak nie... ;-))) Na powaznie, poprosze krotki przyklad (najlepiej dzialajacy) typu:



char lcd_send_string (char a[20]) { for (unsigned char f=1;f<strlen(a);f++) lcd_send_ascii(a[f]); return(0); }



int main (void) lcd_send_string ('Hello world');


PS. A propo's ostatniej dyskusji o promowaniu char-a do 16 bitowego integera. Odpowiedz jest w dokumentacji. ========================================================



7.3.21 Why does the compiler compile an 8-bit operation that uses bitwise oper-ators into a 16-bit operation in assembly? Bitwise operations in Standard C will automatically promote their operands to an int, which is (by default) 16 bits in avr-gcc. To work around this use typecasts on the operands, including literals, to declare that the values are to be 8 bit operands. This may be especially important when clearing a bit: var &= ˜mask; /* wrong way! The bitwise ”not” operator ( . ) will also promote the value in mask to an int. To keep it an 8-bit value, typecast before the ”not” operator: var &= (unsigned char)˜mask; ========================================================

PS2. Pewnie o stringach tez jest... ale cos nie moge znalezc... ghrrr. Z gory dzieki.


Nie tylko w gcc, ale w taka jest postac zapisu stringow w pamieci w jezyku C.

Jesli nie zamierzesz zwracac wyniki, mozesz zadeklarowac jako void. a ma byc wskaznikiem albo tablica, rozmiary podawac nie potrzeba (nie wolno? nie mam k&r pod reka) Deklaracja po uwzglednieniu tych uwacg moze wygladac tak: void lcd_send_string (char *a)

W C tablice sa indeksowane od 0, nie od 1

Cala procedurka po porawkach moze wygladac nastepujaco: void lcd_send_string (char *a) { int i; for(i=0;a[i]!=0;i++) lcd_send_ascii(a[i]); }

Albo, bardziej w stylu C:

void lcd_send_string (char *a) { while(*a) lcd_send_ascii(*a++); }

A tak poza tym to zanim zaczniesz czytac gcc-faq polecam jakas ksiazke o podstawach C. Faq jest dla zaawansowanych uzytkownikow, ktorzy chca poznac "smaczki" gcc, a nie uczyc sie programowania od podstaw.

char moj_tekst1[] = "pierwszy tekst"; char moj_tekst1[] = "drugi tekst";

void LCD_Print(char *data) { while(*data) { lcd_send_ascii(*data++); } }

i teraz: LCD_Print(moj_tekst1); LCD_Print(moj_tekst2); albo LCD_Print("kolejny napis"); Tylko mala uwaga - kazdy taki string zajmuje pamiec RAM, zatem jak masz ich duzo to moze Ci zabraknac RAM-u. Rozwiazaniem jest umieszczenie tekstow we flashu i wyswietlanie ich stamtad, ale nie wiem jak to zrobic w GCC(na codzien pracuje w IAR-C dla AVR), chyba cos z memory_attribute, musisz poszukac w dokumentacji GCC.

No i polecam dobra ksiazke o ANSI C.

Pozdr AK

Podstawy, podstawy. :) I nie ma znaczenia, czy w avr-gcc czy inszy proc:

void lcd_send_string (char *txt) { while (*txt) lcd_send_ascii (*txt++); }

Sposób użycia: lcd_send_string ("ABCD");

A wracając do avr-gcc to poczytaj sobie o umieszczaniu stringów w pamięci programu, normalnie trafiają do pamięci danych i szybko się ona może skończyć.

Ja używam w avr-gcc standardowego mechanizmu printf (RTFM: funkcja fdevopen) i to jest najwygodniejsze rozwiązanie pod słońcem. Jedyna wada to powiększenie kodu programu o kilka KB. A stringi w kodzie bardzo łatwo się używa:

printf_P (PSTR ("test = %d\r\n"), test);

Jasne. Odpowiem wszystkim na raz zeby nie odpisywac kazdemu. Z C a w zasadzie CPP mialem kontakt krotki na uczelni gdzies na 2 roku. Potem odkupilem licencje na Keila i mniej wiecej w tym samym czasie przestalem zajmowac sie rodzinka '51. Ale wzielo mnie na C bo chwilowo obijam sie w domku no i trzeba bylo ruszyc do przodu. Po ksiazke uderze w poniedzialek, bo w tym tygodniu mialem jeszcze troszke zajec. Co zas do samego jezyka wysokiego poziomu, to jestem mile zaskoczony. Do tej pory potrafilem pisac programy po 8-12 KB w czystym asm-ie. Co prawda komentarze zajmowaly 20x wiecej niz program, ale bylem zadowolony i po powrocie do czegos po roku dawalem sobie rade bez problemu. Ale widze ze bylem w bledzie ;-))) Z drugiej strony podpatruje jak soboe GCC radzi w przenoszeniu pewnych rzeczy z C na asm-a. I czasem czlowiek mile sie zaskoczy a czasem odwrotnie ;-)

To juz wiem. Na razie musze poczytac o podstawach, formatach, uniach, strukturach. Co prawda zaciekle pisalem w Paszczalu i Delphi, ale oprocz algorytmu niewiele sie zgadza ;-))) A czytanie manuala do GCC no coz... jak ma sie braki w podstawach...

Tez sie kiedys tego dowiem ;-))))

Dzieki wszystkim, milej nocki ;-)

Ty potrzebujesz kursu C :-) Polecam klasyke Kernigham & Ritchie.

int main (void) { lcd_send_string ("Hello world"); }

zwroc uwage na ' i "

J.

A tak usilowalem nie dac sie zdemaskowac... ;-))) Co do ksiazki to trzymam za jezyk, ale jak po przeczytaniu spisu tresci nie bede madrzejszy to zaskarze... ;-))) wydawnictwo ;-)

Milej nocki.

Zdecydowanie _nie_ - taka klasyka nadaje sie dzisiaj tylko do muzeum. Tylko ANSI C sie liczy. A potem rozszerzenia C99.

No to sie troche rozminalem. Ja mialem inny problem. Mianowicie przy PORTA &= _BV(7) czy PORTA |=

0X80 kompilator wykonywal SBI. Dwie linijki nizej robilem PORTA &= ~_BV(7). Wtedy kompilator tlumaczyl mniej wiecej tak: in r16,porta ldi r17,0x7F and r16,r17 out porta,r16 Ale jak podalem jawnie PORTA &= 0x7F to tlumaczyl "poprawnie" na CBI. Pomoglo zapisanie jako PORTA &= (unsigned char) ~_BV(7).

Milosz Skowyra napisa³:

Problem by³ wtedy tego typu, ¿e mimo jawnych typecastów kompilator i tak sobie promowa³ na inta niestety. Na temat stringów nic nie piszê, bo ju¿ Ci inni dobrze odpowiedzieli

W C++ jest std::string, ale to nie ta klasa wagowa. :-)

void procedurka(const char* const ten_string) {

}

:-)

I nie znajdziesz, w C _nie ma_ stringow.

Pozdrawiam Piotr Wyderski

Nowsze wydania chyba juz opisuja ANSI. A w razie czego roznice sa niewielkie, a czesci wspolnej sporo. Jak jest ze stringami i wskazniki to sie dowie :-)

J.

Zdecydowanie popieram, to antyk wprowadzajacy wiecej zamieszania, niz wyjasniajacy.

C99 to nie jest rozszerzenie, tylko wlasnie _standard_, ISO/ANSI C99. :-) I jego wlasnie nalezy sie trzymac. No, jesli zamierza sie pozostac przy C... Do programowania niskopoziomowego znacznie lepiej nadaje sie jednak C++, m.in. dzieki:

a) przestrzeniom nazw (w koncu brak konfliktow nazw obiektow zadeklarowanych w roznych jednostkach translacji!); b) metaprogramowaniu, pozwalajacemu na automatyczne i dokladne dopasowanie struktury obiektu do _konkretnej_ potrzeby, a nie zmuszajacy do uzywania ogolnego rozwiazania w kazdym przypadku; c) mozliwosci tworzenia aliasow przestrzeni nazw, co umozliwia bezproblemowa wymiane modulow dostarczajacych tego samego interfejsu, lecz (znacznie) rozniacych sie implementacja.

Pozdrawiam Piotr Wyderski

To juz wiem, musze wiecej odrdzewiacza popijac ;-))) W paszczalu stosunkowo rzadko uzywa sie wskaznikow w porownaniu do C, przynajmniej afair, ale zasady te same ;-) Wlasnie boleje nad brakiem typu boolean ;-((( Ale znalazlem posrednie rozwiazanie.

W C99 jest typ boole'owski i nazywa sie _Bool. Zaleca sie jednak uzyc naglowka <stdbool.h>, co daje znane z C++ slowa kluczowe bool, true i false. Sprawdz, czy Twoj kompilator moze pracowac w trybie C99. Jesli nie -- wyrzuc go i uzyj takiego, ktory potrafi. :-) BTW:

formatting link
Pozdrawiam Piotr Wyderski

Jak sie nie chodzi na zajecia to rzadko. Nie bylo list na cwiczeniach ?

W koncu gdzies za tym stoi adres pamieci i niewiele wiecej.

Ale ile to jest 4[a+2], to sie w pascalu nie dowiesz :-)

J.

To bylo jakies 4 lata temu, na drugim roku, wyklad z Algorytmow prowadzony przez faceta promujacego swoja dzialanosc w postaci ksiazki... a laborki z pania ktora pisala na tablicy programy duzymi literkami, zas na pytania studentow dlaczego tego nie da sie skompilowac w Borlandowym CPP, odpowiedziala tekstem SOA #1. Pani z informatyka miala tyle wspolnego co ja z biologia ;-) Nie mam pretensji do prowadzacych bo wiadomo ze zadna szkola czy uczelnie nie przekaze wiedzy o ile student nie bedzie sie chcial dowiedziec wiecej... ale to co usilowali nam przekazac z C to zakrawa na kpine.

A byly... z ciekawosci nawet popatrze... pierwsze zadanie: Napisac program wyswietlajacy na ekranie dowolny rysunek. Kryteria oceny: 3 - wyswietlenie rysunku, 4 - rysunek kolorowy z elementami animowanymi przy wykorzystaniu przelaczania stron grafiki, 5 - dodatowo musi wydawac dzwieki. Drugie tez niezle... liczenie dlugosci przeciwprostokotnej trojkata na podstawie dlugosci bokow, kryteria jeszcze bardziej zenujace. Oooo, ostatnie jest niezle, baza danych studentow, oceny z 5 przedmiotow, musi uzywac wskaznikow na 3, sortowanie wg przedmiotow i ocen na 4, mozliwosc edytowania wprowadz. danych na 5 ;-))) Nio... ale pamietam ze i tak sporo napisalem.

Zgadza sie, ale ciezko jest sie przestawic, zwlaszcza po latach asm-a. W Delphi rzadko uzywalem wskaznikow, chyba ze trzeba bylo przekazywać jakies tabele czy cus... Kwestia przestawienia sie,czytania i uzywania.

Hmmm, mozesz rozjasnic ??

I dreczy mnie jeszcze pare rzeczy... dokumentacja jest sredniawo napisana, nie moge znalezc paru informacji. Np. jak umiescic jakas zmienna pod konkretnym adresem w pamieci, albo ze zmienna ma byc w rejestrze, tudziez jak pisac program zeby po watchdogu poszedl dalej, a nie zaczynal od zera (o init i noinit czytalem ale przynajmniej na razie ciemnosc widze... ;-) kwestia czasu).

Milego wieczorka.

Dnia sob 24. kwietnia 2004 21:39 Milosz Skowyra napisał(a):

Cześć, Miłosz!

Zawsze możesz się przyłożyć ;-)

A po co zmienna pod konkretnym adresem? To kompilator ma sobie ten sos mieszać. Trzeba by chyba osobny segment stworzyć...

register (patrz pkt. 7.3.4 w sekcji FAQ)

Oooo, a _to_ chyba niebezpieczne - po co ten watchdog jest?

Jak najbardziej. Ja używam od ponad roku i nadal uważam się za newbie ;-)

I wzajemnie

to samo co a[4+2] czyli a[6] znaczy 7 z kolei element tablicy a

Tak zrobilem... w katalogu INFO jest dosc sporo informacji... caly czas czytam ;-)

Przyzwyaczilem sie do pewnej konwencji tworzenia menu. oczywiscie w asmie bez problemu. Ze flashu mam zapisane menu w postaci:

1,1,"Adres 1",20,#addres_1,21

I tak 1,1 oznacza zagniezdzenie menu, "Adres 1" ma byc na wyswietlaczu,

20 - to marker ze trzeba wyswietlic wartosc, #adres_1 to polozenie zmiennej w pamieci, 21 to znacznik konca linijki. I tak dalej. Dlatego przydaloby mi sie wiedziec gdzie jest zmienna ;-)

Fakt, znalazlem wczesniej i jakos zapomnialem ;-(

Podczas realizowania pewnych cykli czasem po watchdogu procek powinien zaczac od nowa, a czasem kontynuowac poprzednie dzialania. Dlatego wolalbym sam decydowac co i jak ;-)

Jeszcze zostalo mi wiele lat zycia wiec pewnie kiedys to pojme ;-)

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required