AFON // радиотехник affonya@mail.ru
← Проекты на AVR

Проект 10. Светофор

Модель светофора с полным циклом: красный, красный с жёлтым, зелёный, мигающий зелёный и жёлтый. Проект объединяет управление портом, вложенные задержки и счётчики.

Задача

Воспроизвести цикл работы дорожного светофора.

Микроконтроллер: ATmega8, кварц 4 МГц. Среда: Atmel Studio / avra (или avra / Atmel Studio). Как настроить среду и прошить контроллер — в статье программирование AVR.

Что понадобится

  • ATmega8
  • кварц 8 МГц + 2×22 пФ
  • светодиоды красный, жёлтый, зелёный
  • 3 резистора 330 Ом

Схема подключения

ВыводПодключение
PB0красный светодиод через 330 Ом
PB1жёлтый светодиод через 330 Ом
PB2зелёный светодиод через 330 Ом
RESETчерез 10 кОм на +5 В

Алгоритм

  1. Включить красный на пять секунд.
  2. Добавить жёлтый на секунду — подготовка к движению.
  3. Включить зелёный, затем несколько раз мигнуть им.
  4. Включить жёлтый и вернуться к красному.

Листинг на ассемблере

Код проверен ассемблером и собирается без ошибок. Скачать: a10.asm · a10.hex (готовая прошивка).

;=======================================================
; Проект 10. Светофор (красный PB0, жёлтый PB1, зелёный PB2)
; ATmega8, 8 МГц
;=======================================================
.include "m8def.inc"

.def    temp  = r16
.def    blink = r17
.def    secs  = r18
.def    d1    = r19
.def    d2    = r20
.def    d3    = r21

.cseg
.org    0x0000
        rjmp    RESET

RESET:
        ldi     temp, low(RAMEND)
        out     SPL, temp
        ldi     temp, high(RAMEND)
        out     SPH, temp
        ldi     temp, 0b00000111        ; три светодиода — выходы
        out     DDRB, temp

MAIN:
        ldi     temp, 0b00000001        ; КРАСНЫЙ
        out     PORTB, temp
        ldi     secs, 10
        rcall   DELAY_N

        ldi     temp, 0b00000011        ; красный + жёлтый
        out     PORTB, temp
        ldi     secs, 2
        rcall   DELAY_N

        ldi     temp, 0b00000100        ; ЗЕЛЁНЫЙ
        out     PORTB, temp
        ldi     secs, 10
        rcall   DELAY_N

        ldi     blink, 6                ; зелёный мигает
GR_BLINK:
        in      temp, PORTB
        ldi     r22, 0b00000100
        eor     temp, r22
        out     PORTB, temp
        rcall   DELAY500
        dec     blink
        brne    GR_BLINK

        ldi     temp, 0b00000010        ; ЖЁЛТЫЙ
        out     PORTB, temp
        ldi     secs, 2
        rcall   DELAY_N
        rjmp    MAIN

;--- задержка secs * 500 мс ---
DELAY_N:
        rcall   DELAY500
        dec     secs
        brne    DELAY_N
        ret

DELAY500:
        ldi     d3, 20
M3L:    ldi     d2, 255
M2L:    ldi     d1, 255
M1L:    dec     d1
        brne    M1L
        dec     d2
        brne    M2L
        dec     d3
        brne    M3L
        ret

Пояснения

  • Длинные интервалы набираются вызовом базовой задержки в цикле — подпрограмма принимает число повторов в регистре, что экономит память.
  • Комбинации сигналов задаются одной записью в порт: 0b00000011 — это красный и жёлтый одновременно.
  • Мигание зелёного сделано инверсией одного бита с чётным числом повторов, чтобы цикл завершился при погашенном светодиоде.

Что дальше

Разобравшись с этим проектом, переходите к следующему в разделе проекты на PIC. Справочник по архитектуре и периферии контроллеров — на странице микроконтроллеры AVR.