Автор Тема: Программирование микроконтроллеров AVR на языке C / C++ (Си) в Atmel Studio  (Прочитано 90985 раз)

0 Пользователей и 1 Гость просматривают эту тему.

chip

  • Newbie
  • *
  • Сообщений: 25
    • Просмотр профиля
Программирование на Си для микроконтроллеров немного отличается от обычного программирования тем, что приходится работать с битами и оперировать ими, я тут я приведу примеры часто используемых приемов программирования на языке C++ в Atmel Studio.

Представление чисел:
Например десятичное число 15 можно представить так:
0b00001111 - двоичное
017 - восьмеричное
0x0f - шестнадцатеричное

Математические оператры:
Сложение: +
Вычитание: -
Деление: /
Умножение: *
Остаток: %

Логические операции:
Логическое "И" (AND)&&Пример: <условие1> && <условие2> - возвращает истина(единица) в том случае, когда истинны оба условия 1 и 2, в противном случае возвращает ложь(ноль)
Логическое "ИЛИ" (OR)||Пример: <условие1> || <условие2> - возвращает ложь(ноль) в том случае, когда ложны оба условия 1 и 2, в противном случае возвращает истина(единица)
Логическое "НЕТ" (NOT)!Пример: int k=5; if (!k) {...} Оператор NOT инвертирует условие наоборот, вместо истины(единица) возвратит ложь(ноль) и наоборот. В примере есть переменная которой присвоено число 5, условие if будет выполнятся если переменная k будет равна чему угодно, но только не 5

Побитовые операции:
Отрицание-
Побитовое "И" (AND)&
Побитовое "ИЛИ" (OR)|
Побитовое "XOR"^
Сдвиг битов вправо(эквивалентно делению на 2)>>
Сдвиг битов влево(эквивалентно умножению на 2)<<


Управление портами ввода / вывода на микроконтроллерах AVR:
x-номер порта
DDRx (DDRA,DDRB,...) - Регистр направления передачи данных, конфигурирует контакты как вход(1) или выход(0)
PORTx (PORTA,PORTB,...) - Регистр вывода данных
PINx (PINA,PINB,...) - Регистр ввода данных, служит для чтения значения логического уровня на контактах(если они объявлены как вход)

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

Пример: мы хотим включить все контакты PORTB:
PORTB = 255;//в десятичной системе
PORTB = 0xff;//в шестнадцатеричной системе
PORTB = 0b11111111;//в двоичной системе(визуально более понятно какой контакт включен а какой выключен)

Пример: мы хотим установить высокий уровень на 0-3 контактах PORTB, нам нужно 4 младших бита установить в единицу, остальные биты будет с низким уровнем:
PORTB = 15;//в десятичной системе(трудно понятно, но коротко)
PORTB = 0xf;//в шестнадцатеричной системе(трудно понятно, но еще короче если большое число)
PORTB = 0b00001111;//в двоичной системе(визуально более понятно какой контакт включен а какой выключен)

Установление отдельных битов в единицу ,не затрагивая другие биты
Пример: PORTB = 0b00000010, необходимо на 4 контакт(всего битов 8, отсчет начинается с 0..7) PORTB установить высокий уровень, не изменяя при этом другие контакты, т.е. нужно чтобы в итоге остался высокий уровень на 2 и 4 контактах:
PORTB = 0b00000010; //Присвоим начальное значение 2-й бит = 1
PORTB = PORTB|0b00001000; //Присвоим 4-му биту единицу или подадим высокий уровень на контакт №4
или тоже самое но кратко:
PORTB |= 0b00001000; //Присвоим 4-му биту единицу или подадим высокий уровень на контакт №4

Установление отдельных битов в ноль, не затрагивая другие биты
Пример: PORTB = 0b11111101, необходимо на 4-й контакт PORTB установить низкий уровень, не изменяя при этом другие биты, т.е. нужно чтобы в итоге остался низкий уровень на 2 и 4 контактах:
PORTB = 0b11111101; //Присвоим начальное значение 2-й бит = 0, остальные биты с высоким уровнем
PORTB = PORTB &~ 0b00001000; //Присвоим 4-му биту единицу или подадим высокий уровень на контакт №4
или тоже самое но по другому:
PORTB = PORTB & 0b11110111; //Присвоим 4-му биту единицу или подадим высокий уровень на контакт №4
или тоже самое но кратко:
PORTB &= ~0b00001000; //Присвоим 4-му биту единицу или подадим высокий уровень на контакт №4
PORTB &= 0b11110111; //Присвоим 4-му биту единицу или подадим высокий уровень на контакт №4

Изменение отдельных битов на противоположное значение 1->0 или 0->1, не затрагивая другие биты
Пример: PORTB = 0b00000010, необходимо на 2 контакт PORTB установить низкий уровень, а потом высокий и т.д.:
PORTB ^= 0b00000010; //Результат: PORTB = 0b00000000, т.к. PORTB был равен 0b00000010
PORTB ^= 0b00000010; //Результат: PORTB = 0b00000010, т.к. PORTB был равен 0b00000000
PORTB ^= 0b00000010; //Результат: PORTB = 0b00000000, т.к. PORTB был равен 0b00000010
PORTB ^= 0b00000010; //Результат: PORTB = 0b00000010, т.к. PORTB был равен 0b00000000
и т.д., т.е. при каждом выполнении этой команды "PORTB ^= 0b00000010", изменяется только второй бит на противоположное значение, так можно сделать например мигание светодиодом.

Другие манипуляции с битами, каждое выражение не зависит от предыдущего, просто как примеры и результат этого выражения
PORTB = 0; //Результат: PORTB = 0b00000000, обнуляем
PORTB = 255; //Результат: PORTB = 0b11111111, установим все биты в единицу
PORTB = 0xff; //Результат: PORTB = 0b11111111, установим все биты в единицу

PORTB = 1; //Результат: PORTB = 0b00000001, просто присваиваем единицу
PORTB = 128; //Результат: PORTB = 0b10000000, просто присваиваем 128 в десятичной, а в двоичной будет такой результат
PORTB = 1<<1; //Результат: PORTB = 0b00000010, сдвигаем единицу на 1 позицию влево
PORTB = 1<<2; //Результат: PORTB = 0b00000100, сдвигаем единицу на 2 позиции влево
PORTB = 1<<7; //Результат: PORTB = 0b10000000, сдвигаем единицу на 7 позиций влево
PORTB = 128>>1; //Результат: PORTB = 0b01000000, сдвигаем десятичное число 128 на 1 позицию вправо
PORTB = 128>>2; //Результат: PORTB = 0b00100000, сдвигаем десятичное число 128 на 2 позиции вправо
PORTB = 128>>7; //Результат: PORTB = 0b00000001, сдвигаем десятичное число 128 на 7 позиций вправо
« Последнее редактирование: 09 Август 2013 Пятница 13:05:41 от chip »