#5 основы си для мк

Август 30, 2008

В этом уроке даются основные понятия языка и необходимые примеры использования операторов. В дальнейшем будут появлятся новые операторы.
В отличии от скриптовых языков, си требует указать размер переменной. Это называют еще типом переменной.
Нужно это для правильного расхода памяти.
Например для цикла for на обычном компьютере используют переменную типа int. Считает такой цикл обычно не так много, а памяти выделяет больше.
При программировании мк нам надо следить за расходом памяти и грамотно выделять ее.
В основном в мк счет идет до 65535 или до 255.
Поэтому чаще всего используется переменная char в 1 байт.
Тип int в 2 байта используется для хранения значений 16 битных счетчиков или переменных, требующих 2 байта.
Например это может быть частота для приемника типа 101.2 мгц - 10120.
Если мы будет хранить частоту в десятичном виде, то нам надо будет резервировать переменную другого типа, которая занимает еще больше места. И все равно число надо будет потом преобразовывать в инт.

Поэтому в 90% случаев при программировании мк будем использовать char или int.

Второй тип данных - массивы. Массив - это набор переменных одного типа.
char temp[5];
Это значит, что мы создали как бы 5 виртуальных переменных. Аналогично можно было бы сделать так:
char temp1;
char temp2;
char temp3;
char temp4;
char temp5;
Однако удобство работы с массивом заключается в том, что можно обращаться к определенной части по его номеру.
Номера начинаются с нуля. Например char temp[0] будет первый элемент, а char temp[4] - последний.

Массив изначально инициализируется в 0, но можно все 5 элементов забить своими числами.
char temp[5] = {1, 45, 0, 255, 100};
Числа больше 255 записать нельзя. Так же нельзя записать и отрицательные числа.
Для хранения отрицательных чисел надо явно указать, что переменная должна хранить числа со знаком.
signed char temp[5];
По умолчанию же компилятор принимает unsigned. Однако отрицательные числа тоже используются редко. Температура, даже отрицательная, с цифровых датчиков все равно идет в виде 0-255 и ее надо будет приводить в удобный для нас вид.

Цикл for.
Считает от и до с шагом. Обычно используют для прогонки массива или бит в переменных.
Чтобы цикл заработа, надо для него определить переменную.
Как я уже говорил, это будет char и обычно это i.
for (от; условие до или пока; шаг){
что делать
}

Условием может быть от 0 до 7 или пока переменная такая-то не примет значение х.
Шаг - на сколько надо увеличивать начальную переменную. Обычно на единицу.
Выглядеть это будет вот так:
char i;
for (i=0; i<7; i++)
Такой цикл будет работать, пока i не станет равной 7.
Пример с условием "пока":
char x=5;
char y=10;
for(i=0; x!=0; i++){
x=y-i;
}
Такой цикл будет работать, пока х будет не равен нулю.
Чтобы выполнить это действие, но попроще, есть цикл while.
В нем задается только условеи, при котором выполняется цикл.

char i=5;
while(i!=5){
i=i-1; (или же i--;)
}

Например такой цикл можно использовать для некритичного ко времени ожидания изменения состояния на одном из выводов мк. Например можно ожидать, пока внешнее устройство обработает данные с мк и будет готово к приему новых данных. А до этого мк ничего не должен делать.
while(PINA.1);
Такой вот короткий цикл. Чтобы он работал, условимся, что внешнее устройство при готовности имеет лог0. Пока оно не готово, то на входе мк лог1.
Это значит, что будет НЕ_НОЛЬ и поэтому условие сокращается до макроса PINA.1, который дает 1 или 0. Макросы рассмотрим попозже.

В условиях так же могут быть знаки < > или =< >=.

Для определения шага больше единицы, мы должны писать так: i=i+2.
}

Условия перехода if ... else.
Если условие выполнено, то переходим.
Если же нет, то переходим на другой кусок кода после else.

Это используется для опроса кнопок или выполнения одной из двух задач в зависимости от пришедших данных.
Например у нас есть одна кнопка и при нажати на нее надо зажечь светодиод.

Условия следущие: Все входы на мк мы всегда должны подтягивать внутренними резисторами к плюсу питания.
Кнопка же включается к выводу мк и земле. Пока кнопка не нажата - в мк приходят 5в и на его входе лог1.
Стоит только нажать кнопку и ток потечет через нее напрямую и замкнет вход на землю, создав лог0.

if(PINA.1==0){
включить светодиод
}
Можно это сделать, применив операцию отрицания НЕ и тем самым избавится от сравнения с нулем.
if(!PINA.1){
...
}
В циклах тоже стоял знак !, который вместе со знаком = образует знак неравенства.
А в этом случае отдельно стоящий знак означает логическую операцию НЕ над битом или байтом.
Если бит у нас изначально был лог1, то !PINA.1 значит НЕ_ЛОГ1. Кроме 1 и 0 в битах у нас ничего не может быть  и поэтому оператор if получает на вход 0.
Когда у него на входе 0, то он не выполняется и светодиод не горит. Стоит ему подать на вход число НЕ_НОЛЬ и он сработает.

При нажати на кнопку на пине у нас становится лог0. А т.к. мы его инвертировали, тот этот 0 становится 1 и оператор if срабатывает.

Вот кусок рабочего кода из реального проекта.
#define UP            ((PINB & 0x01)!=0x01)
#define DOWN        ((PIND & 0x20)!=0x20)
#define MENU        ((PIND & 0x40)!=0x40)
  if UP up++; else up = 0;
    if DOWN down++; else down = 0;
    if MENU menu++; else menu = 0;

Операции с битами будут в следущей части и тогда будет понятно, откуда берутся все эти числа.

Оператор switch ... case.
Это альтернатива if ... else и нужна она для обработки более 2-3х условий. Например используется, если надо опрашивать более 2х кнопок или в мк от компьютера приходят данные с ком порта в виде целого байта.

switch(переменная){
case значение1: действие1; break;
case значение2: действие2; break;
case значение3: действие3; break;
default: действие действие по умолчанию;
}

Например пусть будет у нас 8 кнопок на порту А, а выполнять мы будем разные действие.
Если не нажато ничего, то ничего не делаем.

switch(PINA){
case 1: лампочка 1;
break;
case 2: лампочка 2;
break;
case 4: двигатель гаража;
break;
case 8: двигатель ворот;
break;
case 16: насос для воды;
break;
case 32: вентилятор;
break;
case 64: звонок;
break;
case 128: телик;
}
Условие по умолчанию мы не использовали.
break означает прерывание после успешного условия.
Если его не использовать, то будут выполняться все нижеследующие. break можно так же использовать в циклах, если вдруг на каком-то этапе надо будет срочно прерывать весь цикл, не ожидая его окончания.
Правда используется редко.

Откуда взялись все цифры? Об этом в следущем уроке.

Для написания программ достаточно этих знаний языка си.

категория: учим мк avr

ответить

Авторизация только через loginza.

Yandex Google Вконтакте Mail.ru Twitter Loginza MyOpenID OpenID