8
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.

MICROCONTROLADORES 8051 E PIC

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: MICROCONTROLADORES 8051 E PIC

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.

Page 2: MICROCONTROLADORES 8051 E PIC

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

Page 3: MICROCONTROLADORES 8051 E PIC

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;

}

}

}

}

//******************************************

Page 4: MICROCONTROLADORES 8051 E PIC

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);

}

Page 5: MICROCONTROLADORES 8051 E PIC

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

Page 6: MICROCONTROLADORES 8051 E PIC

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

Page 7: MICROCONTROLADORES 8051 E PIC

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

Page 8: MICROCONTROLADORES 8051 E PIC

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); }