Учебник AVR

Содержание

Типы данных, переменные, константы

Тип данных определяет диапазон допустимых значений и пространство отводимое в памяти для констант, переменных и результатов возвращаемых функциями. В таблице ниже представлены стандартные типы данных.

 

Тип Название Размер в битах Диапазон значений
bit Бит 1 0,1
char Символ 8 -128..127
int Целое число 16 -32768..32767
float Вещественное число 32 ±1,175·10-38.. ±3,402·1038
long int Длинное целое 32 -2147483648 .. 2147483647
unsigned char Беззнаковый символ или
логическое значение
8 0..255
TRUE,FALSE
unsigned int Беззнаковое целое 16 0..65535
unsigned long int Беззнаковое длинное целое 32 0..4294967295
bit Бит 1 0,1

Бит — базовая единица информации в вычислительной техники, все остальные типы данных строятся на основе битов. Бит может принимать одно из двух значений «1» или «0», иными словами высокий уровень сигнала или низкий уровень сигнала, есть напряжение или нет напряжения, включено или выключено 🙂

Байт — единица информации состоящая из восьми бит, с помощью байта можно представить 256 различных состояний от 0 до 255, для наглядности они представлены ниже в таблице.

Значение Двоичное представление Шестнадцатиричное представление
0 0b00000000 0x00
1 0b00000001 0x01
2 0b00000010 0x02
254 0b11111110 0xFE
255 0b11111111 0xFF

Тип Char. Байту данных в языке «С» соответствует тип char. Char от англ. «character», поскольку чаще всего используется для хранения символов, а точнее их ASCII-кодов, их можно посмотреть в разделе подназванием «Справочные данные». Тем не менее с его помощью можно обращаться к небольшим целым числам в диапазоне -128..127, а для типа unsigned char от 0..255, поскольку в этом случае знаковый разряд не используется, это справедливо для типа unsigned int и unsigned long int.

Переменная — именованная величина определённого типа, значение которой может изменяться в ходе выполнения программы. Для объявления переменной в языке «С» используется следующий синтаксис:

; например char x;

=; например char x = 0;

Константа — именованная величина определённого типа, значение которой не может изменяться в ходе выполнения программы.

const =; например const char x = 0xFF;

Вверх

Системы счисления

 


Основной системой счисления в программировании для микроконтроллеров является шестнадцатиричная система счисления, но без двоичной и десятичной не обойтись. Ниже приведена таблица, в которой наглядно представлено различие этих систем.

Десятичная система Двоичная система Шестнадцатиричная система
0 0b00000000 0x00
1 0b00000001 0x01
2 0b00000010 0x02
3 0b00000011 0x03
4 0b00000100 0x04
5 0b00000101 0x05
6 0b00000110 0x06
7 0b00000111 0x07
8 0b00001000 0x08
9 0b00001001 0x09
10 0b00001010 0x0A
11 0b00001011 0x0B
12 0b00001100 0x0C
13 0b00001101 0x0D
14 0b00001110 0x0E
15 0b00001111 0x0F

Шестнадцатиричная система счисления не заканчивается числом 0x0F, следующее число будет 0x10 и так до 0xFF.

Вверх

Выполнение арифметических операций

 


Бинарные операции, которые поддерживает язык «C» приведены в таблице ниже.

Приоритет Оператор Значение
1 + (унарный) Реально ничего не меняет
1 — (унарный) Возвращает противоположное по знаку, равное по модулю значение
2 ++ (унарный) Оператор инкремента, увеличивает значение аргумента на 1
2 — (унарный) Оператор декремента, уменьшает значение аргумента на 1
3 * (бинарный) Умножение
3 / (бинарный) Деление
3 % (бинарный) Остаток (деление по модулю)
4 + (бинарный) Сложение
4 — (бинарный) Вычитание
5 =, *=, %=, +=, -= Операторы присвоений (специальные)

