ЯЗЫК СИ ДЛЯ МИКРОКОНТРОЛЛЕРОВ
Минимальная программа на Си может быть такой: main(){}.
Эта программа не делает ничего полезного – но это уже программа и она показывает, что в программе на языке Си должна быть главная функция main – обязательно. Реальные программы на Си конечно больше.
Регистры МК в программе на Си имеют названия, как и в оригинальной технической документации фирмы ATMEL AVR Data Sheets (ДШ) и так как числа в большинстве из них можно менять – для программы регистры являются по сути переменными.
Чтобы поместить число в переменную (в регистр), в Си есть оператор присваивания. Это знак = (называемый в математике "равно"). В Си этот знак не означает равенство. Знак = в Си означает вычислить результат того, что справа от оператора присваивания и поместить этот результат в переменную, находящуюся левее оператора присваивания. Ниже приведены примеры команд на Си, использующие оператор присваивания.
PORTB = PINB + 57; /*Взять (прочитать, считать) значение переменной (регистра) PINB, затем прибавить к нему число 57 и поместить результат в переменную PORTB */
PORTB&=0x5А; /*Прочитать значение переменной PORTB, затем выполнить "поразрядное (побитное) логическое И" между прочитанным значением и числом 0x5А и записать результат в переменную PORTB */
PORTB = 0x23; /*Не читая содержимое переменной PORTB
присвоить ей значение 0x23 */
Вместо & "И" могут быть и другие побитные логические операции: | "ИЛИ", ^ "Исключающее ИЛИ", ~ "инвертирование битов" и арифметические операции: + - * / %.
Запомните! Результатом поразрядных (побитных) логических операций (& | ^ ~ ) является число, которое может быть интерпретировано компилятором как "истина", если оно не ноль, и "ложь", если число ноль.
Целые числа в компиляторе могут быть записаны:
- в десятичной форме: 1234;
- в двоичной форме с префиксом 0b: 0b101001;
- в шестнадцатеричной форме с префиксом 0x: 0x5А;
- в восьмеричной форме с префиксом 0: 0775.
С оператором присваивания используются вот такие сокращения:
Длинная запись | Смысл | Сокращается до |
x = x + 1; | добавить 1 | x++; или ++x; |
x = x - 1; | вычесть 1 | x--; или --x; |
x = x + y; | прибавить y | x += y; |
x = x - y; | вычесть y | x -= y; |
x = x * y; | умножить на y | x *= y; |
x = x / y; | поделить на y | x /= y; |
x = x % y; | остаток от деления | x %= y; |
x--; | вычесть 1 | x -= 1; |
x++; | добавить 1 | x += 1; |
Есть в Си операции, которые изменяют значение переменной и без оператора присваивания:
PORTA++; /* Взять значение переменной PORTA, добавить к ней 1 и записать результат обратно в PORTA –инкрементировать регистр PORTA */
PORTC--; /* Эта строчка на Си означает обратное действие – декрементировать значение регистра PORTC */
Инкремент и декремент удобно использовать для изменения
значения различных переменных-счетчиков. Важно помнить, что они имеют очень низкий приоритет. Поэтому, чтобы быть уверенным в порядке выполнения, желательно писать их отдельной строчкой программы.
Когда инкремент или декремент используется в выражении, то важно, где стоят два знака + или – (перед переменной или после переменной):
А=4;
В=7;
А=В++; /* Взять значение переменной В, присвоить его переменной А, затем добавить 1 к переменной В и сохранить результат в В. Теперь А будет содержать число 7, В будет содержать число 8 */
А=4;
В=7;
А=++В; /* Взять значение переменной В, затем добавить к нему 1 и сохранить результат в В и этот же результат присвоить переменной А. Теперь А будет содержать число 8 и В будет содержать число 8 */
Арифметические операции в Си:
x+y //сложение
x-y // вычитание
x * y // умножение
x / y /* деление. Если числа целые, результат – целое число с отброшенной дробной частью – не округленное! Т.е. если в результате деления на калькуляторе получается 6.23411 или 6.94, то результат будет просто целое число 6. Если числа с плавающей точкой, то есть float или double и записываются с точкой и числом после точки, то и результат будет число с плавающей точкой */
x % y // вычислить остаток от деления нацело
Примеры:
5 / 2 // даст 2
5 % 2 // даст 1
75 / 29 // даст 2
75 % 29 // даст 17
Операторы сравнения (или отношения) используются для сравнения переменных, чисел (констант) и выражений:
x < y // x меньше y
x > y // больше
x <= y // меньше или равно
x >= y // больше или равно
x == y // равно
x != y // не равно
Результат выполнения этих операторов: "истина" это "1" (точнее "не ноль"), "ложно" это "0". Значения, хранимые в переменных (в регистрах) х и у, не изменяются!
Логические операции:
|| // "ИЛИ"
&& // "И"
! // "НЕ"
!(истина) // дает "ложь"
!(ложь) // дает "истина"
В результате логической операции вы получаете не число, а логическое значение "истина" или "ложь". Для логических операций && и || берутся результаты выражений слева и справа от знака операции, преобразованные в "истину" или "ложь", и определяется логический результат операции. Компилятор результат "истина" превращает в 1, а "ложь" в 0.
Ходовые конструкции на Си (в компиляторе CVAVR заготовки этих конструкций находятся под ярлыком "Code Templates" слева вверху. Вы можете выбирать нужные заготовки и вставлять их в свою программу):
if(){}else{}; идеальная конструкция, если вам нужно выполнить какую-то часть программы при наличии каких либо условий:
if (выражение) { /* делать этот код, если выражение "истина" – т.е. результат его вычисления не ноль */ } else { /* делать этот код, если выражение "ложь" – т.е. результат его вычисления равен нулю */ }; |
} else { это не обязательный элемент конструкции:
if (выражение) { /* делать этот код, если выражение "истина" – т.е. результат его вычисления не ноль */ }; |
while(){}; условный цикл – используйте, если вам
нужно выполнять какой то код программы, пока выполняется (существует, справедливо, не ноль) некоторое условие:
while (выражение) { /* делать этот код, если выражение "истина" – т.е. результат его вычисления не ноль. Пока выполняется этот код, выражение не проверяется на истинность. После выполнения кода происходит переход к строке while, чтобы снова проверять истинность выражения */ }; |
Цикл while имеет вариант do – while, при котором код в { } выполняется по меньшей мере один раз независимо от истинности условия в скобках:
do { /* сделать этот код один раз, затем, если выражение есть "истина" – т.е. результат его вычисления не ноль – опять делать код с начала, и так до тех пор, пока выражение "истина" */ } while (выражение); |
for(;;){}; – этот цикл позволяет выполнить часть программы нужное число раз:
char i; /* объявление переменной для for. Это обычная переменная и, значит, может иметь любое допустимое имя по вашему желанию */ for (i=5;i<20;i+=4) { /* код цикла for. i=5 – это начальное выражение. Число 5 просто для примера, может быть таким, как позволяет объявление переменной i, в нашем случае от 0 до 255. i<20 – контрольное выражение. Может быть с разными операторами отношения, важно лишь, чтобы по ходу цикла оно становилось когда-то "ложью" – иначе цикл "зациклится", т.е. никогда не кончится. i+=4 – счетчик. Обычно это i++, т.е. к переменной добавляется 1 каждый "прогон" цикла. Но может быть таким, какое вам требуется, важно лишь достижение когда-либо условия, оговоренного выше! Иначе цикл станет бесконечным. Код цикла for будет первый раз выполнен для i=5, затем по выражению i+=4 i станет 9. Теперь будет проверено контрольное выражение i<20 и так как 9<20 код цикла for будет выполнен еще раз. Так будет происходить до тех пор, пока контрольное выражение "истинно". Когда оно станет "ложно" цикл for закончится и программа пойдет дальше. */ }; |
Начальным условием может быть любое допустимое в Си выражение, результатом которого является целое число. Контрольное выражение определяет, до каких пор будет выполняться цикл. Счетчик показывает, как изменяется начальное выражение перед каждым новым выполнением цикла.
Циклы for(;;) и while() часто используют вот так:
while(1); for (;;); /* Так написанные эти циклы означают: МК выполнять эту строчку пока есть питание, нет сброса и нет прерывания. Когда возникает прерывание, программа переходит на обработчик прерывания и (если в обработчике нет перехода в другое место программы) по завершении кода обработчика опять возвращается в такой цикл */ |
switch(){}; – оператор множественного выбора, позволяет сделать выбор из нескольких вариантов.
switch (выражение) { case 7: /* этот код будет выполняться, если результат вычисления выражения равен числу 7. На этом работа оператора switch закончится */ break; case -28: /* этот код будет выполняться, если результат вычисления выражения равен отрицательному числу -28. На этом работа оператора switch закончится */ break; case 'G': /* этот код будет выполняться, если результат вычисления выражения равен числу, соответствующему символу G в таблице ASCII. На этом работа оператора switch закончится */ break; default: /* этот код будет выполняться, если результат вычисления выражения не равен ни 7, ни -28, ни 'G'. А так же после выполнения кода, не имеющего в конце break. На этом работа оператора switch закончится */ }; /* switch закончен - выполняется дальнейший код программы */ |
case может быть столько, сколько вам нужно. Чтобы программа работала быстрее, старайтесь наиболее вероятные варианты располагать выше!
default - не обязателен. Его можно расположить и не в конце.
break; - если его не использовать, то, найдя нужный вариант, программа будет выполнять и следующие ниже условия case.
goto – оператор безусловного (немедленного) перехода.
mesto_5: /* сюда мы попадем после выполнения строки программы goto mesto_5 */ goto mesto_1; /* перейти в то место программы, где в начале строки написано mesto_1: */ goto mesto_5; /* перейти в то место программы, где в начале строки написано mesto_5: */ mesto_1: /* сюда мы попадем после выполнения строки программы goto mesto_1 */ |
goto существует наверно во всех языках и в ассемблере в том числе. Используйте его с осторожностью! Например: если вы покинете функцию-обработчик прерывания по goto, не завершив ее, то не произойдет автоматического включения прерываний глобально – т.е. не установится бит I в регистре SREG,
Этот бит устанавливается автоматически после полного выполнения функции обработки прерывания и "естественного" выхода из неё.
Дата добавления: 2016-01-09; просмотров: 2897;