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

Проект 04. Кнопка-триггер (включение с фиксацией)

Одна кнопка попеременно включает и выключает светодиод. Проект показывает обработку нажатия как события и обязательное ожидание отпускания.

Задача

Переключать светодиод каждым нажатием одной кнопки.

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

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

  • ATmega8
  • кварц 8 МГц + 2×22 пФ
  • кнопка
  • светодиод + 330 Ом
  • резистор 10 кОм на RESET

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

ВыводПодключение
PD0кнопка на GND, внутренняя подтяжка включается программно
PB0светодиод через 330 Ом
RESETчерез 10 кОм на +5 В

Алгоритм

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

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

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

;=======================================================
; Проект 04. Кнопка-триггер: нажал — включил, нажал — выключил
; ATmega8, 8 МГц. Кнопка PD0, светодиод PB0
;=======================================================
.include "m8def.inc"

.def    temp = r16
.def    d1   = r17
.def    d2   = r18

.cseg
.org    0x0000
        rjmp    RESET

RESET:
        ldi     temp, low(RAMEND)
        out     SPL, temp
        ldi     temp, high(RAMEND)
        out     SPH, temp

        ldi     temp, (1<<PB0)
        out     DDRB, temp
        cbi     DDRD, PD0
        sbi     PORTD, PD0              ; подтяжка кнопки

MAIN:
        sbic    PIND, PD0               ; ждём нажатия
        rjmp    MAIN
        rcall   DEBOUNCE
        sbic    PIND, PD0               ; ложное срабатывание?
        rjmp    MAIN

        in      temp, PORTB             ; инвертируем состояние
        ldi     r20, (1<<PB0)
        eor     temp, r20
        out     PORTB, temp

WAIT_REL:
        sbis    PIND, PD0               ; ждём отпускания
        rjmp    WAIT_REL
        rcall   DEBOUNCE
        rjmp    MAIN

DEBOUNCE:
        ldi     d2, 210
G2L:    ldi     d1, 255
G1L:    dec     d1
        brne    G1L
        dec     d2
        brne    G2L
        ret

Пояснения

  • Инверсия бита — исключающее ИЛИ с маской: ldi r20, (1<<PB0) и eor temp, r20. Команда eor работает только между регистрами, поэтому маску сначала загружают в регистр.
  • Ожидание отпускания принципиально: без него за один долгий нажим программа прокрутит десятки переключений.
  • Антидребезг ставится и на нажатие, и на отпускание — «звенят» оба перехода.

Что дальше

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