Примеры использования арифметических операторов.

char i=10;

i+; //Реально ничего не меняет, поэтому на практике не используется.

i-; //Значение переменной «i»поменяет свой знак, в данном случае станет «-10».

i++; //Этот оператор прибавит 1 к переменной «i», т.е. эквивалентное выражение i=i+1;

i—; //Этот оператор вычтет 1 из переменной «i», т.е. эквивалентное выражение i=i-1;

i=i*10; //В этом выражении значение переменной «i» умножется на 10, а полученный результат перезапишется в

переменную «i», т.е. в результате «i» будет равно 100.

i=i/10; //В этом выражении думаю всё должно быть понятно.

i=15%4; //Это выражение вычисляет остаток, т.е. 15/4=12 с остатком 3 (12 + 3 = 15), вот этот остаток и бует результатом

данного выражения.

i=i-2;   i=i+3;  //Думаю эти выражения в комментариях не нуждаются.

Давайте подробнее остановимся на операторах присвоения.

i=0b00000001;  //Переменной «i» присвоено значение «1» (двоичная система счисления)

i=1;  //Переменной «i» присвоено значение «1» (десятичная система счисления)

i=0x01;  //Переменной «i» присвоено значение «1» (шестнадцатиричная система счисления)

Вверх

Выполнение логических операций

 


Для принятия решений в программах просто необходимо использовать логические операторы.

Простые логические операции приведённые ниже в таблице могут возвращать два значения true(истина) и false(ложь).

Оператор Значение
== Знак равенства, очень часто путают со знаком присвоения «=».
Выражение будет истино, если левая и правая чато выражения будут равны.
!= Знак неравенства
Выражение будет истино, если левая и правая чато выражения будут НЕ равны.
>, < Больше, меньше; истинно, когда значение левого выражения больше (или меньше) значения правого
>=,Выражение истинно, если левая часть «>» или «==» правой, или «
&& «И», истинно, если аргументы И слева И справа являются истиной
|| «ИЛИ», истинно, если аргументы ИЛИ слева ИЛИ справа являются истиной
! «НЕ», истинно, если аргумент принимает ложное значение

Давайте рассмотрим несколько простых примеров. Возьмём две переменные одного типа и сравним их.

Пример 1:

//В языке С такая строчка обозначает комментарий, т.е. на ход выполнения программы не влияет.

char a=1;   //Объявили переменную «a» и присвоели ей значение.

char b=1;   //Объявили переменную «b» и присвоели ей значение.

Теперь подставляем логический оператор, например, оператор равенстава «==».

a == b   //a равно b?

Результатом этого выражения будет истина (true), т.к. 1 == 1.

Пример 2:

char a=1;

char b=0;

a && b

Результатом этого выражения будет ложь (false), т.к. b == 0. «0» в логических конструкциях обозначает ложь(false), т.е. если выражение равно нулю, оно ложно.

Пример 3:

char a=1;

char b=0;

a || b

Результатом этого выражения будет истина (true), т.к. одно из аргументов истинно (a == 1).

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

После того как освоите простые логические выражения, попробуйте составить сложные, они отличаются лиш тем что в левой и правой частях стоит не просто переменная а целое выражение.

Пример:

char a=1;

char b=0;

char c=0;

char d=0;

(a > b) || (c != d)

Теперь давайте разберёмся. Между выражениями стоит знак ИЛИ «||», это значит что если одна из частей выражения (левая или правая) после вычисления даст истину, то итоговый ответ будет истинным. Теперь проверяем левую часть «a > b», это истина, левую часть можно не проверять, т.к. результат уже известен.

Вверх

Команды ветвления (if)

 


Проще всего управлять ходом программы с помощью инструкции ветвления, которая позволяет программе, в зависимости от результата логического выражения, решить, по какому пути выполнения инструкций следует двигаться дальше.

