Бегущие огни на ATtiny2313, первая программа для микроконтроллера

Написал vakula дата Пт, 04/23/2010 - 19:14

Моим первым устройством на микроконтроллере была схема бегущих огней. Линейка из 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 отвечает за скорость бегущей строки, означает, что в тексте программы все вхождения слова SPEED будут заменены на число 3000 (некий аналог задания констант в программе). Функция pause (unsigned int a) определяет задержку примерно (8*a)/f, где a – аргумент функции f – частота тактирования микроконтроллера. В вечном цикле while происходит попеременное включение светодиодов для каждого порта (так как управление осуществляется низким уровнем, то стоит символ НЕТ - «

»). Функция unsigned char _BV(b) возвращает байт, в котором бит под номером b устрановлен в единицу, а все остальные равны 0. Например, _BV(2)==0x04.

Попробует теперь написать аналогичную программу на ассемблере:

Секция Define chapter сопоставляет имена регистров с именами переменных. В секции Const chapter задаются константы, которые влияют на скорость бегущих огней. Далее идет сегмент кода Code segment в котором собственно и содержится код нашей программы. В коде программы сперва инициализируем стек, порты ввода/вывода конфигурируем как выхода, после чего в вечном цикле по одному светодиоды перебираем. Структура кода очень похожа на написанную выше программу С. Код на С более прост для понимания и компактен, но по размеру программы ассемблер обгоняет С (оптимизация не включена): 84 против 312 байт кода у С. Если же включить максимальную оптимизацию для С, то получим 184 байт кода, но придется совсем под другому переписать функцию задержки. Итого имеем, ассемблер более сложен, но код компактен и быстр, а С более прост, но код получившейся программы значительно больше. В заключение привожу видео готового устройства:

Советую не ограничиваться просто бегущим огоньком, а немного поэкспериментировать:

Источник: avrlab.com

Категория: Программное обеспечение

Похожие статьи: