Programowanie uC...

Loading thread data ...

Jarek wrote: > Czy ktoś mi może powiedzieć jakie funkcje z języka C są potrzebne do > programowania uC??

Operacje bitowe. Ogólnie dużo zapisów typu:

#define RED_LED_BIT 3 #define LED_PORT PORTC #define RED_LED_ON LED_PORT|=1<<RED_LED_BIT #define RED_LED_OFF LED_PORT&=~(1<<RED_LED_BIT)

... RED_LED_ON; ...

ewentualnie konstrukacje typu:

a=(long)((((unsigned char *)data)[3])&0x3d);

Jesli zrozumiesz co pisze powyżej to drzwi otwarte do programowania uC ;)

I praktycznie zbędna jest wiedza o stdio, stdlib, na małych mikrokontrolerach biblioteki zewnątrzne się nie przydają.

Podsumowując: moim zdaniem nacisk na sam język C (bity, wskaźniki, etc) natomiast można pominąc biblioteki standardowe.

Reply to
Sebastian Bialy

Tą linijkę ( wyrwaną z kontekstu jakiegoś niezbyt czytelnie napisanego programu ) to lepiej pozostaw sobie na moment jak już opanujesz podstawowe elementy składni : bloki programu, intrukcje warunkowe, iteracje itd. Programowanie uC wbrew pozorom nie polega tylko na żąglowaniu bitami, rzutowaniu typów, itp niskopoziomowymi operacjami. Owszem, że wydusić ze sprzętu jakieś działanie, to jest niezbędne. Ale każdy bardziej złożony program zawiera dużą część niezależną od sprzetu, która jest zapisem jakiegoś algorytmu, który ten program realizuje. I ten algorytm może identycznie wyglądać w C na Avr'a, 8051,PIC'a i na PC'cie.

Drzwi to otwiera nauczenie się solidnych podstaw niezaleznych od platformy.

Czyżby ? I wszytkie operacje na stringach, pamięci itp realizujesz na piechotę własnymi funkcjami... Biblioteki standartowe są m.in. po to żeby zapewnić jaka taką przenośność kodu. Pewnie, że często jest to okupione wiekszą objętością kodu i pisze się własne uproszczone wersje funkcji ( sam tak robię ). Ale pisanie że biblioteki się nie przydają na uC, to raczej nie jest dobra wskazówka dla początkujących.

Reply to
"Miłosz K."

Jesli nie wiesz to nie piszesz w C :-)

Przy czym ten przyklad nawet nie jest trudny :-) Po tudny to trzeba zajrzec do Bieleckiego.

J.

Reply to
J.F.

Oczywiście:

Masz zmienną long a;

chcesz sprawdzić czy ustawiony jest bit nr 19.

Typowe podejście:

#define BIT 19

if(a&(1<<BIT)) { ... }

podejście generuje 4 instrukcje porównania (arv-gcc).

Optymalizacja polega na: zamianie a na wskaźnik, zamianie wskaźnika na wskaźnik na chary, pobraniu chara na pozycji która zawiera bit, i wyandowaniu go. Efekt długiej linijki to 1 instrukcja porównania w asm w avr-gcc (sprawdzone doświadczalnie).

if( ((unsigned char)(&(a)))[BIT/8])&(1<<(BIT-(8*(BIT/8))); ) { ...}

Pisze z głowy i może być z błędem ale mniej więcej o to chodzi. Powtarzam - typowy programista w C byłby zdziwiony taką składnią, ale dla mnie dale to pare cykli mniej. Jedyna rzecz nieprzenośna: little-endian, big-endian, ale łatwo napisac wariant odwrotny.

Dalej będe się upierał, że pisanie w uC wymaga znajomości takich sztuczek. Szczegónie kiedy mowa o przerwaniach.

Napisałem w dodatku z usmieszkiem ";)" żeby była jasna sprawa ze _troche_ żartuje.

