
Начнем с алгоритма работы наших бегущих огней!
Напишем для примера пару программ мигания 7 светодиодов HL1, HL2, HL3, HL4, HL5, HL6, HL7, с использованием цикла for и нескольких переменных, которое значительно упрощают написание программы.
1. При подачи напряжения на плату светодиоды не горят.
2. Нажимаем один раз на кнопку, запускается первая программа.
3. Нажимаем второй раз на кнопку, запускается вторая программа.
4. Нажимаем третий раз на кнопку, светодиоды не горят.
5. Далее цикл повторяется.
Перейдем к написанию программы и рисованию электрической схемы!
1. Создаем новый проект в Atmel Studio 7 по пути File > New > Projec..., выбираем C/C++ и тип проекта GCC C Executable Project, вводим название проекта (Name: и Solution name:).
2. Выбираем тип микроконтроллера с которым будем работать, в нашем случае Atmega8.
Программа нам выдает код в файле main.c*

Приводим его к читабельному виду, удаляем лишние комментарии.

Рисуем электрическую схему наших бегущих огней:

И так схема у нас есть, на ней обозначены микроконтроллер, источник напряжения 5В, 8 резисторов R1-R7 = 300 Ом, R8 = 10 кОм, 7 светодиодов, кнопка. а также обозначены выводы для подключения программатора, вернемся к программе.
Светодиоды у нас подключены к порту РB, настроим в программе ножки порта РB на выход, допишем в программе DDRB = 0b11111111;, укажем, что кнопка у нас подключена к порту PD2 (с подтягивающим резистором R8), командой DDRD &= ~(1 << 2);, настроим ножку №4 микроконтроллера atmega8 на вход. Чтобы наши светодиоды замигали, добавим в программу библиотеку задержек #include <util/delay.h>, для задержки будем использовать функцию _delay_ms(), а также добавим библиотеку прерываний #include <avr/interrupt.h>, далее с помощью оператора #define укажем программе, что наш контроллер будет работать от внутреннего генератора с частой 8МГц допишем в код #define F_CPU 8000000UL.
В программе будем использовать задержки , чтобы каждый раз не писать цифрами время задержки в скобках команды _delay_ms(), присвоим директиве #define имена Z и V которые будут хранить данные о задержке, #define Z 50, #define V 150 соответственно. Также для работы программы объявим три переменные clik, m, r соответственно.
Вот такой получился код:


Для сдвига включения портов с интервалом в одну секунду будем использовать оператор цикла for — (цикл с заданным числом повторений).

Цикл первой программы будет выполняться пока число не достигнет 7, число 7 выбрано потому что задействуем 7 портов микроконтроллера, увеличиваем число на 1 и двигаем с задержкой _delay_ms(V); , вторая программа будет выполняться точно так же, но в обратной последовательности.
Теперь займемся вызовом вектора прерывания и его настройкой , допишем в нашу программу вектор прерывания, в прерывании будем переменную clik увеличивать на 1, после каждого нажатия на кнопку.

Наше прерывание может работать в нескольких режимах, мы будем работать с первым режимом - если низкий уровень на INT0 генерируем запрос прерывания. Выделил его красным.


Допишем в программе

Режимы работы и настройка взяты из datasheet на ATmega8, разрешаем глобальное прерывание командой asm("sei"); - это обязательно, без этой команды работать не будет. В бесконечном цикле с помощью If будем проверять сработало или нет у нас прерывание, в соответствии с срабатываем прерывания и переключать эффекты наших бегущих огней.

Исходный код программы Скачать архив