В языке С оператор условного перехода реализуется с помощью инструкции «if», if с англ. «если». Рассмотрим простейшие примеры.

Пример 1:

char a=1;

char b=0;

if(a > b){   //Если «a» больше чем «b»

//инструкции которые должны быть выполнены

}

else{

//инструкции которые должны быть выполнены если «a» МЕНЬШЕ «b», т.е. выражение «a > b» ложно.

}

Пример 2:

Инструкцию «if» также можно использовать без инструкции «else».

if(истина){

//инструкции которые должны быть выполнены

}

Вверх

Циклы (while,for)

 

Самый простой цикл можно организовать с помощью оператора while. Он выглядит таким образом:

while(условие){
//Этот код выполняется повторно,пока условие остаётся истинно

}

Перед тем как выполнить код, оператор while проверяет условие, если условие не удовлетворяется, код выполняться не будет.

do{

//Этот код выполняется повторно,пока условие остаётся истинно

}while(условие);

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

Существуют бесконечные циклы, которые повторяются снова и снова, получить бесконечный цикл очень легко, нужно чтобы условие цикла всегда было «истинным» значением, например «1» это истина. Один из наиболее часто используемых бесконечных циклов я привёл ниже.

while(1){

//Инструкции, которые будут выполняться бесконечно

}

Теперь рассмотрим оператор for. Этот оператор используется в паре с переменной, любой, возьмём например переменную «i».

Теперь представим что по условию задачи нам нужно чтобы цикл повторился 10 раз, тогда синтаксис условия будет следующим:

for(i=0;i
//Инструкции для выполнения

}

Рассмотрим выражение из которого сотоит условие цикла, оно состоит из трёх частей, в первой части мы присваиваем начальное значение, с которого начнётся отсчёт (например i=0;), во второй части устанавливаем само условие, используя логические ператоры, в данном случае i, а в третьей части прописывается условие, которое увеличивает или уменьшает цикл, в основном используют инкримент или декримент (i++; i—;).

 

Вверх

Инструкция выбора (switch-case)

 


Инструкция switch-case эффективна, если существует необходимость выбора при ограниченном количестве возможных вариантов. Она похожа на усложненную инструкцию if, которая вместо проверки одного условия анализирует множество разных возможностей:

switch (выражение)
{

case c1:

//переходим сюда, если выражение == c1

break;

case c2:

//переходим сюда, если выражение == с2

break;

default:

//если ни одно условие не выполнено, переходим сюда

}

Значением выражения должно быть целое число {int, long или char); cl, с2 и т.д. должны быть константами.Инструкция switch выполняется следующим образом: сначала вычисляется значение выражения, а затем оно сравнивается с константами, указанными после служебного слова case. Если константа соответствует значению выражения, то программа передает управление этой ветви. Если ни один вариант не подходит, выполняется условие default.Для выхода из инструкции switcn необходимо использовать команды break, иначе управление будет переходить от одного случая к следующему.

Вверх

Массивы, работа с массивами

 


Массив — это тип данных, который используется для представления последовательности однотипных значений.

Массивы объявляются подобно обычным переменным, с указанием в квадратых скобках размерости (количества элементов в массиве).

int digits[10] //Массив из десяти элементов типа int

char str[10] //Массив из десяти символов (строка)

Доступ к элементам массива реализуется с помощью индекса(порядкового номера элемента, начиная с 0).

digits[0]=0; //Присвоили первому значению массива число 0

str[0]=’А’; //Присвоили первому элементу строки значение «A»

Многомерные массивы

Язык С допускает использование многомерных массивов. Простыми словами обычный массив это строка(т.е. все элементы располагаются строкой), а многомерный это строки и столбцы, смотрите пример ниже и всё станет понятно.

char a[]={1,2,3,4,5,6,7,8}   //одномерный массив

char b[2][3]={ {1,2,3},   //Двухмерный массив, 2 строки по 3 элемента в каждой

{4,5,6} };

