2016-09-07 2 views
1

Я хочу создать программу в сборке AVR, которая будет опроса состояния мгновенного кнопочного выключателя и переключения состояния светодиода при каждом нажатии переключателя. Я использую Arduino Duemilanove с чипом ATMega328P. У меня есть кнопочный переключатель, подключенный между цифровым выводом 0 и землей, и светодиод с резистором 330 Ом, подключенным между цифровыми выводами 8 и + 5 В. Вот мой код до сих пор:Создание тумблера в сборе AVR

;============== 
; Declarations: 

.def temp = r16 
.org 0x0000 
rjmp Reset 

;============== 

Reset: 
     ser temp 
     out DDRB, temp   ; set all pins on Port B to OUTPUT mode 
     ldi temp, 0b11111110 ; set pin 0 on Port D to INPUT mode 
     out DDRD, temp 
     clr temp 
     out PORTB, temp  ; clear temp and set all pins on Port B to LOW state 
     ldi temp, 0b00000001 ; set pin 0 on Port D to HIGH state 
     out PORTD, temp 

;============== 
; Main Program: 

switch: 
     in temp, PIND   ; get state of pins on Port D 
     cpi temp, 0   ; compare result to 0 (pushbutton is pressed) 
     brne PC+3    ; if != 0, go check again 
     ldi temp, (1<<PB0)  ; otherwise, write logic 1 to pin 0 of Port B 
     out PINB, temp   ; which toggles the state of the pin 
     rjmp switch 

К сожалению, все это делает свет СИД и держать его на независимо от того, сколько раз нажимается кнопка. Я основываю этот код на программе, найденной here, которая включает светодиод на , пока кнопка нажата. Я просто хочу расширить это, чтобы удерживать светодиод в его текущем состоянии, пока кнопка не будет нажата снова. Какие-либо предложения?

+0

Вы должны сравнить только 'PIND0' в '0', используя маску не весь' PIND'. Особенно, если ваш порт оставлен плавающим (освещение на диоде может изменить уровень плавающего штыря и сделать 'cpi temp, 0' всегда неправильным). Кроме того, вы можете использовать инструкцию 'SBI' для изменения отдельных битов в' PINB'. Не уверен, что это сработает, но на данный момент я не вижу других проблем. – Julien

+1

Кнопки отскок. Это не имеет значения в примере кода, но в вашем случае вы получите случайные результаты, даже после намека @ Жюльена. – datafiddler

+0

Я попытался окутать голову, как написать логику 1, чтобы просто PB0 с помощью 'sbi', но я не могу заставить его работать. Использование 'sbi PORTB0, 1' не дает ожидаемых результатов. Я вижу, что вы говорите об отказе кнопки. Может быть, подпрограмма задержки где-нибудь в главном цикле отменит коммутатор? –

ответ

-1

Ваш единственный раз, когда вы пишете HIGH до PB0. Каждый раз при нажатии кнопки необходимо инвертировать состояние штырей, например

in temp, PORTB 
com temp 
out PINB, temp 

Как вы уже ранее установленный темп 1, то 1 в комплиментом бы изменить его на 11111110, таким образом, писать нуля до PINB0 и в следующий раз будет 00000001, повернув назад.

Это упрощенное решение имеет непредсказуемый побочный эффект, поскольку он не учитывает отскок, поэтому вы не уверены, что светодиод будет включен или выключен, когда вы отпустите кнопку, как ожидалось. Это вопрос, который отвлекает от объема этого, и его следует задавать отдельно. Просто хотел дать тебе голову.

+1

Это не проблема. Из таблицы: Написание логического кода на PINxn переключает значение PORTxn, независимо от значения DDRxn. Обратите внимание, что инструкция SBI может использоваться для переключения одного единственного бита в порт. – KIIV

1

Этот код изменяет значение так быстро, что вы не сможете заметить никаких изменений. Каждый раз, когда вы нажимаете кнопку, он будет продолжать переключать значение на все время, когда оно нажато. Вы должны добавить некоторую задержку или просто игнорировать состояние включения в течение некоторого времени. Кроме того, вы должны выбрать из PIND только то, что хотите, путем маскировки (проще всего использовать andi).

.def del = r15 
    clr del 
switch: 
    in temp, PIND   ; get state of pins on Port D 
    andi temp, (1<<PD0) ; you should mask to get only what you want 
    cpi temp, 0   ; compare result to 0 (pushbutton is pressed) 
    brne switch   ; if != 0, go check again 
    cpi del, 0    ; compare del to 0 
    brne dec_jmp   ; if != 0, ignore this run 
    ldi temp, (1<<PB0)  ; otherwise, write logic 1 to pin 0 of Port B 
    out PINB, temp   ; which toggles the state of the pin 
    ldi del, 250   ; next one will be ignored for 250 runs 

dec_jmp: 
    dec del    ; decrement del 
    rjmp switch 
0

вы можете переключить его с помощью НЕ оператор

ldi temp2,0 
switch: 
in temp,PIND 
andi temp,1 ; remove all results except bit.0 
cpi temp,0 ; if pressed (i assume the button is active low) 
brne switch ; loop again if not pressed 
mov temp2,!temp2 ; not operator 
out PORTB,temp2 ; toggle PORTB output 
rjmp switch  ; back to main loop 

 Смежные вопросы

  • Нет связанных вопросов^_^