W 8-bitowym AVR popełniam własnie palikację, gdzie long long jest za mały :(

Reply to
Sebastian Bialy

Jakie operacje ? Masz na myśli printf ? Za bardzo uniwersalne i zajmuje mase pamięci. A może strlen ? Taką drobnicę można napisać w 2 minuty. To może malloc ? O akurat malloc używam, choć na wypasionych atmega dużą ilością pamięci. W zasadzie nie znam przydatnych operacji poza strcmp, strcpy, memset etc. Ale każda z nich jest na tyle trywialna że można napisać własną lepszą czesto. Ja w moich programach uC na palcach jednej reki policze #include <stdio.h> które zastosowałem. I kod jest mimo to przenośny i to nawet dośc sprawnie pomiędzy róznymi architekturami. Bo niestety stdio nie ma przenośnej funkcji on_timer czy czegoś w tym rodzaju ... która akurat jest bardziej przydatna od wypasionego printfa.

Problem w tym, że dostając do reki 90S2313 nie działa printf("Hello world"); bo nie ma na czym wyświetlić. Trzeba najpierw porządnie podłubać z UARTem, a wtedy czesto się okazuje, że własne procedury sa o wiele wydajniejsze niż wbudowane w bibliotekę (co nie przeszkadza im mieć np. takiej samej skladni i obsługi - żeby zapewnić przenośnośc).

Nie jestem wrogiem bibliotek standardowych w ogóle, ale na uC naprawde żadko mialem okazje uznać je za przydatne do czegokolwiek.

Reply to
Sebastian Bialy

Sebastian Bialy napisał(a):

nie ucz ludzi złych nawyków. nauczy się takiego korzystania z makr i zacznie robić koszmarki w stylu:

#define MUL(x,y) x*y int foo = MUL(1+2,3+4);

albo co gorsza:

#define FOO x=1;y=2 if (bar) FOO;

parametry makr wypadałoby ubierać w nawiasy. do tego jeśli makro jest wyrażeniem, wrzucić je całe w nawias, a jeśli instrukcją to ubrać w do ... while(0).

w.

Reply to
Wojtek Kaniewski

Heh, a gdzie ja użyłem parametrycznych makr :) ?

Zdajesz sobie sprawę, że napisanie procedury zapalającej diodę generuje narzut w postaci paru bajtów kodu ? Przy pisaniu na dużego peceta przez myśl by mi nie przeszlo robić takich numerów. Przy pisaniu na uC potrafi uratować dupsko.

Reply to
Sebastian Bialy

Sebastian Bialy napisał(a):

Przykłady, które podałeś sugerują, że większość twoich programów nie przekracza wilkością pamięci 90S2313. Przy takiej pamięci to faktycznie czasem trzeba zaciemnić kod żeby wydusić te parę bajtów oszczędności. Tylko jak ktoś na początku swojej drogi zadaje pytanie od czego powienien zacząć, to po takich radach dojdzie do (fałszywego) wniosku, że to są właściwe wzorce do naśladowania.

A potem np. niektórzy ludzie nauczeni pisac w takim stylu biorą udział w projekcie ,gdzie powstają dziesiątki tysięcy lini kodu, a mnie szlag trafia, jak muszę czytać takie źródła w których roi sie od "magic numbers", komentarzy jak na lekarstwo, a pojedyncze funkcje maja po kilkaset lini.

Ale ponieważ odeszliśmy od zasadniczego tematu , to ja polecam do nauki siegnąć po praźródło czyli Kerninghan&Ritchie. Pozycja w sam raz sie nadaje do uC, bo wszystkie przykłady są do obsłużenia przy pomocy bibliotek standardowych.

Reply to
"Miłosz K."

Sebastian Bialy napisał(a):

#define A 1+2 #define B 3+4 #define C A*B

taki przykład jest lepszy?

zdaję sobie sprawę. nigdzie nie pisałem o funkcjach, ani nie zanegowałem sens korzystania z makr. po prostu jeśli chcesz kogoś uczyć, to ucz od razu tak, żeby sobie w przyszłości nie odstrzelił stopy.

w.

Reply to
Wojtek Kaniewski

Sugerujesz, że mając np. ARM mogę założyć nieskończony czas wykonywania procedury timera ? Sztuczki sztuczkami, ale programując sprzęt nie ma mowy czasami o byciu grzecznym programistą. Cykl jest cykl i go nie przeskoczysz. Swoją droga ostatnio miałem do czynienia wlasnie z podejściem "przenośnym" i skończyło się to za zgrzytaniu zębami na jakośc kodu wygenerowanego przez avr-gcc. Musiałem napisać osobne procedury dla każdego procesora z #ifdef. Nie wszystko można zrobić przenośnie.

Oczywiście, że nie mamy oboje racji. Ani UART_BUFFER=c; ani fprintf(uart,"dupa"); nie są idelne, zależy od zastosowań. Ale zakładam (o ja maluczki) że raczej człowiek ucząc się programować zacznie od migania diodą a nie od napisania FFT na ATTiny.

Świetnie, bo mnie też szlag trafia. Tylko że to chyba nie ma związku z tym wątkiem ?

W tej ksiązce trafisz na przykład migania diodą na 90S2313 albo może na jakąs skromną procedurę inicjacji timera0 z użyciem biblioteki standardowej ?

Obawiam się że sporo przykładów musisz odrzucić w przedbiegach - nie ma monitora (stdout/stdin). Jedyne wyjście to UART żeby choć troche z tych przykładów uruchomić, ale najpierw trzeba wiedzieć JAK go uruchomić.

Reply to
Sebastian Bialy

Może i lepszy, tylko akurat w podanym przeze mnie przypadku raczej takiej wpadki nie bedzie (bo po co liczyn numer pinu ?).

