1
]
МИКРОКОНТРОЛЛЕРЫ
II
Перейдем теперь к участку с номером <4> в программе.
В этой функции (она называется TURNON_LED) примене-
ны две специфичные конструкции языка С - операция сдви-
га (она обозначается символами “« ”) и т.н.
“операция по
месту’.
Операции сдвига в языке С записываются как “« ”
(соответствуют командам LSL и ROL в зависимости от раз-
мера операнда), и “» ” (соответствуют командам LSR и ROR
для типов данных unsigned, ASR и ROR для типов данных
signed - компилятор сам разберется, какими именно коман-
дами воспользоваться). Слева от знака операции - сдвига-
емые данные, справа - число бит, на которое необходимо
их сдвинуть. “Операция по месту” LedTurned 1= 1 « buttonNo
по своему результату в точности соответствует операции
LedTurned = LedTurned I (1 « buttonNo), т.е. установке в пе-
ременной LedTurned бита с номером buttonNo в лог.1 (опе-
рация I - побитовое “или”). Причина появления в языке С
такого специфичного вида операций заключается в том, что
во многих процессорах имеется набор команд, позволяю-
щий выполнить эту операцию более быстрым способом. На-
пример, при. работе на процессорах Intel “обычная” опера-
ция побитового “или” потребует для выполнения трех ко-
манд, а “операция по месту” - всего одну. В микроконтрол-
лерах АТМеда в системе команд процессора таких “быст-
рых” команд нет, поэтому в плане скорости работы и объе-
ма программы “операция по месту” никаких преимуществ
для него не дает, тем не менее рекомендуем в программах
пользоваться именно ей. Причин тому две - традиции про-
граммирования (такая запись для программистов на С и
короче и понятнее), и общие соображения - возможно, со
временем Вам придется перенести программу на другую
платформу, на которой соответствующий набор команд ока-
жется, а это позволит компилятору построить более опти-
мальный код. Не нужно лишать компилятор маленьких ра-
достей © Операции “по месту” есть практически для всех
“обычных” операций - арифметика, битовые операции, ло-
гические операции, сдвиги. Форма их записи - символ со-
ответствующей операции, к которому справа “приписан”
знак “=”, например “+=”, “» = ”, “%=” (в языке С это остаток
от деления числа слева от “%=” на число справа от “%=”).
Участок, отмеченный <5> в программе, примечателен
тем, что в нем появились условные вычисления. Програм-
мистам, написавшим хотя бы одну программу на ассембле-
ре, этот тип вычисления должен быть хорошо знаком: в за-
висимости от результата последней арифметической опе-
рации или операции сравнения, некоторый участок програм-
мы должен быть выполнен или, наоборот, пропущен. В языке
С для описания таких вычислений используется оператор
if.
Синтаксис его следующий:
if
(проверяемое условие) <блок true>
else
<блок false>
Блок false вместе с предшествующим словом
else
мо-
жет отсутствовать, если в нем нет необходимости. Работа-
ет оператор if следующим образом - если проверяемое ус-
ловие оказалось истинным, выполняется блок true, если
ложным - блок false (а если этого блока нет - не выпол-
няется ничего). Скобки вокруг условия являются частью
синтаксиса и не могут быть опущены (в отличие, например,
от другого языка - Pascal). Проверяемое условие - это
обычно набор операций сравнения, соединенный знаками
логических операций. В данном случае это условие можно
“прочитать” так - если соответствующий элемент массива
PWMSign (знак изменения величины границы OCR) боль-
ше нуля (т.е. происходит увеличение яркости светодиода)
и
соответствующий элемент массива PWMBound меньше 255
(т.е. яркость светодиода еще не достигла максимума), то
яркость свечения светодиода нужно увеличить на единицу.
Для увеличения яркости свечения используется специаль-
ная разновидность “операции по месту” - инкремент (обо-
значается знаком “++”). Назначение оператора if вполне оче-
видно - “защитить” уровень яркости светодиода от выхода
за максимальное значение (а следующего оператора if - от
выхода за минимальное значение соответственно). К это-
му следует добавить еще два важных момента - в языке С
нет
логического типа данных как такового (он появился толь-
ко в языке C++, являющемся продолжением языка С), и в
языке С всегда реализуется т.н.
“короткая”
схема вычисле-
ния логических выражений. Для целей работы условного
оператора считается, что нулевое значение, полученное в
результате выполнения арифметических операций, пред-
ставляет собой логическое значение FALSE (ложь), а нену-
левое (причем неважно какое!)-логическое значение TRUE
(истина). В этом смысле условие проверки переменной на
неравенство нулю if (х != 0) можно записать просто как if (х)
- результат будет один и тот же. Суть второго замечания
заключается в том, что вычисление логических выражений
в языке С продолжается ровно до того момента, пока не
становится ясным итог всей операции целиком. Если в це-
почке условий, соединенных логической операцией “И” одно
из условий не выполняется, совершенно очевидно, что и
вся цепочка целиком окажется “ложной” - это следует из
самого определения операции “И”: Поэтому в таком случае
продолжать дальнейшие вычисления бессмысленно. Они
и не продолжаются - компилятор строит код проверки ло-
гических условий таким образом, чтобы в этом случае уп-
равление сразу передалось на блок false. Это, собственно,
и называется “короткой схемой” вычисления. Точно так же
если в цепочке условий, соединенных логической операци-
ей “ИЛИ”, одно из условий выполнилось, вся цепочка усло-
вий гарантированно окажется истинной - так определена
операции “ИЛИ”. Поэтому не следует опасаться задавать
сложные условия в операторе if - лишних действий при их
проверке в программе не будет.
И, наконец, участок, отмеченный <6>, примечателен тем,
что в нем выполняется вызов других функций. Вложенные
вызовы - нормальная практика программирования как на
ассемблере, так и на языке С. Обратите внимание, как они
записываются в программе на С - пишется имя функции,
которую нужно вызвать, после чего в круглых скобках за-
писываются параметры, которые ей нужно передать. Если
параметры для функции не требуются, круглые скобки все
равно должны присутствовать (выглядеть это будет как
“func()”) - по их наличию компилятор отличает имена
функций от имен переменных. Перед вызовом функций
компилятор уже должен знать, как вызываемая функ-
ция “устроена”, поэтому мы и поместили определение
функций STOP_TIMER и TURNON_LED перед функцией
STOP_TIMER_TURNON_LED - обработка программы на
Радиолюбитель - 12/2008 []
39
предыдущая страница 39 Радиолюбитель 2008-12 читать онлайн следующая страница 41 Радиолюбитель 2008-12 читать онлайн Домой Выключить/включить текст