Вверх

Строки

 


Строка в языке С — это массив типа char

Пример объявления строки(символьного массива):

char stroka[10]=»Hello»;

В данном примере размер массива — 10 символов (от 0 до 9), а длина строки «Hello» — 5 символов, посмотрите как произведётся запись символов в массив:

stroka[0]=’H’;

stroka[1]=’e’;

stroka[2]=’l’;

stroka[3]=’l’;

stroka[4]=’o’;

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

char stroka[10];

char stroka[];

Теперь когда строка записана в массив, мы можем обратиться к конкретному символу и изменить его, например давайте изменим символ «H» на символ «s»:

stroka[0]=’s’;

Хочу обратить ваше внимание на кавычки в которых заключена строка или символ, они отличаются:

char stroka[10]=»Hello»;    //Когда присваеваем строку кавычки двойные

stroka[0]=’H’;   //Когда присваеваем символ, перед и после символа ставим апострофы

Вверх

Написание и использование функций

 


Функция — это подпрограмма или микропрограмма, входящая в состав основного цикла программы. Функции очень удобны в использовании, проще «составлять» из функций программу, чем прописывать один и тот же код по нескольку раз.

Давайте рассмотрим строение функции в общем виде:

имя функции

Аргументами функции называются значения, которые передаются функции при вызове. В возвращаемом значении указывается результат, который функция возвращает по
окончании работы. Функции могут иметь не один аргумент, в этом случае аргументы разделяются запятыми.

Пример:

char demo(char a,b){

char c;   //Вспомогательная переменная.

c = (a + b)+(2 * a);   //Любое необходимое выражение.

return c;   //Строка, которая возвращает значение, она обязательна должна присутствовать

}

Тип возвращаемого значения (в данном случае результата вычисления) — char, тип аргументов — char, имя функции — summa, вы можете использовать любое, кроме зарезервированных слов компилятора Си. Смотрете их в help’е компилятора.

Давайте рассмотрим пример и вы убедитесь что лучше один раз посидеть и подумать над грамотным написанием функции, чем потом заниматься копипастом 🙂

char x = 0;

char y = 0;

char demo(char a,b){

char c;

c = (a + b)+(2 * a);

return c;

}

x = demo(10,2);

y = demo(x,15);

z = demo(x,y);

Теперь рассмотрим пример эквивалентный, но без использования функции «demo».

char x = 0, y = 0, z = 0;   //Так можно объявлять переменные одного типа.

x = (10 + 2) + (2 * 10);

y = (x + 15) + (2 * x);

z = (x + y) + (2 * x);

В этом примере мы постоянно переписываем одно и тоже выражение, только подставляем другие аргументы, согласитесь неудобно если это вражение встречается в программе много раз.

И аргументы, и возвращаемое значение функции необязательны. Если что-то отсутствует, вместо него используется ключевое слово void. Значит, если вместо списка аргументов используется void, то при вызове функция не получает никаких аргументов, например:

void main(void){};

Функция «main» ничего не возвращает и у неё нет аргументов, при её вызове, она выполнится только один раз, если конечно не вставить в неё какой нибудь цикл и/или условие.

char demo2(void){};

Функция «demo2» возвращает значение символьного типа, но не имеет аргумента, например это может быть функция которая возвращает псевдослучайное значение, в диапазоне типа char.

Функции без аргументов используются редко, так как связь с такими функциями односторонняя, т.е. осуществляется только посредством возвращаемых значений.

Давайте рассмотрим структуру программы на «С».

void main(void){

while(1){

//Ваша программа

}

}

Функция main это основная функция, она присутствует в любой программе, в теле этой функции обычно прописывается бесконечный цикл, в котором будет исполняться ваша программа.

Все функции которые вы будете использоваться в вашей программе, должны объявляться ДО функции «main», с этим вы встретитесь когда будете подробнее изучать компиляторы.

Вверх