HOME      PROJETOS      PROGRAMAÇÃO     


Teclado PS/2 com Microcontroladores PIC

Introdução
Conectores e Conexões
Lendo as Teclas do Teclado PS/2
     Start Bit
     Bits de Dados
     Parity Bit
     Stop Bit
     Scan Code
     Make Code
     Break Code
Traduzindo Scan Codes em ASCII
Enviando Comandos ao Teclado PS/2
Driver para Teclado PS/2
Como o Driver Funciona
     Velocidade de Repetição do Teclado
     Símbolos para as Teclas de funções
     Símbolos para Controle dos LEDs do Teclado
Programa de Teste
Conclusão





Introdução

Se você tem um projeto que requer a entrada de strings de caracteres, números e caracteres especiais, aqui esta o que procura.

Um teclado comum de PC, conhecido como teclado PS/2, pode ser facilmente conectado ao microntrolador PIC e, com o software disponível aqui, tudo estará "quase" resolvido. Digo "quase" porque, quando temos certeza que pensamos em tudo, logo surge uma situação imprevista.




Conectores e Conexões

Os teclados PS/2, na verdade, são iguais aos teclados DIN de 5 pinos usados nos PCs mais antigos, cujos conectores eram maiores do que os dos PS/2. A figura 1 mostra o esquema dos conectores machos PS/2 de 6 pinos e DIN de 5 pinos.



PS/2 Macho
               
DIN5 Macho
               
Figura 1

A única diferença entre os conectores é física, pois têm tamanhos diferentes, e os pinos também ocupam posições diferentes.

Nos dois conectores, apenas 4 pinos são utilizados na conexão com o Host, e esses pinos têm as mesmas funções.
São eles: o pino de alimentação (+5v), Ground, Data, Clock e os pinos marcados com NC, que nunca são usados.

O teclado PS/2 é um dispositivo serial onde os bits de dados trafegam pelo pino Data, e seu fluxo é controlado pelo pino Clock.

Daqui em diante, chamaremos de Host ao dispositivo no qual o teclado PS/2 esta conectado, seja ele um PC ou Microcontrolador.

Na comunicação entre um dispositivo PS/2 e um Host quem controla o Clock é sempre o dispositivo PS/2. Isso não pode ser esquecido.

A comunicação pode ser feita do PS/2 para o Host, caso em que se pressiona uma tecla no teclado e este envia ao Host o código da tecla pressionada.

A comunicação pode ser feita, também, do Host para o PS/2, para enviar um comando ao teclado a fim de configurá-lo como, por exemplo, para acender um de seus LEDs (Caps Lock, Num Lock ou Scroll Lock).

Uma característica elétrica do PS/2 é que os pinos Data e Clock são do tipo coletor aberto, isto é, eles devem ser polarizados com resistores, de 1K por exemplo, conectados ao +5v. Na figura 2 podemos ver o diagrama de conexão de um PS/2 a um Host.


Conexão de um teclado PS/2 a um Microcontrolador
Figura 2




Lendo as Teclas do Teclado PS/2

Antes de podermos nos comunicar com o teclado PS/2, devemos colocá-lo no estado de recepção, ou seja, configurar as portas Data e Clock do Host para que o PS/2 possa responder as requisições, ou seja, enviar ao Host os valores das teclas pressionadas.

A configuração das portas consiste, em primeiro lugar, interromper o que o teclado esta fazendo. Para isso, devemos levar o pino Data ao nível alto. Como as portas do dispositivo PS/2 são do tipo coletor aberto, o pino DATA deve permanecer em alta impedância (Input), pois supõe-se que há um resistor de pull-up nesse pino. Além disso, devemos levar o pino Clock ao nível baixo (Output), por pelo menos 100us (microsegundos), para que o dispositivo PS/2 entenda que a comunicação foi inibida.

Supondo que o PORTB<2> esteja conectado ao pino Data e o PORTB<3> ao pino Clock, o exemplo abaixo mostra como proceder para obter o estado descrito acima:


bcf PORTB, 2 ; Data=0 bsf TRISB, 2 ; Data=Input bcf PORTB, 3 ; Clock=0 bcf TRISB, 3 ; Clock=Output movlw .100 ; 100us call delay_us ; espera 100us bsf TRISB, 3 ; Clock=Input


Após passar 100us, o pino de Clock deve ser colocado em alta impedância (Input). A partir desse momento, o PS/2 assume o controle começando a gerar sinais de Clock e a enviar uma sequência de 11 bits ao Host. Cada bit dessa sequência deverá ser capturado pelo Host durante o ciclo baixo do Clock. O diagrama da Figura 3 mostra o que acontece em cada ciclo do Clock durante a fase de transmissão do PS/2 para o Host:


Figura 3

No primeiro ciclo de Clock (1), o PS/2 enviará um Start Bit, nos ciclos de 2 a 9 virão os bits que representam o código da tecla pressionada, no ciclo 10 o PS/2 enviará o Parity Bit e no ciclo 11 o Stop bit.



Start Bit

O Start bit, no ciclo 1, caracteriza-se por um pulso baixo no pino Clock enquanto o pino Data é mantido baixo.



Bits de Dados

Os bits de dados, ciclos 2 a 9, serão enviados ao Host iniciando pelo bit de mais baixa ordem (LSB).



Parity Bit

O ciclo 10, é enviado o Parity bit. O PS/2 usa paridade impar, isto é, se nos ciclos de Clock 2 a 9 vierem um número par de dígitos 1, o PS/2 enviará um Parity bit 1. Se nos ciclos de Clock 2 a 9 vierem um número impar de dígitos 1, o PS/2 enviará um Parity bit 0. Por exemplo, se os 8 bits de dados transmitidos forem 00101101, a paridade será 1, pois existe um número par de dígitos 1 nos bits de dados. Se os 8 bits de dados transmitidos forem 10101101, a paridade será 0, pois existe um número impar de dígitos 1 nos bits de dados.



Stop Bit

No ciclo 11, o PS/2 enviará o Stop Bit. O Stop bit é sempre 1.



Scan Code

Na sequência de 11 bits, descrita acima, os 8 bits de dados enviados ao Host é um código chamado Scan Code. Essa sequência é enviada ao Host toda vez que uma tecla é pressionada e, também, quando a tecla é liberada.



Make Code

Quando a tecla é pressionada, os 8 bits de dados do Scan Code recebe o nome de Make Code. Por exemplo, o Make Code da tecla "A" tem o valor 0x1C.



Break Code

Quando a tecla é liberada, os 8 bits de dados do Scan Code recebe o nome de Break Code. Por exemplo, o Break Code da tecla "A" tem o valor 0xF01C.

A tabela abaixo mostra os Make Codes e Break Codes de cada tecla:

Tecla
Make Code
Break Code
 
Tecla
Make Code
Break Code
 
Tecla
Make Code
Break Code
A
1C
F0,1C
 
9
46
F0,46
 
[
54
FO,54
B
32
F0,32
 
`
0E
F0,0E
 
INSERT
E0,70
E0,F0,70
C
21
F0,21
 
-
4E
F0,4E
 
HOME
E0,6C
E0,F0,6C
D
23
F0,23
 
=
55
FO,55
 
PG UP
E0,7D
E0,F0,7D
E
24
F0,24
 
\
5D
F0,5D
 
DELETE
E0,71
E0,F0,71
F
2B
F0,2B
 
BKSP
66
F0,66
 
END
E0,69
E0,F0,69
G
34
F0,34
 
SPACE
29
F0,29
 
PG DN
E0,7A
E0,F0,7A
H
33
F0,33
 
TAB
0D
F0,0D
 
U ARROW
E0,75
E0,F0,75
I
43
F0,43
 
CAPS
58
F0,58
 
L ARROW
E0,6B
E0,F0,6B
J
3B
F0,3B
 
L SHFT
12
FO,12
 
D ARROW
E0,72
E0,F0,72
K
42
F0,42
 
L CTRL
14
FO,14
 
R ARROW
E0,74
E0,F0,74
L
4B
F0,4B
 
L GUI
E0,1F
E0,F0,1F
 
NUM
77
F0,77
M
3A
F0,3A
 
L ALT
11
F0,11
 
KP /
E0,4A
E0,F0,4A
N
31
F0,31
 
R SHFT
59
F0,59
 
KP *
7C
F0,7C
O
44
F0,44
 
R CTRL
E0,14
E0,F0,14
 
KP -
7B
F0,7B
P
4D
F0,4D
 
R GUI
E0,27
E0,F0,27
 
KP +
79
F0,79
Q
15
F0,15
 
R ALT
E0,11
E0,F0,11
 
KP EN
E0,5A
E0,F0,5A
R
2D
F0,2D
 
APPS
E0,2F
E0,F0,2F
 
KP .
71
F0,71
S
1B
F0,1B
 
ENTER
5A
F0,5A
 
KP 0
70
F0,70
T
2C
F0,2C
 
ESC
76
F0,76
 
KP 1
69
F0,69
U
3C
F0,3C
 
F1
05
F0,05
 
KP 2
72
F0,72
V
2A
F0,2A
 
F2
06
F0,06
 
KP 3
7A
F0,7A
W
1D
F0,1D
 
F3
04
F0,04
 
KP 4
6B
F0,6B
X
22
F0,22
 
F4
0C
F0,0C
 
KP 5
73
F0,73
Y
35
F0,35
 
F5
03
F0,03
 
KP 6
74
F0,74
Z
1A
F0,1A
 
F6
0B
F0,0B
 
KP 7
6C
F0,6C
0
45
F0,45
 
F7
83
F0,83
 
KP 8
75
F0,75
1
16
F0,16
 
F8
0A
F0,0A
 
KP 9
7D
F0,7D
2
1E
F0,1E
 
F9
01
F0,01
 
]
5B
F0,5B
3
26
F0,26
 
F10
09
F0,09
 
;
4C
F0,4C
4
25
F0,25
 
F11
78
F0,78
 
'
52
F0,52
5
2E
F0,2E
 
F12
07
F0,07
 
,
41
F0,41
6
36
F0,36
 
PRNT
SCRN
E0,12,
E0,7C 
E0,F0,
7C,E0,
F0,12 
 
.
49
F0,49
7
3D
F0,3D
 
SCROLL
7E
F0,7E
 
/
4A
F0,4A
8
3E
F0,3E
 
PAUSE
E1,14,77,
E1,F0,14,
F0,77

 


 

 
 
   

Note que a maioria dos Scan Codes tem apenas 1 byte mas, algumas teclas podem ter 2, 3 e até 8 bytes, como é o caso da tecla "Pause/Break".

Se uma tecla for mantida pressionada, o mesmo Make Code será enviado repetidamente ao Host, até que a tecla seja liberada, quando, então, um Break Code será enviado.

Os códigos Make Code ou Break Code nada têm a ver com os códigos da tabela ASCII que representam os caracteres como 0x61="a", 0x41="A", 0x62="b", 0x42="B", 0x31="1", 0x32="2",etc. Assim, para poder exibir um caracter, num LCD por exemplo, será necessário mapear os códigos ASCII dentro de uma tabela de Scan Codes. A matriz abaixo, alocada na memória de programa, mostra como isso é feito num programa em linguagem Assembler num microcontrolador PIC18Fxxxx:


Mapeamento dos Códigos ASCII nos Scan Codes

scancodes_table ; nome da tabela ; COLUNAS ; 0 1 2 3 4 5 6 7 8 9 A B C D E F ; ------------------------------------------------------------------------------ ; F9 F5 F3 F1 F2 F12 F10 F8 F6 F4 TAB " DB 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x22,0x0F ; 0 LINHAS ; ; ALT SFL CTRL q 1 z s a w 2 WIN DB 0x10,0x11,0x12,0x13,0x14,0x71,0x31,0x17,0x18,0x19,0x7A,0x73,0x61,0x77,0x32,0x1F ; 1 ; ; c x d e 4 3 spc v f t r 5 MENU DB 0x20,0x63,0x78,0x64,0x65,0x34,0x33,0x27,0x28,0x20,0x76,0x66,0x74,0x72,0x35,0x2F ; 2 ; ; n b h g y 6 m j u 7 8 DB 0x30,0x6E,0x62,0x68,0x67,0x79,0x36,0x37,0x38,0x39,0x6D,0x6A,0x75,0x37,0x38,0x3F ; 3 ; ; , k i o 0 9 . ; l p - DB 0x40,0x2C,0x6B,0x69,0x6F,0x30,0x39,0x47,0x48,0x2E,0x3B,0x6C,0x00,0x70,0x2D,0x4F ; 4 ; ; / ~ Ž = CAPL SFD ENTR [ ] DB 0x50,0x2F,0x7E,0x53,0xB4,0x3D,0x56,0x57,0x58,0x59,0x0D,0x5B,0x5C,0x5D,0x5E,0x5F ; 5 ; ; \ BKSP END 4 HOME . DB 0x60,0x5C,0x62,0x63,0x64,0x65,0x93,0x67,0x68,0x98,0x6A,0xA0,0x97,0x6D,0x6E,0x6F ; 6 ; ; 0 DEL 2 5 6 8 ESC NMLK F11 + 3 - SYSR 9 SRLL DB 0x70,0x9B,0x9F,0x73,0x9E,0x9D,0x1B,0x94,0x78,0x79,0x7A,0x7B,0x96,0x7D,0x95,0x7F ; 7 ; ; F7 DB 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F ; 8


Na tabela acima podemos observar que o caracter "a", cujo código ASCII é 0x61, esta mapeado na posição 0x1C da tabela, que corresponde ao Scan Code da tecla "A".

Devemos observar, também, que a tabela acima somente faz o mapeamento para os caracteres minúsculo. Se quisermos mapear os caracteres maiúsculos, devemos montar uma outra tabela, semelhante a essa, substituindo os códigos ASCII dos caracteres minúsculos por maiúsculo, pois só existe um Scan Code para cada tecla. A escolha entre maiúsculas e minúsculas é apenas uma condição, que deve ser prevista no programa, onde a tecla "Caps Lock" pode estar acionada ou não.




Traduzindo Scan Codes em ASCII

Abaixo, vemos uma subrotina escrita em linguagem Assembler para microcontroladores da família 18F, usada para traduzir um Scan Code em caracter ASCII.

A tabela de Scan Codes usada, que é a mesma descrita acima, e cujo nome é scancodes_table, esta alocada na memória de programa do microcontrolador (memória Flash).

Ao entrar na subrotina, o registrador W deve conter o Scan Code 0x1C a ser traduzido para ASCII e, ao sair da subrotina, o registrador W conterá o código ASCII 0x61 que coresponde ao caracter "a".


movlw 0x1C ; carrega W com Scan Code 0x1C call traduzir ; chama a rotina de traducao .... ; aqui W contem o codigo ASCII .... ; faz alguma coisa com W .... .... traduzir movwf copia ; salva uma copia do Scan Code movlw UPPER(scancodes_table) ; endereco UPPER da tabela de Scan Code movwf TBLPTRU ; carrega indexador movlw HIGH(scancodes_table) ; endereco HIGH da tabela de Scan Code movwf TBLPTRH ; carrega indexador movlw LOW(scancodes_table) ; endereco LOW da tabela de Scan Code movwf TBLPTRL ; carrega indexador movf copia, w ; recarrega o Scan Code addwf TBLPTRL, f ; soma o Scan Code na parte LOW do endereco btfss STATUS, C ; estouro??? goto leitura ; NAO --> vai pegar o ASCCI infsnz TBLPTRH, f ; SIM --> incrementa a parte HIGH do endereco incf TBLPTRU, f ; se estourar, incrementa a parte UPPER do endereco leitura tblrd *+ ; le a posicao calculada movf TABLAT, w ; pega o codigo ASCII lido naquela posicao return ; retorna ao chamador com o ASCII carregado em W .... .... ....


No exemplo acima, como a tabela de Scan Codes foi alocada na memória de programa (memória Flash) do microcontrolador, usa-se a instrução TBLRD para ler o conteúdo dessa memória. A instrução TBLRD pega um byte na posição de memória apontada pelos registradores TBLPTRx ,coloca o byte no registrador TABLAT e, em seguida, o registrador W é carregado com o valor desse registrador.




Enviando Comandos ao Teclado PS/2

Apesar de mais trabalhosa, a comunicação Host-PS/2 não é tão complicada como parece. A comunicação Host-PS/2 é usada quando se deseja enviar um comando para configurar o teclado e deve obedecer o protocolo ilustrado na Figura 4.


Clique na imagem para ver melhor
Figura 4

Primeiramente, o Host deve colocar o pino de Clock em nível baixo pelo menos por 100us (microsegundos).

A seguir, o Host deve colocar o pino Data em nível baixo e o pino Clock em nível alto (Input) para caracterizar o estado Request to Send. Lembrar que, para colocar um pino em estado alto, você deve torná-lo um pino de entrada, pois eles são do tipo coletor aberto.

Quando o PS/2 percebe esse estado, ele começa a gerar sinais de Clock.

Nesse momento, o Host deve começar a ler os sinais de Clock e colocar um bit de dado no pino Data quando o sinal de Clock estiver baixo (Clock=0). O PS/2 vai pegar o bit de dado do pino Data quando o sinal de Clock estiver alto (Clock=1).

O Host deve enviar ao PS/2 uma sequência de 8 bits de dados, onde cada bit deve ser colocado no pino Data quando o PS/2 fizer Clock=0. O sinal Clock=1 deve ser ignorado pelo Host; apenas deve ser lido a fim de sincronizar os ciclos.

Após enviar 8 bits de dados, o Host deverá enviar um Parity bit ao PS/2. O PS/2 sempre espera paridade impar, isto é, se nos 8 bits de dados enviados o número de dígitos 1 for par, o Parity bit deverá ser 1, caso contrário, deverá ser 0. Se isso não acontecer, haverá um erro na comunicação.

Após enviar o Parity bit, o pino Data deve ser colocado no modo de entrada (Input) e o PS/2 responderá com ACK, fazendo Data=0 e Clock=0.

Após receber Data=0, o Host deve tornar o pino Data e Clock como entrada novamente.

A seguir, o PS/2 enviará o código de retorno (response code) ao Host para confirmar se o comando foi aceito. Geralmente o response code é 0xFA, porém, isso não está representado no diagrama.

Abaixo podemos ver uma tabela dos comandos que podem ser enviados ao teclado PS/2. Essa tabela foi retirada de um site em inglês e teve uma tradução resumida.





Tabela de Comandos do Teclado PS/2


COMANDO FUNÇÃO DESCRIÇÃO
0xFF Reset PS/2 responde "ACK" (0xFA) e entra em dodo "RESET"
0xFE Resend PS/2 responde reenviando o byte enviado anteriormente.
0xFD * Set Key Type Make Desabilita Break Codes e repetição automática para as teclas especificadas. PS/2 responde "ACK" (0xFA), desabilita o escaneamento, se estiver habilitado, e lê a lista de teclas enviadas pelo Host. PS/2 responde "ACK" (0xFA) para cada tecla..
0xFC * Set Key Type Make/Break Semelhante ao comando anterior, exceto que este somente desabilita a repetição automática.
0xFB * Set Key Type Typematic Semelhante ao comando anterior, exceto que este somente desabilita os Break Codes.
0xFA * Set All Keys Typematic/Make/Break PS/2 responde "ACK" (0xFA). Recoloca todas as teclas em seu estado normal, isto é, reabilta os Make, Break e repetição automática.
0xF9 * Set All Keys Make PS/2 responde "ACK" (0xFA). Semelhante ao 0xFD, exceto que se aplica a todas as teclas.
0xF8 * Set All Keys Make/Break PS/2 responde "ACK" (0xFA). Semelhante ao 0xFC, exceto que se aplica a todas as teclas.
0xF7 * Set All Keys Typematic PS/2 responde "ACK" (0xFA). Semelhante ao 0xFB, exceto que se aplica a todas as teclas.
0xF6 Set Default Carrega o delay da taxa de repetição automática (10.9cps / 500ms), tipos de teclas e habilita Scan Codes do grupo 2.
0xF5 Disable Encerra o escaneamento do teclado, carrega valores defaults (ver comando "Set Default"), e aguarda novas instruções.
0xF4 Enable Reabilita o teclado após a desabilitação feita pelo comando "Disable" (0xF5).
0xF3 Set Typematic Rate/Delay O Host deve seguir este comando com um argumento que define a taxa de repetição e o retardo como descrito abaixo:
Repeat Rate
Bits 0-4
Rate(cps)
 
Bits 0-4
Rate(cps)
 
Bits 0-4
Rate(cps)
 
Bits 0-4
Rate(cps)
00h
30.0
 
08h
15.0
 
10h
7.5
 
18h
3.7
01h
26.7
 
09h
13.3
 
11h
6.7
 
19h
3.3
02h
24.0
 
0Ah
12.0
 
12h
6.0
 
1Ah
3.0
03h
21.8
 
0Bh
10.9
 
13h
5.5
 
1Bh
2.7
04h
20.7
 
0Ch
10.0
 
14h
5.0
 
1Ch
2.5
05h
18.5
 
0Dh
9.2
 
15h
4.6
 
1Dh
2.3
06h
17.1
 
0Eh
8.6
 
16h
4.3
 
1Eh
2.1
07h
16.0
 
0Fh
8.0
 
17h
4.0
 
1Fh
2.0

Delay

Bits 5-6
Delay (seconds)
00b
0.25
01b
0.50
10b
0.75
11b
1.00
0xF2 * Read ID) O PS/2 responde enviando um device ID de dois bytes com 0xAB, 0x83. (0xAB é enviado primeiro, seguido de 0x83.).
0xF0 * Set Scan Code Set PS/2 responde "ACK" (0xFA) e, então, le o byte de argumento enviado pelo Host. O byte de argumento pode ser 0x01, 0x02, or 0x03 para selecionar o grupo de Scan Codes 1, 2 ou 3, respectivamente. PS/2 responde a esse argumento "ACK" (0xFA). Se o argumento for 0x00, o PS/2 responde "ACK" (0xFA) seguido do grupo de Scan Codes corrente.
0xEE Echo O PS/2 responde "Echo" (0xEE).
0xED Set/Reset LEDs O Host segue este comando com um byte de argumento que especifica o estado dos LEDs "Num Lock", "Caps Lock", e" Scroll Lock". Esse argumento é definido como:
MSB LSB
Sempre 0 Sempre 0 Sempre 0 Sempre 0 Sempre 0 Caps Lock Num Lock Scroll Lock
Onde "Caps Lock", "Num Lock", "Scroll Lock" representam os estados de cada LED, sendo 0 apagado ou 1 aceso.
  *    Somente teclado PS/2




Driver para Teclado PS/2

Para facilitar a conexão e a comunicação entre um Host e um teclado PS/2, desenvolvemos um driver com funções que permitem ler as teclas e enviar comandos ao teclado. O driver foi escrito em linguagem Assembler para microcontroladores PIC da família 18F mas pode ser adaptado para outros chips.

Antes de explicar o funcionamento do driver, devemos alertar que ele usa uma função de temporização interna, fornecida pelo módulo delay_service.inc, cujo fonte se encontra na pasta do projeto. O módulo delay_service.inc deve ser configurado no programa com segue:

delay_temp RES 1 ; registrador de trabalho CLOCK equ 20000000 ; frequencia de clock do PIC

Onde o registrador "delay_temp" é apenas um registrador de trabalho e "CLOCK" é um símbolo que informa qual a frequência de clock usada pelo microcontrolador. Isso torna o driver independente da frequência de clock selecionada, e faz com que o programador possa selecionar qualquer frequência de clock para o projeto, porém, aconselho não usar frequências muito baixas como 4MHZ.

O microcontrolador escolhido para o projeto do driver, e do programa de teste, foi o PIC18F4520. O projeto foi desenvolvido no MPLAB da Microchip.

O projeto completo pode ser obtido baixando o arquivo TECLADO_PS2_v07.zip.

Descomprima o arquivo TECLADO_PS2_v07.zip no HD para gerar a pasta TECLADO_PS2_v07, que contem o projeto com todos os arquivos necessários para compilá-lo. Entre na pasta TECLADO_PS2_v07 e clique duas vezes sobre o arquivo ps2kdb.mcp para abrir o projeto no MPLAB.

O programa teclado.asm é o programa principal, que é usado para testar o driver do teclado PS/2.

O driver, propriamente dito, é o módulo ps2keyboard_18f_services.inc cujo fonte é fornecido no diretório do projeto. Esse módulo é o responsável por executar as funções de acesso ao teclado e possui as funções descritas na tabela abaixo.


Tabela de Funções do Driver do Teclado PS/2



FUNÇÃO DESCRIÇÃO

ps2kbd_init Configura registradores e as portas DATA e CLOCK para a comunicação com o dispositivo PS2. Entrada: Não há Saida : DATA=1, CLOCK=0 e flags=0

ps2kbd_read Le o Scan Code da tecla pressionada num teclado PS2/DIN5 e devolve o caracter ASCII mapeado para o respectivo Scan Code. Entrada: Não há Saida : W = conterá o caracter ASCII mapeado para o Scan Code referente a tecla pressionada.

ps2kbd_trans Traduz um Scan Code no seu caracter correspondente. Entrada: W contem o Scan Code Saida : W conterá o caracter ASCII correspondente ao Scan Code

ps2kbd_getscan Retorna o Scan Code de uma tecla. Para traduzir o Scan Code em seu caracter ASCII, use a função "ps2kbd_trans". Entrada: Não há Saida : W conterá o Scan Code da tecla pressionada.

ps2kbd_cmd Envia um comando para o teclado. Entrada: W contem o dado Saida : Não há

ps2kbd_req2send Coloca o dispositivo PS2 no estado "request to send" para o Host enviar comandos. Entrada: Não há Saida : Não há

ps2kbd_getresp Le o código de retorno de um comando enviado ao teclado. Entrada: Não há Saida : W conterá o código de retorno

ps2kbd_reset Reset do teclado. Entrada: Não há Saida : W = 0xFA --> reset bem sucedido

ps2kbd_echo Pede um eco ao teclado Entrada: Não há Saida : W = 0xEE --> eco bem sucedido

ps2kbd_ledson Acende o LED identificado pelo valor do registrador W. Entrada: W contem a identificação do LED a ser aceso: ps2_SCRLKBIT.......... SCROLL LOCK ps2_NUMLKBIT.......... NUM LOCK BIT ps2_CAPSLKBIT......... CAPS LOCK BI Saida : W conterá o return code do teclado: W=0xFA --> OK

ps2kbd_ledsoff Apaga o LED identificado pelo valor do registrador W. Entrada: W contem a identificação do LED a ser apagado ps2_SCRLKBIT.......... SCROLL LOCK ps2_NUMLKBIT.......... NUM LOCK BIT ps2_CAPSLKBIT......... CAPS LOCK BIT
Saida : W conterá o return code do teclado: W=0xFA --> OK




Como o Driver Funciona

Para poder se comunicar com o teclado, o driver ps2keyboard_18f_services.inc usa alguns alguns símbolos e registradores de controle, que devem ser configurados pelo programador na memória RAM do microcontrolador, onde são configuradas as portas de I/O para os pinos Data e Clock.


UDATA 0x80 ps2kbdTRIS equ TRISA ; I/O do teclado ps2kbdLAT equ LATA ; Latch do teclado ps2kbdPORT equ PORTA ; Porta do teclaco ps2kbdDATA equ 2 ; bit data ps2kbdCLOCK equ 3 ; bit clock ps2flags res 1 ; flags do servico ps2caps equ 0 ; caps bit --> b'00000000'=OFF b'00000001'=ON ps2capsmsk equ 1 ; mascara ---> b'00000001' ps2ct res 1 ; contador de bits ps2cpy res 1 ; ps2r1 res 1 ; ps2r2 res 1 ; ps2ledslat res 1 ; latch dos LEDs do teclado ps2buff res 3 ; buffer de leitura


Onde:

 ps2kbdTRIS   é o registrador de configuração de I/O que indica se um bit da porta é entrada ou saída.
 ps2kbdLAT   é o Latch da porta selecionada.
 ps2kbdPORT   é o nome da porta selecionada.
 ps2kbdDATA   é o bit Data selecionado na porta para receber ou enviar dados.
 ps2kbdCLOCK   é o bit Clock selecionado na porta para receber os sinais de Clock.


O arquivo que contem o driver deve ser incluido na sessão de programa. O driver deve ser incluido no início do programa, pois contem a macro instrução onkey, que pode ser usada pelo programador a fim de testar o caracter lido no teclado. Se o programador não desejar usar essa macro, o driver pode ser incluido em qualquer posição do programa, lembrando que ele funciona como uma subrotina e usa a instrução RETURN para voltar ao chamador.

MAIN CODE #include <ps2keyboard_18f_services.inc> ; inclusao do driver


Agora que o driver esta carregado, ele deve ser inicializado, para que os registradores e as portas de I/O sejam configurados com valores iniciais. A inicialização do driver é feita com uma chamada à função ps2kbd_init .

call ps2kbd_init ; inicializa o driver

Nesse momento, o teclado deve estar pronto para funcionar e, para ter certeza, pode-se fazer uma chamada à função ps2kbd_echo que, no caso do teclado estar funcionando corretamente, retornará, no registrador W, o valor 0xEE. Exemplo:

call ps2kbd_echo ; pede para o teclado ecoar xorlw 0xEE ; verifica o eco btfss STATUS, Z ; teclado respondeu o eco??? goto erro ; NAO --> erro .... ; SIM --> continua aqui .... ....

Após ter certeza que o teclado está funcionando corretamente, podemos ler uma tecla usando a função ps2kbd_read que retornará, no registrador W, o código ASCII do caracter da tecla pressionada. Ao entrar na função ps2kbd_read, ela fica esperando que o operador pressione uma tecla. Exemplo:

call ps2kbd_read ; leitura o teclado movwf letra ; salva o caracter .... ; continua...

Uma vez obtido o caracter no teclado, podemos usar a macro onkey para verificar esse caracter. A macro onkey espera que o caracter obtido tenha sido salvo num registrador. No trecho de programa abaixo, temos um exemplo onde a macro onkey compara um caracteres carregados em W com o caracter lido no teclado, (salvo "letra").
No primeiro teste, se a comparação resultar igual, a macro desvia para a localização "apagalcd", senão, a instrução seguinte será executada.
No segundo teste, se a comparação resultar igual, a macro desvia para a localização zero da memória, provocando o reset do microcontrolador (reboot), senão, a instrução seguinte será executada.


UDATA 0x80 ; .... ; .... ; letra res 1 ; registrador de trabalho .... ; .... ; MAIN CODE #include "ps2keyboard_18f_services.inc" .... .... ; inicio call ps2kbd_init ; configura o PS/2 .... ; .... ; readps2 call ps2kbd_read ; leitura o teclado movwf letra ; salva o caracter teste1 movlw "k" ; W="k" --> caracter esperado onkey letra, apagalcd ; se o registrador "letra" contem "k", vai para "apagalcd" ; teste2 movlw "r" ; W="r" --> caracter esperado onkey letra, 0x0000 ; se o registrador "letra" contem "r", reset no PIC ; .... ; .... ; apagalcd call SR_LCDCLEAR ; apaga o LCD goto readps2 ; .... ; .... ; END ;





Velocidade de Repetição do Teclado


Como o teclado envia um Make Code quando uma tecla é pressionada, e um Break Code quando a tecla é liberada, o driver usa um artifício para não responder ao envio do Break Code, pois isso ocorre num tempo que varia de acordo com a velocidade de digitação e acarreta a repetição da leitura. Para conseguir evitar o rebote da rotina de leitura, um retardo de tempo é inserido no final desta, esperando que o operador libere a tecla antes que esse tempo se esgote.

O tempo de retardo, em milisegundos, é controlado pelo símbolo ps2_brkdelay, definido dentro do fonte do driver e seu valor default é 100ms. Se for necessário, o programador pode aumentar ou diminuir esse tempo para conseguir o efeito desejado, porém, tempos muito curtos podem produzir repetições indesejadas na leitura.



Símbolos para as Teclas de funções


A tabela abaixo mostra o mapeamento das teclas de funções onde os símbolos, iniciados por   "_",  podem ser usados no programa para identificá-las.


 Símbolo   Mapa   Scan Code   Tecla 
_ESC 0x1B 0x76 Escape
_F1 0x05 0x05 F1
_F2 0x06 0x06 F2
_F3 0x04 0x04 F3
_F4 0x0C 0x0C F4
_F5 0x03 0x03 F5
_F6 0x0B 0x0B F6
_F7 0x83 0x83 F7
_F8 0x0A 0x0A F8
_F9 0x01 0x01 F9
_F10 0x09 0x09 F10
_F11 0x78 0x78 F11
_F1 0x07 0x07 F12
_SYSREQ 0x96 0x7C Print/Screen/SysRq
_SCROLLK 0x95 0x7E SCROLL LOCK
_PAUSEBRK 0x94 0x77 PAUSE/BREAK
_TAB 0x90 0x0D TAB
_BKSP 0x93 0x66 BACKSPACE
_CAPSLOCK 0x58 0x58 CAPS LOCK
_SHIFTL 0x12 0x12 SHIFT do lado esquerdo
_SHIFTR 0x59 0x59 SHIFT do lado direito
_CTRL_L 0x14 0x14 CTRL do lado esquerdo
_WIN 0x1F 0x1F Windows
_AL 0x11 0x11 ALT
_ALTGR 0x11 0x11 ALTGR
_MENU 0x2F 0x2F MENU
_CTRL_R 0x14 0x14 CTRL do lado direito
_HOME 0x97 0x6C HOME
_END 0x98 0x69 END
_INSERT 0x99 0x70 INSERT
_PAGEUP 0x9A 0x7D PAGE UP
_DEL 0x9B 0x71 DELETE
_PAGEDN 0x9C 0x7A PAGE DOWN
_UP 0x9D 0x75 ARROW UP
_RIGHT 0x9E 0x74 ARROW RIGHT
_DOWN 0x9F 0x72 ARROW DOWN
_LEFT 0xA0 0x6B ARROW LEFT
_NUMLOCK 0xB0 0x77 NUM LOCK




Símbolos para Controle dos LEDs do Teclado


O teclado possui três LEDs que podem ser controlados pelas funções ps2kbd_ledson e ps2kbdledsoff do driver. São eles: Caps Lock, Num Lock e Scroll Lock. A tabela abaixo contem os símbolos definidos dentro do código fonte do driver, e que podem ser usados pelo programador.


 Símbolo   Bitmap   LED 
ps2_SCRLKBIT b'00000001' SCROLL LOCK
ps2_NUMLKBIT b'00000010' NUM LOCK
ps2_CAPSLKBIT b'00000100' CAPS LOCK

Exemplo:

movlw ps2_SCRLKBIT ; LED Scroll Lock call ps2kdb_ledson ; acende LED Scroll Lock movlw ps2_CAPSLKBIT ; LED Caps Lock call ps2kbd_ledsoff ; apaga LED Caps Lock .... ....






Programa de Teste

O projeto do programa de teste usa um LCD serial descrito em  Interface para LCD HD44780 com 2 fios , cujo módulo de controle, lcd_services.inc, escrito em linguagem Assembler, também se encontra no diretório deste projeto de teclado PS/2 para sua apreciação. O módulo lcd_services.inc também usa a função de temporização delay_services.inc, o que o torna independente da frequência de clock selecionada para o projeto.

Do modo como é fornecido, o hardware do projeto requer configuração mínima para funcionar, necessitando um microcontrolador PIC18F4520, com clock externo a cristal de 20MHz, um LCD de 2 linhas por 16 colunas, e um teclado PS/2.

A comunicação com o teclado será configurada com o Clock no PORTA<3> e Data no PORTA<2>.

O LCD terá o pino Clock em PORTB<3> e o pino Data em PORTB<4>.

O projeto já foi compilado com a configuração acima e o arquivo binário ps2kbd.hex pode ser gravado diretamente no seu microcontrolador mas, se desejar, altere o projeto segundo suas necessidades.

Ao ligar o circuito, o programa piscará rapidamente todos os LEDs do teclado e, ao mesmo tempo, mostrará as mensagens "TECLADO PS2 v1.1" e "Teclado OK!!!" no LCD. Após um segundo, o LCD será apagado e o programa vai esperar alguma tecla ser pressionada. Se qualquer tecla de caracter (a-z / 0-9) for pressionada, o seu valor será mostrado no LCD, uma após outra. Se uma das teclas de funções, definidas na tabela abaixo, for pressionada, a função, definida no programa para a respectiva tecla, será executada.

TECLA FUNÇÃO DA TECLA
 Cap Lock   Trava/destrava o teclado em maiusculas/minusculas. 
 Del   Apaga o LCD. 
 F1   Habilita/Desabilita funcao de leitura de Scan Codes. 
 F12   Pisca todos os LEDs do teclado. 
 BackSpace   Retrocede o cursor do LCD apagando o caracter sobre ele. 
 Home   Move o cursor para a coluna 1 da linha 1. 
 End   Move o cursor para o fim da linha corrente. 
 Seta a direita   Move o cursor para a proxima coluna. 
 Seta a esquerda   Move o cursor para a coluna anterior. 
 Seta para baixo   Move o cursor para a proxima linha. 
 Seta para cima   Move o cursor para a linha anterior. 
 Print/Screen/Sys Rq   Reboot no microcontrolador. 



Conclusão

Espero que essa matéria possa ajudar na programação de funções para teclados PS/2 conectados a microcontroladores PIC. Para ir mais a fundo no assunto, aconselho a abrir o arquivo fonte ps2keyboard_18f_services.inc para observar mais atentamente seu funcionamento.

Topo da Página








Índice dos circuitos




H P S P I N

Desde 04 de Março de 2010

Atualização: 19 de Mar de 2024