AVR123:Глава 5
Содержание
Язык Си для AVR.
Как раз то, что необходимо и достаточно для микроконтроллеров.
По умолчанию компилятор CVAVR
В других компиляторах могут быть незначительные отклонения, нюансы не связанные с языком Си, а обусловленные стараниями и предпочтениями разработчиков этих компиляторов.
Минимальная программа на Си может быть такой: <source lang="c">main(){}</source> Эта программа не делает ни чего полезного — но это уже программа и она показывает что в программе на языке Си — должна быть главная функция main — обязательно !
Скачайте и Распечатайте.[Памятка Си для МК на ОДНОЙ странице.
Рассказывая про МК я говорил вам, что: Задача программы МК:
- читать числа из регистров и памяти МК,
- делать что-то с числами, данными и
- записывать числа в регистры и память.
Только так программа может общаться с МК.
Как это делать на языке Си
- Регистры МК
- ( регистры - это ячейки-байты в памяти МК AVR ) в программе на Си имеют названия как и в ДШ и так как числа в большинстве из них можно менять - для программы регистры являются по сути переменными.
- Переменная
- - это набор ячеек в памяти в которых можно хранить число или числа и менять их. Переменная имеет адрес и имя.
- Константа
- - это как переменная но менять содержимое нельзя.
Подробней о переменных и константах написано ниже.
1) Чтобы поместить число в переменную (в регистр) в языке Си есть оператор присваивания
это знак "=" ( называемый в математике "равно" ) "=" в Си означает вычислить результат того что справа от оператора присваивания и поместить этот результат в переменную находящуюся левее оператора присваивания.
<source lang="c"> PORTB = PINB + 34;/* Эта строчка на Си означает взять (прочитать, считать) значение переменной (регистра) PINB, затем прибавить к нему число 34 и поместить результат в переменную PORTB */
ПЕРЕМЕННАЯ = PINC; /* Эта строчка на Си означает взять (прочитать, считать) значение переменной (регистра) PINC и поместить результат в переменную с именем ПЕРЕМЕННАЯ */ </source> Чтобы в Си взять (прочитать) число из регистра или значение переменной нужно написать его название НЕ непосредственно с лева от оператора присваивания !
Примеры :
- a) Строка где переменная стоит слева от = но через знак &
<source lang="c">PORTB & = 0x23;</source>
на Си означает - прочитать содержимое переменной PORTB, затем выполнить "поразрядное (побитное) логическое И" между прочитанным значением и числом 0x23 и поместить (записать, присвоить) результат в переменную PORTB
- b) Строка где переменная стоит непосредственно слева от =
<source lang="c">PORTB = 0x23;</source>
на Си означает - не читая содержимое переменной PORTB присвоить ей значение 0x23 уничтожив то что было там раньше.
:Вместо & "И" (AND - только 1 и 1 дают 1) могут быть и другие побитные логические операции: • | "ИЛИ" (OR только 0 и 0 дают 0) • ^ "Исключающее ИЛИ" (XOR изменить бит напротив "1") • ~ "инвертирование битов" (INV изменить биты регистра) • арифметические операции: + - * / %
С оператором присваивания используются вот такие сокращения:
ДЛИННАЯ ЗАПИСЬ | СМЫСЛ | СОКРАЩАЕТСЯ ДО |
---|---|---|
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; |
Примеры :
<source lang="c"> 00010010 | 01001111 // "ИЛИ" - только 0 и 0 дают 0 // англ. название OR
01011111 // это результат
// только биты_5 в обоих числах были нули
00010010 & 01001111 // "И" - только 1 и 1 дают 1 // англ. название AND
00000010 // это результат
// только биты_2 в обоих числах были единицы
00010010 ^ 01001111/* "исключающее ИЛИ" - результат любое из пары чисел в котором инвертированы (изменены) биты напротив битов равных "1" в другом числе. англ. название XOR */ 01011101 // это результат /* изменились биты во втором числе напротив установленных битов 4 и 1 первого числа. */
~ 01001111 /* инвертировать биты те что были "1" станут "0" и наоборот */ 10110000 // это результат</source>
Запомните ! |
---|
Результатом поразрядных (побитных)
логических операций : & | ^ ~ является число ! Которое может быть интерпретировано компилятором как "истина" если оно не ноль и "ложно" если число ноль. |
Числа
В компиляторе можно записывать в виде указанном в его Help ! Раздел - константы - Constants.
например - Целые числа могут быть записаны : <source lang="c"> - в десятичной форме - 1234
- в двоичной форме с префиксом 0b так: 0b101001
- в шестнадцатеричной форме с префиксом 0x так: 0x5А
- в восьмеричной форме с префиксом 0 так: 0775</source>
Числа с плавающей точкой имеют в записи эту точку и какое либо число после этой точки, так: <source lang="c">61.234 или так: 73.0 и так: .786
и могут иметь в конце F вот так: 61.234F</source> ТОЧКА ОБЯЗАТЕЛЬНА !
Различные представления числа D3h равно 0xD3 равно 0b1101 0011 равно 211 | |||||||||
---|---|---|---|---|---|---|---|---|---|
шестнадцатеричное число 0xD3 | |||||||||
0 | x | D | 3 | ||||||
двоичное представление - число 0b1101 0011 | |||||||||
0 | b | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 |
номера бита | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
два в степени равной номеру бита | |||||||||
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | ||
число 211 в десятичном виде это сумма степеней двойки где биты равны "1" | |||||||||
Сложите | +128 | +64 | +16 | +2 | +1 |
Четыре бита это 1 "нибл" (полубайт) или 1 символ в 16-ричной системе или десятичное число от 0 до 15.
"В уме" удобно оперировать ниблами:двоичный десятичный 16-ричный
двоичный | десятичный | 16-ричный |
---|---|---|
0000 | 0 | |
0001 | 1 | |
0010 | 2 | |
0011 | 3 | |
0100 | 4 | |
0101 | 5 | |
0110 | 6 | |
0111 | 7 | |
1000 | 8 | |
1001 | 9 | |
1010 | 10 | A |
1011 | 11 | B |
1100 | 12 | C |
1101 | 13 | D |
1110 | 14 | E |
1111 | 15 | F |
Для перевода чисел из одного вида в другой можно использовать калькулятор Windows в инженерном виде.
Есть в Си операции которые изменяют значение переменной и без оператора присваивания : <source lang="c"> PORTA++; /* Эта строчка на Си означает взять значение переменной PORTA добавить к ней 1 и записать результат обратно в PORTA говорят: Инкрементировать регистр PORTA */
PORTC--; /* Эта строчка на Си означает обратное действие! Декрементировать - вычесть 1 из значения регистра PORTC */ </source>
Инкремент и декремент удобно использовать для изменения значения различных переменных счетчиков.
Важно помнить что они имеют очень низкий приоритет - поэтому чтобы быть уверенными в порядке выполнения желательно писать их отдельной строчкой программы !
Длинные выражения можно писать в несколько строк. <source lang="c"> /* ЗЕЛЕНЫМ я пишу комментарий к программе в Си он может быть написан в несколько строк
и пустых строк тоже */
// или в одну после двух черточек </source> Компилятор игнорирует все что написано в комментариях !
Вы не компилятор !
Не игнорируйте, пишите комментарии и читайте !
Когда инкремент или декремент используется в выражении то важно где стоят два знака + или - перед переменной или после переменной : <source lang="c"> a=4; b=7;
a = b++; /* Эта строчка на Си означает Взять значение переменной b присвоить его переменной a затем добавить 1 к переменной b и сохранить результат в b
Теперь a будет содержать число 7 b будет содержать число 8 */
a=4; b=7;
a = ++b; /* Эта строчка на Си означает Взять значение переменной b затем добавить к нему 1 и сохранить результат в b и этот же результат присвоить переменной a
Теперь a будет содержать число 8 и b будет содержать число 8 */ </source>
2) Арифметические операции в Си
<source lang="c"> x + y // сложение x - y // вычитание x * y // умножение
x / y /* деление.
Если числа целые результат - целое число с отброшенной дробной частью - не округленное !
т.е. если в результате деления на калькуляторе получается 6.23411 или 6.94 то результат будет просто целое число 6 - запомните !
Если числа с плавающей точкой, то есть float или double и записываются с точкой и числом после точки, то и результат будет число с плавающей точкой без отбрасывания дробной части 131.9739 / 6.18 даст 21.355 */
x % y // вычислить остаток от деления нацело
// примеры:
5 / 2 // даст 2
5 % 2 // даст 1
75 / 29 // даст 2
75 % 29 // даст 17 </source>
3) Операторы сравнения (или отношения):
<source lang="c"> используются для сравнения переменных, чисел (констант) и выражений. x < y // X меньше Y x > y // больше x <= y // меньше или равно x >= y // больше или равно x == y // равно x != y /* не равно
Результат выполнения этих операторов:
"истина" это "1" (точнее "не ноль")
"ложно" это "0"
Значения хранимые в переменных (в регистрах) х и у НЕ изменяются!
Берутся (считываются) значения хранящиеся (или содержащиеся) в переменных и сравниваются */
! /* "НЕ" - логическое отрицание */ </source>
4) Логические операции :
<source lang="c"> | | // "ИЛИ" - только "ложь" и "ложь" // дают "ложь"
&& // "И" - только "истина" и "истина" // дают "истина"
! // "НЕ" - логическое отрицание
/* Правило - в Си считается:
"Ложь" (False) только ноль.
"Истина"(True)- не ноль. или так: (!0)
- /
!(истина) // дает "ложь"
!(ложь) // дает "истина" </source> В результате логической операции вы получаете НЕ ЧИСЛО, а логическое значение "истина" или "ложь"
Для логических операций && и || берутся результаты выражений слева и справа от знака операции преобразованные в "истину" или "ложь" и определяется логический результат операции.
Компилятор, для определенности наверно, результат "истина" превращает в 1 а не в любое отличное от 0 число.
Логические операции могут объединять несколько проверяемых условий.
Пример:
<source lang="c"> if((выражение1)&&((выражение2) || (выражение3))) {/* Код программы здесь будет выполняться если: Выражение1 "Истина" (значит не ноль) и хотя бы одно из выражений 2 и 3 тоже "Истина" (значит не ноль).
- /};</source>
Подробнее о логических операциях обязательно прочитайте по в низу этой страницы !
Приоритет операций в языке Си перечислены в порядке убывания приоритета. Операции, приведённые на одной строчке, имеют одинаковый приоритет. Операции, помеченные как R->L, исполняются справа налево.
- () [] -> .
- Унарные (R->L): ! ~ - * & sizeof (type) ++ --
- Бинарные арифметические: * / %
- Бинарные арифметические + -
- Сдвиг: << >>
- Сравнение: < <= > >=
- Сравнение: == !=
- Битовая: &
- Битовая: ^
- Битовая: |
- Логическая: &&
- Логическая: ||
- Тернарная (R->L): ?:
- Операции с присваиванием (R->L):
= | += | -= | = | /= | &= | |= | ^= | <<= | >>= |
{
{InfoBlock|Чтобы точно знать порядок выполнения операций программой используйте скобки ( )
( () + ( () * () ) ) Ведь скобки ( ) имеют наивысший приоритет.|Совет:}}
Самое интересное !
Ходовые конструкции на Си В компиляторе [CVAVR заготовки этих конструкций находятся под ярлыком "Code Templates" слева вверху. Вы можете выбирать нужные заготовки и вставлять их в свою программу.
5) if(){ }else{ }; идеальная конструкция если вам нужно выполнить какую то часть программы при наличии каких либо
условий или при их отсутствии :
<source lang="c"> if (выражение) { код на Си /* делать этот код если выражение "истина" - т.е. результат его вычисления не ноль */ } else { код на Си /* делать этот код если выражение "ложь" - т.е. результат его вычисления равен нулю */ };
// } else { это не обязательный элемент конструкции, без него так :
if (выражение) { код на Си /* делать этот код если выражение "истина" - т.е. результат его вычисления не ноль */ }; </source>
6)while(){ }; условный цикл ( цикл с условием ) - используйте если вам
нужно выполнять какой то код программы пока выполняется (существует,
справедливо, "истино" - значит "не ноль") некоторое условие, результат вычисления выражения :
<source lang="c"> while (выражение) { код на Си /* делать этот код если выражение "истина" - т.е. результат его вычисления не ноль. Пока выполняется этот код выражение не проверяется на истинность ! После выполнения кода происходит переход к строке while снова проверять истинность выражения */ }; </source> Цикл while имеет вариант
do - while при котором код в { } выполняется по меньшей мере один раз не зависимо от истинности условия в скобках : <source lang="c"> do { код на Си /* сделать этот код один раз
затем, если выражение есть "истина" - т.е. результат его вычисления не ноль - опять делать код с начала, и так до тех пор пока выражение истина */ } while (выражение); </source> 7) for(;;){ }; - этот цикл позволяет выполнить часть программы нужное число раз: <source lang="c"> char i; /* объявление переменной для for это обычная переменная Си и значит может иметь любое допустимое имя по вашему желанию и тип */ for (i=5; i i = 5 это начальное выражение, то что в начале будет в переменной i
Число 5 просто для примера, может быть таким, как позволяет объявление типа переменной i, в нашем случае это char в большинстве компиляторов по-умолчанию это без знаковый символьный тип - он может хранить числа от 0 до 255 i < 20 - контрольное выражение Может быть с разными операторами отношения, важно лишь чтобы по ходу цикла оно становилось когда-то "ложью" - иначе цикл "зациклится" т.е. ни когда не кончится.
i += 4 - это счетчик или изменение переменной цикла. Обычно это i++ т.е.к переменной добавляется 1 каждый "прогон" цикла. Но опять же может быть таким какое вам требуется.
- Начальным условием
- - может быть любое допустимое в Си выражение результатом которого является целое число.
- Контрольное выражение
- - определяет до каких пор будет выполнятся цикл.
- Счетчик
- - показывает как изменяется начальное выражение перед каждом новом выполнении цикла .
- Выражение
- - значит это может быть не просто переменная, а что-то посложней, например:
i =(7 + i*4) или i = (функция других переменных)
<source lang="c"> Циклы for(;;) и while()
часто используют вот так:
while(1);
for (;;);
/* Так написанные эти циклы означают :
МК выполнять эту строчку пока есть питание, нет сброса и нет прерывания. Когда возникает прерывание, программа переходит на обработчик прерывания и (если в обработчике нет перехода в другое место программы) по завершении кода обработчика опять возвращается в такой цикл. */
while(1){ код программы };
for (;;){ код программы };
/* Так написанные эти циклы означают :
МК выполнять код программы пока есть питание, нет сброса и нет прерывания. Когда возникает прерывание, программа переходит на обработчик прерывания и (если в обработчике нет перехода в другое место программы) по завершении кода обработчика опять возвращается сюда и продолжает выполнять код программы */ </source>
8)switch(){ }; - оператор множественного выбора,
позволяет вам сделать выбор из нескольких вариантов. <source lang="c"> switch (выражение) { case 5: код на Си /* этот код будет выполняться если результат вычисления выражения равен числу 5
на этом работа оператора switch закончится */ break;
case -32: код на Си /* этот код будет выполняться если результат вычисления выражения равен отрицательномц числу -32
на этом работа оператора switch закончится */ break;
case 'G': код на Си /* этот код будет выполняться если результат вычисления выражения равен числу соответствующему символу G в таблице ASCII
на этом работа оператора switch закончится */ break;
default: код на Си /* этот код будет выполняться если результат вычисления выражения не равен ни 5 ни -32 ни 'G'
А так же после выполнения кода не имеющего в конце break;
на этом работа оператора switch закончится */ };
/* switch закончен - выполняется дальнейший код программы */ </source>
- case
- - может быть столько сколько вам нужно, чтобы программа работала быстрее старайтесь наиболее вероятные варианты располагать выше!
- default
- - не обязателен. Его можно расположить и не в конце.
- break;
- - если его не использовать то найдя нужный вариант программа будет выполнять и следующие ниже условия case
[Прочитайтеподробней о switch с примерами.
[Скачайте и распечатайте таблицу символов ASCII на ОДНОЙ странице!
ОГЛАВЛЕНИЕ
1.1.5. Использование комментариев в тексте программы
1.2. ТИПЫ ДАННЫХ И ИХ ОБ ЯВЛЕНИЕ
1.2.5. Переменные перечислимого типа
1.2.10. Переменные с изменяемой структурой
1.2.11. Определение объектов и типов
1.3.2. Преобразования при вычислении выражений
1.3.3. Операции отрицания и дополнения
1.3.4. Операции разадресации и адреса
1.3.6. Мультипликативные операции
Я обнаружил ошибку в разделе 1.3.10 | |
правильно вот так: Операция логического И вырабатывает значение 1 если оба операнда имеют НЕ нулевые значения. |
1.3.11. Операция последовательного вычисления
1.3.13. Операции увеличения и уменьшения
1.3.15. Составное присваивание
1.3.16. Приоритеты операций и порядок вычислений
1.5.1. Определение и вызов функций
1.5.2. Вызов функции с переменным числом параметров
1.5.3. Передача параметров функции main
1.6. СТРУКТУРА ПРОГРАММЫ И КЛАССЫ ПАМЯТИ
1.6.1. Исходные файлы и объявление переменных
1.6.3. Время жизни и область видимости программных объектов
1.6.4. Инициализация глобальных и локальных переменных
1.7. УКАЗАТЕЛИ И АДРЕСНАЯ АРИФМЕТИКА
1.7.1. Методы доступа к элементам массивов
1.7.2. Указатели на многомерные массивы
1.7.5. Динамическое размещение массивов
2. ОРГАНИЗАЦИЯ СПИСКОВ И ИХ ОБРАБОТКА
2.1.1. Методы организации и хранения линейных списков
2.1.2. Операции со списками при последовательном хранении
2.1.3. Операции со списками при связном хранении
2.1.4. Организация двусвязных списков
2.1.6. Сжатое и индексное хранение линейных списков
2.2. СОРТИРОВКА И СЛИЯНИЕ СПИСКОВ
2.2.3. Сортировка посредством выбора
2.2.5. Сортировка списков путем слияния
2.2.6. Быстрая и распределяющая сортировки
2.3. ПОИСК И ВЫБОР В ЛИНЕЙНЫХ СПИСКАХ
2.3.4. Методы вычисления адреса
2.3.5. Выбор в линейных списках
Вообще сайт СитФорум по программированию ПК рулит!
Оглавление
Список ошибок, допущенных в книгеhr
1.2 Переменные и арифметические выражения
1.8 Аргументы. Вызов по значению
1.10 Внешние переменные и область видимости
Глава 2. Типы, операторы и выражения
2.6 Операторы отношения и логические операторы
2.8 Операторы инкремента и декремента
2.10 Операторы и выражения присваивания
2.12 Приоритет и очередность вычислений
3.7 Инструкции break и continue
Глава 4. Функции и структура программы
4.1 Основные сведения о функциях
4.2 Функции, возвращающие нецелые значения
5.2 Указатели и аргументы функций
5.5 Символьные указатели функции
5.6 Массивы указателей, указатели на указатели
5.8 Инициализация массивов указателей
5.9 Указатели против многомерных массивов
5.10 Аргументы командной строки
6.1 Основные сведения о структурах
6.5 Структуры со ссылками на себя
7.3 Списки аргументов переменной длины
7.6 Управление ошибками (stderr и exit)
7.8 Другие библиотечные функции
7.8.2 Анализ класса символов и преобразование символов
7.8.4 Исполнение команд операционной системы
7.8.7 Генератор случайных чисел
Глава 8. Интерфейс с системой UNIX
8.2 Нижний уровень ввода-вывода (read и write)
8.3 Системные вызовы open, creat, close, unlink
8.4 Произвольный доступ (lseek)
8.5 Пример. Реализация функций fopen и getc
8.7 Пример. Распределитель памяти
Приложение A. Справочное руководство
А2.5.3. Константы с плавающей точкой
A2.5.4. Константы-перечисления
A4. Что обозначают идентификаторы
A6.2. Целочисленные преобразования
A6.3. Целые и числа с плавающей точкой
А6.5. Арифметические преобразования
A7.3.1. Обращение к элементам массива
A7.3.3. Обращение к структурам
A7.3.4. Постфиксные операторы инкремента и декремента
А7.4.1. Префиксные операторы инкремента и
A7.4.2. Оператор получения адреса
A7.4.3. Оператор косвенного доступа
A7.4.5. Оператор унарный минус
A7.4.6. Оператор побитового отрицания
A7.4.7. Оператор логического отрицания
A7.4.8. Оператор определения размера sizeof
A7.5. Оператор приведения типа
A7.6. Мультипликативные операторы
A7.12. Оператор побитового исключающего ИЛИ
A7.13. Оператор побитового ИЛИ
A7.15. Оператор логического ИЛИ
A8.1. Спецификаторы класса памяти
A8.3. Объявления структур и объединений
A11. Область видимости и связи
A11.1. Лексическая область видимости
A12.1. Трехзнаковые последовательности
А12.3. Макроопределение и макрорасширение
A12.7. Генерация сообщения об ошибке
A12.10. Заранее определенные имена
Приложение B. Стандартная библиотека
B1.4. Функции ввода-вывода символов
B1.5. Функции прямого ввода-вывода
B1.6. Функции позиционирования файла
B1.7. Функции обработки ошибок
B2. Проверки класса символа: ctype.
B3. Функции, оперирующие со строками: string.
B4. Математические функции: math.
B5. Функции общего назначения: stdlib.
B7. Списки аргументов переменной длины: stdarg.
B10. Функции даты и времени: time.
B11. Зависящие от реализации пределы: limits.и float.
Приложение С. Перечень измененийhr
Предметный указатель - язык Си
--Nekolex 20:47, 27 сентября 2009 (UTC)