AVR123:Глава 5 — различия между версиями

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск
Строка 2: Строка 2:
 
[[AVR123 | Вернуться на главную]]
 
[[AVR123 | Вернуться на главную]]
  
 +
== Язык Си для AVR. ==
  
== Язык Си для AVR.==
+
Как раз то, что необходимо и достаточно
 
 
Как раз то, что необходимо и достаточно  
 
 
для микроконтроллеров.
 
для микроконтроллеров.
  
Строка 14: Строка 13:
 
'''Минимальная программа на Си''' может быть такой:
 
'''Минимальная программа на Си''' может быть такой:
 
<source lang="c">main(){}</source>
 
<source lang="c">main(){}</source>
Эта программа не делает ни чего полезного — но это уже программа и она показывает что в программе на языке Си — должна быть главная функция main — обязательно !
+
Эта программа не делает ни чего полезного — но это уже программа и она показывает что в программе на языке Си — должна быть главная функция main — обязательно !
  
Скачайте и Распечатайте.[http://avr123.nm.ru/csyntax.pdf Памятка Си для МК на ОДНОЙ странице.]
+
Скачайте и Распечатайте.'''[http://avr123.nm.ru/csyntax.pdf Памятка Си для МК на ОДНОЙ странице.]'''
  
Рассказывая про МК я говорил вам, что:
+
Рассказывая про МК я говорил вам, что:
 
Задача программы МК:
 
Задача программы МК:
 +
 
* читать числа из регистров и памяти МК,
 
* читать числа из регистров и памяти МК,
* делать что-то с числами, данными       и  
+
* делать что-то с числами, данными и
* записывать числа в регистры и память.  
+
* записывать числа в регистры и память.
  
 
Только так программа может общаться с МК.
 
Только так программа может общаться с МК.
  
 +
== Как это делать на языке Си ==
  
== Как это делать на языке Си ==
+
; Регистры МК
 +
: ( ''регистры'' - это ячейки-байты в памяти МК AVR ) в программе на Си имеют названия как и в ДШ и так как числа в большинстве из них можно менять - для программы регистры являются по сути переменными.
 +
; Переменная
 +
: - это набор ячеек в памяти в которых можно хранить число или числа и менять их. Переменная имеет адрес и имя.
 +
; Константа
 +
: - это как переменная но менять содержимое нельзя.
  
;Регистры МК
+
=== Подробней о переменных и константах написано ниже. ===
:( ''регистры'' - это ячейки-байты в памяти МК AVR ) в программе на Си имеют названия как и в ДШ и так как числа в большинстве из них можно менять - для программы регистры являются по сути переменными.
 
;Переменная
 
:- это набор ячеек в памяти в которых можно хранить число или числа и менять их. Переменная имеет адрес и имя.
 
;Константа
 
:- это как переменная но менять содержимое нельзя.
 
  
====Подробней о переменных и константах написано ниже. ====
+
==== 1) Чтобы поместить число в переменную (в регистр) в языке Си есть оператор присваивания ====
  
# Чтобы поместить число в переменную (в регистр) в языке Си есть оператор присваивания
 
 
это знак "=" ( называемый в математике "равно" )
 
это знак "=" ( называемый в математике "равно" )
"="   в Си означает вычислить результат того что справа от оператора присваивания и поместить этот результат в переменную находящуюся левее   оператора присваивания.    
+
"=" в Си означает вычислить результат того что справа от оператора присваивания и поместить этот результат в переменную находящуюся левее оператора присваивания.
{{InfoBlock|В Си знак <nowiki>"="</nowiki> НЕ означает равенство!|Запомните!}}  
+
 
 +
{{InfoBlock|В Си знак <nowiki>"="</nowiki> НЕ означает равенство!|Запомните!}}
 +
 
 
<source lang="c">
 
