Меню
Вопросы/ответы
500

Программа "Бегущий огонек"

Программа "Бегущий огонек"

Теперь нам предстоит решить более сложную задачу. В этот раз мы возьмем другой микроконтроллер, для которого Вам придеться спаять другой программатор (не пугайтесь, так и было задумано, лишняя тренировка не помешает), плюс к этому нам нужно написать программу для мигания восьмью светодиодами, при чем поочереди в определенной последовательности

Но прежде чем это делать, давайте разберемся с нашим программатор, итак, как уже было сказано МК мы сменим - на ATmega16. Для начало вспомним схему прошлого программатора для AT90S2313. От порта LPT нам нужно подсоеденить провода к Меге16 к портам, к которым мы подключали их к прошлому МК. Для этого нужно посмотреть на схему Меги16 из ДатаЩита:

Теперь к соответствующим портам нужно все подключить как по этой универсальной схеме для программаторов МК семейства AVR:


А также вспомнить схему нашего универсального программатора:

Подсоединяете все как по этой схеме, только не забывайте о том, что все остальное нужно сделать как на предыдущем программаторе, а тоесть подключить питание к соответстующим ножкам (GND - к минусу, АVCС и VCC  - к плюсу - батарейка на 6 Вольт) и кварц (1-4МГц) с конденсаторами(около 33 Пикофарад) к XTAL1 и XTAL2

Так спаяли? Точно правильно? Проверьте хорошенько

Теперь можно приступить к программе, компиляторами будет пользоваться теми же самыми (кто не знает марш в предыдущую статью)

Для начала соберем нашу схему, она должна выглядеть примерно вот так:

Итак, что мы на ней видим:

1)Две кнопки без фиксации, прикрепленные к портам A0 и A1
2)8 светодиодов, прикрепленных к портам B0 по B7
3)2 Токоограничивающих резисторов на 100 Ом
4)Частотозадающий модуль (кварц (1-4Мгц) + 2 стабилизирующих конденсатора на 33 пикофарада)
5)Клемы для подключения к батарее (6 вольт)
6)Сокет под микросхему ATмега16 (DIP-40)

Прежде всего необходимо определиться со скоростью пробегания огонька.
Оптимальным вариантом для этого является значение периода пробегания
числом, кратным 8, что значительно упрощает вычисления.
Пусть период пробегания огонька будет равным 1,6 секунды, тогда время
горения одного огонька составит: 1,6/8=0,2 секунды = 200 миллисекунд
В промежуток времени между задержками, должен погаснуть предыдущий
огонек и зажечься следующий, то есть алгоритм пробегания огонька от B0
к B7:
зажечь B0
задержка...
погасить B0, зажечь B1
задержка...
...
...
погасить B6, зажечь B7
задержка...
погасить B7

Для задержки на 200 милисекунд мы будем использовать команду "delay_ms" модуля "delay.h":
PORTB = 0x00;
PORTB.0=1;
delay_ms(200);
PORTB.0=0;
PORTB.1=1;
delay_ms(200);
PORTB.1=0;
PORTB.2=1;
delay_ms(200);
PORTB.2=0;
PORTB.3=1;
delay_ms(200);
PORTB.3=0;
PORTB.4=1;
delay_ms(200);
PORTB.4=0;
PORTB.5=1;
delay_ms(200);
PORTB.5=0;
PORTB.6=1;
delay_ms(200);
PORTB.6=0;
PORTB.7=1;
delay_ms(200);
PORTB.7=0;
delay_ms(200);
PORTB.7=0;

Команда PORTB = 0x00; гасит все светодиоды, прикрепленные к порту B
аналогично прописываем механизм перемещения огонька в обратную сторону

Для того, чтобы привязать перемещения к кнопке используется команда
PIN, прописанная в условии, она используется для считывания бита с
любой лапки порта ввода-вывода, например для считывания факта нажатия
кнопки с лапки D0 можно использовать следующий код:
if (PIND.0 == 0)
{
}
Берется условие равенства 0 как факт нажатия кнопки потому, что кнопка замыкает ногу микроконтроллера на землю

Но даже если все это совместить и написать прграмму, она все равно не будет работать, так как она пройдет цикл один раз и остановится, а для того чтобы создать бесконечный цикл в языке Си используется функция While(1) {};

Вот теперь можно полностью собрать всю программу воедино, смотрим что получилось:

#include "mega16.h"
#include "delay.h"

void main(void)
{
DDRB=0xff;
DDRC=0x00;

while(1)
{
if (PINA.0 == 0)
{
PORTB = 0x00;
PORTB.0=1;
delay_ms(200);
PORTB.0=0;
PORTB.1=1;
delay_ms(200);
PORTB.1=0;
PORTB.2=1;
delay_ms(200);
PORTB.2=0;
PORTB.3=1;
delay_ms(200);
PORTB.3=0;
PORTB.4=1;
delay_ms(200);
PORTB.4=0;
PORTB.5=1;
delay_ms(200);
PORTB.5=0;
PORTB.6=1;
delay_ms(200);
PORTB.6=0;
PORTB.7=1;
delay_ms(200);
PORTB.7=0;
delay_ms(200);
}

if (PINA.1 == 0)
{
PORTB = 0x00;
PORTB.7=1;
delay_ms(200);
PORTB.7=0;
PORTB.6=1;
delay_ms(200);
PORTB.6=0;
PORTB.5=1;
delay_ms(200);
PORTB.5=0;
PORTB.4=1;
delay_ms(200);
PORTB.4=0;
PORTB.3=1;
delay_ms(200);
PORTB.3=0;
PORTB.2=1;
delay_ms(200);
PORTB.2=0;
PORTB.1=1;
delay_ms(200);
PORTB.1=0;
PORTB.0=1;
delay_ms(200);
PORTB.0=0;
delay_ms(200);
}

if ((PINA.0 == 1)&&(PINA.1 == 1)) //Если не нажаты обе кнопки, то погасить все светодиоды
{
PORTB = 0x00;
}
}
}

< - Предыдущая статья
< - На главную
Автор: AsonD©.
[/l]