Моим первым устройством на микроконтроллере была схема бегущих огней. Линейка из 15-ти светодиодов, которые попеременно загораются. Принципиальная схема такого устройства предельно проста. По сравнению с макетной платой здесь появились только 15 светодиодов, у которых анод общий, а катоды подсоединены к портам ввода/вывода микроконтроллера и столько же токоограничительных резисторов R3-R17 по 360 ом. Светодиоды управляются низким уровнем на выводе микроконтроллера (так как для низкого уровня микроконтроллер может выдать больший ток, около 20мА, чем для высокого, но не стоит забывать про суммарный ток, который может выдать порт).
Теперь рассмотрим порты ввода/вывода. У ATtiny2313 есть 15 линий ввода/вывода, которые сгруппированы в 2 порта: PortB – 8 выводов и PortD – 7 выводов. Вся работа микроконтроллера состоит из правильного шевеления ножками, а искусство программирования – заставить его так делать. Также ножки портов по совместительству могут выполнять другие функции: быть входом встроенного АЦП, внешнего прерывания, выходом USART’а и множество других функций, но их использование рассмотрим немного попозже. Для использования портов ввода вывода их нужно сперва сконфигурировать, за это отвечают регистры PORTX и DDRX, где X – имя порта. Приведем табличку их возможных состояний (n=0..7 – номер вывода в порту):
Как видно из таблицы при значении DDRXn =1 порт работает как выход, и логический уровень на его выходе равен биту PORTXn. При значении DDRXn =0 вывод PXn будет работать на вход, а бит PORTXn определяет, подключен ли к входу внутренний подтягивающий резистор или нет. Логический уровень на выводе PXn можно считать из бита PINXn. Перейдем к практике, предлагаю написать программу, которая будет по очереди зажигать каждый из 15 светодиодов, сперва напишем программу на С, а потом для разнообразия на ассемблере.
Секция Define chapter сопоставляет имена регистров с именами переменных. В секции Const chapter задаются константы, которые влияют на скорость бегущих огней. Далее идет сегмент кода Code segment в котором собственно и содержится код нашей программы. В коде программы сперва инициализируем стек, порты ввода/вывода конфигурируем как выхода, после чего в вечном цикле по одному светодиоды перебираем. Структура кода очень похожа на написанную выше программу С. Код на С более прост для понимания и компактен, но по размеру программы ассемблер обгоняет С (оптимизация не включена): 84 против 312 байт кода у С. Если же включить максимальную оптимизацию для С, то получим 184 байт кода, но придется совсем под другому переписать функцию задержки. Итого имеем, ассемблер более сложен, но код компактен и быстр, а С более прост, но код получившейся программы значительно больше.
Советую не ограничиваться просто бегущим огоньком, а немного поэкспериментировать:
Все коды программ можно скачать hier.