Start Publikacje Skrypt do zajęć z programowania mikrokontrolerów AVR w językuC - CZĘŚĆ V

Skrypt do zajęć z programowania mikrokontrolerów AVR w językuC - CZĘŚĆ V

Drukuj Email
Wpisany przez inż. Arkadiusz Krysiak   


OPA

 

1.14. Volatile

Bardzo ważny operator nieulotności. Z tego względu zostanie omówiony oddzielnie. Powiedzmy, iż napisaliśmy procedury obsługi działające w przerwaniu. Umieszczają one jakąś wartość w komórce pamięci i więcej nic z nią nie robią. Dopiero program w pętli głównej ma odebrać poprzez adres bezwzględny zawartość tej komórki. Jednak kompilator stwierdzając że pod daną nazwę zapisywana jest wartość nigdzie więcej nie używana w procesie optymalizacji usuwa zbędne rozkazy dotyczące nigdzie nie używanych zmiennych. Aby tego nie dokonał musimy zadeklarować daną komórkę pamięci z operatorem nieulotności volatile. Operator ten powoduje, iż mimo braku zauważalnego przez kompilator użycia zmiennej przez nazwę nie są usuwane rozkazy pozornie wyglądające na zbędne.

Przykład:

volatile float pomocnicza

 

1.15. Definicja funkcji

Definicja funkcji wygląda następująco:

zwracany-typ nazwa-funkcji(lista-parametrów,...) { ciało-funkcji... }

zwracany-typ jest typem zmiennej zwracanej przez funkcję. Zwracanym typem nie może być tablica lub funkcja.

Nazwa-funkcji jest to etykieta identyfikująca definicję funkcji.

Lista-parametrów jest to wykaz zmiennych, z którymi funkcja jest wywoływana. Poszczególne parametry wywołania są oddzielone przecinkami. Jeśli funkcja nie posiada parametrów wywołania to lista parametrów wywołania przyjmuje typ void.

W przypadku, gdy funkcja nie zwraca parametrów, zapisujemy zwracany typ jako void.

Zapowiedź funkcji zapisujemy dokładnie w ten sam sposób jak funkcję, ale z pominięciem bloku instrukcji.

zwracany-typ nazwa-funkcji ( lista-parametrów);

Zwracany typ i nazwa funkcji w zapowiedzi muszą dokładnie odpowiadać deklaracji funkcji i parametrów wywołania. Zapowiedź umieszcza się dla czytelności powyżej funkcji głównej main ale deklarację funkcji w takim wypadku możemy umieścić poniżej jej użycia. Jeśli nie używamy zapowiedzi funkcji to deklarację funkcji obowiązkowo należy dokonać przed jej pierwszym użyciem i innej funkcji.

Przykład:

int joe(float, double, int);

To jest definicja prototypu funkcji joe (zapowiedź)

int joe(float coin, double total, int sum)
/*...*/
}

To jest definicja funkcji joe (deklaracja funkcji)

int mary (void), *lloyd(double);

To jest definicja prototypu bezparametrowej funkcji mary zwracającej typ int. Funkcja llyod jest zdefiniowana jako funkcja wywoływana z parametrem typu double i z parametrem zwracanym typu int.

int (*peter)();

Zdefiniowano peter jako wskaźnik do bezparametrowej funkcji zwracającej typ int. Wartość wskaźnika peter możemy zmieniać tak, aby stanowił on referencję do dowolnej funkcji.

int (*aaron(char *(*)(void)) (long, int);

zdefiniowano funkcję aaron która zwraca wskaźnik do innej funkcji.

int (*aaron(char *(*)(void)) (long, int);

Funkcja aaron pobiera jako parametr wskaźnik do funkcji która zwraca wskaźnik do zmiennej znakowej char i nie pobiera parametrów w wywołaniu.

int (*aaron(char *(*)(void)) (long, int);

Zwracana funkcja zwraca typ int i posiada dwa parametry jeden typu long a drugi typu int.

int (*aaron(char *(*)(void)) (long, int);