TECLADO MATRICIAL - Página 1/8
PROGRAMAÇÃO C PARA MICROCONTROLADORES 8051 E PIC PALAVRAS-CHAVE Microcontrolador 8051, Microcontrolador PIC 16F877A, Teclado matricial, multiplexação, vetor, array.
UNIDADE DE ESTUDOS:
TECLADO MATRICIAL Nesta unidade de estudos vamos explorar o funcionamento e a
aplicação do teclado matricial amplamente encontrado em
sistemas e equipamentos eletrônicos, tais como: telefones,
alarmes, elevadores e uma ampla variedade de aplicações. Este
componente tem como finalidade servir de entrada de dados
do usuário para que o sistema realize determinada ação.
Em se tratando de sistema de autenticação de senhas, por
exemplo, atualmente existem alternativas inovadoras, tais como:
impressão digital, rfID, reconhecimento facial e você lida com
essas tecnologias diariamente. Um bom motivo para utilizar o
teclado matricial é essencialmente o custo de implementação
que pode significar dezenas de vezes abaixo da autenticação
por impressão digital.
METODOLOGIA Será analisado o funcionamento do teclado matricial de modo
a implementar um algoritmo de leitura de cada tecla através da
programação. Para a entrada de uma senha vários dígitos,
estudaremos as variáveis indexadas (vetores) para armazenar as
entradas do usuário e processar as informações digitadas.
A abordagem desta unidade de estudos utiliza a programação
C para o microcontrolador AT89S52, da família MCS-51 ou
popularmente chamada de “8051” de modo que as informações
inseridas no teclado sejam exibidas em display LCD 16x2. Depois
a atividade é revista com a programação C para o
microcontrolador PIC16F877A da família PIC 16F.
RECURSOS Para desenvolver e experimentar este material é necessário um
computador ou notebook com sistema operacional Windows ou
posterior e baixar o pacote de programas disponível em
www.u8051.com.br o qual contém as seguintes ferramentas de
desenvolvimento: Compilador 8051, Compilador PIC, Software
de simulação Proteus-ISIS.
AVALIAÇÃO DE DESEMPENHO A secção ATIVIDADES PROPOSTAS apresenta um conjunto de
exercícios de dificuldade incremental a fim de avaliar o seu
entendimento a cerca desta unidade de estudos.
RESULTADOS ESPERADOS Ao concluir o desenvolvimento das atividades propostas, você
deverá ser capaz de utilizar teclados matriciais com maior ou
menor número de teclas, bem como adaptar o código fonte C
para outros modelos de microcontroladores.
TECLADO MATRICIAL - Página 2/8
Fig. 8: Coluna 1
Fig. 9: Coluna 2
Fig. 10: Teclado 4x4
Fig. 10: Teclado 4x4
TECLADO MATRICIAL COM AT89S52 Os teclados matriciais são geralmente utilizados em projetos
nos quais o usuário precisa interagir com o sistema, como
computadores, calculadoras, senhas acesso, de atendimento e
de acesso às centrais de alarme, etc. Para este estudo vamos
considerar um teclado 4x3 conforme as figuras abaixo.
Figura 1: Teclado matricial 4x3 ; Fig. 2: Conexão das Linhas; Fig. 3: Conexão das Colunas
Observe que temos 12 botões, mas apenas 7 conexões. Isto por
que os botões estão organizados em linhas e colunas de modo
a formar uma matriz, daí o termo matricial.
Ao pressionar o botão, uma
coluna é conectada com uma
linha gerando uma combinação
única de coluna-linha.
Por exemplo, na figura 4 (ao
lado) ao pressionar o botão “1”
ocorre a união da coluna 1 e
linha 1.
Figura 4: Esquema do Teclado matricial 4x3
Tanto linhas quanto colunas são conectadas diretamente ao PORT do microcontrolador, define-se as colunas como saída e as linhas como entrada de dados. Após essa configuração no microcontrolador, a corrente em nível lógico 0 de um I/O “derruba” a corrente em nível 1 de outro I/O.
VERIFICANDO A COLUNA 1
Define-se a coluna 1 em nível lógico baixo (0) e as demais colunas em nível alto (1);
Em seguida, deve-se ler cada I/O conectado na coluna 1, que são os botões 1, 4, 7, *.
Figura 5: Definindo Linhas como entradas (em 1) e ativando apenas coluna 1 (em 0)
Ao pressionar algum desses botões, o nível 0 desta coluna derrubará o nível 1 da linha cujo botão estiver pressionado. Então, se alguma linha estiver em nível baixo, é aí que encontramos a tecla pressionada!
ESQUEMÁTICO 8051 Considere em nosso estudo o esquema da figura abaixo.
Você encontrará esta simulação na pasta C:\8051\ISIS77\EXEMPLOS\8051_TECLADO_MATRICIAL_COM_LCD.DSN
Este esquema foi desenhado no software Proteus-ISIS versão 7 ou posterior utilizando os seguintes componentes:
Referência Componente AT89C52 Microcontrolador AT89C52 KEYPAD-PHONE Teclado Matricial LM016L Display LCD 16x2
Uma versão portátil deste simulador pode ser executada a partir da pasta 8051\ISIS77\BIN\ISIS.EXE
Figura 7: Executando o Simulador ISIS
PROGRAMAÇÃO A seguir temos a programação para ler as colunas 1 e 2 do teclado matricial. Ao identificar a linha em nível baixo, é atribuído o respectivo valor à variável char tecla.
#include<at89x52.h>
#include<lcd.h>
#define IO_COLUNA1 P1_0
#define IO_COLUNA2 P1_1
#define IO_COLUNA3 P1_2
#define IO_LINHA1 P1_4
#define IO_LINHA2 P1_5
#define IO_LINHA3 P1_6
#define IO_LINHA4 P1_7
char tecla=' ';
void main()
{
lcd_init(); //Inicializa LCD e limpa tela
//Define linhas como entradas
IO_LINHA1=1;
IO_LINHA2=1;
IO_LINHA3=1;
IO_LINHA4=1;
while(1)
{ tecla=' ';
//Ativando coluna 1
IO_COLUNA1=0;
IO_COLUNA2=1;
IO_COLUNA3=1;
//Verificando teclas da coluna 1
if(IO_LINHA1==0) tecla='1';
if(IO_LINHA2==0) tecla='4';
if(IO_LINHA3==0) tecla='7';
if(IO_LINHA4==0) tecla='*';
//Ativando coluna 2
IO_COLUNA1=1;
IO_COLUNA2=0;
IO_COLUNA3=1;
//Verificando teclas da coluna 2
if(IO_LINHA1==0) tecla='2';
if(IO_LINHA2==0) tecla='5';
if(IO_LINHA3==0) tecla='8';
if(IO_LINHA4==0) tecla='0';
//Exibe tecla pressionada
if(tecla!=' '){
lcd_gotoxy(1,1);
lcd_putchar(tecla);
}
}
} Observe o código-fonte C acima: Coloca-se em nível baixo uma única coluna e realiza-se a leitura de cada uma as quatro linhas, para determinar qual tecla foi pressionada.
Em seguida, aplica-se nível 0 em outra coluna e repete-se a leitura de cada linha.
Por isso você deve ser capaz de ler o teclado completamente, inclusive um teclado 4x4 como o modelo KEYPAD-SMALLCALC (figura ao lado).
0 1 1
1
1
1
1
Col1 Col2 Col3
Lin1
Lin2
Lin3
Lin4
Lin1
Lin2
Lin3
Lin4
Col1 Col2 Col3
Linha1
Linha2
Linha3
Linha4 Fig. 6: Microcontrolador 8051 com teclado matricial 4x3 e LCD 16x2
TECLADO MATRICIAL - Página 3/8
Programa 1
Programa 2
O COMANDO #define As definições #define facilitam a compreensão e as alterações
futuras do código-fonte C e ficam alocadas na memória ROM
(memória de programa) não ocupando o escasso espaço RAM
reservado para as variáveis. Durante a compilação o compilador
substitui todas as definições pelos respectivos significados
#define.
Considere a definição: #define IO_COLUNA1 P1_0
Podemos então escrever o identificador IO_COLUNA1 invés de
P1_0, pois por definição são eles equivalentes.
Atualmente existem outras formas de validar senhas de
acesso, tais como rfid e biometria, por exemplo.
Entretanto, o baixo custo de implementação com teclado
matricial pode ser um diferencial para a viabilidade de
novos projetos.
O TIPO DE DADO bit e int1
O tipo int1 é um dado booleano que suporta apenas os valores
0 e 1 e equivale ao tipo de dado bit do 8051. As variáveis
booleanas bit e int1 são frequentemente utilizadas para
sinalizar a ocorrência de eventos. Mesmo que o evento tenha
terminado, é possível saber se ele já aconteceu verificando o
valor dessas variáveis. Variáveis do tipo bit (no 8051) e int1 (no
PIC) ocupam apenas 1 bit da memória RAM do
microcontrolador, enquanto o tipo char ocupa 8 vezes mais e o
tipo int ocupa 16 vezes o espaço de 1 bit.
APRIMORANDO A LEITURA Se você remover a instrução lcd_gotoxy(1,1) perceberá que a varredura de leitura do teclado ocorre centenas de vezes por segundo. Se estiver digitando uma senha, até mesmo um curto clique na tecla preencherá todos os dígitos da senha com o mesmo digito. A solução é identificar cada evento pressionar-e-soltar a tecla para evitar a repetição.
No exemplo a seguir, as variáveis b1 e b2 registram o instante em que os botões “1” ou “4” são pressionados. Por exemplo, quando a tecla em IO_LINHA1 é pressionada, a variável char tecla recebe ‘1’ e b1 recebe 1. Não importa agora que a tecla ainda esteja pressionada, pois o teste b1==0 é falso e não ocorre mais a repetição. Porém, ao soltar esta tecla, a variável b1 retorna a 0, podendo então, registrar um novo clique. Esta mesma lógica ocorre na tecla “4”.
#include<at89x52.h> #include<lcd.h> #define IO_COLUNA1 P1_0 #define IO_COLUNA2 P1_1 #define IO_COLUNA3 P1_2 #define IO_LINHA1 P1_4 #define IO_LINHA2 P1_5 #define IO_LINHA3 P1_6 #define IO_LINHA4 P1_7 char tecla=' '; bit b1, b2; void main(){ //Define linhas como entradas IO_LINHA1=1; IO_LINHA2=1; IO_LINHA3=1; IO_LINHA4=1; lcd_init(); while(1){ tecla=' '; //Ativa coluna 1 IO_COLUNA1=0; IO_COLUNA2=1; IO_COLUNA3=1; //Verificando clique na tecla 1 ************ if(IO_LINHA1==0 && b1==0) { tecla='1'; b1=1; //impede a repetição } if(IO_LINHA1==1) b1=0; //soltou a tecla //Verificando clique na tecla 4 ************ if(IO_LINHA2==0 && b2==0) { tecla='4'; b2=1; //impede a repetição } if(IO_LINHA2==1) b2=0; //soltou a tecla //Se foi pressionada alguma tecla, exibe if(tecla!=' ') lcd_putchar(tecla); } }
Considere que o código fonte acima implementa apenas a
leitura das teclas “1” e “4” do teclado matricial. Criando um total
de 12 variáveis booleanas, como por exemplo b1 até b12 você
deve ser capaz de construir a leitura completa do teclado
identificando o pressionar-e-soltar de cada tecla.
CRIANDO UMA FUNÇÃO PARA LEITURA DO TECLADO MATRICIAL A leitura de teclas é uma tarefa que você pode querer reutilizar
em várias situações no programa, como por exemplo: digitar
uma senha ou altera-la; digitar um código secreto de ajustes,
etc. Por isso, o próximo código-fonte implementa a função
keypad.
Considere também que apenas a leitura das teclas 1 e 4 foram
aqui construídas (mas você já sabe como programar a leitura de
todo o teclado), por isso, o programa testa a entrada da senha
correta contendo 3 dígitos: “141”
#include<at89x52.h>
#include<lcd.h>
#include<delay.h>
#define IO_COLUNA1 P1_0
#define IO_COLUNA2 P1_1
#define IO_COLUNA3 P1_2
#define IO_LINHA1 P1_4
#define IO_LINHA2 P1_5
#define IO_LINHA3 P1_6
#define IO_LINHA4 P1_7
#define TAM_SENHA 3
char tecla=' ';
bit b1, b2;
char valorDigitado[TAM_SENHA]= {' ',' ',' '}; char senha[TAM_SENHA]= {'1','4','1'}; //senha pre-def
char indice=0;
char keypad(); //protótipo da funcao
void main()
{
//Define linhas como entradas
IO_LINHA1=1;
IO_LINHA2=1;
IO_LINHA3=1;
IO_LINHA4=1;
lcd_init();
while(1)
{
tecla=keypad(); //executa funcao keypad
if(tecla!=' ') //se pressionou tecla
{
valorDigitado[indice]=tecla;
indice++;
lcd_gotoxy(1,1);
lcd_putchar(valorDigitado[0]);
lcd_putchar(valorDigitado[1]);
lcd_putchar(valorDigitado[2]);
if(indice==TAM_SENHA)
{
if( valorDigitado[0]==senha[0] &&
valorDigitado[1]==senha[1] &&
valorDigitado[2]==senha[2])
{
lcd_gotoxy(2,1);
lcd_puts("Senha Correta");
}
else
{
lcd_gotoxy(2,1);
lcd_puts("Senha Invalida");
}
delay_ms(1000); //espera 1 seg
lcd_init(); //limpa LCD
valorDigitado[0]=' ';
valorDigitado[1]=' ';
valorDigitado[2]=' ';
indice=0;
}
}
}
}
//******************************************
TECLADO MATRICIAL - Página 4/8
valorDigitado[0]
valorDigitado[1]
valorDigitado[2]
senha[0]
senha[1]
senha[2]
if( valorDigitado[0]==senha[0] &&
valorDigitado[1]==senha[1] &&
valorDigitado[2]==senha[2])
{
lcd_gotoxy(2,1);
lcd_puts("Senha Correta");
}
else{
lcd_gotoxy(2,1);
lcd_puts("Senha Invalida");
}
char keypad() //funcao keypad
{
tecla=' ';
//Ativa coluna 1
IO_COLUNA1=0;
IO_COLUNA2=1;
IO_COLUNA3=1;
if(IO_LINHA1==0 && b1==0)
{
tecla='1';
b1=1; //impede a repetição
}
if(IO_LINHA1==1) b1=0; //soltou a tecla
if(IO_LINHA2==0 && b2==0)
{
tecla='4';
b2=1; //impede a repetição
}
if(IO_LINHA2==1) b2=0; //soltou a tecla
return tecla; //Retorna a tecla pressionada
}
A definição TAM_SENHA especifica tamanho do vetor, bem
como o número de caracteres que irá armazenar. Por isso, você
deve ser capaz de criar uma senha de 4 ou mais dígitos por
exemplo.
Além disso, você deve ser capaz de adicionar o código secreto
#44 que exibe a senha padrão, e também permitir um limite de
3 tentativas para digitar a senha correta antes de exibir a
mensagem “Bloqueado”.
VETORES EM C Neste tópico vamos conhecer o uso de vetores ou arrays
(matrizes) em C no contexto em que foi apresentado no
programa anterior. Se você deseja aprofundar seu
entendimento acerca de vetores, recomendo que este tópico
seja considerado apenas o seu ponto de partida.
Um vetor é uma variável indexada, ou seja, comporta várias
informações do tipo de dado em que o vetor é declarado.
Considere a seguinte declaração:
#define TAM_SENHA 3
char valorDigitado[TAM_SENHA]= {' ',' ',' '}; char senha[TAM_SENHA]={'1','4','1'};
O vetor valorDigitado têm 3 índices e
cada índice armazena um dado do tipo
char. Assim temos que o vetor tenha os
seguintes índices ao lado.
Além disso, ao vetor foi atribuído uma sequência de 3 espaços
dentro de aspas simples. Cada índice recebeu um espaço, ou
seja, o vetor está “em branco”:
valorDigitado[0]=' ';
valorDigitado[1]=' '; valorDigitado[2]=' ';
O vetor senha também têm 3 índices que
armazenam dados do tipo char. Assim temos
os seguintes índices:
Para este vetor foi atribuído a sequência “411” de modo que o
vetor esteja com os seguintes dados:
senha[0]='4';
senha[1]='1';
senha[2]='1';
As variáveis indexadas foram disponibilizadas na programação
com o propósito de armazenar uma determinada quantidade de
valores do mesmo tipo. Esses dados armazenados no vetor são
denominados itens do vetor.
Podemos então analisar o seguinte trecho de código.
if(tecla!=' ') //se pressionou tecla
{
valorDigitado[indice]=tecla;
indice++;
if(indice==3)
{
//compara valorDigitado e senha
}
}
Considere a variável índice começando em zero. Quando a tecla
for pressionada pela primeira vez, o vetor valorDigitado[0]
receberá o valor de tecla. Depois, índice valerá 1. Quando uma
tecla for pressionada novamente, valorDigitado[1] receberá o
valor de tecla. Então índice valerá 2. Finalmente ao terceiro
clique, valorDigitado[2] receberá o valor de tecla. Indice receberá
3, então a senha está completa e é realizada a comparação.
Se for digitado “411” teremos os seguintes itens nos vetores: Digitado no teclado Pré-definido
valorDigitado[0]='4'; senha[0]='4';
valorDigitado[1]='1'; senha[1]='1';
valorDigitado[2]='1'; senha[2]='1';
Comparando os
itens de um vetor
com os do outro é
possível validar se
cada valor
armazenado é igual
ou diferente,
conforme o trecho
de código ao lado.
Você deve interpretar a validação da seguinte forma:
Se o dígito armazenado em valorDigitado[0] for igual ao dígito
pré-definido em senha[0] “e” se o dígito em valorDigitado[1]
for igual pré-definido em senha[1] “e” se dígito armazenado
em valorDigitado[2] for igual à senha[2].
O duplo operador relacional &&, “E” (And) impõe que todas as
condições devem ser verdadeiras para a execução do if. Se
qualquer teste resultar falso, então o bloco else é executado.
Depois de tratar as informações atribuídas à cada índice do
vetor valorDigitado, este deve ser “esvaziado” para receber
uma nova tentativa de acesso, partindo do índice zero,
novamente. Por isso, temos o seguinte trecho em C:
valorDigitado[0]=' ';
valorDigitado[1]=' ';
valorDigitado[2]=' ';
indice=0;
EXIBINDO VETORES NO LCD (8051)
Para exibir todo o conteúdo de um vetor em display LCD,
utiliza-se a função lcd_puts passando como parâmetro o nome
do vetor sem o índice. O exemplo a seguir exibe o vetor senha.
#include<at89x52.h>
#include<lcd.h>
#define TAM_SENHA 3
char senha[TAM_SENHA]= {'1','4','1'};
void main()
{ lcd_init();
lcd_puts(senha);
}
TECLADO MATRICIAL - Página 5/8
Os compiladores C geralmente oferecem a biblioteca strings.h
a qual implementa diversas funções de manipulação de
variáveis indexadas (strings). Por exemplo, a função strcmp
compara o valor de duas strings e retorna se não iguais,
diferentes, maior ou menor. Nesta atividade você analisou
como comparar duas variáveis indexadas e testar se são iguais
ou diferentes aplicando os comandos que servirão em
qualquer compilador C, como também para qualquer
microcontrolador já criado.
ATIVIDADES PROPOSTAS
1 Desenhar o esquemático da figura 6 no software
simulador ISIS (ver em C:\8051\ISIS77\EXEMPLOS);
2 Digitar, compilar o programa 1 no software JFE;
3 Simular o programa 1 no software ISIS;
4 Ampliar a leitura de 2 para todas as teclas;
5 Digitar, compilar o programa 2 no software JFE;
6 Simular o programa 2 no software ISIS;
7 Ampliar a leitura de 2 para todas as teclas empregando
a lógica pressionar-e-soltar;
8 Exibir a mensagem de bloqueio após 3 tentativas
inválidas;
9 Estender a senha para 4 dígitos, sendo a “palavra-chave”
correta “2021”;
10 Reduzir a senha para 3 dígitos novamente;
11 Implementar o código secreto #44;
12 Utilizar o operador relacional Or invés de And para
comparar os vetores valorDigitado e senha.
13 Desafio supremo: Implementar o código secreto #11
que solicita a nova senha padrão, ou então, esse outro
desafio: Implementar a leitura completa do componente
KEYPAD-SMALLCALC (figura 10).
14 Discriminar pelo menos 5 sistemas que utilizam teclado
matricial;
TECLADO MATRICIAL COM PIC 16F877A Este tópico repete a lição da leitura do teclado matricial. No
entanto, o microcontrolador é o PIC16F877A. A diferença
central é que neste chip, ao definir as linhas do teclado como
entrada de dados, os respectivos I/O’s apresentam estado
lógico coletor aberto, que nesta aplicação você pode considerar
como “sem tensão” e que C interpreta como nível lógico 0.
VERIFICANDO A COLUNA 1
Define-se a coluna 1 em nível lógico alto (1) e as demais colunas em nível baixo (0);
Em seguida, deve-se ler cada I/O conectado na coluna 1, que são os botões 1, 4, 7, *.
Figura 11: Definindo Linhas como entradas (em 0) e ativando apenas coluna 1 (em 1)
Ao pressionar algum desses botões, o nível 1 desta coluna “subirá” o nível 0 da linha cujo botão estiver pressionado. Se alguma linha estiver em nível alto então encontramos a tecla pressionada!
OS COMANDOS #use fast_io( ) e set_tris( )
Por padrão os I/O’s do PIC estão configurados para entrada de
dados ou input. Quando necessitamos alterar essa configuração
padrão, para por exemplo, utilizar um ou mais I/O’s como saída
ou output, necessitamos incluir a diretiva #use_fast_io. Quando
o I/O é definido no modo input, este fica em coletor aberto ou
tristate, necessitando de resistores Pull-Up para definir o estado
lógico 1 destas entradas.
No PIC-C Compiler, o software de desenvolvimento do PIC que
utilizamos neste estudo reserva a função set_tris para que o
programador defina quais I/O’s serão utilizados como entrada
ou saída (input/output), sendo que o valor 0 define Output e 1
define Input.
A sintaxe de escrita da função set_tris é:
set_tris_D(valor);
valor é um binário literal que definirá quais I/O’s serão entrada e saída do respectivo PORT. O C reconhece como notação binária uma expressão iniciada por “0b”.
Considere os exemplos de uso da função set_tris:
set_tris_d(0b11110000);
I/O D7 D6 D5 D4 D3 D2 D1 D0 Val 1 1 1 1 0 0 0 0
Direção Entr Entr Entr Entr Saída Saída Saída Saída
Aqui os I/O’s D7, D6, D5 e D4 estão configurados como entrada enquanto D3, D2,DC1 e D0 são saídas de dados, por exemplo.
Ao alterar a direção padrão de dados você deve incluir a diretiva #use fast_io(x) onde x é o PORT, como por exemplo #use fast_io(d) para escolher PORTD.
OS COMANDOS output_bit( ), input( ) A função output_bit(IO, nível lógico) atribui o nível
lógico ao I/O especificado.
A função input(IO) retorna o nível lógico encontrado no
“IO” especificado.
A diretiva #use fast_io(IO) especifica que o programado
irá decidir quais I/O’s serão entrada com o comando set_tris(IO).
1 0 0
0
0
0
0
Lin1
Lin2
Lin3
Lin4
TECLADO MATRICIAL - Página 6/8
Engenharia Curso de microcontrolador online pic 8051 programação jfe pic c compiler projeto s microgenios gravador cu scopic aeci sp progisp u sbasp atmega Arduino faculdade unisinos feeva le.br pucrs ufrgs uninter faccat ita unisanta unoeste anhanguera u sp unesp feec feelt ufrj pucminas unitaumaua ime unopar fam ufsc pucpr fei fatec uninove ead uniceug Anchieta uceff ufpel rogercom ufal edu br fpb up unifacs fatecpr feitep univap fen/ufg famen dombosco utfpr cefet uni pifam senai impacta unilasalle uva uc s.br unifor upe.br unig.br ifrs.edu.br
Programa 3
ESQUEMÁTICO PIC Você encontrará esta simulação na pasta
C:\8051\ISIS77\EXEMPLOS\PIC_TECLADO_MATRICIAL_COM_LCD.DSN
Considere neste estudo o esquema da figura abaixo, o qual pode ser recriado no software ISIS utilizando os seguintes componentes:
Referência Componente PIC16F877A Microcontrolador PIC16F877A KEYPAD-PHONE Teclado Matricial LM016L Display LCD 16x2
Uma versão portátil deste simulador pode ser executada a partir da pasta 8051\ISIS77\BIN\ISIS.EXE
Figura 7a: Executando o Simulador ISIS
PROGRAMAÇÃO A seguir temos a programação para ler as colunas 1 e 2 do teclado matricial. Ao identificar a linha em nível baixo, é atribuído o respectivo valor à variável char tecla.
#include<16F877A.H>
#use delay (clock=4000000)
#include <lcd.h>
#use fast_io(D)
#fuses nowdt, nobrownout, xt, noput
#define IO_COLUNA1 PIN_D0
#define IO_COLUNA2 PIN_D1
#define IO_COLUNA3 PIN_D2
#define IO_LINHA1 PIN_D4
#define IO_LINHA2 PIN_D5
#define IO_LINHA3 PIN_D6
#define IO_LINHA4 PIN_D7
#define TAM_SENHA 3
char tecla=' ';
int1 b1, b2;
char valorDigitado[3]={' ',' ',' '};
char senha[3]={'1','4','1'};
char indice=0;
char keypad(); //protótipo da função
void main()
{
//Define colunas como saidas (0000)
//Define linhas como entradas (1111)
set_tris_D(0b11110000);
lcd_init();
while(1)
{
tecla=keypad(); //le teclado
if(tecla!=' ') //se pressionou tecla
{
valorDigitado[indice]=tecla;
indice++;
lcd_gotoxy(1,1);
lcd_putc(valorDigitado[0]);
lcd_putc(valorDigitado[1]);
lcd_putc(valorDigitado[2]);
if(indice==TAM_SENHA)
{
if( valorDigitado[0]==senha[0] &&
valorDigitado[1]==senha[1] &&
valorDigitado[2]==senha[2])
{
lcd_gotoxy(1,1);
lcd_putc("Senha Correta");
}
else
{
lcd_gotoxy(2,1);
lcd_putc("Senha Invalida");
}
delay_ms(1000);
lcd_init();
valorDigitado[0]=' ';
valorDigitado[1]=' ';
valorDigitado[2]=' ';
indice=0;
}
}
}
}
//******************************************
char keypad()
{
tecla=' ';
//Ativa coluna 1
output_bit(IO_COLUNA1,1);
output_bit(IO_COLUNA2,0);
output_bit(IO_COLUNA3,0);
if(input(IO_LINHA1)==1 && b1==0)
{
tecla='1';
b1=1; //impede a repetição
}
if(input(IO_LINHA1)==0) b1=0; //soltou a tecla
if(input(IO_LINHA2)==1 && b2==0)
{
tecla='4';
b2=1; //impede a repetição
}
if(input(IO_LINHA2)==0) b2=0; //soltou a tecla
return tecla; //Retorna a tecla pressionada
}
O TIPO DE DADO bit e int1
O tipo int1 é um dado booleano que suporta apenas os valores 0 e 1 e equivale ao tipo de dado bit do 8051. As variáveis booleanas bit e int1 são frequentemente utilizadas para sinalizar a ocorrência de eventos. Mesmo que o evento tenha terminado, é possível saber se ele já aconteceu verificando o valor dessas variáveis. Essas variáveis do tipo bit (no 8051) e int1 (mo PIC) ocupam apenas 1 bit da memória RAM do microcontrolador, enquanto o tipo char ocupa 8 vezes mais e o tipo int ocupa 16 vezes.
ATIVIDADES PROPOSTAS
1 Desenhar o esquemático da figura 12 no software
simulador ISIS (ver em C:\8051\ISIS77\EXEMPLOS);
Fig. 12: Microcontrolador PIC com teclado matricial 4x3 e LCD 16x2
Linha1
Linha2
Linha3
Linha4
Col1 Col2 Col3
TECLADO MATRICIAL - Página 7/8
2 Digitar e compilar o programa 3 no software PIC-C
Compiler;
3 Simular o programa 3 no software ISIS;
4 Ampliar a leitura de 2 para todas as teclas;
5 Adaptar para o PIC16F877A as atividades elaboradas
para o microcontrolador AT89C52.
CONCLUSÃO Nesta unidade abordamos a programação do teclado matricial 4x3, bem como a lógica e o conceito de funcionamento deste componente, tornando este estudo adaptável a teclados matriciais com outras dimensões. O uso do comando #define torna simples a instalação do teclado matricial numa configuração diferente daquela apresentada na figura 6. Vimos também que as variáveis indexadas, comumente denominadas vetores ou arrays são muito uteis para armazenar e processar as informações recebidas através do teclado. Por fim, temos proposições de atividades para aprofundar o estudo e uma secção de anexos com as bibliotecas lcd.h que implementam as funções de uso do display LCD.
LICENÇA DE USO DESTE MATERIAL Todas as informações apresentadas funcionam em nível de simulação de software. Você pode baixa-las no site www.u8051.com.br e utiliza-las de forma parcial ou integral e livremente como material didático.
Documento atualizado em 12/05/2022 11:26 Prof. Cristian M.G ([email protected])
www.u8051.com.br
TECLADO MATRICIAL - Página 8/8
ANEXOS: BIBLIOTECAS LCD Nesta página você encontra a biblioteca lcd.h para o microcontrolador 8051 e a biblioteca lcd.h para o microcontrolador PIC. Ambas implementam a comunicação entre o microcontrolador e o display LCD.
Biblioteca lcd.h para 8051 Você deve copiar o código lcd.h (logo abaixo) para 8051 e colar no JFE. Em seguida, deverá clicar no menu File > Save As... e salvar na pasta 8051\SDCC\INCLUDE e preencher o nome lcd.h e finalmente clicar no botão Salvar. // PINOS PIC PINOS LCD // P2_0 D4 // P2_1 D5 // P2_2 D6 // P2_3 D7 // P2_4 enable // P2_5 rs #define lcd_en P2_4 #define lcd_rs P2_5 #define lcd_DELAY 155 /* Delay for 1 ms */ #define lcd_clear() lcd_command(0x1) //Limpa o lcd #define lcd_origin() lcd_command(0x2) //Set to origin lcd /*************************************************** * Prototype(s) * ***************************************************/ void lcd_delay(unsigned char ms); void lcd_enable(void); void lcd_command(unsigned char command); void lcd_putchar(unsigned char ascii); void lcd_puts(unsigned char *lcd_string); void lcd_init(void); void lcd_gotoxy(char linha, char coluna); void lcd_cursor(bit blink); void lcd_shift_left(); void lcd_shift_right(); void lcd_cursor(bit blink){ if(blink) lcd_command(0x0F); else lcd_command(0x0C); } //*********************************************************** void lcd_gotoxy(char linha, char coluna){ //lcd_command(0x7F+coluna); switch(linha){ case 1: lcd_command(0x7F + coluna); break; case 2: lcd_command(0xBF + coluna); break; case 3: lcd_command(0x93 + coluna); break; case 4: lcd_command(0xD3 + coluna); break; } } //*********************************************************** void lcd_delay(unsigned char ms) { unsigned char n; unsigned int i; for (n=0; n<ms; n++) { for (i=0; i<lcd_DELAY; i++); /* For 1 ms */ } } //*********************************************************** void lcd_enable(void) { lcd_en = 0; /* Clear bit P2.4 */ lcd_delay(1); lcd_en = 1; /* Set bit P2.4 */ } //*********************************************************** void lcd_command(unsigned char command) { lcd_rs = 0; /* Clear bit P2.5 */ P2 = (P2 & 0xF0)|((command>>4) & 0x0F); lcd_enable(); P2 = (P2 & 0xF0)|(command & 0x0F); lcd_enable(); lcd_delay(1); } //*********************************************************** void lcd_putchar(unsigned char ascii) { lcd_rs = 1; /* Set bit P2.5 */ P2 = (P2 & 0xF0)|((ascii>>4) & 0x0F); lcd_enable(); P2 = (P2 & 0xF0)|(ascii & 0x0F); lcd_enable(); lcd_delay(1); } //*********************************************************** void lcd_puts(unsigned char *lcd_string) { while (*lcd_string){ lcd_putchar(*lcd_string++); } } //*********************************************************** void lcd_init(void) { lcd_en = 1; /* Set bit P2.4 */ lcd_rs = 0; /* Clear bit P2.5 */ lcd_command(0x33); lcd_command(0x32); lcd_command(0x28); lcd_command(0x0C); lcd_command(0x06); lcd_command(0x01); /* Clear */ lcd_delay(256); } //*********************************************************** void lcd_shift_left(){ lcd_command(0x18); } //*********************************************************** void lcd_shift_right(){ lcd_command(0x1C); }
Biblioteca lcd.h para PIC Você deve copiar o código lcd.h (logo abaixo) para PIC e colar no PIC-C Compiler. Em seguida, deverá clicar no menu File > Save As... e salvar na pasta C:\Arquivos de Programas(x86))\PICC\Devices e preencher o nome lcd.h e então clicar no botão Salvar.
// PINOS PIC PINOS LCD // B0 enable // B1 rs // B2 rw // B4 D4 // B5 D5 // B6 D6 // B7 D7 // // Os pinos D0 a D3 do LCD não são usados. struct lcd_pin_map { // This structure is overlayed BOOLEAN enable; // on to an I/O port to gain BOOLEAN rs; // access to the LCD pins. BOOLEAN rw; // The bits are allocated from BOOLEAN unused; // low order up. ENABLE will int data : 4; // be pin B0. } lcd; #byte lcd = 6 #define set_tris_lcd(x) set_tris_b(x) #define lcd_type 2 // 0=5x7, 1=5x10, 2=2 linhas #define lcd_line_two 0x40 // Endereco de RAM da aª linha BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; // Estes bytes sao enviados ao lcd para incicializa-lo struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; #separate void lcd_send_nibble( BYTE n ) { lcd.data = n; delay_cycles(1); lcd.enable = 1; delay_us(2); lcd.enable = 0; } #separate void lcd_send_byte( BYTE address, BYTE n ) { lcd.rs = 0; delay_us(50); lcd.rs = address; delay_cycles(1); lcd.rw = 0; delay_cycles(1); lcd.enable = 0; lcd_send_nibble(n >> 4); lcd_send_nibble(n & 0xf); } #separate void lcd_init() { BYTE i; set_tris_lcd(LCD_WRITE); lcd.rs = 0; lcd.rw = 0; lcd.enable = 0; delay_ms(15); for(i=1;i<=3;++i) { lcd_send_nibble(3); delay_ms(5); } lcd_send_nibble(2); for(i=0;i<=3;++i) lcd_send_byte(0,LCD_INIT_STRING[i]); delay_ms(10); } #separate void lcd_gotoxy( BYTE y, BYTE x) { BYTE address; if(y!=1) address=lcd_line_two; else address=0; address+=x-1; lcd_send_byte(0,0x80|address); } #separate void lcd_putc( char c) { lcd_send_byte(1,c); break; } // funcoes adicionadas por Daniel Corteletti #separate void lcd_cursor_on() { lcd_send_byte(0,0x0E); } #separate void lcd_cursor(int blink){ if(blink) lcd_send_byte(0,0x0F); else lcd_send_byte(0,0x0C); } #separate void lcd_shift_left() { lcd_send_byte(0,0x18); } #separate void lcd_shift_right() { lcd_send_byte(0,0x1C); }