Я доработал программу, которая считает количество нажатий кнопки. Теперь количество отображается с помощью 8-сегментного светодиодного индикатора. Для простоты я использовал один индикатор, соответственно отобразить можно только одну цифру. Поэтому программа считает до 9, а при следующем нажатии сбрасывает счетчик.
В схеме используется индикатор RL-S3910. Это индикатор с общим катодом (минусом). Схема выводов на рис. 1.
Рис. 1. Схема выводов RL-S3910 |
Светодиоды, насколько я понял из даташита, рассчитаны на ток 20 мА. Прямое напряжение на светодиоде я принял за 2 В. К каждому нужно подключить резистор R = (6В - 2В)/0,02А = 200Ом.
Восьмиразрядные двоичные числа, каждое из которых представляет десятичную цифру, отображаемую индикатором, я записываю в SRAM (процедура SAVE_TEST_DATA, листинг 1). Каждый бит числа соответствует одному сегменту индикатора. Лучше было бы записать их в EEPROM, но пока пусть будет так.
Двоичные числа, представляющие десятичные цифры на индикаторе я записываю подряд, начиная с адреса, помеченного меткой "Numbers". Место для них резервируется с помощью директивы .BYTE. Получение адреса необходимого числа производится сложением адреса "Numbers" со значением счетчика нажатий. Таким образом мы получили подобие одномерного массива.
Обработчик прерывания инкрементирует счетчик нажатий. Потом с помощью команды cpi я сравниваю значение счетчика с константой 10. Фактически эта команда производит вычитание константы из регистра без изменения содержимого последнего. Если счетчик насчитал меньше 10, результат вычитания отрицательный, и в регистре SREG устанавливается флаг отрицательного значения Z. В этом случае мы пропускаем сброс счетчика и переходим к отображению числа нажатий. В противном случае - сбрасываем счетчик и начинаем считать с нуля.
Двоичные числа, представляющие десятичные цифры на индикаторе я записываю подряд, начиная с адреса, помеченного меткой "Numbers". Место для них резервируется с помощью директивы .BYTE. Получение адреса необходимого числа производится сложением адреса "Numbers" со значением счетчика нажатий. Таким образом мы получили подобие одномерного массива.
Обработчик прерывания инкрементирует счетчик нажатий. Потом с помощью команды cpi я сравниваю значение счетчика с константой 10. Фактически эта команда производит вычитание константы из регистра без изменения содержимого последнего. Если счетчик насчитал меньше 10, результат вычитания отрицательный, и в регистре SREG устанавливается флаг отрицательного значения Z. В этом случае мы пропускаем сброс счетчика и переходим к отображению числа нажатий. В противном случае - сбрасываем счетчик и начинаем считать с нуля.
Листинг 1.
.device ATiny26 .include "tn26def.inc" .equ Numbers_count = 10 .def temp = r16 .def Counter = r17 .dseg Numbers: .BYTE Numbers_count .cseg .org 0 rjmp RESET ; Reset handler rjmp EXT_INT0 ; IRQ0 handler reti; rjmp PIN_CHANGE ; Pin change handler reti; rjmp TIM1_CMP1A ; Timer1 compare match 1A reti; rjmp TIM1_CMP1B ; Timer1 compare match 1B reti; rjmp TIM1_OVF ; Timer1 overflow handler reti; rjmp TIM0_OVF ; Timer0 overflow handler reti; rjmp USI_STRT ; USI Start handler reti; rjmp USI_OVF ; USI Overflow handler reti; rjmp EE_RDY ; EEPROM Ready handler reti; rjmp ANA_COMP ; Analog Comparator handler reti; rjmp ADC ; ADC Conversion Handler ; EXT_INT0: inc Counter cpi Counter, 0b00001010 brbs 2, SKIP_RESET clr Counter SKIP_RESET: rcall LOAD_DATA out PORTA, r0 reti LOAD_DATA: ldi ZH, High(Numbers) ldi ZL, Low(Numbers) clr temp add ZL, Counter adc ZH, temp ld r0, Z ret; SAVE_TEST_DATA: ldi YH, High(Numbers) ldi YL, Low(Numbers) ;DP, C, B, A, D, E, F, G ;0 ldi temp, 0b01111110 st Y+, temp ;1 ldi temp, 0b01100000 st Y+, temp ;2 ldi temp, 0b00111101 st Y+, temp ;3 ldi temp, 0b01111001 st Y+, temp ;4 ldi temp, 0b01100011 st Y+, temp ;5 ldi temp, 0b01011011 st Y+, temp ;6 ldi temp, 0b01011111 st Y+, temp ;7 ldi temp, 0b01110000 st Y+, temp ;8 ldi temp, 0b01111111 st Y+, temp ;9 ldi temp, 0b01111011 st Y+, temp ret; RESET: ldi r16, RAMEND ; Main program start out SP, r16 ;set all A port contacts to OUT mode ldi temp, 0b11111111 out DDRA, temp ;turn off Analog Comparator ldi temp, (1<<ACD) out ACSR, temp ;pull-up resistor ldi temp, 0b00000010 out PORTB, temp /* ISC01 ISC00 Description 0 0 The low level of INT0 generates an interrupt request. 0 1 Any change on INT0 generates an interrupt request. 1 0 The falling edge of INT0 generates an interrupt request. 1 1 The rising edge of INT0 generates an interrupt request. When changing the ISC10/ISC00 bits, INT0 must be disabled by clearing its Interrupt Enable bit in the GIMSK Register. Otherwise an interrupt can occur when the bits are changed. */ ldi temp, (1<<ISC00) out MCUCR, temp ldi temp, (1<<ISC01) out MCUCR, temp ;allow external interrupt interrupt INT0 ldi temp, (1<<INT0) out GIMSK, temp sei rcall SAVE_TEST_DATA rcall LOAD_DATA out PORTA, r0 MAIN_CYCLE: rjmp MAIN_CYCLE
Вот как это всё выглядит:
А вот как это работает:
Комментариев нет:
Отправить комментарий