<source lang="c">
PORTB = PINB + 34;/* Эта строчка на Си означает взять (прочитать, считать)  
+
PORTB = PINB + 34;/* Эта строчка на Си означает взять (прочитать, считать)
                    значение переменной (регистра) PINB, затем прибавить  
+
значение переменной (регистра) PINB, затем прибавить
                    к нему число 34 и поместить результат в переменную PORTB */
+
к нему число 34 и поместить результат в переменную PORTB */
 +
 
 +
ПЕРЕМЕННАЯ = PINC; /* Эта строчка на Си означает взять (прочитать, считать)
 +
значение переменной (регистра) PINC и поместить результат
 +
в переменную с именем ПЕРЕМЕННАЯ */
 +
</source>
 +
Чтобы в Си взять (прочитать) число из регистра или значение переменной нужно написать его название НЕ непосредственно с лева от оператора присваивания !
  
ПЕРЕМЕННАЯ = PINC; /* Эта строчка на Си означает взять (прочитать, считать)
+
===== Примеры : =====
                      значение переменной (регистра) PINC и поместить результат
 
                      в переменную с именем ПЕРЕМЕННАЯ */
 
</source>
 
Чтобы  в  Си взять (прочитать) число из регистра или значение переменной нужно написать его название НЕ непосредственно с лева от  оператора присваивания !
 
  
=== Примеры : ===
+
: a) Строка где переменная стоит слева от = но через знак &
  
:a) Строка где переменная стоит слева от  =  но через знак  &
 
 
<source lang="c">PORTB & = 0x23;</source>
 
<source lang="c">PORTB & = 0x23;</source>
  
на Си означает - прочитать содержимое переменной PORTB, затем выполнить "поразрядное (побитное) логическое И" между прочитанным значением и числом 0x23 и поместить (записать, присвоить) результат в переменную PORTB  
+
на Си означает - прочитать содержимое переменной PORTB, затем выполнить "поразрядное (побитное) логическое И" между прочитанным значением и числом 0x23 и поместить (записать, присвоить) результат в переменную PORTB
 +
 
 +
: b) Строка где переменная стоит непосредственно слева от =
  
:b) Строка где переменная стоит непосредственно слева от  = 
 
 
<source lang="c">PORTB = 0x23;</source>
 
<source lang="c">PORTB = 0x23;</source>
  
на Си означает - не читая содержимое переменной PORTB присвоить ей значение   0x23   уничтожив то что было там раньше.
+
на Си означает - не читая содержимое переменной PORTB присвоить ей значение 0x23 уничтожив то что было там раньше.
<pre>:Вместо & "И" (AND - только 1 и 1 дают 1) могут быть и другие побитные логические операции:
+
<pre>:Вместо & "И" (AND - только 1 и 1 дают 1) могут быть и другие побитные логические операции:
  • | "ИЛИ"   (OR только 0 и 0 дают 0)  
+
• | "ИЛИ" (OR только 0 и 0 дают 0)
  • ^ "Исключающее ИЛИ" (XOR изменить бит напротив "1")
+
• ^ "Исключающее ИЛИ" (XOR изменить бит напротив "1")
  • ~ "инвертирование битов" (INV изменить биты регистра)
+
• ~ "инвертирование битов" (INV изменить биты регистра)
  • арифметические операции:   + - * / %</pre>
+
• арифметические операции: + - * / %</pre>
  
 
С оператором присваивания используются вот такие сокращения:
 
