39
Programowanie
Elektronika dla Wszystkich
Dzi zajmiemy siê czym, od czego zaczyna
siê wiêkszoæ ksi¹¿ek o C dla du¿ych kom-
puterów. Dlaczego dopiero teraz? Wspomi-
na³em ju¿ o tym i napiszê raz jeszcze: mikro-
kontrolery rz¹dz¹ siê innymi prawami ni¿
stacje robocze. Tam gdzie w stacji roboczej
wystêpuje BIOS oraz System Operacyjny,
sprawiaj¹ce razem, ¿e wypisanie informacji
na ekranie jest najprostsz¹ mo¿liw¹ rzecz¹,
tam w mikrokontrolerze... nie ma nic. Musie-
limy po kolei nauczyæ siê podstawowych
operacji na rejestrach, dopiero póniej wspi-
naæ siê coraz wy¿ej. Szczêliwie rejestry
mamy ju¿ za sob¹. Dzi na celu mamy dotar-
cie do funkcji printf oraz jej bliskich znajo-
mych. Dowiemy siê, jak realizowane s¹ ope-
racje strumieniowe tak naturalne w du¿ych
maszynach. Nie bez znaczenia jest fakt
powstania nowej p³ytki. Funkcja printf, bar-
dzo uniwersalna i o wielkich mo¿liwociach,
zajmuje stosunkowo du¿o pamiêci programu.
Hello world
Stwórzmy folder na nowy program. Skopiuj
do niego plik makefile. Mo¿esz wzi¹æ go z
poprzednich programów albo te¿ bezpored-
nio z folderu C:\WinAVR\sample. W Program-
mers Notepadzie tworzymy nowy projekt.
Mo¿esz nazwaæ go na przyk³ad helloworld.
Do projektu dodajemy plik makefile i zaczy-
namy jego edycjê. Niezbêdne zmiany zazna-
czone s¹ na rysunku 37.
Teraz zgodnie z wprowadzonymi zmiana-
mi tworzymy g³ówny plik programu o nazwie
main.c. Dodajemy go do projektu w oknie
Programmers Notepada. W pliku tym wpisu-
jemy kod z listingu 52. Skompilowanie pro-
gramu przyniesie dwie niespodzianki:
1. Program zajmuje zaskakuj¹co du¿o miejsca
w pamiêci (u mnie ponad 1kB!).
2. Program w zasadzie nic nie robi, a raczej:
nie daje ¿adnych zewnêtrznych oznak dzia³ania.
Pierwszy problem zaskoczy³ mnie kiedy,
prawdopodobnie tak samo jak móg³ zasko-
czyæ teraz wiêkszoæ Czytelników. Jego roz-
wi¹zanie wymaga nieco gimnastyki. Ze
wzglêdu na objêtoæ materia³u poczekamy
z tym do czêci 8. Teraz przyjrzyjmy siê prob-
lemowi z nicnierobieniem naszego programu.
Pytanie podstawowe brzmi: gdzie proce-
sor ma wys³aæ podany mu napis Hello
world!? W typowym programie
komputerowym bêdzie to zwyk-
le konsola... Nasza p³ytka posia-
da wywietlacz LCD, jednak
kompilator nic o tym nie wie.
Posiada tak¿e port szeregowy.
Wiele kompilatorów w³anie
port szeregowy uzna³oby za
domylne wyjcie dla naszego
napisu. W AVR-GCC zosta³o to
rozwi¹zane inaczej. Domylnym
miejscem, gdzie dane bêd¹ wysy-
³ane, bêdzie pierwsze otwarte
urz¹dzenie. Zanim przejdziesz
dalej, zajrzyj do ramki ABC... C
Jak dzia³aj¹ strumienie.
W ramach kursu nie mieli-
my jeszcze okazji zaj¹æ siê por-
tem szeregowym. Zróbmy to teraz. Zgodnie
z tym, czego nauczylimy siê do tej pory,
funkcje zwi¹zane z transmisj¹ danych umie-
cimy w oddzielnym module. Utwórz pliki rs.c
oraz rs.h. Pamiêtaj, aby do pliku makefile
dodaæ nowy plik kodu ród³owego. Przypo-
minam o tym na rysunku 38. Kod, jaki nale-
¿y wpisaæ w plik rs.c, znajduje siê na listingu
53. Nie ma w nim nic niezwyk³ego w prak-
tyce przyk³ady takie mo¿na znaleæ w doku-
mentacji technicznej procesorów AVR.
Listing 54 pokazuje kod, który powinien
znaleæ siê w pliku nag³ówkowym. Deklaru-
jemy tutaj funkcje, które zdefiniowane zosta-
³y w pliku ród³owym. Od tej chwili bêdzie-
my mogli swobodnie u¿ywaæ ich wszêdzie
tam gdzie do³¹czymy plik rs.h.
Dodatkowo w naszym nag³ówku definu-
jemy dwa makra pomocne przy obliczaniu
danej wpisywanej do rejestru UBRR, która
wyznacza prêdktoæ transmisji. Makro
pomocnicze RS_MAKE_UBRR jest przenie-
sieniem na C opisanego w dokumentacji spo-
sobu obliczania potrzebnej wartoci. Sta³a
F_CPU deklarowana jest z poziomu pliku
makefile.
Zwracam Twoj¹ uwagê na fakt, jak
wa¿ne jest otoczenie nawiasami obliczeñ
makra RS_MAKE_UBRR. Wstaw w wy-
obrani zawarty w nim tekst tak jak robi
to preprocesor w miejscu wyst¹pienia
jego wywo³ania. Zauwa¿, co sta³oby siê,
gdyby nawiasów nie by³o. Szczególnie
widoczne jest to w miejscu, gdzie obliczo-
n¹ wartoæ przesuwamy.
PP
PP
rr
rr
oo
oo
gg
gg
rr
rr
aa
aa
m
m
m
m
oo
oo
w
w
w
w
aa
aa
nn
nn
ii
ii
ee
ee
pp
pp
rr
rr
oo
oo
cc
cc
ee
ee
ss
ss
oo
oo
rr
rr
óó
óó
w
w
w
w
w
w
w
w
jj
jj
êê
êê
zz
zz
yy
yy
kk
kk
uu
uu
CC
CC
czêæ 7
Rys. 37 Zmiany w pliku makefile
Listing 52 wypisanie prostego tekstu
#include <avr\io.h>
#include <stdio.h>
iinntt
main((
vvooiidd
))
{{
puts((
Hello world!
));;
}}
Listing 53 plik rs.c
#include <avr\io.h>
#include rs.h
iinntt
rs_put((
cchhaarr
znak))
{{
// Oczekiwanie a¿ bufor nadajnika jest pusty
wwhhiillee
((!!((
1
<<<<UDRE0 && UCSR0A)))) {}
UDR0 == znak;;
rreettuurrnn
0
;;
}}
iinntt
rs_get((
vvooiidd
))
{{
cchhaarr
znak;;
// Oczekiwanie na pojawienie siê danej
wwhhiillee
((!!((
1
<<<<RXC0 && UCSR0A)))) {}
znak == UDR0;;
rreettuurrnn
znak;;
}}
Utwórz teraz ostatni potrzebny nam,
nowy plik. Zapisz go pod nazw¹ harddef.h.
Tak jak robilimy to poprzednio, zmiecimy
w nim wszystkie definicje dotycz¹ce czêci
sprzêtowej. Za tak¹ mo¿emy uznaæ prêdkoæ
transmisji. Mo¿e wydaje Ci siê to bezcelowe
tworzenie nowego pliku dla jednej tylko
danej. Jednak trzeba wzi¹æ pod uwagê, ¿e pro-
gram mo¿e siê rozrastaæ. Najlepiej od pocz¹t-
ku utrzymywaæ w nim porz¹dek. Zawartoæ
wspomnianego pliku pokazuje listing 55.
Jeli zaczynasz siê gubiæ w tym, co robi-
my, nie poddawaj siê teraz! Przed nami ostat-
nia prosta, która nada sens wszystkim naszym
dzia³aniom. Listing 56 pokazuje zmienion¹
funkcjê main. Teraz program po skompilowa-
niu i w³adowaniu danych do procesora
zacznie dzia³aæ zgodnie z naszym zamierze-
niem. Konieczne bêdzie pod³¹czenie p³ytki do
wolnego portu RS232 w naszym komputerze.
Do komunikacji wykorzystaæ mo¿na dowolny
program terminala. Mo¿e byæ to nawet termi-
nal wbudowany w rodowisko BASCOM.
Transmisjê nale¿y skonfigurowaæ na:
Liczba bitów na sekundê: 4800
Bity danych: 8
Parzystoæ: Brak
Bity stopu: 1
Rysunek 39 pokazuje efekt dzia³ania pro-
gramu. Po ka¿dym zerowaniu
procesor wyle kolejny napis.
Zgodnie z dokumentacj¹, funk-
cja puts dodaje na koniec znak
nowej linii. Nie wprowadza jed-
nak znaku powrotu karetki, co
daje widoczny na rysunku
39 efekt. Nie ka¿dy termi-
nal zinterpretuje przesy³a-
ne dane w taki w³anie spo-
sób, jednak aby zupe³nie
pozbyæ siê problemu, mo-
¿emy napis zamieniæ na:
Hello world!\r
W ten sposób rêcznie dodamy przed
znakiem nowej linii znak powrotu karet-
ki i wszystkie nowe napisy u³o¿¹ siê
jeden pod drugim.
Jaki to ma sens
Dobrze wiêc... utworzylimy, zajmuj¹cy po-
nad 1KB pamiêci, program wypisuj¹cy za po-
moc¹ portu RS ³adne przywitanie. Pocz¹tek
nie wypad³ nam zachwycaj¹co. Zmniejszanie
zajêtoci pamiêci zwi¹zane bêdzie z tematem,
który chcê omówiæ dopiero w
kolejnej czêci. Teraz zajmijmy
siê poznaniem funkcji, która tak
naprawdê sprawia, ¿e biblioteka
stdio jest potê¿nym narzêdziem
Przeczytaj ramkê ABC... C
printf, razem z do³¹czonymi do
niej tabelkami. Nie wygl¹da to
mo¿e w tej chwili najprociej,
dlatego te¿ proponujê natych-
miast przejæ do przyk³adu poka-
zanego na listingu 57. Jedyne,
co musisz zmieniæ, to zawartoæ
funkcji main. Ze wzglêdu na
oszczêdnoæ miejsca inicjacja
portu szeregowego, która nie
uleg³a zmianie, zosta³a wykrop-
kowana.
Dzia³anie przyk³adowego
programu pokazuje rysunek 40.
Pobaw siê tym kodem. Sprawd,
"
Programowanie
Elektronika dla Wszystkich
ABC... C
Jak dzia³aj¹ strumienie?
Pamiêtasz, jak do tej pory obs³ugiwalimy napisy na
wywietlaczu LCD? Pisalimy oddzielne funkcje do
wypisania ³añcucha znaków, do wypisania liczby
w formacie dziesiêtnym czy szesnastkowym.
Idea funkcji operuj¹cych na zasadzie strumieni
zdejmuje z nas obowi¹zek tworzenia wszystkich prze-
kszta³ceñ. Wymaga od nas jedynie stworzenia funkcji
wypisuj¹cej oraz odczytuj¹cej jeden znak. Genialnoæ
pomys³u pokazuje rysunek w ramce:
Funkcje get i put
Dwie powy¿sze funkcje nie s¹ dok³adnie okrelone
przez standard ANSI C. W AVR-GCC musz¹ one
mieæ formê jak poni¿ej:
iinntt
put((
cchhaarr
znak))
iinntt
get((
vvooiidd
))
Funkcja put powinna zwracaæ 0, jeli wysy³anie
znaku przebieg³o pomylnie, w innym przypadku
zwracamy wartoæ ujemn¹, co spowoduje przerwanie
dzia³ania operuj¹cej na niej funkcji nawet jeli
wszystkie jej dane nie zosta³y wys³ane. Podobnie sytu-
acja ma siê z funkcj¹ get. Tutaj jednak funkcja nor-
malnie zwraca odebran¹ dan¹, gdy wyst¹pi b³¹d, nale-
¿y zwróciæ wartoæ ujemn¹.
Inicjowanie urz¹dzenia
Zak³adaj¹c, ¿e posiadamy ju¿ gotowe funkcje put oraz
get, musimy jeszcze poinformowaæ funkcje z bibliote-
ki stdio o tym, ¿e chcemy w³anie z nich korzystaæ.
Wykonujemy to za pomoc¹ funkcji fdevopen. Jej
sk³adniê przedstawiam poni¿ej:
fdevopen((put,, get,,
0
));;
Ostatni parametr jest niewykorzystany i powinien
mieæ zawsze wartoæ 0. Po wywo³aniu jak wy¿ej,
podane funkcje zostan¹ przyporz¹dkowane, odpo-
wiednio, domylnemu wyjciu oraz wejciu. Od tej
chwili wywo³anie przyk³adowej funkcji puts z listingu
52 da oczekiwany efekt przes³ania kolejnych znaków
H e l l o w o r l d !, kolejno do
funkcji put. Co z kolei w niej bêdzie siê dzia³o z prze-
s³anymi znakami, to ju¿ kwestia naszych potrzeb
i inwencji.
Listing 54 plik rs.h
#ifndef RS_H_INCLUDED
#define RS_H_INCLUDED
#define RS_MAKE_UBRR(baud) (F_CPU/(baud*16l)-1)
#define RS_SET_BAUD(baud) \
{UBRR0H = (uint8_t)(RS_MAKE_UBRR(baud)>>8); \
UBRR0L = (uint8_t)RS_MAKE_UBRR(baud); }
iinntt
rs_put((
cchhaarr
znak));;
iinntt
rs_get((
vvooiidd
));;
#endif
// RS_H_INCLUDED
Listing 55 plik harddef.h
#ifndef HARDDEF_H_INCLUDED
#define HARDDEF_H_INCLUDED
#define DEF_BAUD 4800
#endif
// HARDDEF_H_INCLUDED
Listing 55 plik harddef.h
#ifndef HARDDEF_H_INCLUDED
#define HARDDEF_H_INCLUDED
#define DEF_BAUD 4800
#endif
// HARDDEF_H_INCLUDED
Listing 56 zmiany w pliku main umo¿liwiaj¹ce dzia³anie programu
#include <avr\io.h>
#include <stdio.h>
#include rs.h
#include harddef.h
iinntt
main((
vvooiidd
))
{{
////////////////////////////////////////////
// Inicjacja portu szeregowego
RS_SET_BAUD((DEF_BAUD));;
UCSR0C ==
1
<<<<URSEL0 ||
1
<<<<UCSZ01 ||
1
<<<<UCSZ00;;
UCSR0B ==
1
<<<<RXEN0 ||
1
<<<<TXEN0;;
UCSR0A ==
0
;;
// Koniec inicjacji
////////////////////////////////////////////
// Inicjacja funkcji domylnych strumieni io
fdevopen((rs_put,, rs_get,,
0
));;
puts((
Hello world!
));;
}}
Rys. 38 Dodanie pliku rs.c
Rys. 39 Efekt dzia³ania programu
jakie efekty da
podanie okrelo-
nej szerokoci lub
precyzji. Wypró-
buj ró¿ne flagi.
Spróbuj skorzys-
taæ tak¿e z typów
s oraz S.
Poniewa¿ jest
to doæ ciekawe,
proponujê Ci zapoznanie siê z rysunkiem 41,
który pokazuje ostatni kod uruchomiony za
pomoc¹ programu AVRStudio. Spróbuj same-
mu przeprowadziæ pokazan¹ na nim symulac-
jê. Widzimy tutaj, w jaki sposób poszczegól-
ne argumenty s¹ przesy³ane do funkcji.
Widzimy, ¿e jest to jak najbardziej zgodne
z opisem w ramce o naszej funkcji. Zauwa¿,
¿e w tym przypadku tak¿e parametr okrelaj¹-
cy adres ³añcucha formatowania przesy³any
jest przez stos. Informacja o tym znajduje siê
w dokumentacji do³¹czonej do WinAVR... nie
ma dla nas tak du¿ego znaczenia przesy³anie,
nieznanej nam wczeniej, otwartej listy argu-
mentów.
Pamiêæ programu
Jeli w którym momencie zada³e sobie pyta-
nie, dlaczego ci¹gle umieszczam ³añcuchy w
pamiêci danych, zamiast jak ju¿ pokazywalimy
"#
Programowanie
Elektronika dla Wszystkich
ABC... C
printf
Dowolnoæ argumentów... jak to dzia³a?
Sk³adnia funkcji printf wygl¹da nastêpuj¹co:
iinntt
printf((
ccoonnsstt cchhaarr
fmt,,......))
Widoczne trzy kropki to nie ¿adne wprowadzone
przeze mnie uproszczenie. To doæ ciekawa oraz ca³-
kowicie formalna cecha jêzyka C. Trzy kropki poja-
wiaj¹ siê zawsze za ostatnim argumentem. Nie mo¿na
za nimi umieciæ jeszcze kolejnego, ustalonego argu-
mentu. Format, z jakim mamy tutaj do czynienia ozna-
cza, ¿e zaraz za parametrem fmt mo¿emy umieciæ
dowoln¹ iloæ dowolnych parametrów.
Pierwszym parametr nazywany jest z angielska
Format String, co mo¿na t³umaczyæ jako ³añcuch
formatuj¹cy. W nim zawarte s¹ informacje, jakie para-
metry zosta³y wprowadzone i z jego pomoc¹ s¹ one
odzyskiwane. Sposób podawania odpowiednich infor-
macji pojawi siê za chwilê, teraz jednak skupmy siê na
reszcie argumentów.
Ka¿dy kolejny argument, wpisany w miejsce
trzech kropek, jest umieszczany na stosie. Jednak
wrzucane s¹ one od ty³u. W efekcie, w chwili
wywo³ania funkcji, pierwszy argument znajduje siê na
samym szczycie stosu i mo¿e byæ jako pierwszy
z niego zdjêty. Zmienne zdejmowane bêd¹ od naj-
m³odszego bajtu do najstarszego.
W ten sposób mo¿na do funkcji przekazaæ argu-
menty w objêtoci ograniczonej jedynie pojemnoci¹
pamiêci przeznaczonej na stos. Jest to niezwykle
wygodne w funkcji takiej jak printf, gdzie nie da siê
okreliæ, jakie argumenty bêd¹ potrzebne, jednak
z mo¿liwoci tej trzeba korzystaæ bardzo ostro¿nie...
Ryzyko i wady rozwi¹zania
Osoby obeznane trochê z programowaniem zdaj¹
sobie sprawê z tego, jak wa¿nym elementem jest stos.
Jakikolwiek b³¹d w przep³ywie informacji miêdzy sto-
sem a rejestrami mo¿e skutkowaæ zawieszeniem siê
ca³ego programu. Trzeba zdaæ sobie sprawê, ¿e o ile
w przypadku zwyczajnych funkcji, z ustalonymi para-
metrami, to kompilator dba o prawid³ow¹ obs³ugê
stosu, nie jest on w stanie pilnowaæ jego dzia³ania, gdy
korzystamy z otwartej listy argumentów. Gdy decydu-
jemy siê na takie dzia³anie, to na nas spoczywa odpo-
wiedzialnoæ za prawid³owe jego funkcjonowanie.
Kompilator nie bêdzie tak¿e w stanie sprawdziæ, czy
podawane argumenty s¹ w³aciwego typu. Bardzo
wa¿ne jest wiêc, aby podane argumenty zgadza³y siê
z tym, co deklarujemy w ³añcuchu formatowania.
W innym przypadku funkcja printf mo¿e nie zdj¹æ
wszystkich informacji ze stosu. Mo¿e tak¿e zdj¹æ ich
zbyt wiele. B³¹d stosu mo¿e spowodowaæ, ¿e dalej, do
rejestrów wpisane zostan¹ przypadkowe dane.
W skrajnym przypadku mieci zostan¹ wprowadzone
do licznika rozkazów... rozumiesz na pewno, co siê
wtedy stanie.
Oprócz koniecznej ostro¿noci trzeba zwróciæ
uwagê na jeszcze jedn¹ sprawê. Jeli wywo³ywana
funkcja posiada jedynie sta³e
argumenty, w miarê mo¿li-
woci s¹ one umieszczane
bezporednio w rejestrach.
Odpowiedni podprogram w
chwili uruchomienia zna
dok³adnie typy wszystkich
argumentów ma je podane
niejako na tacy. Jeli na-
tomiast wywo³ujemy funkcjê
z otwart¹ list¹ parametrów,
wszystkie one musz¹ zostaæ
umieszczone na stosie. Wy-
maga to dodatkowego czasu
oraz kodu przed wywo³aniem
podprogramu. Sam podpro-
gram tak¿e musi byæ bardziej
rozbudowany.
Ogólnie, jeli to mo¿li-
we, funkcji tego typu raczej
siê unika. Czasami jednak
jest to albo jedyne... albo naj-
lepsze rozwi¹zanie mimo
wszystkich wad.
Format
Wiemy ju¿ co i jak siê dzieje
w naszej funkcji. Teraz do-
wiemy siê, jak j¹ wykorzys-
taæ. Bardzo wa¿ny jest ³añ-
cuch formatuj¹cy. To w nim
zawarta jest informacja o przekazanych paramet-
rach oraz o sposobie, w jaki zostan¹ one
wywietlone. Znaki z ³añcucha formatuj¹cego s¹
wysy³ane bezporednio na wyjcie do chwili
natrafienia na znak %. Znaki wystêpuj¹ce za
nim s¹ interpretowane jako informacja o kolej-
nym argumencie.
Rysunek powy¿ej pokazuje format opisu
argumentu oraz sposobu jego wywietlenia.
Z naszego punktu widzenia, najwa¿niejsza jest
informacja o typie argumentu. Oznaczenia po-
szczególnych typów przedstawia tabela 6. Nie
sugeruj siê zbyt mocno podanymi tam typami
zmiennych. Najwa¿niejsze jest zachowanie ich
rozmiaru. Pod tym wzglêdem int oraz unsigned
int s¹ identyczne.
Przydatne flagi zamieci³em w tabeli 7.
Nasz kompilator udostêpnia tylko jeden
modyfikator: l oznaczaj¹cy, ¿e zamiast zmien-
nej typu int podajemy zmienn¹ typu long int.
Znaczenie precyzji oraz szerokoci wyjania
dodatkowa, niewielka ramka.
printf pola precyzja oraz szerokoæ
Znaczenie pola precyzji zmienia siê zale¿nie od typu.
Dla typów zmiennoprzecinkowych oznacza ono liczbê
miejsc po przecinku. Dla typów numerycznych
minimaln¹ liczbê cyfr (dope³nienie zerami, niezale¿-
nie od flagi ). Dla ³añcuchów oznacza maksymaln¹
liczbê znaków, jaka ma zostaæ wypisana.
Jeli d³ugoæ napisu tworzonego przez dane prze-
kszta³cenie jest mniejsza ni¿ szerokoæ, dodawane s¹
spacje, wzglêdnie zera (flaga 0) po lewej lub prawej
(flaga -) stronie napisu. Parametr ten nigdy nie
powoduje przyciêcia wyniku.
Rys. 40 Dzia³anie
programu
z listingu 57
Tabela 6 oznaczenia typów w ³añcuchu
formatowania
Tabela 7 flagi w ³añcuchu formatowania
sobie w pamiêci programu... Bardzo siê
z tego pytania cieszê. Jeli jeszcze tego nie
zrobi³e popatrz na wynik symulacji. £añ-
cuch zajmuje cenn¹ pamiêæ RAM, jednocze-
nie do jej inicjacji konieczna jest kopia
danych w pamiêci ROM.
Omawiane funkcje, tak jak wiêkszoæ
z wystêpuj¹cych w AVR-GCC, posiadaj¹
specjalne wersje z przyrostkiem _P. Zmodyfi-
kuj poprzedni program zgodnie z listingiem
58. Konieczne bêdzie dodanie do programu
nag³ówka <avr\pgmspace.h>. Efekt zmiany
mo¿na zaobserwowaæ w symulacji na rysun-
ku 42. Od strony funkcjonalnej nie powinny
pojawiæ siê widoczne zmiany.
Na identycznej zasadzie mo¿esz zmodyfi-
kowaæ pierwszy z programów.
Podsumowanie
Dzi poznalimy bardzo wa¿n¹ funkcjê z bib-
lioteki standardowej C. Wykorzystalimy j¹
w jeden z najprostszych sposobów. Praktyka
jest jednak taka, ¿e w AVR-GCC, standardo-
we funkcje wejcia/wyjcia, dzia³aj¹ce na
domylnych strumieniach nie zosta³y dobrze
zoptymalizowane. Musimy liczyæ siê z tym,
¿e jest to jednak narzêdzie darmowe i czasami
daje to odczuæ. Jest jednak szansa na poprawê
mia³em okazjê testowaæ najnowsze bibliote-
ki i ich dzia³anie rzeczywicie zosta³o popra-
wione. Jednak dopóki nie powstanie nowa
wersja ca³ego pakietu, zmiana bibliotek
wymaga rêcznych modyfikacji. W najbli¿-
szym odcinku bêdziemy pracowaæ na stru-
mieniach innych ni¿ domylne okazuje siê,
¿e funkcje te s¹ lepiej optymalizowane, jeli
chodzi o rozmiar kodu. Dodatkowo daje to
mo¿liwoæ wykorzystania tych samych pod-
programów do wysy³ania danych przez
RS232 czy na LCD, co sprawia, ¿e poznawa-
na biblioteka staje siê coraz ciekawsza.
Rados³aw Koppel
radoslaw.koppel@elportal.pl
"$
Programowanie
Elektronika dla Wszystkich
Rys. 41 przesy³anie argumentów do funkcji printf
Rys. 42 Efekt umieszczenia ³añcucha formatowania w pamiêci programu
Listing 57 wykorzystanie funkcji printf
iinntt
main((
vvooiidd
))
{{
iinntt
a ==
1234
;;
iinntt
b ==
0xff
;;
((......))
fdevopen((rs_put,, rs_get,,
0
));;
printf((
a(%%d)=%d\r\n
a(%%x)=%x\r\n
a(%%X)=%X\r\n
b(%%#x)=%#x\r\n
b(%%o)=%o\r\n
,,
a,, a,, a,, b,, b));;
}}
Listing 58 wykorzystanie pamiêci programu
dla ³añcucha formatowania
printf_P((PSTR((
a(%%d)=%d\r\n
a(%%x)=%x\r\n
a(%%X)=%X\r\n
b(%%#x)=%#x\r\n
b(%%o)=%o\r\n
)),,
a,, a,, a,, b,, b));;
R
E
K
L
A
M
A
Zastosowanie: rodek penetruj¹cy i smaru-
j¹cy, przenikaj¹cy rdzê, wypieraj¹cy wodê,
myj¹cy z brudu i kurzu
Opis: CRC 5-56 - wielofunkcyjny preparat dla
potrzeb serwisowych. rodek penetruj¹cy i
smaruj¹cy, przenikaj¹cy rdzê, wypieraj¹cy
wodê, myj¹cy z brudu i kurzu. Sk³ada siê z
oleju parafinowego, organicznych inhibitorów
korozji co pozwala na utworzenie bariery chro-
ni¹cej przed dostêpem wody i tlenu.
W³asnoci:
n
szybko penetruje, wnikaj¹c w najmniejsze
pory, szczeliny w rozwiniêtej powierzchni-
dobre w³asnoci smarne- wypiera wilgoæ
z uk³adów elektrycznych i zap³onowych
n
luzuje zardzewia³e po³¹czenia
n
tworzy cienk¹ warstwê ochronn¹, przeciw-
dzia³aj¹ca korozji wywo³anej wp³ywami atmos-
ferycznymi
n
nie oddzia³uje z metalami i ich stopami
n
nie oddzia³uje z wiêkszoci¹ plastików, gum,
powierzchni lakierowanych (w razie w¹tpli-
woci - zalecany test technologiczny)
n
opakowania aerozolowe wyposa¿one s¹ w
zawór 360° dzia³ania oraz cienk¹ rurkê aplika-
cyjn¹.
n
Gaz pêdny - niepalny CO2 - co skutkuje
97% wykorzystaniem aktywnego preparatu
Sposób u¿ycia:
n
Na³o¿yæ preparat i pozwoliæ na jego penet-
racjê
n
Dla uruchomienia zawilgoconego silnika,
nanieæ preparat na cewkê i przewody zap³onu
n
W przestrzeniach o trudnym dostêpie u¿yæ
rurki aplikacyjnej
n
W razie potrzeby CRC 5-56 mo¿na usun¹æ,
zmyæ wykorzystuj¹c CRC Brakleen lub CRC
Quickkleen
Dane techniczne (bez gazu pêdnego)
Kolor . . . . . . . . . . . . . . . przeroczysta ciecz
o lekko bursztynowym zabarwieniu
Ciê¿ar w³aciwy (20°C) . . . . . . . . 0,82 g/cm
3
Punkt zamarzania . . . . . . . . . . . . . . < -50°C
Punkt zap³onu . . . . . . . . . . . . . . . . . . . 78°C
Gruboæ warstwy (24 godz., 20°C) . . . . 1-2u
Wydajnoæ z 1l (20°C ) . . . . . . . . . . . 100m
2
Odpornoæ termiczna . . . . . . . . . . . . . 120°C
(150°C - nara¿enie chwilowe)
CRC 5−56 − wielofunkcyjny preparat dla potrzeb serwisowych
Zamówienia przyjmuje Dział Handlowy AVT, 01−939 Warszawa, ul. Burleska 9, tel. (22) 568 99 50, fax (22) 568 99 55, e−mail: handlowy@avt.pl
w w w. s k l e p . a v t . p l
200 ml
kod handlowy:
KON36
cena:
10 z³