;АВТОР: Измайлов Александр (SANCHOS) при содействии Игоря Кляндина ;Учтите, что это первая в моей жизни конструкция на МК по этому на ;какую-либо награду типа Нобиля она не претендует ;**************************************************************************** ;* * ;* ЧАСЫ * ;* * ;**************************************************************************** ; ver 1.17 for 1878we1 ; типа в этой версии есть: ; 1. индикация время в формате hh_mm_ss ; 2. ввод время с клавиатуры mode/pos/inc ; 3. звуковая сигнализация нажатия кнопки ; 4. будильник в формате hh_mm - будит в течении минуты ; 5. установка будильника в формате on/off_hh_mm ; 6. отключение сработавшего будильника по нажатию кнопки ; ;программа опроса клавиатуры 4*3 #define pb_dr a2 ;регистр управления порта В #define pb_wr b2 ;рабочий регистр порта В #define temp1 c1 ;временная переменная 1 #define temp2 c2 ;временная переменная 2 #define temp3 c3 ;временная переменная 3 #define key_code c0 ;код нажатой клавиши #define row_code c1 ;код строки #define col_mask c2 ;маска столбца #define key1 c4 ;стек нажатых кнопок #define key2 c5 ;стек нажатых кнопок ; ;ВРЕМЯ #define sec1 d0 ;здесь хранится время #define sec2 d1 ; #define min1 d2 ; #define min2 d3 ; #define hor1 d4 ; #define hor2 d5 ; ; ;РЕЖИМЫ #define kolv d0 ;кол-во прерываний #define pos d1 ;позиция на индикаторе #define mode d2 ;mode #define onind d3 ;индикация включена #define flagp d4 ;флаг прерывания ; ;БУДИЛЬНИК #define bhor1 b0 ; #define bhor2 b1 ; #define bmin1 b2 ; #define bmin2 b3 ; #define budil1 b4 ;флаги будильника #define bud_on b4,0001b ;будильник включен #define snd_on b4,0010b ;пора издать писк ; ;АДРЕСА port_io =00h ;сегмент порты port_cf =018h ;сегмент конфига портов ;ОЗУ keyba =040h ;сегмент клавиш indic =keyba+08h ;сегмент индикация time =indic+010h ;сегмент под время temp =time+08h ;сегмент времянки regim =temp+08h ;сегмент режимы budil1 =regim+08h ;-//- будильник 1 ; ;--- область векторов прерываний процессора----------------------------- jmp start ;<0> Начальный пуск программы nop ;<1> Сторожевой таймер(не используется) rst ;<2> выход за границу стека jmp time_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,007h,07Fh,06Fh ; таблица .even ; ; ;***************************************************************************** ;***************************************************************************** ;***************************************************************************** start: ; jsr initB ;формирование конфигурации порта B ;формирование конфигурации порта A ldr #b,port_cf ; movl b1,00011011b ;заполнение регистра управления порта movl b1,00011111b ;3-сканирующие на вход/выход movl b1,00011111b ;4-активный выход movl b1,00000000b ;5-резисторы отключены movl b1,0 ;6-прерывания запрещены movl b1,0 ;7-прерывания запрещены jsr sound2 ;писк после запуска ldr #d,time ;адрес с временем clr sec1 ; clr sec2 ; clr min1 ; clr min2 ; clr hor1 ; clr hor2 ; ldr #d,regim ;адрес с режимами clr kolv ;кол-во прерываний clr pos ;позиция на индикаторе clr flagp ;флаг прерывание clr mode ;mode ; ldr #b,budil1 ;сбрасываем будильник clr bhor1 ; время clr bhor2 ; clr bmin1 ; clr bmin2 ; clr b4 ;и флаги ; jsr time_start ; запуск таймера ; loop: nop ; jsr bcd_7 ; jsr led_scan ; jsr delay ;всё это надо чтобы jsr delay ;засветить цифру перед опросом ; movl d2,00000000b ;выключить всё в порту B (гасим леды) ldr #d,regim ; ;МИГАНИЕ mov a1,kolv ;загоним в темп bicl a1,1000b ;оставим 3 разряда bich a1,1111b ; cmpl a1,00h ;если <> 0 jne $55 ;уйти clr onind ;иначе сбросить флаг $55: cmpl a1,04h ;если <> половина jne $56 ; inc onind ;установим флаг $56: ; mov a1,kolv ;загоним в темп bicl a1,0000b ;оставим 5 разряда bich a1,1110b ; cmpl a1,00h ;если не 0 jeq $57 cmpl a1,08h jeq $57 jmp $58 $57: ldr #b,budil1 ;сегмент будилка bttl snd_on ; jeq $58 ; jsr sound2 ;заодно и пикнем если будильник сработал $58: ; ; ;************************************************************************** $90: jsr keyboard ; ; cmpl key_code,12 ;если ничего jeq $80 ;выйти ; ldr #b,budil1 ;сегмент будилка bttl snd_on ;если не сработал идти дальше jeq $110 ; bicl snd_on ;иначе сбросим флаг пиканья jmp $80 ;и выйдем (выключение сигнала) $110: ; jsr sound1 ;если кнопка нажата - короткий писк ;ОБРАБОТКА КЛАВИШИ mode cmpl key_code,1 ;если не mode jne $81 ;идти дальше clr pos ; inc mode ;иначе прибавить cmpl mode,3 ;если mode не выше крыши jne $80 ;пойти дальше clr mode ;иначе очистить jmp $80 ; $81: ;Обработка клавиши MODE закончена cmpl mode,1 ;если mode не 1(установка время) jne $83 ;то уйти в конец первой mode ;иначе проверяем дальше cmpl key_code,2 ;если не 2 (изменеие позиции) jne $82 ;то пойти дальше на изменение значения inc pos ;сдвинем позицию на экране cmpl pos,3 ;если позиция не выше крыши jne $80 ;то пойти дальше clr pos ;иначе чистить позицию jmp $80 ;после изменения позиции выйти $82: ;позиция выставлена, mode=1 cmpl key_code,3 ;если не 3 (изменение значения) jne $80 ;то выйти из обработки mode=1 cmpl pos,0 ;если pos <> 0 то уйти дальше jne $84 ; ldr #d,time ;загрузим время clr sec1 ;и очистим секунды clr sec2 ; jmp $80 ;если были секунды - уйти $84: ; cmpl pos,1 ;если pos <> 1 то уйти дальше jne $85 ; ldr #d,time ;загрузим время inc min1 ;прибавить минуту cmpl min1,10 ;если не больше jne $80 ;пойти дальше clr min1 ;иначе сбросить inc min2 ;и добавить десяток cmpl min2,6 ;если десятков не много jne $80 ;уйти clr min2 ;иначе сбросить десятки jmp $80 ;если были минуты - уйти $85: ; cmpl pos,2 ;если pos <> 2 то уйти дальше jne $80 ; ldr #d,time ; inc hor1 ; cmpl hor2,2 ;если часов больше 20 то jeq $87 ;пойти на 87 cmpl hor1,10 ;иначе если младших не много jne $80 ;пойти в конец clr hor1 ;иначе сбросить младший и inc hor2 ;прибавить десяток jmp $80 ;пойти в конец $87: ; cmpl hor1,4 ;иначе если младших не много jne $80 ;пойти в конец clr hor1 ;иначе сбросить младший и clr hor2 ; старший $83: ;end of mode=1 ; ;УСТАНОВКА БУДИЛЬНИКА cmpl mode,2 ;если mode = 2 (установка будильника) jne $100 ;если нет - уйти ; cmpl key_code,2 ;если не 2 (изменеие позиции) jne $101 ;то пойти дальше на изменение значения inc pos ;сдвинем позицию на экране cmpl pos,3 ;если позиция не выше крыши jne $80 ;то пойти дальше clr pos ;иначе чистить позицию jmp $80 ; ;позиция выставлена, mode=2 $101: ; cmpl key_code,3 ;если не 3 (изменеие значения) jne $80 ;то пойти дальше ; cmpl pos,2 ;если pos=0 - установка on/off jne $102 ;если нет, то дальше ; ldr #b,budil1 ; bttl bud_on ; jeq $103 ;если не включен, то дальше bicl bud_on ;иначе выключить jmp $80 ;и перейти в конец $103: bisl bud_on ;включить jmp $80 ;и перейти в конец ;флаг состояния установлен! $102: cmpl pos,0 ;если pos=0 - минута jne $104 ; ; ldr #b,budil1 ;загрузим время inc bmin1 ;прибавить минуту cmpl bmin1,10 ;если не больше jne $80 ;пойти дальше clr bmin1 ;иначе сбросить inc bmin2 ;и добавить десяток cmpl bmin2,6 ;если десятков не много jne $80 ;уйти clr bmin2 ;иначе сбросить десятки jmp $80 ; $104: ; cmpl pos,1 ;если pos <> 1 то уйти дальше jne $80 ; ldr #b,budil1 ; inc bhor1 ; cmpl bhor2,2 ;если часов больше 20 то jeq $106 ;пойти на 106 cmpl bhor1,10 ;иначе если младших не много jne $80 ;пойти в конец clr bhor1 ;иначе сбросить младший и inc bhor2 ;прибавить десяток jmp $80 ;пойти в конец $106: ; cmpl bhor1,4 ;иначе если младших не много jne $80 ;пойти в конец clr bhor1 ;иначе сбросить младший и clr bhor2 ;сбросить десяток $100: ;end of mode=2 ; ; $80: jsr initB ;возвращаю конфиг на место, чтоб индикатор ;работал jmp loop ;зациклим ; ;***************************************************************************** ;***************************************************************************** ;***************************************************************************** initB: ; ldr #b,port_cf ;сегмент регистров конфигурации портов ;формирование конфигурации порта B movl b2,00011011b ;заполнение регистра управления порта movl b2,11111111b ;3-все вход/выход movl b2,11111111b ;4-активный выход movl b2,0 ;5-резисторы отключены movl b2,0 ;6-прерывания запрещены movl b2,0 ;7-прерывания запрещены rts ;возврат ;#######################################################: ; обработка прерывания от таймера : ;#######################################################: time_count: ; push #d ; push #b ; ldr #d,port_io ; bich d4,1110b ;обнуляeм для следующего счета ldr #d,regim ; inc kolv ;прибавим кол-во прерываний inc flagp ;выставим флаг прерывания (в этой версии не надо) cmpl kolv,020h ;досчитывать время если пора jeq $91 ; jmp $40 ;если время не пришло - уходим ; ;************************************************************************* $91: ;коль время пришло, так посчитаем clr kolv ;сбросим счетчик прерываний ldr #d,time ; ;время проверяем inc sec1 ;прибавим секунду ; cmpl sec1,10 ;если не больше 10 jne $10 ;пойти в конец clr sec1 ;иначе сбросим inc sec2 ;и добавим во второй разряд cmpl sec2,6 ;если не больше 6 jne $10 ;пойти в конец clr sec2 ;иначе сбросим inc min1 ;и добавим минуту ; cmpl min1,10 ;если не больше 10 jne $10 ;пойти в конец clr min1 ;иначе сбросим inc min2 ;и добавим во второй разряд cmpl min2,6 ;если не больше 6 jne $10 ;пойти в конец clr min2 ;иначе сбросим inc hor1 ;и добавим час ; cmpl hor2,2 ;если часов больше 20 то jeq $11 ;пойти на 11 cmpl hor1,10 ;иначе если младших не много jne $10 ;пойти в конец clr hor1 ;иначе сбросим inc hor2 ;прибавить десяток jmp $10 ;пойти в конец ; $11: ; cmpl hor1,4 ;иначе если младших не много jne $10 ;пойти в конец clr hor1 ;иначе сбросим clr hor2 ; ; $10: ;БУДИЛЬНИК ;место где можно проверить будильник ldr #b,budil1 ; bttl bud_on ; jeq $40 ;если не включен, то дальше cmp hor1,bhor1 ; jne $40 ; cmp hor2,bhor2 ; jne $40 ; cmp min1,bmin1 ; jne $40 ; cmp min2,bmin2 ; jne $40 ;если так и не совпало то уйти ; cmpl sec1,0 ;включить будильник если 00 секунд jne $41 ;если не равна - уйти cmpl sec2,0 ; jne $41 ;если не равна 0, то уйти bisl snd_on ;установим флаг пиканья $41: ; cmpl sec1,9 ;выключить будильник если 59 секунд jne $42 ;если секунды <> 9, то уйти cmpl sec2,5 ; jne $42 ;если секунды <> 5, то уйти bicl snd_on ;сбросим флаг пиканья если минута кончилась $42: ; $40: pop #b ; pop #d ; rti ;выходим ;-------Инициализация таймера----------------------------------------- time_start: ; ldr #d,port_io ; movl d4,00010000b ;Работа с Регистром Конфигурации movl d5,01001010b ;16 бит + / + cpu-clk + пред. + на 1/8 movl d4,00000010b ;Работа с Мл.Байтом Регистра Интервала movl d5,9 ;значение младшего байта интервала movl d4,00000110b ;Работа со Ст.Байтом Регистра Интервала movl d5,61 ;значение старшего байта регистра интервала movl d4,00000011b ;запуск таймера на счет ;Ст*256+Мл=61*256+9=125000 (1/32 секунда) stie ;включаем прерывание rts ;возврат ;#######################################################: ; дешифрация для семиэлементного индикатора : ;#######################################################: bcd_7: ; ldr #d,regim ; cmpl mode,0 ;если моде = 0 jeq time_set ;уйти на обычный ход cmpl mode,1 ;если моде = 1 jeq time_set ;уйти на установку времени cmpl mode,2 ; =2 jeq budilo1 ;будильник nop budilo1: ; ldr #c,indic+08h ;ИНДИКАЦИЯ ДЛЯ БУДИЛЬНИКА ldr #a,temp ; ldr #b,budil1 ; movl c0,01110111b ;A nop ldr #c,indic ;ИНДИКАЦИЯ ДЛЯ БУДИЛЬНИКА movl c7,00111000b ;L movl c6,10000110b ;1. movl c5,10001000b ;_ movl c2,01000000b ;- bttl bud_on ; jeq $21 ;если не установлен - уйти movl c5,11011100b ;если да - квадратик сделать $21: ; mov c0,bmin1 ; mov c1,bmin2 ; mov c3,bhor1 ; mov c4,bhor2 ; ; mov a0,c0 ;сохраняем в темпе (а0) 8-й разряд jsr to_led ;переход в подпрограмму преобразования в 7-й код mov c0,a0 ;возвращаем обратно ; mov a0,c1 ;сохраняем в темпе (а0) 7-й разряд jsr to_led ;переход в подпрограмму преобразования в 7-й код mov c1,a0 ;возвращаем обратно ; mov a0,c3 ;сохраняем в темпе (а0) 5-й разряд jsr to_led ;переход в подпрограмму преобразования в 7-й код mov c3,a0 ;возвращаем обратно ; mov a0,c4 ;сохраняем в темпе (а0) 4-й разряд jsr to_led ;переход в подпрограмму преобразования в 7-й код mov c4,a0 ;возвращаем обратно ; cmpl onind,0 ;если все светится то дальше jne $20 ; cmpl pos,0 ; jne $22 ;если не 0 (минуты) то дальше clr c0 ; clr c1 ; $22: cmpl pos,1 ;часы jne $23 ; clr c3 ; clr c4 ; $23: cmpl pos,2 ;признак jne $20 ; clr c5 ; $20: ; jmp exit_indic ;уйти на выход ; time_set: ; ldr #c,indic+08h ;ИНДИКАЦИЯ ДЛЯ ВРЕМЯ И УСТАНОВКИ ЕГО ldr #b,budil1 ; movl c0,0 bttl bud_on ; jeq $21 ;если не установлен - уйти movl c0,11011100b ;если да - квадратик сделать $21: ; ldr #c,indic ldr #d,time ; ldr #a,temp ; ; mov c0,sec1 ;засуним время в сегмент индикации mov c1,sec2 ; mov c3,min1 ; mov c4,min2 ; mov c6,hor1 ; mov c7,hor2 ; ; ldr #d,regim ; ;преобразуем его mov a0,c0 ;сохраняем в темпе (а0) 8-й разряд jsr to_led ;переход в подпрограмму преобразования в 7-й код mov c0,a0 ;возвращаем обратно ; mov a0,c1 ;повторяем снова ... jsr to_led ;7-й разряд mov c1,a0 ; ; cmpl mode,0 ;if mode=0 jeq $70 ;then goto 70 cmpl pos,0 ;if not pos=0 jne $70 ;then goto 70 cmpl onind,0 ;if not onind=0 jne $70 ;then goto 70 clr c1 ; clr c0 ; $70: ; movl c2,01000000b ;6-й разряд ; mov a0,c3 ;5-й разряд jsr to_led ; mov c3,a0 ; ; mov a0,c4 ;4-й разряд jsr to_led ; mov c4,a0 ; ; cmpl mode,0 ;if mode=0 jeq $71 ;then goto 71 cmpl pos,1 ;if not pos=1 jne $71 ;then goto 71 cmpl onind,0 ;if not onind=0 jne $71 ;then goto 71 clr c3 ; clr c4 ; $71: ; movl c5,01000000b ;3-й разряд ; mov a0,c6 ;2-й разряд jsr to_led ; mov c6,a0 ; ; mov a0,c7 ;1-й разряд jsr to_led ; mov c7,a0 ; ; cmpl mode,0 ;if mode=0 jeq exit_indic ;then goto cmpl pos,2 ;if not pos=2 jne exit_indic ;then goto cmpl onind,0 ;if not onind=0 jne exit_indic ;then goto clr c6 ; clr c7 ; jmp exit_indic exit_indic: ; rts ;возврат ;########################################################: ;# подпрограмма преобразования в 7 код #: ;########################################################: to_led: ; push #d ; ldr #d,port_io ; bich a0,1111b ;убиваем старшую тетраду mdal a1,code ;грузим указатель на 7-ый код mdah a4,code ; add a1,a0 ;+ двоичное число (смещение) mtpr #6,a1 ;непосредственная адресация к памяти mtpr #7,a4 ; mov a0,d7 ;меняем двоичный на 7-ый pop #d ; rts ;выход ;########################################################: ;# Подпрограмма вывода на индикацию #: ;########################################################: led_scan: ; ldr #a,indic+08h ;грузим ldr #d,port_io ; ldr #5,0c0h ;указатели movl d2,0 ;выключаем индикацию inc a7 ;переключаем сканирующую cmpl a7,10 ;если не больше 10 jne $1 ;то дальше clr a7 ;иначе первый разряд $1: ; movl a5,010h ;?????????????????????????? add a5,a7 ;и bich a5,0001b ;сбросим бит динамика mov d1,a5 ;посылаем её в порт А ; movl a6,indic ;вычисляем где add a6,a7 ;лежат данные mtpr #4,a6 ; mov d2,d6 ;посылаем в порт В ;восстанавливаем rts ;выход ;************************************************************************ ;* подпрограмма опроса клавиатуры * ;* 4строки*3столбца * ;* линии строк работают как выходы * ;* линии столбцов работают как входы с притягивающими к Vcc резисторами * ;************************************************************************ ;размещение кнопок на клавиатуре ;слева-направо, сверху-вниз sym_set: .byte 1,2,3,4,5,6,7,8,9,10,0,11 keyboard: ; ldr #a,port_cf ;сегмент регистров конфигурации портов ldr #b,port_io ;сегмент рабочих регистров портов ldr #c,keyba ;1ый сегмент рабочих переменных ; movl b1,00001111b ;выключить дешифратор - 1111 ;и динамик на ноге PA4/C - 0 movl pb_dr,00001011b ;запись в 3ий подрегистр movl pb_dr,10001111b ;старшая тетрада-входы movl pb_dr,00001101b ;запись в 5ый подрегистр movl pb_dr,01110000b ;на столбцы клав-ры повешены резисторы ;предварительное сканирование клавиатуры ;младшая тетрада порта В выставлена в ноль ;старшая тетрада работает как вход bicl pb_wr,1111b ;сбросил мл. тетраду ;пропустил 12 такта (в оригенале - 2) nop ; btgh pb_wr,1111b ;проверил старшую тетраду на ноль jz key_code12 ;если мл. тетрада вся установлена ; ;далее идет сканирование клавиатуры movl row_code,1110b ;код верхней строки клав-ры movl key_code,255 ;инициализировал смещение next_row: ; movl col_mask,00010000b ;маска левого столбца клав-ры mov pb_wr,row_code ;записываем код строки в порт В next_col: ; inc key_code ;увеличил смещение на 1 mov temp3,pb_wr ;читаем значение порта В во временную переменную and temp3,col_mask ;сравниваем значение порта В с кодом столбца jz key_def ;переходим к блоку преобразования в истинный код shl col_mask ;сдвигаем маску столбца влево btth col_mask,0111b ;проехали последний столбец? jnz next_col ;переходим к опросу следующей кнопки в строке stc ;установил флаг переноса rlc row_code ;сдвигаем код строки влево btth row_code,0001 ;проехали последнюю строку? jnz next_row ;переходим к опросу следующей строки key_code12: ; movl key_code,12 ;кнопка не была нажата jmp no_key ;обхожу таблицу ; ;по смещению key_code в таблице определяем нажатую кнопку key_def: ; mdal temp1,sym_set ;младший байт адреса таблицы в temp1 mdah temp2,sym_set ;старший байт адреса таблицы в temp2 add temp1,key_code ; adc temp2 ;добавили к адресу таблицы смещение mtpr #6,temp1 ; mtpr #7,temp2 ;загрузили регистр косвенной адресации этим адресом mov key_code,d7 ;получили истинное название кнопки ; ;по последовательности key1 key2 key_code ; определяю факт нажатия кнопки cmpl key1,12 ;была ли отжата кнопка jnz no_key ; cmpl key2,12 ;была ли нажата кнопка jz no_key ; cmp key2,key_code ;равны ли последние опросы jnz no_key ; mov key1,key2 ; mov key2,key_code ; jmp key_exit ; ; no_key: mov key1,key2 ; mov key2,key_code ; movl key_code,12 ; key_exit: ; movl b1,00000000b ;включить дешифратор, динамиk выключен movl b2,00000000b ;вырубить всё в порту B ;иначе засвечивается мусор на индикаторе rts ;выход из процедуры обработки клавы ;--------------------------------короткий писк (10 импульсов на динамик) sound1: ;при нажатии на кнопочки push #d ; ldr #d,indic+08h ; ldr #b,port_io ; movl b1,00001111b ;чтобы прикрыть дешифратор movl d4,10 ; $20: jsr delay ; bish b1,0001b ;выставим 1 на динамик jsr delay ; bich b1,0001b ;выставим 0 на динамик dec d4 ; jnz $20 ; movl b1,00000000b ;чтобы открыть дешифратор pop #d ; rts ; ;длинный писк (50 импульсов на динамик) sound2: ; push #d ; ldr #d,indic+08h ; ldr #b,port_io ; movl b1,00001111b ;чтобы прикрыть дешифратор movl d4,50 ; $20: jsr delay ; bish b1,0001b ;выставим 1 на динамик jsr delay ; bich b1,0001b ;выставим 0 на динамик dec d4 ; jnz $20 ; movl b1,00000000b ;чтобы открыть дешифратор pop #d ; rts ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay: ;задержка на 6*255*500нс push #d ; ldr #d,indic+08h ; nop ; movl d0,255 ;предполагается что d - это temp $10: nop ; dec d0 ;Это пустой цикл (задержка) jnz $10 ; pop #d ; rts ;