Синтаксис та основні оператори мови с.
Складні програмні проекти можна більш компактно описувати (в порівнянні з мовою Assembler) за допомогою мови програмування С, якому присутні можливості мов низького та високого рівнів, а також великою бібліотекою функцій.
Алфавіт мови С складається з букв латинського алфавіту, цифр, та спеціальних символів. При заданні ідентифікаторів sysreg та Sysreg не є однаковими. Усі ключові слова повинні бути набрані строковими літерами. Між операторами повинен стояти символ «пробіл». Закоментовані строки починаються з двох символів //.
Константи у мові С декларуються за допомогою директиви #define згідно з синтаксисом:
#define ім’я константи значення;
При роботі з апаратними засобами зручно записувати константи у двійковій та 16-ичній формах. Перед значенням констант ставляться символи 0b та 0x для двійкового та 16-ичного представлення відповідно. Регістр символів при задаванні 16-их констант на має значення.
Базовими цілими типами даних в мові С являються сhar (розмір 1 байт, діапазон значень - 128 127) та int (розмір 2 байта, діапазон значень – 32768 32767). Модифікатор unsigned, що задається перед іменем базового типу, дозволяє вказувати значення заданих вище типів даних як числа без знаку: unsigned сhar (розмір 1 байт, діапазон значень 0 255), unsigned int (розмір 2 байта, діапазон значень 0 65535). При цьому старший розряд є бітом даних, а не знаковим бітом числа.
Усі змінні повинні бути декларовані до їх використання у програмі. При запису імен змінних необхідно враховувати регістр символів. Формат задання змінних:
тип даних ім’я змінної [= початкове значення];
Якщо кілька змінних мають однаковий тип даних, то при заданні їх ідентифікатори можна перераховувати через кому. Початкове значення змінної можна не вказувати. Приклади:
char A=10;
int B, C, D;
unsigned int E, F.
Розглянемо основні оператори мови С.
Оператор задавання значення має наступний синтаксис:
Ідентифікатор = вираз;
В виразах над операндами можуть використовуватись наступні арифметичні та логічні операції мови С:
Арифметичні операції:
+ додавання;
– віднімання;
* множення,
/ ділення.
Логічні операції:
|| логічне АБО;
&& логічне ТА;
! логічне НІ;
| побітова операція АБО;
& побітова операція ТА;
^ побітова операція виключне АБО;
побітова операція НІ;
<< логічний зсув ліворуч;
>> логічний зсув праворуч.
Мова С відноситься до суворо типізованих мов програмування: змінним одного типу не можна безпосередньо призначати значення іншого типу даних. Для однозначного визначення пріоритету операцій у виразах необхідно використовувати дужки ( ). Приклад оператора призначення:
A = (B+C)*D;
Оператор умови if/else дозволяє виконувати одну з двох дій в залежності від умови. Синтаксис оператора:
if (умова) вираз1
[else вираз2];
Умова це вираз, що задається за допомогою операцій відношення:
== дорівнює;
!= не дорівнює;
< менше;
<= менше або дорівнює;
> більше;
>= більше або дорівнює.
Якщо ця умова є істиною, то виконується вираз1, у іншому разі – вираз2. Частина else не обов’язкова. Якщо, в залежності вид умови необхідно виконати фрагмент програми, що складається з декількох операторів, то їх необхідно помістити між фігурними дужками { }. Приклад використання умовного оператору:
if (A==B) {C=D+E; I=N+5}
else {C=D–E; I=N–5;}
Оператор вибору switch/case дозволяє вибірково виконати фрагмент програмного коду, в залежності від значення виразу. Формат оператору:
switch (вираз з цілими числами) {
case константа1: вираз1;
break;
case константа2: вираз2;
break;
case константа N: вираз N;
break;
[ default: дія за умовчанням;] }
Оператор break повинен знаходитись у всіх гілках, інакше не буде мати місце вибіркове виконання команд у гілках після case. Гілку default можна не вказувати. Приклад використання оператора вибору:
switch (num) {
case 0: A=B+C; C=D+2;
break;
case 1: A=B–C; C=D+10;
break;
case 5: A=B*C; C=D+15;
break; }
Оператор циклу з параметром for використовується у тих випадках, коли нам відома до виклику циклу кількість його ітерацій. Синтаксис оператора циклу for:
for (початкове значення ітератора; умовний вираз; модифікація ітератора)
{
оператори в тілі циклу;
}
Розглянемо роботу цикала for: початкове значення ітератора визначає значення лічильника при вході у цикл; після цього аналізується умовний вираз (цикл виконується доки умова є істиною). Кожен раз після усіх строчок тіла циклу виконується модифікація ітератора, тобто змінюється значення лічильника. Вихід з циклу станеться, як тільки умовний вираз отримає значення false. Приклад оператору циклу:
s=0;
m = 1;
for (i=1; i<=10; i++)
{ s=s+i;
m=m*i; }
Оператор циклу з передумовою while застосовується, коли число повторень невідомо, та необхідно здійснити певну умову. Формат оператору наведений нижче:
while (умовний вираз)
{
Оператори тіла циклу;
}
Оператор починається з ключового слова while, за яким слідує логічний вираз, що повертає значення false або true. Оператори, що у фігурних дужках, утворюють тіло циклу. Приклад використовування оператору циклу while:
a=0;
while (a<10)
{ b=(c+d)*a-f;
a=a+2; }
Підпрограми на мові С оформлюються у вигляді функцій. Опис функції має наступний синтаксис:
[Тип виразу, що повертаємо] ім’я тіла ([список параметрів])
{
[декларації локальних змінних]
оператори тіла функції;
[return вираз;]
}
Якщо функція не повертає значення, то тип значення, що повертається не вказується і секція return не використовується. За відсутності параметрів після імені функції обов`язково вказують порожні круглі дужки ( ). Тіло функції заключається в фігурні дужки { }. Змінні, що об`явлені в тілі функції, є локальними (які видно тільки в межах тіла функції). Функції, що повертають значення, можна повертати в правій частині операторів присвоювання.
Розглянемо приклад декларації функції, що повертає, в залежності від значенния аргументу С, суму чи різність двох цілих чисел:
int sum (int A, int B, char C)
{
if (C>=0) return A+B;
else return A–B;
}
Приклад функції, що не має аргументів і неповертає значення:
init_data ( ) {
A=10;
B=100+А; }
При програмуванні мікроконтролера часто виникає необхідність використовувати асемблерний код в програмі, що написана на мові С. В цьому випадку фрагмент програми, що складений з асамблерних операторів, розміщується в операторні дужки:
#asm
оператори мови асемблер
#endasm ;
Приклад фрагменту програми на мові Assembler:
#asm
mov r1,r5
ldi r17,0xf5
#endasm ;
Одиничний асемблерний оператор в тілі С – програми, може бути записаний у вигляді директиви #asm ("Оператор мови Assembler”);.
Приклад:
#asm("out 0x12,r16"); //виконати команду out 0x12,r16.
Функції, написані на асемблері, повертають значення через регістр R30 для типів char і unsigned char, і регіструють пару (R31, R30) для типів int і unsigned int (в R31 – старший, а в R30 – молодший байти). Параметри функції передаються через стек, на вершину котрого вказують регістр Y, причому старший байт слова записує за старшою адресою. Механізми виклику та повернення з функції виконується засобами компілятору С. Директива #pragma warn- забороняє компілятору генерувати попередження про те, що функція не повертає результат стандартним засобом (за допомогою оператору return).
В якості приклада розглянемо асемблерну функцію, що виконує додавання двох цілих чисел і повертає значення типу int (пояснення до ассемблерного коду надаються):
int summa (int A, int B)
{
#asm
ldd R27, Y+3 завантажити старший байт параметру А;
ldd R26, Y+2 завантажити молодший байт параметру А;
ldd R25, Y+1 завантажити старший байт параметру В;
ld R24, Y; завантажити молодший байт параметру В;
add R24, R26 виконати додавання молодших байтів А і В;
adc R25, R27 виконати додавання старших байтів А і В з урахуванням прапору переносу С;
mov R30, R24 записати молодший байт додатка до регістру R30;
mov R31, R25 записати старший байт додатка до регістру R31;
#endasm
}
Виклик даної процедури виконується наступним чином:
int С;
C=summa (10, 15);
Часто у асемблерних підпрограмах виникає необхідність отримати доступ до значень змінних, що визначені в С–програмі. Розміщення змінних (у регістрах процесора чи пам’яті даних) можна визначити з файлу з розширенням *.map, ім’я якого збігається з іменем файлу, в якому зберігається код програми. Цей файл генерується компілятором та знаходиться в одному каталозі з основним модулем програми.
Розглянемо структуру програми на С. Текст основного модуля програми починається з директив препроцесора #include <ім’я файлу.h>, за допомогою яких у програмний код проекту підвантажуються файли заголовків, в яких зберігається значення різних констант, ідентифікаторів та прототипи функцій. Приклад використання даної директиви, що завантажує файл заголовку mega2561.h:
#include <mega2561.h>
Після цього визначаються значення констант (за допомогою директив #define) та глобальних змінних.
Наступним кроком є декларація функцій, що використовуються у головній програмі, що розміщена в тілі функції main(), з операторів якої починається виконання програми. Тіло функції main() розміщено між двома фігурними дужками {}.
- 7.091501"Комп’ютерні системи та мережі".
- Програмна модель мікроконтролера Atmel avr aTmega 2561.
- Структура регістру станів
- Система команд мікроконтролера avr aTmega2561.
- Результати виконання логічних операцій
- Синтаксис та основні оператори мови с.
- Зміст, правила оформлення звіту, організація і проведення занять
- Лабораторні роботи Лабораторна робота 1
- Тема 1: Опис інтерфейсу компілятора мови с CodeVision avr
- Тема 2: Управління блоком світлодіодів
- Порядок виконання завдання:
- Тема 3: Вивчення принципів організації програмного опитування клавіатури
- Тема 4: Вивчення принципів роботи ацп мікроконтролеру на прикладі обробки сигналів з термодатчика
- Лабораторна робота 5 Тема 5: Реалізація виведення даних на жк-дисплей та обмін інформацією між пеом та мікроконтролером через послідовний порт rs-232
- Список рекомендованої літератури