Бегущие огни на ATtiny2313, первая программа для микроконтроллера
Моим первым устройством на микроконтроллере была схема бегущих огней. Линейка из 15-ти светодиодов, которые попеременно загораются. Принципиальная схема такого устройства предельно проста. По сравнению с макетной платой здесь появились только 15 светодиодов, у которых анод общий, а катоды подсоединены к портам ввода/вывода микроконтроллера и столько же токоограничительных резисторов R3-R17 по 360 Ом.
Светодиоды управляются низким уровнем на выводе микроконтроллера (так как для низкого уровня микроконтроллер может выдать больший ток, около 20мА, чем для высокого, но не стоит забывать про суммарный ток, который может выдать порт).
Линейка светодиодов у меня организована на SMD компонентах, но это дело вкуса.
Теперь рассмотрим порты ввода/вывода. У ATtiny2313 есть 15 линий ввода/вывода, которые сгруппированы в 2 порта: PortB – 8 выводов и PortD – 7 выводов. Вся работа микроконтроллера состоит из правильного шевеления ножками, а искусство программирования – заставить его так делать. Также ножки портов по совместительству могут выполнять другие функции: быть входом встроенного АЦП, внешнего прерывания, выходом USART’а и множество других функций, но их использование рассмотрим немного попозже. Для использования портов ввода вывода их нужно сперва сконфигурировать, за это отвечают регистры PORTX и DDRX, где X – имя порта. Приведем табличку их возможных состояний (n=0..7 – номер вывода в порту):
Как видно из таблицы при значении DDRXn =1 порт работает как выход, и логический уровень на его выходе равен биту PORTXn. При значении DDRXn =0 вывод PXn будет работать на вход, а бит PORTXn определяет, подключен ли к входу внутренний подтягивающий резистор или нет. Логический уровень на выводе PXn можно считать из бита PINXn. Перейдем к практике, предлагаю написать программу, которая будет по очереди зажигать каждый из 15 светодиодов, сперва напишем программу на С, а потом для разнообразия на ассемблере. Программа на С выглядит так:
#include <avr/io.h> #define SPEED 3000 //Скорость бегущих огней void pause (unsigned int a) //Задержка { unsigned int i; for (i=a;i>0;i--); } int main(void) { unsigned char i; DDRB=0xff; //Инициализация портов ввода/вывода DDRD=0x7f; PORTB=0xff; PORTD=0x7f; while (1) //Вечный цикл { for (i=0;i<8;i++) //По одному зажигаем светодиоды на PORTB { PORTB=~_BV(i); pause(SPEED); } PORTB=0xff; for (i=0;i<7;i++) //По одному зажигаем светодиоды на PORTD { PORTD=~_BV(i); pause(SPEED); } PORTD=0x7f; } }
Теперь немного пояснений. Думаю, для тех, кто писал на С для ПК особых затруднений не возникнет. Строка #include
Попробует теперь написать аналогичную программу на ассемблере:
Секция Define chapter сопоставляет имена регистров с именами переменных. В секции Const chapter задаются константы, которые влияют на скорость бегущих огней. Далее идет сегмент кода Code segment в котором собственно и содержится код нашей программы. В коде программы сперва инициализируем стек, порты ввода/вывода конфигурируем как выхода, после чего в вечном цикле по одному светодиоды перебираем. Структура кода очень похожа на написанную выше программу С. Код на С более прост для понимания и компактен, но по размеру программы ассемблер обгоняет С (оптимизация не включена): 84 против 312 байт кода у С. Если же включить максимальную оптимизацию для С, то получим 184 байт кода, но придется совсем под другому переписать функцию задержки. Итого имеем, ассемблер более сложен, но код компактен и быстр, а С более прост, но код получившейся программы значительно больше. В заключение привожу видео готового устройства:
Советую не ограничиваться просто бегущим огоньком, а немного поэкспериментировать:
Расскажите как сделать
Расскажите как сделать бегущие огни как в сериале рыцарь дорог
А как в сериале "Рыцарь
А как в сериале "Рыцарь дорог"?
Начинающие, ну неужели никто
Начинающие, ну неужели никто не собрал до сих пор это?
расскажите какие проблемы были, что сложно было сделать, что легко.
Свои мнения!
Ха-ха-ха!
Ну я начинающий! :))) Ну какие проблемы?? Собрал, прошил МК - заработало. Ну чего тут сложного? Повесить на каждую ногу светодиод с резистором!? Делай уже!