Kurs AVR5, Elektronika i programowanie
[ Pobierz całość w formacie PDF ]Kurs AVR-GCC cz.5 (v1)
Ostatnio omawiane były tablice i funkcje, a jeszcze wcześniej: zmienne, pętle i instrukcje warunkowe. W tej części kursu tematem przewodnim będzie tekst i działania na tekście. Napiszę też kilka zdań na temat preprocesora języka C. Kolejnym omawianym zagadnieniem będzie podział kodu źródłowego programu na oddzielnie kompilowane pliki. W części praktycznej będziemy bawić się alfanumerycznym wyświetlaczem LCD, przyłączymy do AVRa termometr cyfrowy ds18b20, a dalej połączymy AVRa z komputerem PC poprzez port szeregowy RS232C.
Programy z tekstemDotąd w przykładach z kursu używane były jedynie zmienne liczbowe. A co z tekstem ? Oczywiście tekst przechowuję się w pamięci komputera również w postaci liczb. Po prostu małym i wielkim literom alfabetu, cyfrom oraz wszystkim innym znakom przyporządkowuje się kolejne liczby z pewnego zakresu. Zwykle jeden znak zajmuje w pamięci komputera jeden bajt (osiem bitów), najczęściej używanym bywa kodowanie lub jego rozszerzenia.
Tablica kodów ASCII.
Literom alfabetu, cyfrom oraz wszystkim innym znakom przyporządkowuje się kolejne liczby. Kliknij w obrazek, żeby obejrzeć całość.
Inaczej inż jest w wielu innych językach programowania w C nie przewidziano specjalnego typu zmiennej przeznaczonego do przechowywania tekstu. W języku C do przechowywania tekstu wykorzystuje się tablice typu char. Aby zapamiętać tekst kolejne pola tablicy wypełniane są kodami ASCII znaków tworzących tekst.
Tablica wypełniona kodami ASCII kolejnych liter tworzących napis "Siemka!". W języku C tekst przechowuje się po prostu w tablicach typu char.
W kodzie źródłowym programu można posługiwać się stałymi znakowymi i stałymi napisowymi. Stała znakowa ma postać znaku objętego pojedynczymi cudzysłowami i posiada wartość liczbową kodu ASCII tego znaku.
int jeden_znak ;
char jakis_napis[7];
/* W zmiennej jeden_znak znajdzie się wartość 65(kod ASCII znaku A) */ jeden_znak = 'A';
/* Zapisujemy tekst do tablicy znak po znaku */
jakis_napis[0] = 'S';
jakis_napis[1] = 'i';
jakis_napis[2] = 'e';
jakis_napis[3] = 'm';
jakis_napis[4] = 'k';
jakis_napis[5] = 'a';
jakis_napis[6] = '!';
Stałe napisowe tworzy się obejmując fragment tekstu parą podwójnych cudzysłowów. Definiując tablicę znakową można ją jednocześnie zainicjować stałą napisową. Tym sposobem tablica, w momencie jej tworzenie, zostanie wypełniona kodami ASCII kolejnych znaków tworzących napis.
/*Tworzona tablica zostanie wypełniona ciągiem znaków */
char jakis_napis[] = "Siemka!";
/* Zawartość tablicy: jakis_napis[0] = 'S'
jakis_napis[1] = 'i'
jakis_napis[2] = 'e'
jakis_napis[3] = 'm'
jakis_napis[4] = 'k'
jakis_napis[5] = 'a'
jakis_napis[6] = '!'
jakis_napis[7] = 0x0 */
W przykładzie wyżej, w tablicy za ostatnim znakiem napisu, kompilator dodatkowo wstawi bajt o wartości zero. Znak o kodzie zero pełni tu rolę znacznika końca ciągu znaków. Jest zasadą w języku C że ciągi znaków kończą się znakiem o kodzie równym zero. Tekst może mięć dowolną długość, aby się tylko zmieścił w tablicy wzraz z ograniczającym go bajtem zero.
Jeżeli w stałej napisowej potrzeba wstawić znak podwójnego cudzysłowu, to należy go poprzedzić znakiem backslash (\"). A jeśli chcemy wstawić sam znak backslash, to należy wpisać dwa znaki backslash (\\). Są to tzw. sekwencje specjalne zaczynające się od znaku backslash, dalej jeszcze będę o nich pisał.
/* Do tablicy zapisany zostanie ciąg znaków: abcdef"gh\i\jklmnop"qrs'tuv'wxyz */
char jakis_napis[] = "abcdef\"gh\\i\\jklmnop\"qrs'tuv'wxyz";
Jeśli jakaś funkcja oczekuje jako argumentu tablicy typu char, to jako argument, zamiast nazwy tablicy, można wstawić stałą napisową.
/* Definicja tablicy */
char tablica[]="KURS AVR-GCC";
/* Definicja przykładowej funkcji, która jak argumentu oczekuje tablicy typu char */
void funkcja(char tablica[])
{ }
int main(void)
{ /* Wywołanie funkcji */
funkcja(tablica);
/* Jako argument można wstawić stałą napisową */
funkcja("KURS AVR-GCC");
W języku C brakuje również operatorów przeznaczonych do działań na tekście, takie operacje jak porównywanie czy łączenie napisów pozostaje zaprogramować samemu. Nie jest to nic specjalnie trudnego, oto kilka przykładów prostych operacji na tekstach:
Wykorzystując instrukcję pętli można porównywać dwa ciągi znaków.
/* Przyrównanie ciągu znaków */
unsigned char i; char str1[]= "KURS AVR-GCC";
char str2[]= "KURS AVR-GCC";
for(i=0; str1[i]==str2[i] && str1[i]; i++);
/* Jeśli warunek spełniony, to porównywane ciągi znaków róźnią się */ if(str1[i] || str2[i])
Podobne używając instrukcji pętli można połączyć dwa lub więcej napisów w jeden tekst.
/* Łączenie ciągów znaków */
unsigned char i,j;
char str1[]= "KURS";
char str2[]= " AVR-GCC";
char str3[]= " cz.5";
char buffer[18];
/* Łączy trzy ciągi znaków .
Całość zostanie zapisana w tablicy 'buffer[]' */
for(i=0,j=0;
buffer[j]=str1[i];
i++,j++);
for(i=0 ;
buffer[j]=str2[i];
i++,j++);
for(i=0 ; buffer[j]=str3[i]; i++,j++);
A tak z pomocą instrukcji pętli for można wyznaczyć długość ciągu znaków zakończonego zerem.
/* Obliczanie długości ciągu znaków */
char s[] = "KURS AVR-GCC";
unsigned char i;
/* Zmienna 'i' zawierać będzie długość ciągu znaków w tablicy 's[]'
. Bajt o wartości zero na końcu ciągu nie jest liczony. */
for(i=0; s[i]; i++);
Jeżeli zamierzamy na wyświetlaczu alfanumerycznym pokazać wartość zmiennej liczbowej, to koniecznym będzie zamienić wartość liczbową na ciąg znaków. Kawałek kodu poniżej zmienia 16-bitową liczbę całkowitą bez znaku na odpowiadający jej ciąg cyfr (kodów ASCII cyfr). Wartość liczbowa w zmiennej 'a' jest cyklicznie w pętli dzielona przez 10, dopóki nie stanie się zerem - dzielenie całkowite. Obliczana w każdej iteracji pętli reszta z dzielenia stanowi cyfrę stojącą na kolejnej pozycji w liczbie, idąc w kierunku od cyfry najmniej znaczącej do najbardziej znaczącej. Reszta z dzielenia (liczba z zakresu 0..9) zmieniana jest na kod ASCII cyfry przez dodanie do niej wartości kodu ASCII cyfry zero (48).
...
[ Pobierz całość w formacie PDF ]