Boris Putintsev
на спор.
Лови программу.
Готовую компилируй заливай ставь.
Бесплатно
Но ничего ты делать не будешь. Пустая болтовня потому что как обычно у вас
; OLIMP-003 Multifunctional Counter
; Версия под индикатор BS-046GA-001 с общим анодом
;
; Copyright Vladislav B. Ivanov (с) 2017
; Russia, Astrakhan
;
;
vladislav370@gmail.com.include "c:\vlad\asm\Appnotes\m8def.inc"
.org 0x000
.equ SS = 2 ; защелкивание регистров индикаторов, 1-Wire
.equ MOSI = 3 ; данные
.equ SCK = 5 ; стробирование 595х
.equ max_digits = 4 ; число разрядов в индикаторе
.equ blink_time = 19 ; частота мигания символами
rjmp RESET ; на начало программы
reti
reti
rjmp tim2_OVF
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
;------------------------------------------------------------------------
; ОБРАБОТКА ПРЕРЫВАНИЯ ПЕРЕПОЛНЕНИЯ ТАЙМЕРА 2 ДЛЯ РЕЖИМА КАЛИБРОВКИ УУВД
; ВО ВСЕХ ДРУГИХ РЕЖИМАХ ПРЕРЫВАНИЕ НЕ ИСПОЛЬЗУЕТСЯ
;------------------------------------------------------------------------
tim2_OVF:
push r16
in r16, SREG
push r16
ldi r16, 127 ; число переполнений TCNТ2 для 1 секунды
cp r1, r16
breq add_TCNT2_one_sec
inc r1
rjmp exit_int2
add_TCNT2_one_sec:
clr r1
ldi r16, 59
cp r7, r16
breq reset_system_sec
inc r7
rjmp update_sys_counter
reset_system_sec:
clr r7
update_sys_counter:
sbis PINC, 0 ; при отсутствии или обрыве
rjmp exit_int2 ; ленты не выводим цифры
mov r16, r20
andi r16, 0b01111111
cpi r16, 5 ; в режимах установок
brsh exit_int2 ; тоже ничего не выводим
ldi r20, 0b10000001 ; чтоб оно не машало
exit_int2:
pop r16
out SREG, r16
pop r16
reti
;------------------------------------------------------------------------
; процедура заполняет индикатор или нужное число его разрядов символом.
; символ просто выводится в порт SPI, последовательно, бит за битом. При
; этом, то что ранее было в регистрах - не стирается, а смещается вправо.
;
; r16 - символ который надо вывести цифра или ' '
; r17 - количество символов которое надо вывести
; r19 - номер выводимого разряда
write_spi:
push r18
push r17
push r16
write_spi_char:
cbi PORTB, MOSI
nop
nop
nop
nop
rcall convert_IN_lamp ; на выходе в r16 будет битовая маска цифр 0-9
write_spi_loop:
nop
nop
nop
nop
push r19
ldi r19, 4 ; число бит в разряде
push r16
write_next_bit_spi:
cbi PORTB, SCK
nop
nop
nop
nop
lsl r16
brcS set_spi_1
cbi PORTB, MOSI
rjmp set_spi_0
set_spi_1:
sbi PORTB, MOSI
set_spi_0:
nop
nop
nop
nop
sbi PORTB, SCK
dec r19
brne write_next_bit_spi
pop r16
dec r17
pop r19
brne write_spi_loop
write_spi_skip:
pop r16
pop r17
pop r18
add r19, r17
ret
;------------------------------------------------------------------------
; преобразование кода 1-2-4-8 согласно разведению дорожек платы
convert_IN_lamp:
andi r16, 0b01111111
cpi r16, '0'
breq kod0
cpi r16, '1'
breq kod1
cpi r16, '2'
breq kod2
cpi r16, '3'
breq kod3
cpi r16, '4'
breq kod4
cpi r16, '5'
breq kod5
cpi r16, '6'
breq kod6
cpi r16, '7'
breq kod7
cpi r16, '8'
breq kod8
cpi r16, '9'
breq kod9
ldi r16, 0b11110000 ; лампа не светится
ret
kod0: ldi r16, 0b00000000
ret
kod1: ldi r16, 0b00010000
ret
kod2: ldi r16, 0b00100000
ret
kod3: ldi r16, 0b10000000
ret
kod4: ldi r16, 0b10010000
ret
kod5: ldi r16, 0b01010000
ret
kod6: ldi r16, 0b01000000
ret
kod7: ldi r16, 0b01100000
ret
kod8: ldi r16, 0b01110000
ret
kod9: ldi r16, 0b00110000
ret
;------------------------------------------------------------------------
; процедура выполняет "защелкивание" данных в регистрах
; вывода после чего данные сразу же выводятся на индикатор
store_spi:
nop
nop
nop
nop
cbi PORTB, 2
nop
nop
nop
nop
nop
nop
nop
nop
sbi PORTB, 2
nop
nop
nop
nop
ret
;------------------------------------------------------------------------
; процедура перевода числа из r16 в десятичное число
; результат возвращается в регистры r16:r17:r18
;------------------------------------------------------------------------
bin8_dec3:
clr R18
div1_l: subi R16, 100 ;вычитаем 100 пока не получим отрицательную разность
brcs d1_end
inc R18 ; +1 к разряду сотен
rjmp div1_l
d1_end: subi R16, -100 ;корректируем остаток, добавляя 100
clr R17
div2_l: subi R16, 10 ;вычитаем 10 пока не получим отрицательную разность
brcs d2_end
inc r17 ; +1 к разряду десяток
rjmp div2_l
d2_end: subi R16, -10 ;корректируем остаток, добавляя 10
ori r16, $30
ori r17, $30
ori r18, $30
ret
;------------------------------------------------------------------------
update_ind:
mov r16, r20
andi r16, 0b01111111
cpi r16, 5
brsh select_setup
mov r16, r21
andi r16, 0b10000000
breq display_set_off
select_setup:
cbi PORTB, 1 ; включаем индикацию (ШИМ яркости)
mov r19, r15
andi r19, 0b00001000
breq dgts
mov r16, r3 ; мигание всеми символами
andi r16, 0b01111111 ; индикатора при оконч ленты
cpi r16, 64
brlo dgts
display_set_off:
sbi PORTB, 1 ; отключаем индикатор (мигание)
dgts: mov r16, r15
andi r16, 0b10000000
breq sgr_0
sbi PORTB, 0 ; включаем разделитель
ret
sgr_0: cbi PORTB, 0 ; выключаем разделитель
ret
;------------------------------------------------------------------------
RESET: ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
; инициализация портов
;
ldi r16, 0b00111111 ; биты 0-5 порта B
out DDRB, r16 ; работает на выход
clr r16 ; порт C
out DDRC, r16 ; работает на вход,
out DDRD, r16 ; и порт D тоже работает на вход
; PORTC
; 0 - датчик окончания ( 1 - лента есть, 0 - лента закончилась)
; 1 - упр. реле реверса (1 - реверс вкл, 0 - выкл)
; 2 - кнопка Откат \
; 3 - кнопка Стоп \ при отпущенных кнопках должно быть 5V!
; 4 - кнопка Уск вперед / эти входы должны быть подтянуты к шине
; 5 - кнопка Уск назад / питания через R5.1к. При нажатии ноль.
; PORTD
; биты:
; 6 - счетные ипмульсы с ДД
; 7 - датчик движения (1 - лента движется, 0 - стоит)
; счетчик прерываний переполнения тамера 2
clr r1
; регистр фиксации первого импульса секундного
; счетного интервала в режиме калибровки УУВД
clr r2
; счетчик для организации мигания символами
clr r3
; счетчик пред-делителя счетных импульсов
clr r4
; главный счетчик секунд
clr r5
; главный счетчик минут
clr r6
; счетчик секунд от внутреннего таймера для калибровки УУВД
clr r7
; счетчик яркости индикатора ШИМ
clr r8
; сохранное значения таймера #2
clr r9
; регистр статуса устройства (битовая маска)
clr r10
; 0 - состояние датчика счетных импульсов
; 1 - состояние датчика движения ленты
; 2 - направление строки визуализации движения вправо|влево
; 3 - направление счета вперед|назад
; 4 - включена уск. перемотка вперед
; 5 - включена уск. перемотка назад
; 6 - команда включения противоположной перемотки
; 7 - команда отмены включения противополжной перемотки
; регистр опций вывода и мультиплексирования разрядов
clr r15
; младшие 3 бита счетчик мультиплексирования разрядов
; 000 - экспонируются доп. символы
; 001 - цифра 1
; 010 - цифра 2
; 011 - цифра 3
; 100 - цифра 4
; установленный бит 3 отключает весь индикатор (для мигания)
; старшие 4 бита управление выводом доп. символов
; 4...6 - номер сегмента линии движения ленты
; 000 - все нижние сегменты выключены
; 001 - 1 сег
; 010 - 2 сег
; 011 - 3 сег
; 100 - 4 сег
; 101 - 5 сег
; 110 - резерв
; 111 - резерв
; 7 - включен разделитель разрядов ЧЧ:ММ
; регистр управления обновлением вывода данных на индикатор
clr r20
; в основных режимах:
; 0 - не обновлять
; 1 - обновить показания минут и секунд
; 2 - вывести пустой экран
; 2 - РЕЗЕРВ
; 3 - РЕЗЕРВ
; 4 - РЕЗЕРВ
;
; в режима установок:
; 5 - скорость ленты
; 6 - режимы визуализации
; 7 - включение режима калибровки скорости
; 8 - направление счета в режиме реверс
; 9 - выключение счетчика
; 10 - яркость индикатора
; регистр пользовательских установок (копия этого регистра в eeprom)
clr r21
; биты 0-1 скорость ленты на рабочем ходу
; xxxxxx00 считать в метрах, дециметрах
; xxxxxx01 скорость 9
; xxxxxx10 скорость 19
; xxxxxx11 скорость 38
; биты 2-3 режим визуализации движения ленты на рабочем ходу
; xxxx00xx отключена полностью идет только счёт
; xxxx01xx мигает разделитель в такт секундам
; xxxx10xx бежит строка, разделитель не мигает
; xxxx11xx бежит строка и мигает разделитель
; бит 4
; xxx1xxxx активен режим калибровки скорости УУВД
; бит 5
; xx1xxxxx не анализовать состояние реверса (1 при реверсе считать вперед)
; бит 6
; РЕЗЕРВ
; бит 7
; 1xxxxxxx
; счетчик выключен (счет идет но нет вывода данных)
clr r22
; регистр управления клавиатурой в режиме установок
; биты 0-2 во взвденном состоянии указывают что нажата:
; xxxxxxx1 кнопка <СТОП>
; xxxxxx10 кнопка ->>
; xxxxx100 кнопка <<-
; xxxxx000 все кнопки отпущены
; xxxx1xxx событие "дребезг" первое нажатие любой из кнопок
; xxx11xxx событие "нажатие" когда было 2 опроса кнопок,
; и в обоих случаях отмечено нажатие кнопки
ldi r23, 99
; частота обновления индикатора 0-99 (копия этого регистра в eeprom)
; битовая маска с номером разрядов которые должны мигать
clr r24
; таймер #2 будет работать в асинхронном
; режиме от часового кварца 32768 Гц
clI
clr r16
out TIMSK, r16
ldi r16, (1<<AS2)
out ASSR, r16
clr r16
out TCNT2, r16
out OCR2, r16
ldi r16, (1<<CS20) ; подделитель отключен, работаем от CK кварца
out TCCR2, r16
wait_t: nop
nop
nop
in r16, ASSR
cpi r16, 0b00001000
brne wait_t ; ждем готовности битов в регистре ASSR
;------------------------------
; загрузка параметров из EEPROM
ldi r17, 0
rcall read_EEPROM_byte
cpi r16, 255
brne select_cali
; параметры по умолчанию при первом запуске такие:
; - скорость 19
; - разделители мигают в такт секундам
; - калибровка откл
; - реверс счет идет назад
; - индикация включена
ldi r16, 0b10000110
select_cali:
mov r21, r16
;-----------------------------------
; проверяем запуск режима калибровки
andi r16, 0b00010000
breq int_2OVF_disable
;------------------------------
mov r16, r21
andi r16, 0b00000011
brne setup_int2_ovf
andi r21, 0b11101111 ; не допускаем калибровку при счете в метрах!
rjmp int_2OVF_disable
setup_int2_ovf:
; при калибровке активируем прерывание
; по переполнению таймера TCNT2
clr r16
out TIFR, r16
ldi r16, (1<<OCIE2)
out TIMSK, r16
int_2OVF_disable:
seI
; начальное состояние импульса счета
clr r16
sbic PIND, 6
ldi r16, 0b00000001
or r10, r16
; начальное состояние ДД
ldi r16, 0b00000010
sbic PIND, 7
clr r16
or r10, r16
;------------------------------
; яркость индикатора из EEPROM
ldi r17, 1
rcall read_EEPROM_byte
cpi r16, 100
brsh set_freq_def
mov r23, r16
rjmp check_setup_mode
set_freq_def:
ldi r16, 99
ldi r17, 1
rcall write_EEPROM_byte
mov r23, r16
check_setup_mode:
; --------------------------------
; при нажатии кнопки СТОП в момент
; сброса вход в режим установок
sbis PINC, 3
rjmp setup_mode
; выводим все нули
ldi r17, 1
ldi r19, 1
ldi r16, 0
rcall display_parm
ldi r16, 0
rcall display_parm
rcall store_spi
rjmp MAIN
;-----------------------
; вход в режим установок (нажатие удержание кнопки СТОП после сброса)
setup_mode:
; включаем ":" при входе в сетап
ldi r16, 0b10000000
or r15, r16
ldi r20, 99
ori r20, 128
;-----------------------
; ОСНОВНОЙ ЦИКЛ
MAIN: clr r16
sbic PIND, 6 ; чтение счетного импульса - высший приоритет!
ldi r16, 1 ; иначе он будет теряться что приведет
mov r17, r10 ; к сбоям счета
andi r17, 0b00000001 ; состояние счетного
cp r17, r16 ; импульса не изменилось
breq counter_idle ; ничо не делаем в этом случае
ldi r17, 1
eor r10, r17 ; новое значение счетного импульса сохр
mov r17, r21
andi r17, 0b00000010 ; на скорости 9 и L считаем фронты и спады
breq counter_9
cpi r16, 0 ; на скорости 19, 38 считаем только фронты
breq counter_idle
counter_9:
rcall counter
; -----------------------------------------
; ОПРОС СЧЕТЧИКА АСИНХРОННОГО ТАЙМЕРА TCNT2
counter_idle:
in r16, TCNT2 ; счетный регистр таймера TCNT2
cp r16, r9 ; сравниваем с ранее полученным
breq MAIN ; при равенстве не делаем ничего
mov r9, r16
; уст. частоты обновления индикатора
inc r8
ldi r16, 100
cp r8, r16
breq update_ind_now
; уст яркости индикатора
cp r8, r23
brlo displ_expose
; отключение индикатора и разделителей (ШИМ)
sbi PORTB, 1
cbi PORTB, 0
displ_expose:
mov r16, r9
cpi r16, 1 ; самый низкий временный приоритет
brne MAIN ; при обработке медленных
rcall read_slow_sensor ; сенсоров (кнопки, статусы режимов ЛПМ и тд)
inc r3
rjmp MAIN
update_ind_now:
clr r8
mov r16, r20
andi r16, 0b10000000 ; нет запроса на обновление данных
breq no_update_counters
andi r20, 0b01111111 ; флаг запроса обновления данных сбрасываем
cpi r20, 0
breq no_update_counters
; -----------------
; ОБНОВЛЕНИЕ СЧЕТЧИКА
cpi r20, 1
breq update_mm_ss ; обновить данные счетчика
cpi r20, 2
breq update_blank
; -----------------
; РЕЖИМЫ УСТАНОВОК
cpi r20, 5
breq setup_sp ; установка скорости
cpi r20, 6
breq setup_vi ; режим визуализации
cpi r20, 7
breq setup_ca ; режим включения калибровки
cpi r20, 8
breq setup_re ; режим счета при реверсе
cpi r20, 9
breq setup_of ; отключение счетчика
cpi r20, 10
breq setup_br ; яроксть индикатора
rjmp no_update_counters
update_blank:
; -----------------
; ПРОБЕЛЫ
ldi r17, 1
ldi r19, 1
ldi r16, 255
rcall display_parm
ldi r16, 255
rcall display_parm
rcall store_spi
rjmp no_update_counters
update_mm_ss:
; -----------------
; РЕЖИМ СЧЕТА
mov r16, r21
andi r16, 0b00010000
brne update_ss_ss
rcall update_counter_min
rcall update_counter_sec
rcall store_spi
rjmp no_update_counters
update_ss_ss:
;------------------
; РЕЖИМ КАЛИБРОВКИ
rcall update_system_count
rcall update_counter_sec
rcall store_spi
no_update_counters:
rcall update_ind
rjmp MAIN
;---------------------
; РЕЖИМЫ УСТАНОВОК
setup_sp:
rcall setup_speed
rcall store_spi
rjmp no_update_counters
setup_vi:
rcall setup_vis
rcall store_spi
rjmp no_update_counters
setup_ca:
rcall setup_cal
rcall store_spi
rjmp no_update_counters
setup_re:
rcall setup_rev
rcall store_spi
rjmp no_update_counters
setup_of:
rcall setup_off
rcall store_spi
rjmp no_update_counters
setup_br:
rcall setup_frq
rcall store_spi
rjmp no_update_counters
;------------------------------------------------------------------------
; *** ОБРАБОТКА СЧЕТНЫХ ИМПУЛЬСОВ ***
;------------------------------------------------------------------------
counter:
mov r16, r20
andi r16, 0b01111111
cpi r16, 5 ; в режиме установок
brsh setup_active ; счёт запрещен !!
sbic PINC, 0 ; при отсутствии или обрыве
rjmp lenta_est ; ленты счёт запрещен !
setup_active:
ret
lenta_est:
mov r18, r21
andi r18, 0b00000011 ; при счете в метрах
cpi r18, 0 ; визуализация отключена
breq visual_done
mov r16, r15
ror r16
ror r16
ror r16
ror r16
mov r17, r10
andi r17, 0b000000100
cpi r17, 0
brne count_vis_sub
; визуализация движения ленты вперед
andi r16, 0b00000111
cpi r16, 0
breq visual_done
cpi r18, 0b00000011
brne vis_add_9_19
mov r17, r4
andi r17, 0b00000001
breq visual_done
vis_add_9_19:
cpi r16, 5
brlo inc_sg
clr r16
inc_sg: inc r16
lsl r16
lsl r16
lsl r16
lsl r16
andi r16, 0b01110000
ldi r17, 0b10001111
and r15, r17
or r15, r16
rjmp visual_done
; визуализация движения ленты назад
count_vis_sub:
andi r16, 0b00000111
cpi r16, 0
breq visual_done
cpi r18, 0b00000011
brne vis_sub_9_19
mov r17, r4
andi r17, 0b00000001
breq visual_done
vis_sub_9_19:
cpi r16, 2
brsh dec_sg
ldi r16, 6
dec_sg: dec r16
lsl r16
lsl r16
lsl r16
lsl r16
andi r16, 0b01110000
ldi r17, 0b10001111
and r15, r17
or r15, r16
visual_done:
mov r17, r10
andi r17, 0b000001000
cpi r17, 0
brne count_sub
rcall counter_add
ret
count_sub:
rcall counter_sub
ret
;------------------------------------------------------------------------
; ПРЯМОЙ СЧЕТ (в r18 биты установленной скорости)
;------------------------------------------------------------------------
counter_add:
cpi r18, 0
breq count_add_L ; счет в метрах
ldi r19, 15 ; на скорости 38 каждые 16 фронтов импульсов = 1 сек
cpi r18, 0b00000011
breq count_add_38
ldi r19, 7 ; на скорость 19 каждые 8 фронтов импульсов = 1 сек
count_add_38:
cp r19, r4
breq add_sec
inc r4
ldi r19, 8
cpi r18, 0b00000011
breq delim_add_38
ldi r19, 4
delim_add_38:
cp r4, r19
breq set_add_off_dlm
ret
set_add_off_dlm:
mov r19, r10 ; при перемотках мигание
andi r19, 0b00110000 ; двоеточия запрещаем
brne play_dlm_add_disable
mov r19, r21
andi r19, 0b00001000 ; разделители включены
brne play_dlm_add_disable ; постоянно
ldi r19, 0b01111111
and r15, r19 ; иначе отключаем
ret
play_dlm_add_disable:
ret
;--- счет вперед в МЕТРАХ, ДЕЦИМЕТРАХ
count_add_L:
ldi r20, 0b10000001
ldi r19, 7 ; 7 фронтов и спадов импульсов = 10 см
cp r19, r4
breq add_md
inc r4
ret
add_md: clr r4
mov r19, r5
cpi r19, 99
breq reset_md
inc r5
ret
reset_md:
clr r5
mov r19, r6
cpi r19, 99
breq reset_mm
inc r6
ret
reset_mm:
clr r6
ret
; -- счет вперед в МИНУТАХ и СЕКУНДАХ ск 9, 19, 38
add_sec:
ldi r20, 0b10000001
mov r19, r21
andi r19, 0b00001100 ; разделители отключены
breq dlm_off_add_sec ; пользователем
ldi r19, 0b10000000
or r15, r19
dlm_off_add_sec:
clr r4
mov r19, r5
cpi r19, 59
breq reset_sec
inc r5
rjmp reset_calibrator
reset_sec:
clr r5
mov r16, r21
andi r16, 0b00010000 ; в режиме калибровки
brne reset_calibrator ; минуты вообще не считаем
mov r19, r6
cpi r19, 99
breq reset_min
inc r6 ; счетчик минут
ret
reset_min:
clr r6
ret
;--- сброс счетчика калибратора
reset_calibrator:
mov r16, r21
andi r16, 0b00010000
breq no_reset_calibrator
mov r16, r2
cpi r16, 0
brne no_reset_calibrator
; при отсчете первой секунды с ленты
; сброс системного счетчика секунд,
; что синхронизирует оба счетчика
clr r1
clr r6
clr r5
inc r2
mov r7, r5
no_reset_calibrator:
ret