Программирование Arduino на C. Часть 1

Поднимем вопрос программирования Arduino на языке Си. Зачем это может понадобиться, ведь на языке Arduino писать значительно проще? Во-первых, код на Си весит намного меньше, чем на Arduino (насколько меньше увидите дальше). Во-вторых, он может выполняться быстрее (для задач, где критична высокая скорость). Кроме того, это может стать первым шагом при освоении собственно микроконтроллеров. Как всегда здесь не будет теории, только практика.

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

 

Если на Arduino было необходимо наличие функций loop и setup, то на Си должна быть функция main, возвращающая тип int. Внутри этой функции и будет находится наш код.

Поставим себе простейшую задачу — зажечь светодиод на порту №13. И тут мы столкнемся с тем, что собственно на микроконтроллере нет 13 порта. Посмотрим распиновку (pinout) микроконтроллера, установленного в Ардуино (atmega328p).

atmega328w_pinout

 

Тут обращаем внимание на PB0 — PB7, PC0 — PC6, PD0 — PD7. Это и есть порты для подключения устройств, с ними и предстоит работать. Посмотрим, как эти порты соотносятся с портами Arduino.

http://foros.giltesa.com/otros/arduino/fc/docs/pinout/uno.jpg

Мы задались целью зажечь светодиод на 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 бит

Теперь нужно подать напряжение на данный порт. Делается это командой PORTB, где B — снова порт. Напряжение подается единицей, отсутствие напряжения — 0. По аналогии запишем команду

чтобы подать напряжение на 5 бит.

Код целиком:

Что в этом коде нехорошо, так это то, что мы указывали сразу все биты одного порта. Иногда мы не знаем заранее, подается питание на тот или иной бит и изменять мы его не должны, а значит, мы не можем сами подавать туда 0 или 1. Поэтому важно уметь настраивать нужный бит, без изменения остальных.

Для этого потребуется знание логических операций и операций над битами.

Логическое ИЛИ (|)

Результат ИЛИ равен 1 если хотя бы один из операндов равен 1.

a b ИЛИ
0 0 0
0 1 1
1 0 1
1 1 1

Логическое И (&)

Результат И равен 1 если оба операнда равны 1.

a b И
0 0 0
0 1 0
1 0 0
1 1 1

 

Побитовые сдвиги влево и вправо (<< и >>)

Данные операции сдвигают все биты числа вправо или влево на заданное количество позиций.

Например, запись 1<<2 означает, что биты изначального числа 00000001 сдвинутся влево на 2 позиции и получится 00000100.

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

Мы должны PB5 настроить на выход. Сделаем это так:

1<<5 это 1 в 5 бите, т.е. 0b00100000. Применяем логическое ИЛИ для текущего состояния порта B и данного числа. Так как 1 находится только в 5 бите, то и в результате изменится лишь 5 бит порта B (станет 1), остальные биты останутся без изменений. Результат операций перезаписывается в DDRB.

Тоже самое проделаем и для отправки сигнала:

Вновь, благодаря данным операциям изменится состояние лишь 5 бита порта B.

Код программы:

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

%d1%81%d0%b8ard

На языке Си код занимает 144 байта, на Ардуино — 710, т.е. разница почти в 5 раз и это всего при двух командах.

 

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *