Zahlavi

Выберите язык

Программа для управления кнопками блока ЭПС-103 (и управления моторами)

Замечательно иметь возможность написать любую надпись на дисплее. EPS-103 может сказать нам, что делает наша программа. Еще одно периферийное устройство, которое необходимо освоить, — это клавиатура. EPS-103 имеет в общей сложности 16 переключателей. Прежде всего, две большие кнопки Вверх и Вниз. Под открывающейся дверью мы находим кнопки от 0 до 9 и кнопку E. И трехпозиционный переключатель MODE, который фактически работает как три отдельных переключателя, один из которых всегда постоянно замкнут.

16 переключателей подключены к матрице 4 x 4 провода. Вход в матрицу подключен к порту А схемы 8255А, т.е. по адресу 5800h. Активна только нижняя половина порта. Старшие четыре бита по схеме не используются. Здесь будет возможность расширить клавиатуру дополнительными пользовательскими кнопками. Выход с матрицы направляется на порт В схемы 8255А, т.е. на адрес 5801h. Опять же, активны только младшие четыре бита. В верхней половине порта внутренние перемычки W1, W2 и W3 с маркировкой Test подключены в соответствии со схемой.

Пользоваться матричной клавиатурой довольно просто. На вход записывается двоичное число 1110 (1101, 1011, 0111), а затем на выходе считывается матрица. По его двоичному значению (1111, 1110, 1101, 1011, 0111) мы знаем, какой переключатель был активирован. Значение 1111 означает, что ни одна кнопка не нажата. В следующей таблице показаны значения каждого переключателя. Звездочка заменяет биты, не влияющие на работу клавиатуры. Программа обычно перезаписывает их всеми единицами.

Write
Address 5800h
Read
Address 5801h 
Button
EPS-103 
 MyCode
   bin   hex   bin   hex     4600h   4601h 
 Group 0    1111 1110   0FE   **** 1110  0*E  1     01h
 **** 1101  0*D  2/E    02h
 **** 1011  0*B  3/U    03h
 **** 0111  0*7  4/W    04h
 Group 1   1111 1101   0FD   **** 1110  0*E  5    05h
 **** 1101  0*D  6    06h
 **** 1011  0*B  7    07h
 **** 0111  0*7  8/D    08h
 Group 2   1111 1011   0FB   **** 1110  0*E  9    09h
 **** 1101  0*D  0    0Ah
 **** 1011  0*B  E    0Bh
 **** 0111  0*7  Not used  -  -
 Group 3   1111 0111   0F7   **** 1110  0*E  PRG  10h  
 **** 1101  0*D  TCH  20h  
 **** 1011  0*B  RUN + Up  30h  0Ch
 **** 0111  0*7  RUN + Down  30h  0Dh

 

Переключатель RUN подключен немного иначе, чем другие переключатели. Он последовательно с кнопками вверх и вниз. Это означает, что использование переключателя PRG или TCH отключает кнопки «Вверх» и «Вниз». Поэтому необходимо сначала идентифицировать эти три кнопки и кнопки «Вверх» и «Вниз» с ними в первом цикле. Только впоследствии во втором цикле сканируем остальные кнопки. После определения нажатой клавиши мы можем начать действие. Например, написать на дисплее, какая клавиша нажата.

Для работы этой программе потребуется оперативная память. Мы будем использовать пространство, выделенное под стек. Стек начинается с адреса 4700h и заполняется в сторону меньших значений. Вот почему я выбрал адреса с 4600h по 4603h. Они довольно близки к стеку, поэтому оригинальная прошивка определенно не использует их ни для чего другого. При этом они находятся достаточно далеко от начала стека, чтобы наша программа не перезаписывала их другими данными при использовании стека.

По адресу 4600h пишем код нажатой клавиши из тройки PRG, TCH, RUN. Если какая-то из оставшихся клавиш нажата, пишем ее код по адресу 4601h. Выводить название нажатой кнопки на дисплей имеет смысл только тогда, когда оно изменилось. Поэтому также используются управляющие адреса 4602h и 4603h. Копируем в них значения основных адресов 4600h и 4601h. Сравнив оригиналы и копии, мы можем увидеть, изменилось ли состояние клавиатуры.

Сканирование клавиатуры может быть частью основной программы. Но обычно повторяющиеся действия обрабатываются каким-то прерыванием. EPS-103 имеет генерируемое аппаратное прерывание RST7.5 от генератора импульсов NE555. Период импульса и, следовательно, повторение прерывания составляет 4 мс. Это может быть использовано для работы с клавиатурой. Нам просто нужно убедиться, что наш обработчик завершится до того, как прерывание снова сработает. Например, согласно документации очистка ЖК-дисплея занимает 15 мс. Это означает, что мы не сможем управлять дисплеем во время перерыва.

В целях изучения мы будем использовать прерывание RST7.5, но только для сканирования клавиатуры. Записываем результат сканирования в оперативную память по адресам 4600h и 4601h. В основной программе будет цикл, который будет считывать эти адреса и выполнять обработку на основе содержимого, включая запись на дисплей.

Введение в программу такое же, как и в программу Hello world. Сначала мы устанавливаем адрес стека в ОЗУ на 4700h, а затем инициализируем схему 8255A. Затем нам нужно правильно установить прерывание. RST7.5 необходимо включить, записав 0 в бит 2 регистра маски прерывания. Это делается по инструкции SIM. Затем мы можем вызвать прерывание с помощью инструкции EI. Бесконечный цикл будет многократно считывать адреса 4600h и 4601h и сравнивать их с копиями по адресам 4602h и 4603h. Если они отличаются, мы сначала обновляем копии. Затем стираем весь дисплей и пишем на нем настройку переключателя MODE, а затем название нажатой кнопки. Программа не обрабатывает возможность одновременного нажатия нескольких кнопок.

Чтобы программа имела определенную функцию, мы можем активировать двигатели в соответствующем направлении, нажимая кнопки 2/E, 3/U, 4W и 8/D. Отпустив кнопку, глушим двигатель. Если кто-то модифицирует программу, чтобы отслеживать большее количество одновременных нажатий кнопок, он должен тщательно продумать, как реагировать на них. Например, можно одновременно запускать двигатели азимута и угла места. Нет смысла активировать вращение одного мотора с обеих сторон одновременно. Изменение направления вращения при работающем двигателе может повредить двигатель.

Интерфейс двигателей подключен к порту C схемы 8255A, то есть по адресу 5802h. Двигатели управляются записью управляющего байта в этот порт. Значение отдельных битов следующее:

 Биты адреса 5802h   Функция 
 0   Направление возвышения: 0 = Up; 1 = Down
 1   Подъемный двигатель: 0 = Off; 1 = On
 2   High Speed: 0 = Off; 1 = On
 3   Азимутальное направление: 0 = West; 1 = East
 4   Азимутальный двигатель: 0 = Off; 1 = On
 5   Nepoužito
 6   Nepoužito
 7   Nepoužito

 Соответствующая программа может выглядеть так:

; Program Keyboard EPS-103
          jmp Start
.ORG 003Ch
          jmp IntRST75
.ORG 0040h
.dseg
nokey  .text "and no other key is pressed"
key1   .text "and Key 1 is pressed"
key2   .text "and Key 2/E is pressed"
key3   .text "and Key 3/U is pressed"
key4   .text "and Key 4/W is pressed"
key5   .text "and Key 5 is pressed"
key6   .text "and Key 6 is pressed"
key7   .text "and Key 7 is pressed"
key8   .text "and Key 8/D is pressed"
key9   .text "and Key 9 is pressed"
keyA   .text "and Key 0 is pressed"
keyE   .text "and Key E is pressed"
keyup  .text "and Key Up is pressed"
keydn  .text "and Key Down is pressed"
keyprg .text "MODE PRG "
keytch .text "MODE TCH "
keyrun .text "MODE RUN "

.cseg

Start:    lxi  sp, 4700h   ; Set Stack Address


          mvi  a, 82h      ; CW
          sta  5803h       ; 8255A Write Control Word
          xra  a           ; 0 -> a
          sta  5802h       ; 0 -> port C: stop motors
          mvi  a, 0Ch      ; LCD Command: Display on, cursor off
          call sub_1B70    ; Command -> LCD

          mvi  a, 00h
          sta  4600h       ; Initialization RAM
          sta  4601h       ; Initialization RAM
          sta  4602h       ; Initialization RAM
          sta  4603h       ; Initialization RAM
          mvi  a, 0Bh      ; Mask interrupt, 0000 1011, 0 -> bit2
          sim              ; Set mask
          ei               ; Enable Interrupt


TestKey:  lxi  h, 4600h    ; Source RAM
          mov  a, m        ; value -> a
          lxi  h, 4602h
          cmp  m           ; Compare the value with the copy
          jnz  TestCont    ; if value 4600h <> value 4602h, jump
          lxi  h, 4601h    ; Source RAM
          mov  a, m        ; Compare the value with the copy
          lxi  h, 4603h
          cmp  m           ; Compare the value with the copy
          jz   TestKey     ; if value 4601h = value 4603h, nothing changed, test again


TestCont: lxi  h, 4600h    ; Source RAM
          mov  a, m        ; value -> a
          sta  4602h       ; copy

          lxi  h, 4601h    ; Source RAM
          mov  a, m        ; value -> a
          sta  4603h       ; copy


          mvi  a, 01h      ; LCD Command: Clear Display
          call sub_1B70    ; Command -> LCD


          lxi  h, 4600h    ; Mode switch MyCode
          mov  a, m        ; Switch status
          cpi  10h         ; Is the PRG key?
          jnz  Test20      ; If not, jump
          lxi  h, keyprg   ; Address of text
          mvi  b, 09h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  Test01

Test20:   lxi  h, 4600h    ; Mode switch MyCode
          mov  a, m        ; Switch status
          cpi  20h         ; Is the TCH key?
          jnz  Test30      ; If not, jump
          lxi  h, keytch   ; Address of text
          mvi  b, 09h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  Test01


Test30:   lxi  h, keyrun   ; Address of text
          mvi  b, 09h      ; Number of characters
          call WrStr       ; Text -> LCD


Test01:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  01h         ; Is the 1 key?
          jnz  Test02      ; If not, jump
          lxi  h, key1     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp TestKey      ; Neverending loop


Test02:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  02h         ; Is the 2/E key?
          jnz  Test03      ; If not, jump
          lxi  h, key2     ; Address of text
          mvi  b, 16h      ; Number of characters
          call WrStr       ; Text -> LCD

          mvi  a, 18h      ; 0001 1000 East = On
          sta 5802h
          jmp TestKey      ; Neverending loop


Test03:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  03h         ; Is the 3/U key?
          jnz  Test04      ; If not, jump
          lxi  h, key3     ; Address of text
          mvi  b, 16h      ; Number of characters
          call WrStr       ; Text -> LCD

          mvi  a, 02h      ; 0000 0010 Up = On
          sta 5802h
          jmp TestKey      ; Neverending loop

Test04:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  04h         ; Is the 4/W key?
          jnz  Test05      ; If not, jump
          lxi  h, key4     ; Address of text
          mvi  b, 16h      ; Number of characters
          call WrStr       ; Text -> LCD

          mvi  a, 10h      ; 0001 0000 West = On
          sta  5802h
          jmp  TestKey     ; Neverending loop


Test05:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  05h         ; Is the 5 key?
          jnz  Test06      ; If not, jump
          lxi  h, key5     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp TestKey      ; Neverending loop

Test06:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  06h         ; Is the 6 key?
          jnz  Test07      ; If not, jump
          lxi  h, key6     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

Test07:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  07h         ; Is the 7 key?
          jnz  Test08      ; If not, jump
          lxi  h, key7     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

Test08:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  08h         ; Is the 8/D key?
          jnz  Test09      ; If not, jump
          lxi  h, key8     ; Address of text
          mvi  b, 16h      ; Number of characters
          call WrStr       ; Text -> LCD

          mvi  a, 03h      ; 0000 0011 Down = On
          sta  5802h
          jmp  TestKey     ; Neverending loop

Test09:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  09h         ; Is the 9 key?
          jnz  Test0A      ; If not, jump
          lxi  h, key9     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

Test0A:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  0Ah         ; Is the 0 key?
          jnz  Test0B      ; If not, jump
          lxi  h, keyA     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

Test0B:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  0Bh         ; Is the E key?
          jnz  Test0C      ; If not, jump
          lxi  h, keyE     ; Address of text
          mvi  b, 14h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

Test0C:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  0Ch         ; Is the Up key?
          jnz  Test0D      ; If not, jump
          lxi  h, keyup    ; Address of text
          mvi  b, 15h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

Test0D:   lxi  h, 4601h
          mov  a, m        ; Key MyCode
          cpi  0Dh         ; Is the Down key?
          jnz  TestNoK     ; If not, jump
          lxi  h, keydn    ; Address of text
          mvi  b, 17h      ; Number of characters
          call WrStr       ; Text -> LCD
          jmp  TestKey     ; Neverending loop

TestNoK:  lxi  h, nokey    ; Address of text
          mvi  b, 1Bh      ; Number of characters
          call WrStr       ; Text -> LCD

          mvi  a, 00h
          sta  5802h       ; 0 -> PortC: stop motors
          jmp  TestKey     ; Neverending loop


          hlt              ; For sure


; Write 1 byte command
sub_1B70: call sub_1B7E    ; Wait for LCD ready
          sta  4802h       ; Write command byte
          ret


; Write 1 byte data
sub_1B77: call sub_1B7E    ; Wait for LCD ready
          sta  4803h       ; Write data byte
          ret


; Wait for LCD ready
sub_1B7E: push psw
loc_1B7F: lda  4800h       ; Read LCD status
          ani  80h         ; Test bit 7: 0 = ready
          jnz  loc_1B7F    ; if not, repeat
          pop  psw
          ret

; Write string on LCD
WrStr:    mov  a, m
          call sub_1B77    ; Character -> LCD
          inx  h           ; Address of next characters
          dcr  b           ; Decrement counter
          jnz  WrStr
          ret


; Interrupt handling RST7.5
IntRST75: push psw         ; Save the contents of the registers to the stack
          push b
          push d
          push h


          mvi  a, 0F7h
          sta  5800h       ; Scan Group 3
          lda  5801h
          ori  0F0h
          cpi  0FEh        ; Is the PRG key?
          jnz  TCH_20      ; If not, jump
          mvi  a, 10h      ; The key is PRG, MyCode = 10h
          sta  4600h
          jmp  ScanGr0     ; Go scan group 0


TCH_20:   cpi  0FDh        ; Is the TCH key?
          jnz  RUN_30      ; If not, jump
          mvi  a, 20h      ; The key is TCH, MyCode = 20h
          sta  4600h
          jmp  ScanGr0     ; Go scan group 0


RUN_30:   cpi  0FBh        ; Are the RUN + Up keys?
          jnz  RUN_31      ; If not, jump
          mvi  a, 30h      ; The key is RUN, MyCode = 30h
          sta  4600h
          mvi  a, 0Ch      ; and the key is Up, MyCode = 0Ch
          sta  4601h
          jmp  EndISR      ; Finish scanning


RUN_31:   cpi  0F7h        ; Are the RUN + Down keys?
          jnz  RUN_32      ; If not, jump
          mvi  a, 30h      ; The key is RUN, MyCode = 30h
          sta  4600h
          mvi  a, 0Dh      ; and the key is Up, MyCode = 0Dh
          sta  4601h
          jmp  EndISR      ; Finish scanning


RUN_32:   mvi  a, 30h      ; The key must be RUN
          sta  4600h


