;: программа измерения частоты для 1878ВЕ1 автор ;: Богомолов Д. версия 1.0, (идея частотомера AN592, ;: алгоритм преобразования двоичного числа в двоично- ;: -десятичное AN526. Microchip Technology Inc.) ;: PB0-PB7 сегменты индикатора A,B,...,H. ;: PA0-PA2 разряды индикатора 1-8. PA3 - не используется ;: PA4 вход частоты (обязательно через резистор ~470 Ом) ;--- область векторов прерываний процессора----------------------------- jmp start ;<0> Начальный пуск программы nop ;<1> Сторожевой таймер(не используется) rst ;<2> выход за границу стека jmp count ;<3> Таймер A nop ;<8> не используется nop ;<5> не используется nop ;<6> Порт A (прерывания не используются) nop ;<7> Порт B (прерывания не используются) nop ;<8> nop ;<9> nop ;<10> nop ;<11> nop ;<12> nop ;<13> nop ;<14> rst ;<15>Завершение записи в флэш code: .byte 03fh,006h,05bh,04Fh,066h,06Dh,07Dh,027h,07Fh,06Fh ; таблица .even ;#######################################################: ; Точка старта программы : ;#######################################################: start: jsr init ;инициализация портов и таймера loop: jsr b_bcd ;двойчный к двоично-десятичному jsr bcd_7 ;в код 7-и элементного индикатора jsr led_scan ;переключение сканирующей jsr sec ;пуск и стоп через 1 с jsr data ;вывод данных из таймера jsr led_scan ;переключение сканирующей jmp loop ;бесконечный цикл ;#######################################################: ; старт таймера и индикации на 1 секунду : ;#######################################################: sec: movl d4,3 ;разрешение работы таймера movl b1,00001011b ;выбор регистра кофигурации порта а movl b1,00000111b ;перевод вывода а4 (TCLC) на вход movl a3,70 ;устанавливаем movl a2,5 ;начальные $3: movl a1,232 ;значения циклов $2: movl a0,243 ; $1: nop ;начало циклa nop ; nop ; nop ; nop ; dec a0 ;уменьшение -1 jnz $1 ;переход 1 (цикл 14 х 243) jsr led_scan ;изменение сканирующей (+38 тактов) dec a1 ;уменьшение -1 jnz $2 ;переход 2 (цикл 1 х 232) dec a2 ;уменьшение -1 jnz $3 ;переход 3 (цикл 2 х 5) $4: dec a3 ;добавок (цикл 4 х 70) jnz $4 ;переход 4 ; ((14*243)+46)*232+6)*5+70*4+10=4000000 nop ; movl b1,00001011b ;обращение к регистру конфигурации порта а movl b1,00010111b ;перевод вывода а4 (TCLC) на выход (0) ;окончание счёта (всего 4.000.000 тактов) rts ;выход ;########################################################: ;# инициализация портов и таймера #: ;########################################################: init: ldr #a,40h ;сегмент источник таймера ldr #b,18h ;сегмент регистров конфигурации портов ldr #c,48h ;сегмент индикация ldr #d,0 ;сегмент порты ;формирование конфигурации порта A movl b1,00011011b ;заполнение регистра управления порта для ;формирования конфигурации порта в ;автоинкрементном режиме movl b1,00010111b ;3-сканирующие на вход/выход movl b1,00010111b ;4-активный выход movl b1,00001000b ;5-резисторы отключены(кроме PA3) movl b1,0 ;6-прерывания запрещены movl b1,0 ;7-прерывания запрещены ;формирование конфигурации порта B movl b2,00011011b ;заполнение регистра управления порта для ;формирования конфигурации порта в ;автоинкрементном режиме movl b2,11111111b ;3-все вход/выход movl b2,11111111b ;4-активный выход movl b2,0 ;5-резисторы отключены movl b2,0 ;6-прерывания запрещены movl b2,0 ;7-прерывания запрещены ;формирование конфигурации таймера movl d4,00010010b ;Работа с Регистром Конфигурации movl d5,01011111b ;16 бит + / + внешний вх.+ пред. + на 1/256 movl d4,00000010b ;Работа с Мл.Байтом Регистра Интервала movl d5,0 ;значение младшего байта интервала movl d4,00000110b ;Работа со Ст.Байтом Регистра Интервала movl d5,0 ;значение старшего байта регистра интервала movl a0,020h ; movl a1,0f6h ;начальная загрузка movl a2,02fh ;для теста movl a3,0a7h ;(87654321) clr a4 clr a5 clr a6 clr a7 rts ;возврат ;#######################################################: ; обработка прерывания от таймера : ;#######################################################: count: ldr #a,40h ;загрузка mov a3,d4 ;сохраняем переполнение bich d4,1110b ;обнуляeм для следующего счета bicl a3,1111b ;убиваем не нужные swap a3 ;разряды bicl a3,1 ; shr a3 ;устанавливаем в начало inc a3 ;фиксируем прерывание rti ;выходим ;########################################################: ; выемка данных из таймера и прескалера : ;########################################################: data: stie ;разрешение прерывания на процессор nop ;если было прерывание таймера nop ;то перейдём на count ;затем немного ждём, и clie ;запрещаем прерывание ldr #a,40h ;устанавливаем область работы clr a0 ;очистка цикла ;сохраняем таймер movl d4,00001011b ;обращение к младшему байту nop ;пауза !!! mov a1,d5 ;сохранение младшего байта movl d4,00001111b ;обращение к старшему байту nop ;пауза !!! mov a2,d5 ;сохранение старшего байта ;выемка данных из прескалера $9: bish d1,1 ;импульс на вход таймера bich d1,1 ; dec a0 ;счетчик -1 movl d4,00001011b ;обращение к младшему байту nop ;пауза !!! mov a4,d5 ;сохранение младшего байта cmpl a0,0 ;выход jeq $8 ;если перебрали всё cmp a1,a4 ;сравнение jeq $9 ;если не было переноса то снова $8: ;иначе получаем в а0 хвост movl d4,0 ;стоп таймера clr a4 ;обнуляем, что не нужно clr a5 ; clr a6 ; movl a7,5h ; $7: shl a0 ;подвигаем к краю rlc a1 ; rlc a2 ; rlc a3 ; dec a7 ; jnz $7 ;пока а7 не =0 rts ;выходим ;########################################################: ; Преобразование двоичного к двоично-десятичному : ;########################################################: b_bcd: ldr #a,40h ; ldr #c,48h ; movl c4,27 ;количество разрядов в источнике ;(счетчик цикла) $53: cmpl a7,0 ;сравниваем с 0 jz $40 ;если =0 нечего тестировать выходим mov c5,a7 ;иначе посылаем в темп jsr test ;переходим к тесту тетрад на >=5 mov a7,c5 ;востанавливаем из темпа $40: cmpl a6,0 ;продолжаем дальше тоже самое ... jz $41 ; mov c5,a6 ; jsr test ; mov a6,c5 ; $41: cmpl a5,0 ; jz $42 ; mov c5,a5 ; jsr test ; mov a5,c5 ; $42: cmpl a4,0 ; jz $43 ; mov c5,a4 ; jsr test ; mov a4,c5 ; $43: rlc a0 ; rlc a1 ; rlc a2 ;сдвиг всего на 1 бит rlc a3 ; rlc a4 ; rlc a5 ; rlc a6 ; rlc a7 ; dec c4 ;цикл 27 раз (3 байта + 3 разряда переполнения) jne $53 ; rts ;возврат ;#######################################################: ; дешифрация для семиэлементного индикатора : ;#######################################################: bcd_7: ldr #c,50h ; mov c0,a4 ;подготовка данных: mov c1,a4 ;распихиваем в 50h swap c1 ;получившееся двоично-десятичное mov c2,a5 ;число, в каждый адрес mov c3,a5 ;по тетраде. swap c3 ; mov c4,a6 ; mov c5,a6 ; swap c5 ; mov c6,a7 ; mov c7,a7 ; swap c7 ; ldr #a,48h ; movl a1,0 ; movl a2,0 ; mov a0,c7 ;сохраняем в темпе (а0) 8-й разряд jsr to_led ;переход в подпрограмму преобразования в 7-й код jsr no_o ;гашение не значашего 0 mov c7,a0 ;возвращаем обратно mov a0,c6 ;повторяем снова ... jsr to_led ;7-й разряд bish a0,8 ;засвечиваем кило-точку jsr no_o ; mov c6,a0 ; mov a0,c5 ;6-й разряд jsr to_led ; jsr no_o ; mov c5,a0 ; mov a0,c4 ;5-й разряд jsr to_led ; jsr no_o ; mov c4,a0 ; mov a0,c3 ;4-й разряд jsr to_led ; bish a0,8 ; jsr no_o ; mov c3,a0 ; mov a0,c2 ;3-й разряд jsr to_led ; jsr no_o ; mov c2,a0 ; mov a0,c1 ;2-й разряд jsr to_led ; jsr no_o ; mov c1,a0 ; mov a0,c0 ;1-й разряд jsr to_led ; mov c0,a0 ; rts ;возврат ;########################################################: ;# подпрограмма преобразования в 7 код #: ;########################################################: to_led: bich a0,1111b ;убиваем старшую тетраду mdal a1,code ;грузим указатель на 7-ый код mdah a4,code ; add a1,a0 ;+ двоичное число (смещение) mtpr #6,a1 ;непосредственная адресация к памяти mtpr #7,a4 ; mov a0,d7 ;меняем двоичный на 7-ый rts ;выход ;########################################################: ;# подпрограмма тестирования тетрад #: ;# если тетрада >=5 то к ней прибавляется 3 #: ;########################################################: test: cmpl c5,5 ;сравниваем с 5 tdc ;переносим флаг заёма в z jz $44 ;если <5 пропускаем +3 addl c5,3 ;если >=5 +3 $44: swap c5 ;меняем тетрады cmpl c5,5 ;сравниваем с 5 tdc ;переносим флаг заёма в z jz $45 ;если <5 пропускаем +3 addl c5,3 ;если >=5 +3 $45: swap c5 ;возвращаем тетрады на место rts ;конец ;########################################################: ;# Подпрограмма вывода на индикацию #: ;########################################################: led_scan: push #a ;сохраняем push #c ;рабочие регистры ldr #a,48h ;грузим ldr #c,50h ;нужные ldr #5,0c0h ;указатели movl d2,0 ;выключаем индикацию inc a7 ;переключаем сканирующую bich a7,00fh ;нужны только bicl a7,1000b ;три разряда movl a5,010h ; add a5,a7 ;и mov d1,a5 ;посылаем её в порт А movl a6,50h ;вычисляем где add a6,a7 ;лежат данные mtpr #4,a6 ; mov d2,d6 ;посылаем в порт В ;восстанавливаем pop #c ;старые значения pop #a ;регистров rts ;выход (всего 38 такт.) ;#######################################################: ; подпрограмма гашения незначащих нулей : ;#######################################################: no_o: cmpl a2,0 ;проверка не было ли значащей цифры jne $87 ;иначе на выход cmpl a0,00111111b ;сравнение с 0 jeq $89 ;если эквивалентно, то переход на гашение cmpl a0,10111111b ;сравнение с 0. jne $88 ;если не эквивалентно, то это первая ;значащая цифра и переход на отмену ;следующих проверок $89: clr a0 ;гашение знака jmp $87 ;и на выход $88: inc a2 ;+1 отмена проверок $87: rts ;возврат .END