#define CLI asm("cli\n"); //разрешить маскируемые прерывания
Далее в программе используют только имя макроса:
CLI;
Кроме директивы определения символа или макроса #define, существует директива обратного действия #undef. Приведем пример ее использования:
#define VALUE 10
int number[VALUE];
#undef VALUE
В этом примере мы сначала назначили переменной VALUE значение 10. Далее в строке 2 мы воспользовались этим значением, чтобы определить массив целых чисел из 10 элементов. Далее переменная VALUE нам не нужна. И мы отменили ее определение директивой #undef.
Следующая рассматриваемая нами директива — это директива #include. Ранее мы установили, что эта директива используется для присоединения к разрабатываемому программному модулю другого файла. При этом у программиста появляется возможность использовать в тексте программы ранее объявленные переменные или вызывать функции, которые были определены в другом файле. Присоединяемые файлы называют заголовочными файлами. Например, следующая запись необходима для присоединения к разрабатываемой программе файла стандартных функций ввода/вывода:
#include
Символы <> указывают на определенное место расположение файла stdio.h в папках директории компилятора.
Назначение директивы #error — упрощение процесса отладки разрабатываемой программы. Вы можете записать следующее выражение:
#error Programm made a logic error
Если в процессе выполнения программа достигнет приведенной строки, то на экран будет выведено приведенное сообщение.
Также для целей отладки используется директива #line. Эта директива отмечает номерами те инструкции программы, которые следуют за директивой. В результате, в процессе отладки можно идентифицировать тот фрагмент программы, который исполняется в текущий момент отладки.
Функции директивы #pragma определяются конкретным типом используемого компилятора. Для компилятора ICC12 эта директива определения сегментов данных и программы в исходном тексте программы на Си, для объявления подпрограмм прерывания, а также для присвоения желаемых значений ячейкам памяти с фиксированными адресами. Последнее позволяет инициализировать таблицу векторов прерываний в микроконтроллерах. Приведенный ниже пример демонстрирует использование директивы #pragma для объявления подпрограммы с именем TOISR в качестве подпрограммы прерывания:
#pragma interrupt_handler TOISR
void TOISR(void);
Объявление подпрограммы TOISR как подпрограммы прерывания информирует компилятор о том, что в конце этой подпрограммы он должен расположить ассемблерную инструкцию возврата из прерывания rti. В конце обычной функции компилятор подставляет инструкцию возврата из подпрограммы rts.
Директива #pragma также используется для задания начального адреса расположения в памяти сегментов программного кода или кодов данных. Запишем вектор прерывания для подпрограммы TOISR в таблицу векторов прерывания МК. Мы знаем, что в соответствие с картой памяти МК, вектор прерывания по переполнению таймера должен располагаться по адресу 0x0B1E. Следующая запись помещает адрес начала подпрограммы TOISR в две ячейки памяти, начиная с адреса 0x0B1E:
#pragma abs_adress:0xB1E
void (*Timer_Overflow_interrupt_vector[]) = {TOISR};
#pragma end _abs_adress
Более подробно оформление подпрограмм прерывания мы обсудим в главе 4.
3.7. Конструкции программирования
В теории программирования доказано, что любая программа может быть закодирована с помощью комбинаций трёх конструкций: последовательность операторов, выбор и итерация. В этом разделе мы рассмотрим набор операторов языка Си и типовые примеры их использования для реализации конструкций цикла (итерации) и принятия решения (выбора).
3.8. Операторы для организации программных циклов
В языке Си существует несколько операторов, которые позволяют реализовать циклические вычисления (итерации). В этом параграфе мы рассмотрим программные конструкции циклов с операторами for, while, do while.
3.8.1. Оператор FOR
Оператор for предназначен для реализации циклов со счетчиком. В операторе for могут автоматически реализоваться сразу три операции: инициализация счётчика цикла, проверка его значения и модификация. Синтаксис оператора for:
for (<выражение1>; <выражение2>; <выражение3>)
<операторы тела цикла>
Рассмотрим типичный пример реализации цикла с оператором for:
1 for(i = 0; i < 10; i = i++)
2 {
3 inst 1;
4 inst 2;
5 :
6 :
7 inst n;
8 }