ScanGr0:  mvi  a, 0FEh     ; Mask Group 0
          sta  5800h       ; Write mask
          lda  5801h       ; Scan Group 0
          ori  0F0h

          cpi  0FEh        ; Is the 1 key?
          jnz  Gr0_2       ; If not, jump
          mvi  a, 01h      ; The key is 1, MyCode = 01h
          sta  4601h
          jmp  EndISR      ; Finish scanning


Gr0_2:    cpi  0FDh        ; Is the 2/E key?
          jnz  Gr0_3       ; If not, jump
          mvi  a, 02h      ; The key is 2/E, MyCode = 02h
          sta  4601h
          jmp  EndISR      ; Finish scanning


Gr0_3:    cpi  0FBh        ; Is the 3/U key?
          jnz  Gr0_4       ; If not, jump
          mvi  a, 03h      ; The key is 3/U, MyCode = 03h
          sta  4601h
          jmp  EndISR      ; Finish scanning


Gr0_4:    cpi  0F7h        ; Is the 4/W key?
          jnz  Gr1_1       ; If not, jump
          mvi  a, 04h      ; The key is 4/W, MyCode = 04h
          sta  4601h
          jmp EndISR       ; Finish scanning

Gr1_1:    mvi  a, 0FDh     ; Mask Group 1
          sta  5800h       ; Write mask
          lda  5801h       ; Scan Group 1
          ori  0F0h


          cpi  0FEh        ; Is the 5 key?
          jnz  Gr1_2       ; If not, jump
          mvi  a, 05h      ; The key is 5, MyCode = 05h
          sta  4601h
          jmp  EndISR      ; Finish scanning

Gr1_2:    cpi  0FDh        ; Is the 6 key?
          jnz  Gr1_3       ; If not, jump
          mvi  a, 06h      ; The key is 6, MyCode = 06h
          sta  4601h
          jmp  EndISR      ; Finish scanning


Gr1_3:    cpi  0FBh        ; Is the 7 key?
          jnz  Gr1_4       ; If not, jump
          mvi  a, 07h      ; The key is 7, MyCode = 07h
          sta  4601h
          jmp  EndISR      ; Finish scanning


Gr1_4:    cpi  0F7h        ; Is the 8/D key?
          jnz  Gr2_1       ; If not, jump
          mvi  a, 08h      ; The key is 8/D, MyCode = 08h
          sta  4601h
          jmp  EndISR      ; Finish scanning

Gr2_1:    mvi  a, 0FBh     ; Mask Group 2
          sta  5800h       ; Write mask
          lda  5801h       ; Scan Group 2
          ori  0F0h

          cpi  0FEh        ; Is the 9 key?
          jnz  Gr2_2       ; If not, jump
          mvi  a, 09h      ; The key is 9, MyCode = 09h
          sta  4601h
          jmp  EndISR      ; Finish scanning

Gr2_2:    cpi  0FDh        ; Is the 0 key?
          jnz  Gr2_3       ; If not, jump
          mvi  a, 0Ah      ; The key is 0, MyCode = 0Ah
          sta  4601h
          jmp  EndISR      ; Finish scanning


Gr2_3:    cpi  0FBh        ; Is the E key?
          jnz  NoKeyIs     ; If not, jump
          mvi  a, 0Bh      ; The key is E, MyCode = 0Bh
          sta  4601h
          jmp  EndISR      ; Finish scanning

NoKeyIs:  mvi  a, 00h      ; no key is pressed, MyCode = 00h
          sta  4601h

; Finish scanning
EndISR:   pop  h           ; Restore the contents of the registers from the stack
          pop  d
          pop  b
          pop  psw
          ei               ; Enable Interrupt
          ret

.END

 

Полученный двоичный файл загружается программистом в стертую память EPROM и может быть протестирован. Я считаю, что информация, представленная в этой программе, поможет всем, кто хотел бы исследовать оригинальную прошивку EPS-103. Вы можете скачать исходный текст указанной программы в файле KeyboardEPS103.asm.

No comments

Leave your comment

In reply to Some User