Поднимем вопрос программирования Arduino на языке Си. Зачем это может
понадобиться, ведь на языке Arduino писать значительно проще?
Во-первых, код на Си весит намного меньше, чем на Arduino (насколько
меньше увидите дальше). Во-вторых, он может выполняться быстрее (для
задач, где критична высокая скорость). Кроме того, это может стать
первым шагом при освоении собственно микроконтроллеров. Как всегда здесь
не будет теории, только практика.
Для начала необходимо подключить библиотеку, позволяющую отправлять-принимать сигналы. Делается это командой
#include <avr/io.h>
Если на Arduino было необходимо наличие функций loop и setup, то на Си
должна быть функция main, возвращающая тип int. Внутри этой функции и
будет находится наш код.
int main (void) {
}
Поставим себе простейшую задачу — зажечь светодиод на порту №13. И тут
мы столкнемся с тем, что собственно на микроконтроллере нет 13 порта.
Посмотрим распиновку (pinout) микроконтроллера, установленного в Ардуино
(atmega328p).
Тут обращаем внимание на PB0 — PB7, PC0 — PC6, PD0 — PD7. Это и есть
порты для подключения устройств, с ними и предстоит работать. Посмотрим,
как эти порты соотносятся с портами Arduino.
Мы задались целью зажечь светодиод на 13 порту. По распиновке Arduino
мы видим, что там находится порт PB5. Собственно, правильнее сказать,
что порт B, 5 бит. В программе будем работать сразу со битами порта B
(0-7), но постараемся не затрагивать биты кроме 5.
Сначала нужно обозначить B5 как выход, то, что на Ардуино делалось командой pinMode (13, OUTPUT).
На Си для этого существует команда DDRB, где B — порт (соответственно, могло быть DDRC и DDRD).
У порта B 8 битов, каждый из которых может быть настроен на выход (1) и вход (0). Поэтому, мы можем задать двоичное число, где каждому биту соответствует 0 или 1.
Например, запись
говорит о том, что 0 бит порта B, т.е. PB0 (8 порт Ардуино) будет выходом (OUTPUT), остальные — входом (INPUT). 0b перед числом позволяет указывать двоичную запись числа.
Так как мы работает с PB5, то 1 мы должны поставить в 5 бит
DDRB = 0b00100000
Теперь нужно подать напряжение на данный порт. Делается это командой PORTB, где B — снова порт. Напряжение подается единицей, отсутствие напряжения — 0. По аналогии запишем команду
чтобы подать напряжение на 5 бит.
Код целиком:
Результат ИЛИ равен 1 если хотя бы один из операндов равен 1.
Логическое И (&)
Результат И равен 1 если оба операнда равны 1.
Побитовые сдвиги влево и вправо (<< и >>)
Данные операции сдвигают все биты числа вправо или влево на заданное количество позиций.
Например, запись 1<<2 означает, что биты изначального числа 00000001 сдвинутся влево на 2 позиции и получится 00000100.
Воспользуемся данными операциями, чтобы работать только с необходимыми битами портов.
Мы должны PB5 настроить на выход. Сделаем это так:
1<<5 это 1 в 5 бите, т.е. 0b00100000. Применяем логическое ИЛИ для текущего состояния порта B и данного числа. Так как 1 находится только в 5 бите, то и в результате изменится лишь 5 бит порта B (станет 1), остальные биты останутся без изменений. Результат операций перезаписывается в DDRB.
Тоже самое проделаем и для отправки сигнала:
Вновь, благодаря данным операциям изменится состояние лишь 5 бита порта B.
Код программы:
Теперь посмотрим, сколько памяти требует данный код и аналогичный код на Ардуино.
На языке Си код занимает 144 байта, на Ардуино — 710, т.е. разница почти в 5 раз и это всего при двух командах.
по материалам http://studrobots.ru/arduino-c-1/
Сначала нужно обозначить B5 как выход, то, что на Ардуино делалось командой pinMode (13, OUTPUT).
На Си для этого существует команда DDRB, где B — порт (соответственно, могло быть DDRC и DDRD).
У порта B 8 битов, каждый из которых может быть настроен на выход (1) и вход (0). Поэтому, мы можем задать двоичное число, где каждому биту соответствует 0 или 1.
Например, запись
DDRB = 0b00000001
говорит о том, что 0 бит порта B, т.е. PB0 (8 порт Ардуино) будет выходом (OUTPUT), остальные — входом (INPUT). 0b перед числом позволяет указывать двоичную запись числа.
Так как мы работает с PB5, то 1 мы должны поставить в 5 бит
DDRB = 0b00100000
Теперь нужно подать напряжение на данный порт. Делается это командой PORTB, где B — снова порт. Напряжение подается единицей, отсутствие напряжения — 0. По аналогии запишем команду
PORTB = 0b00100000
чтобы подать напряжение на 5 бит.
Код целиком:
#include <avr/io.h>
int main (void) {
DDRB = 0b00100000;
PORTB = 0b00100000;
}
Что в этом коде нехорошо, так это то, что мы указывали сразу все биты
одного порта. Иногда мы не знаем заранее, подается питание на тот или
иной бит и изменять мы его не должны, а значит, мы не можем сами
подавать туда 0 или 1. Поэтому важно уметь настраивать нужный бит, без
изменения остальных.
Для этого потребуется знание логических операций и операций над битами.
Логическое ИЛИ (|)
Для этого потребуется знание логических операций и операций над битами.
Логическое ИЛИ (|)
Логическое И (&)
Результат И равен 1 если оба операнда равны 1.
Побитовые сдвиги влево и вправо (<< и >>)
Данные операции сдвигают все биты числа вправо или влево на заданное количество позиций.
Например, запись 1<<2 означает, что биты изначального числа 00000001 сдвинутся влево на 2 позиции и получится 00000100.
Воспользуемся данными операциями, чтобы работать только с необходимыми битами портов.
Мы должны PB5 настроить на выход. Сделаем это так:
DDRB |= (1<<5);
1<<5 это 1 в 5 бите, т.е. 0b00100000. Применяем логическое ИЛИ для текущего состояния порта B и данного числа. Так как 1 находится только в 5 бите, то и в результате изменится лишь 5 бит порта B (станет 1), остальные биты останутся без изменений. Результат операций перезаписывается в DDRB.
Тоже самое проделаем и для отправки сигнала:
PORTB |= (1<<5);
Вновь, благодаря данным операциям изменится состояние лишь 5 бита порта B.
Код программы:
#include <avr/io.h>
int main (void) {
DDRB |= (1 << 5);
PORTB |= (1 << 5);
}
Теперь посмотрим, сколько памяти требует данный код и аналогичный код на Ардуино.
На языке Си код занимает 144 байта, на Ардуино — 710, т.е. разница почти в 5 раз и это всего при двух командах.
по материалам http://studrobots.ru/arduino-c-1/