С оператором присваивания используются вот такие сокращения:
{|class="wikitable"
+
 
!|ДЛИННАЯ ЗАПИСЬ||СМЫСЛ||СОКРАЩАЕТСЯ ДО
+
{| class="wikitable"
 +
!|ДЛИННАЯ ЗАПИСЬ || СМЫСЛ || СОКРАЩАЕТСЯ ДО
 
|-
 
|-
||x = x + 1;||добавить 1||x++; или ++x;  
+
| |x = x + 1; || добавить 1 || x++; или ++x;
 
|-
 
|-
||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;||умножить на 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 = x % y; || остаток от деления || x %= y;
 
|-
 
|-
||x--;||вычесть 1||x -= 1;
+
| |x--; || вычесть 1 || x -= 1;
 
|-
 
|-
||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>
 +
 +
{| class=wikitable
 +
!|Запомните !
 +
|-
 +
| |Результатом поразрядных (побитных)
 +
логических операций :
 +
& | ^ ~
 +
является число ! Которое может быть интерпретировано компилятором как "истина" если оно не ноль и "ложно" если число ноль.
 +
|}
 +
 +
Числа
 +
 +
В компиляторе можно записывать в виде указанном в
 +
его 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>
 +
ТОЧКА ОБЯЗАТЕЛЬНА !
 +
 +
{| class=wikitable width=75%
 +
|-
 +
!colspan="10"|Различные представления числа D3h равно 0xD3 равно 0b1101 0011 равно 211
 +
|-
 +
!colspan="10" |шестнадцатеричное число 0xD3
 +
|-
 +
| |0 || x
 +
| colspan="4"|D
 +
| colspan="4"|3
 +
|-
 +
!colspan="10"|двоичное представление - число 0b1101 0011
 +
|-
 +
| width=10%|0
 +
| width=10%|b
 +
| width=10%|1
 +
| width=10%|1
 +
| width=10%|0
 +
| width=10%|1
 +
| width=10%|0
 +
| width=10%|0
 +
| width=10%|1
 +
| width=10%|1
 +
|-
 +
| colspan="2"|номера бита
 +
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0
 +
|-
 +
!colspan="10"| два в степени равной номеру бита
 +
|-
 +
| | || || 128 || 64 || 32 || 16 || 8 || 4 || 2 || 1
 +
|-
 +
!colspan="10"|число 211 в десятичном виде это сумма степеней двойки где биты равны "1"
 +
|-
 +
| colspan="2"|Сложите || +128 || +64 || || +16 || || || +2 || +1
 +
|}
 +
 +
Четыре бита это 1 "нибл" (полубайт) или 1 символ в 16-ричной системе или десятичное число от 0 до 15.
 +
 +
"В уме" удобно оперировать ниблами:двоичный десятичный 16-ричный
 +
 +
{| class = wikitable align=top
 +
! width="33%" align="center" | двоичный
 +
! width="33%" align="center" | десятичный
 +
! width="34%" align="center" | 16-ричный
 +
|-
 +
| width="33%" align="center" | 0000
 +
| width="67%" align="center" colspan="2" | 0
 +
|-
 +
| width="33%" align="center" | 0001
 +
| width="67%" align="center" colspan="2" | 1
 +
|-
 +
| width="33%" align="center" | 0010
 +
| width="67%" align="center" colspan="2" | 2
 +
|-
 +
| width="33%" align="center" | 0011
 +
| width="67%" align="center" colspan="2" | 3
 +
|-
 +
| width="33%" align="center" | 0100
 +
| width="67%" align="center" colspan="2" | 4
 +
|-
 +
| width="33%" align="center" | 0101
 +
| width="67%" align="center" colspan="2" | 5
 +
|-
 +
| width="33%" align="center" | 0110
 +
| width="67%" align="center" colspan="2" | 6
 +
|-
 +
| width="33%" align="center" | 0111
 +
| width="67%" align="center" colspan="2" | 7
 +
|-
 +
| width="33%" align="center" | 1000
 +
| width="67%" align="center" colspan="2" | 8
 +
|-
 +
| width="33%" align="center" | 1001
 +
| width="67%" align="center" colspan="2" | 9
 +
|-
 +
| width="33%" align="center" | 1010
 +
| width="33%" align="center" | 10
 +
| width="34%" align="center" | A
 +
|-
 +
| width="33%" align="center" | 1011
 +
| width="33%" align="center" | 11
 +
| width="34%" align="center" | B
 +
|-
 +
| width="33%" align="center" | 1100
 +
| width="33%" align="center" | 12
 +
| width="34%" align="center" | C
 +
|-
 +
| width="33%" align="center" | 1101
 +
| width="33%" align="center" | 13
 +
| width="34%" align="center" | D
 +
|-
 +
| width="33%" align="center" | 1110
 +
| width="33%" align="center" | 14
 +
| width="34%" align="center" | E
 +
|-
 +
| width="33%" align="center" | 1111
 +
| width="33%" align="center" | 15
 +
| width="34%" align="center" | F
 +
|}
 +
 +
Для перевода чисел из одного вида в другой можно использовать калькулятор Windows в инженерном виде.
 +
 +
Есть в Си операции которые изменяют значение
 +
переменной и без оператора присваивания :
 +
<source lang="c">
 +
PORTA++; /* Эта строчка на Си означает взять значение переменной PORTA
 +
добавить к ней 1 и записать результат обратно в PORTA
 +
говорят: Инкрементировать регистр PORTA */
 +
 +
PORTC--; /* Эта строчка на Си означает
 +
обратное действие!
 +
Декрементировать - вычесть 1 из значения регистра PORTC */
 +
</source>
 +
 +
Инкремент и декремент удобно использовать для изменения значения различных переменных счетчиков.
 +
 +
Важно помнить что они имеют очень низкий приоритет - поэтому чтобы быть уверенными в порядке выполнения желательно писать
 +
их отдельной строчкой программы !
 +
 +
{{InfoBlock|В конце выражения или конструкции в программе на Си ставят точку с запятой. |Обратите внимание !}}
 +
 +
Длинные выражения можно писать в несколько строк.
 +
<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):
 +
 +
{|
 +
| width=5%|=
 +
| width=5%|+=
 +
| width=5%|-=
 +
| width=5%|=
 +
| width=5%|/=
 +
| width=5%|&=
 +
| width=5%| |=
 +
| width=5%|^=
 +
| width=5%|<<=
 +
| width=5%|>>=
 +
|}{
 +
 +
{InfoBlock|Чтобы точно знать порядок выполнения операций программой используйте скобки ( )
 +
 +
( () + ( () * () ) )
 +
Ведь скобки ( ) имеют наивысший приоритет.|Совет:}}
 +
 +
== Самое интересное ! ==
 +
 +
<font color="#3366ff">Ходовые конструкции на Си</font>
 +
В компиляторе '''[http://avr123.nm.ru/CVAVR CVAVR]''' заготовки этих конструкций находятся под ярлыком "'''Code Templates'''" слева вверху. Вы можете выбирать нужные заготовки и вставлять их в свою программу.
 +
 +
[[Image:05 temp.png]]
 +
 +
'''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
 +
 +
[http://www.citforum.ru/programming/c/h14.shtml#145 Прочитайте]подробней о ''switch'' с примерами.
 +
 +
[http://avr123.nm.ru/ascii.pdf Скачайте и распечатайте таблицу символов ASCII на ОДНОЙ странице!]

Версия 03:01, 27 сентября 2009

Вернуться на главную

Язык Си для 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, исполняются справа налево.

  1. () [] -> .
  2. Унарные (R->L): ! ~ - * & sizeof (type) ++ --
  3. Бинарные арифметические: * / %
  4. Бинарные арифметические + -
  5. Сдвиг: << >>
  6. Сравнение: < <= > >=
  7. Сравнение: == !=
  8. Битовая: &
  9. Битовая: ^
  10. Битовая: |
  11. Логическая: &&
  12. Логическая: ||
  1. Тернарная (R->L): ?:
  2. Операции с присваиванием (R->L):
= += -= = /= &= |= ^= <<= >>=

{

{InfoBlock|Чтобы точно знать порядок выполнения операций программой используйте скобки ( )

( () + ( () * () ) ) Ведь скобки ( ) имеют наивысший приоритет.|Совет:}}

Самое интересное !

Ходовые конструкции на Си В компиляторе CVAVR заготовки этих конструкций находятся под ярлыком "Code Templates" слева вверху. Вы можете выбирать нужные заготовки и вставлять их в свою программу.

05 temp.png

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 на ОДНОЙ странице!