TECLADO MATRICIAL - Página 1/6
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 de 50 a 100 vezes menos do que a 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/6
Fig. 8: Coluna 1
Fig. 9:
Coluna 2
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 um sistema, como computadores, calculadoras, senhas acesso e 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 8 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) temos que 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í encontramos a tecla pressionada!
ESQUEMÁTICO 8051
Considere em nosso estudo o esquema da figura abaixo.
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_putchar(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 das quatro linhas, uma a uma 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
Fig. 6: Microcontrolador 8051 com teclado matricial 4x3 e LCD 16x2
Col1 Col2 Col3
Lin1 Lin2 Lin3 Lin4
Lin1 Lin2 Lin3 Lin4
Col1 Col2 Col3
Linha1 Linha2 Linha3 Linha4
TECLADO MATRICIAL - Página 3/6 Programa 1
Programa 2 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.
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 IO_LINHA1 é pressionado, à variável tecla é atribuída ‘1’
e b1 recebe 1. Não importa agora que IO_LINHA1 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”.
No dicionário dos programadores, as variáveis b1 e b2 são denominadas flags por que ambas têm a finalidade de sinalizar um evento, assumindo geralmente os valores 0 e 1 apenas. As variáveis booleanas do tipo bit (no 8051) e int1 (no PIC) atendem a esse propósito e ocupam pouca memória RAM do chip.
#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 implementadas, 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;
} } } }
//******************************************
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 dos vetores, bem como o número de caracteres que irão 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”.
TECLADO MATRICIAL - Página 4/6
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");
}
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;
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;
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 é que 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!
O compilador aqui utilizado para o PIC é o CCS que implementa as funções para manipular os I/O’s do microcontrolador. São elas:
1 0 0
0 0
0 0
Lin1 Lin2 Lin3 Lin4
TECLADO MATRICIAL - Página 5/6
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 feevale.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
set_tris_IO(0bXXXXXXX); //IO é o PORT (A,B,C,D ou E) No PIC você deve especificar os I/O’s que serão utilizados como entrada e quais serão saída de dados. A instrução set_tris define a direção dos dados sendo 0=Output e 1=Input. O primeiro “X”
à esquerda corresponde ao Port 7 (D7) e o último “X” define a direção do Port 0 (D0). O comando a seguir define D7, D6, D5 e D4 como entrada de dados, enquanto que D3, D2, D1 e D0 atuam como saída:
set_tris_D(0b11110000);
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 I/O 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).
#include<16F877A.H>
#use delay (clock=4000000)
#include <lcd.h>
#use fast_io(D)
#fuses nowdt, nobrownout, xt, noput, noprotect
#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 funcao 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 }
ESQUEMÁTICO PIC
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
ATIVIDADES PROPOSTAS
1 Desenhar o esquemático no software simulador ISIS;
2 Digitar, compilar o programa 1 no software PIC-C Compiler;
3 Simular o programa 1 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 25/11/2021 08:08 Prof. Cristian M.G ([email protected])
www.u8051.com.br
Fig. 12:
Microcontrolador PIC com teclado matricial 4x3 e LCD 16x2
Linha1 Linha2
Linha3 Linha4
Col1 Col2 Col3
TECLADO MATRICIAL - Página 6/6
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);
}