Reply to
Sebastian Bialy

Masakra to już lepiej stosować coś ala MISRA C i wlutować szybszy kwarc;) Bo optymalizacje na etapie klepania kodu są bez sensu przy dobrym kompilatorze.

Reply to
point

na szybko sklecony przykład obrazujący idee:

*************** main.c ************* #define BIT 13 long a=0; char x; void bad(void) { if(a&((long)1<<BIT)) { x=0; } } void good(void) { if( (((unsigned char *)(& a))[BIT/8])&(((unsigned char)1)<<(BIT % 8)) ) { x=0; } } int main(void) { return 0; } **********************************************

kompilacja:

@avr-gcc -O3 -Wall -mmcu=atmega8 -Wall -o test.elf main.c @avr-objdump -h -S test.elf >test.lst

**********************************************

wyniki:

0000005c <bad>: 5c: 80 91 60 00 lds r24, 0x0060 60: 90 91 61 00 lds r25, 0x0061 64: a0 91 62 00 lds r26, 0x0062 68: b0 91 63 00 lds r27, 0x0063 6c: 2d e0 ldi r18, 0x0D ; 13 6e: b6 95 lsr r27 70: a7 95 ror r26 72: 97 95 ror r25 74: 87 95 ror r24 76: 2a 95 dec r18 78: d1 f7 brne .-12 ; 0x6e 7a: 81 70 andi r24, 0x01 ; 1 7c: 90 70 andi r25, 0x00 ; 0 7e: 89 2b or r24, r25 80: 11 f0 breq .+4 ; 0x86 82: 10 92 64 00 sts 0x0064, r1 86: 08 95 ret

00000088 <good>: 88: 80 91 61 00 lds r24, 0x0061 8c: 85 ff sbrs r24, 5 8e: 02 c0 rjmp .+4 ; 0x94 90: 10 92 64 00 sts 0x0064, r1 94: 08 95 ret

Jak widac jest _zasadnicza_ różnica w jakości.

PS. Mam nadzieje, że nie pomyliłem się w liczeniu bitów :)

Reply to
Sebastian Bialy

Sebastian Bialy napisał(a):

nie wiem jak mam Ci inaczej tłumaczyć, że nie piję konkretnie do Twojego kodu tylko do sposobu korzystania z makr, który prezentujesz. ktoś może _w_przyszłości_, nie będąc świadomym potencjalnych problemów, wziąć z Ciebie przykład.

po prostu jestem zdania, że jeśli rzuca się przykładowym kodem, to nie na skróty, tylko porządnie, zgodnie ze wszelkim zasadami sztuki. chyba, że zaznaczy się, że w zasadzie nie powinno się tak pisać, chyba że wie się co się robi, że to tylko ilustracja problemu itd.

w.

Reply to
Wojtek Kaniewski

Użytkownik Sebastian Bialy napisał:

...

...

I tak filozofia Windows (z brzytwą na poziomki) zawitała do urządzeń, które powstały w założeniu jako efektywne. :)))

Reply to
A.Grodecki

Sebastian Bialy napisał(a):

#ifdef jest własnie jednym z elementów do tworzenia przenośnego kodu ( jeśli wprost jest nieprzenośny )

Jak programy do migania diodą będzie pisał byle jak ( korzystając z bylejakich porad ), to nigdy nie dojdzie do FFT. Ale jak nabędzie doświadczenia ( i dobrych zwyczajów ) w C np. na PC, to bedzie w stanie napisać nawet FFT jako swój pierwszy program na mikrokontroler.

Masz rację, ale moją intencją było wskazanie pozycji ogólnej n.t. C, w której autor nie trzyma sie konkretnego kompilatora, OS itp.

Niestety , nie kojarzę żadnej pozycji w j.polskim która byłaby jednoczesnie podręcznikiem podstaw C i jeszcze na przykładzie uC.

Reply to
"Miłosz K."

Sebastian Bialy napisał(a):

której wersji kompilatora używasz? 3.4.4 generuje coś takiego:

0000005c <bad>: 5c: 80 91 60 00 lds r24, 0x0060 60: 90 91 61 00 lds r25, 0x0061 64: a0 91 62 00 lds r26, 0x0062 68: b0 91 63 00 lds r27, 0x0063 6c: 95 ff sbrs r25, 5 6e: 02 c0 rjmp .+4 ; 0x74 <bad+0x18> 70: 10 92 64 00 sts 0x0064, r1 74: 08 95 ret

fakt, kopiowanie całego słowa do rejestrów jest zbędne, ale to pokazuje, że z wersji na wersję różnica przestaje być zasadnicza. pewnie za jakiś czas oba przypadki będą przekładane na identyczny kod, jeśli już tak nie jest w gałęzi 4.x.

w.

Reply to
Wojtek Kaniewski

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.