Guia CNC Brasil - Tudo sobre CNC, Router, Laser, Torno e 3D Print
ELETRÔNICA / ELÉTRICA => Eletrônica Básica => Microcontroladores => Tópico iniciado por: Marcos Dornelas em 20 de Fevereiro de 2011, 18:52
-
Oi pessoal.
Sou eu mais uma vez recorrendo aos mestres da programacao!
Dessa vez pessoal gostaria de saber como controlar de fato o cursor do display LCD,digo controlar de fato,pois quero direcionar o cursor para a posicao que eu quiser sem que ele rode todo o display...
Usando a biblioteca do lcd do pic18F452 nao fui bem sucedido.
Me parece que para se fazer algo assim e nescessario "ler" o LCD (atravez do R/W,se ano me engano) porem como usar esses dado?
Alem do mais se antes eu envio um dado ao LCD quer dizer que o Port que uso é saida,para que que eu faça a leitura,nao seria nescessario usar um outro Port como entrada ou posso usar o mesmo?
Gostaria de controlar esse bendito cursor.Gostaria de fazer algo assim:
Mudo a posicao do cursor,coluna por coluna,para na coluna desejada escrever um dado.
E possivel! Mas como? Ja usei diversos comando de cursor combinado com algumas outras funcoes e nada!
Uso o PIC18F452 e o MPLAB C18.
Se puderem mandar exemplos,agradeço!(sou meio lento :-[)
Desde já Obrigado!
Sei que posso contar com voces,pois ja me valeram algumas vezes de desespero!
Marcos Dornelas!
-
Marcos,
Um LCD possui uma memória RAM (DDRAM) interna, onde cada endereço de memória está associado a uma posição do display (linha x coluna). Ao enviar um byte (de dados) ao LCD, pode-se enviar o endereço da RAM previamente, de modo que o byte de dados seja escrito nessa posição da RAM. Na figura, exemplo da memória de display de 2 linhas x 40 colunas. É isso!!
Dar uma lida no manual do display ajuda!!
-
Usando a biblioteca do lcd do pic18F452 nao fui bem sucedido
a biblioteca doLCD vc pode utilizar com qualquer uC ... basta que vc configure corretamente os pinos do uC ...
a grosso modo pois vai depender de sua biblioteca escrever no display será assim:
#include "biblioteca_LCD.h" // inclusão da biblioteca para o LCD
lcd_inicia (valores); //inicia o display
lcd_posicao(2,3); // define localizaçao da escrita linha 2, coluna 3
lcd_escreve("Ola mundo!"); // imprime Ola mundo! no display
Mas como falei, vc precisa ver como é a biblioteca e se necessário fazer os devidos ajustes.
-
Obrigado por me responderem,porem eu nao compreendi muito bem as respostas!
Eu sei como enviar dados para o LCD,como escrever nele e algumas outras "coisa"
o que eu nao consigo de fato e controlar o cursor.
Me disseram que era nescessario "ler" o LCD para fazer isso,porem como fazer algo assim sem usando um port como saida ?
Ex:
#include<p18f452.h>//biblioteca do microcontrolador
...
#define R/W PORTEbits.RE0//o pino RE0 = R/W do LCD
...
void main(){
...
TRISE=0x00;/*configuro todos do PORTE como saidas pois nale tambem estara os outros pinos
do LCD como enable e o Rs */
R/W=0;//R/w igual a zero enquanto envio dados e comandos para o LCD
...
}
.
Ai vem a minha duvida:
minilathe o senhor afirmou que que microcontrolador possui uma memoria RAM,
sei disso tanto que alguns LCD's possuem um microcontrolador muito comum,o HITACHI HD44780.
Entao lhe pergunto:Como eu faco para acessar a memoria desse microcontrolador do LCD e assim dirigir o cursor para tal ponto?
Blackmore muito obrigado pela indicaçao do livro do Alberto Noburo,ja estou usando ele,pena que o capitulo de LCD nao deixe claro como posicionar o cursor em qualquer uma das colunas e controlar seu deslocamento!
Os comandos da biblioteca do pic nao me foram muito uteis.Por acaso voce saberia algum desses comando,funcoes para controle do cursor?
Espero que tenha deixado mais clara as minhas duvidas!
Obrigado mais uma vez
e peço desculpas por importuna-los mais uma vez!
Marcos Dornelas
-
Marcos,
Existe um protocolo de comunicação entre o PIC e o HD44780, onde são enviadas informações do PIC ao LCD. E para posicionar o cursor não é necesário ler o LCD. Nesse protocolo, o PIC escreve o endereço e depois a informação a ser mostrada no LCD, é simples assim...
Voce precisa ler um pouco mais sobre como um LCD funciona, há linhas de dados de de controle (D0, D1, D2, D3, RS, E). É só acionar adequadamente essas linhas e o LCD (na verdade, o HD44780) faz o que voce manda...
O que a biblioteca de LCD na linguagem C (ou assembly, Basic, ...) faz é empacotar essa sequência de sinais. Mas, ao invés de sair usando a biblioteca, eu gastaria um pouco de tempo para entender o que ela faz, como se liga um display ao PIC, etc. Pois isso não é nada complicado.
-
Marcos , nao tenho muito conhecimento no C18 , mas já fiz algo parecido em Assembly e MikroC.
Esclareça mais um detalhe para que os companheiros possam lhe orientar melhor:
Voce deseja movimentar o cursor e manter os caracteres que já estão escritos no LCD nas devidas posições , ou seria uma função de edição em que a posição onde o cursor apareçe é apagada para entrar outro dado ?
-
Marcos Dornelas
primeiro vou apenas reforçar a recomendação do mestre minilathe
Voce precisa ler um pouco mais sobre como um LCD funciona, há linhas de dados de de controle (D0, D1, D2, D3, RS, E). É só acionar adequadamente essas linhas e o LCD (na verdade, o HD44780) faz o que voce manda...
depois que você ler sobre o assunto acima você vai entender esta linha já comentada...
lcd_posicao(2,3); // define localizaçao da escrita linha 2, coluna 3
Como você possui o livro do Alberto, o capítulo 8 (pag 183) explica como controlar o display, e caso vc esta utilizando a biblioteca LCD do Alberto eu lhe adianto que ela possui um erro em uma das ultimas linhas da biblioteca, por este fato o display não irá funcionar, é neessário a correção, mas vc primeiro precisa entender como o display funciona, ok?
-
Marcos , nao tenho muito conhecimento no C18 , mas já fiz algo parecido em Assembly e MikroC.
Esclareça mais um detalhe para que os companheiros possam lhe orientar melhor:
Voce deseja movimentar o cursor e manter os caracteres que já estão escritos no LCD nas devidas posições , ou seria uma função de edição em que a posição onde o cursor apareçe é apagada para entrar outro dado ?
Bom dia Beto, teria como você ou outro usuário que também tenha conhecimento em assembly p/ pic, postar um exemplo em assembly para escrever a letra A em qualquer posição no display lcd usando cristal de 20mhz? eu tentei alterar programas ja prontos para entender o funcionamento mas não tive exito. Teria algo com o pic 16f877A ou 18F4550? obrigado, abraço.
-
Procure o livro Conectando o PIC . Tem exemplos sobre isso que quer .
Senão poste o código aqui que fica mais fácil para ajudar .
Se mudou um codigo que operava em 4Mhz para 20 Mhz , atenção a configuração do cristal tem que ser HS
Ex.
__CONFIG _WDT_ON & _HS_OSC
-
Procure o livro Conectando o PIC . Tem exemplos sobre isso que quer .
Senão poste o código aqui que fica mais fácil para ajudar .
Se mudou um codigo que operava em 4Mhz para 20 Mhz , atenção a configuração do cristal tem que ser HS
Ex.
__CONFIG _WDT_ON & _HS_OSC
Vou dar uma olhada, tinha visto só o desbravando o pic com o 16f84 ou 16f628a.
Então eu coloquei essa configuração, acho que o problema mesmo ta sendo no Delay, outra coisa que queria tirar dúvida, em assembly como faço para mostrar pro programa que o pino D4 do lcd está no port c2, pino D5 do lcd está no port c3, pino D6 do lcd está no port b1, pino D7 do lcd está no port b2? É só um exemplo no caso dos pinos, tentei achar isso também e não consegui, é só uma suposição que eu tenha somente estes pinos livres para envio de dados, os outros pinos do lcd ja estão conectados em outros pinos quaisquer. Vi que em C eu tenho como alterar os pinos para envio de informações, mas em asm eu não encontrei nenhum exemplo.
Qualquer coisa então eu posto o código a noite quando estiver em casa, obrigado pela ajuda.
-
Aparecido :
Em C , dependendo do compilador , a coisa fica mais facil quando se utiliza pinos nao adjacentes , falando do port é claro, pois podemos definir isso . Uso o MikroC e é bem facil fazer como vc mesmo disse.
Já em Assembly é um pouco mais trabalhoso, mas não impossível , já que temos que criar algumas rotinas para facilitar a manipulação do byte ou nibble antes de entrega-lo aos pinos de saída que não serão pinos do mesmo port .
No caso mais comum , Byte direto no port , faço assim ,
#DEFINE DISPLAY PORTD ; BARRAMENTO DE DADOS DO DISPLAY
Ou seja , na rotina de escrita no LCD simplesmente carrego o caractere que quero escrever e chamo a rotina. ( Creio ser este o exemplo no conectando o Pic )
;-----------------------------------------------------------------------------------------
ESCREVE
MOVWF DISPLAY ; ATUALIZA DISPLAY (PORTD)
NOP ; PERDE 1US PARA ESTABILIZAÇÃO
BSF ENABLE ; ENVIA UM PULSO DE ENABLE AO DISPLAY
MOVLW .1
CALL DELAY_MS ; DELAY DE 1MS
RETURN ; RETORNA
;-----------------------------------------------------------------------------------------
No seu caso , como quer utilizar pinos que não fazem parte do mesmo port e ainda utilizando comunicação através de 4 bits ( nibble) , pode-se fazer uma rotina , primeiramente dividindo o dado a ser escrito em duas partes e armazenando em duas variáveis temporarias ; depois atraves de intruções de comparação tipo BTFSS e BTFSC setar ou resetar esses pinos relativos ao dado a ser escrito.
Ex- Testa o bit menos signicativo do dado , se verdadeiro seta o pino menos significativo PortC2 que estará ligado a D4 .
Em tempo , não recordo se o menos significativo vai em D4 ou D7 na ligação de 4 bits do LCD.
Tambem nao esqueça que além dos caracteres , estes pinos escrevem os comandos no display, na rotina de inicialização do mesmo.
Eu faria o seguinte . Montaria o LCD e o Pic com o cristal na frequencia que utilizará , com comunicação 8 bits num port completo para testar . Uma vez acertado o hardware , display mostrando um "hello word" qualquer, ai sim partiria para testar a 4 bits e depois em pinos de ports diferentes . Mas isso é só minha sugestão.
Sucesso aí ...
-
Olhei ontem a noite os meus backups, não consegui encontrar a ultima versão da lógica que estava fazendo, peguei uma mais antiga, retirei algumas coisas da lógica para ficar mais facil de corrigir, posso ter esquecido de retirar algumas coisas. Só preciso inicializar o LCD corretamente e escrever um caractere, o resto eu me viro e corrijo com calma. Uma outra dúvida, como posso fazer para o Pic realizar toda lógica mas em paralelo ele fazer leitura de um encoder? obrigado, abraço.
;*************************************************************************************************************
;Alarme residencial
;*************************************************************************************************************
#include <P16F877A.inc> ;modelo do PIC
;*************************************************************************************************************
TEMP1 equ 22h ;Variavel temporaria
TEMP2 equ 23h ;Variavel temporaria
TEMP3 equ 24h ;Variavel temporaria
TempLCD equ 25h ;Tempo do LCD
senha1 equ 26h ;digito 1 da senha
senha2 equ 27h ;digito 2 da senha
senha3 equ 28h ;digito 3 da senha
senha4 equ 29h ;digito 4 da senha
senha equ 30h
caractere equ .4 ;digitos da senha
senhaala equ .2010 ;senha do alarme
Tempsenha equ 30h
digito equ 31h
flag equ 32h
ende equ 33h ;endereço
dado equ 34h ;dados
#define BANK0 BCF STATUS, RP0 ;Seta o banco 0 de memória
#define BANK1 BSF STATUS, RP0 ;Seta o banco 1 de memória
#define E PORTE,2
#define RS PORTC,1
#define D4 PORTA,3
#define D5 PORTA,2
#define D6 PORTA,1
#define D7 PORTA,0
;*************************************************************************************************************
org 00h ;vetor de reset
goto inicio ;vai para o inicio do programa
;*************************************************************************************************************
;Rotina de inicio do programa
;*************************************************************************************************************
inicio
bsf STATUS,RP0 ;muda para banco 1
movlw 06h
movwf ADCON1 ;Usar as portas A e E como I/O e nao como A/D
movlw B'00000000'
clrf TRISA
clrf TRISB
clrf TRISC
clrf TRISD
clrf TRISE
movwf TRISA
movlw B'00000000'
movwf TRISC
movlw B'11110000'
movwf TRISD
movlw B'00000000'
movwf TRISE
movlw .31
movwf TRISB
clrf OPTION_REG
bcf STATUS,RP0 ;muda para banco 0
clrf PORTA
clrf PORTB
clrf PORTC
clrf PORTD
clrf PORTE
call reseta_valores
call Inicia_lcd ;chama rotina de configuracao do Display
call Tela_inicial
;*************************************************************************************************************
;Rotina principal
;*************************************************************************************************************
principal
bcf C3
call Delay_1s
call Delay_1s
bsf C1
goto principal
;*************************************************************************************************************
;Sub-rotina de escrita da mensagem de tela inicial no lcd
;*************************************************************************************************************
Tela_inicial
call linha1
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw 'A'
call wr_dado
call Delay_3us
movlw 'l'
call wr_dado
call Delay_3us
movlw 'a'
call wr_dado
call Delay_3us
movlw 'r'
call wr_dado
call Delay_3us
movlw 'm'
call wr_dado
call Delay_3us
movlw 'e'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw 'D'
call wr_dado
call Delay_3us
movlw 'e'
call wr_dado
call Delay_3us
movlw 's'
call wr_dado
call Delay_3us
movlw 'l'
call wr_dado
call Delay_3us
movlw 'i'
call wr_dado
call Delay_3us
movlw 'g'
call wr_dado
call Delay_3us
movlw 'a'
call wr_dado
call Delay_3us
movlw 'd'
call wr_dado
call Delay_3us
movlw 'o'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
call linha2
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw '*'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw '>'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw 'L'
call wr_dado
call Delay_3us
movlw 'i'
call wr_dado
call Delay_3us
movlw 'g'
call wr_dado
call Delay_3us
movlw 'a'
call wr_dado
call Delay_3us
movlw 'r'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
call Delay_1s
call linha2
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
return
;*************************************************************************************************************
;Sub-rotina de escrita da mensagem de alarme ligado no lcd
;*************************************************************************************************************
Tela_ligado
call linha1
call Delay_1s
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw 'A'
call wr_dado
call Delay_3us
movlw 'l'
call wr_dado
call Delay_3us
movlw 'a'
call wr_dado
call Delay_3us
movlw 'r'
call wr_dado
call Delay_3us
movlw 'm'
call wr_dado
call Delay_3us
movlw 'e'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw 'l'
call wr_dado
call Delay_3us
movlw 'i'
call wr_dado
call Delay_3us
movlw 'g'
call wr_dado
call Delay_3us
movlw 'a'
call wr_dado
call Delay_3us
movlw 'd'
call wr_dado
call Delay_3us
movlw 'o'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
call linha2
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw '#'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw '>'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
movlw 'D'
call wr_dado
call Delay_3us
movlw 'e'
call wr_dado
call Delay_3us
movlw 's'
call wr_dado
call Delay_3us
movlw 'l'
call wr_dado
call Delay_3us
movlw 'i'
call wr_dado
call Delay_3us
movlw 'g'
call wr_dado
call Delay_3us
movlw 'a'
call wr_dado
call Delay_3us
movlw 'r'
call wr_dado
call Delay_3us
movlw ' '
call wr_dado
call Delay_3us
call Delay_1s
call linha2
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
return
;*************************************************************************************************************
; Sub-rotina para iniciar configuracao do display
;*************************************************************************************************************
Inicia_lcd
bsf E
nop
nop
nop
bcf RS
nop
nop
nop
movlw 03h
movwf PORTA
bcf E
call Delay_15ms
bsf E
nop
nop
nop
bcf RS
nop
nop
nop
movlw 03h
movwf PORTA
bcf E
call Delay_15ms
bsf E
nop
nop
nop
bcf RS
nop
nop
nop
movlw 03h
movwf PORTA
bcf E
call Delay_15ms
bsf RS
nop
nop
nop
movlw 02h
movwf PORTA
bcf E
call Delay_15ms
bsf E
nop
nop
nop
bcf RS
nop
nop
nop
movlw 02h
movwf PORTA
bcf E
call Delay_15ms
movlw 28h ;00101000 ==> Modo de comunicação de 4 bits
call wr_inst ;duas linhas e matriz 8x5 ou 7x5
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
movlw 08h
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
movlw 01h
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
movlw 01h
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
movlw 06h ;Escreve deslocando o cursor para a direita
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
movlw 0Eh ;Display aceso com cursor fixo
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
movlw 01h ;Limpa o display e retorna o cursor para o inicio (home)
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
return
;*************************************************************************************************************
;Sub-rotina para posicionar o curso na linha 1
;*************************************************************************************************************
linha1
movlw 0x80 ;poe cursor na linha 1 na posição 0
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
return
;*************************************************************************************************************
;Sub-rotina para posicionar o curso na linha 2
;*************************************************************************************************************
linha2
movlw 0xC0 ;poe cursor na linha 1 na posição 0
call wr_inst
call Delay_15ms ;atraso de 15ms para a instrucao ser escrita no LCD
return
;*************************************************************************************************************
;Sub-rotina para habilitar o display lcd para dados
;*************************************************************************************************************
wr_inst
movwf TempLCD ;coloca valor no registrador temporario
bsf E
call Delay_3us
bcf RS ;habilita para comandos
call Delay_3us
swapf TempLCD,W
andlw B'00001111'
movwf PORTA
bcf E
call Delay_3us
movf TempLCD,W
andlw B'00001111'
bsf E
call Delay_3us
bcf RS ;habilita para dados
call Delay_3us
movwf PORTA
bcf E
return
;*************************************************************************************************************
;Sub-rotina para escrever dado no display lcd
;*************************************************************************************************************
wr_dado
movwf TempLCD ;Armazena o dado em TempLCD
bsf E ;Habilita LCD
call Delay_3us
bsf RS ;Seta LCD para modo dados
call Delay_3us
swapf TempLCD,W
andlw B'00001111'
movwf PORTA
bcf E ;Finaliza operação, desabilitando o LCD
movf TempLCD,w
andlw B'00001111'
bsf E ;Habilita LCD
call Delay_3us
bsf RS ;Seta LCD para modo dados
call Delay_3us
movwf PORTA
bcf E ;Finaliza operação, desabilitando o LCD
return
;*************************************************************************************************************
;Sub-rotina para resetar valores
;*************************************************************************************************************
reseta_valores
movlw .11
movwf senha1 ;inicializa senha1 com o valor de "*"
movlw .11
movwf senha2 ;inicializa senha1 com o valor de "*"
movlw .11
movwf senha3 ;inicializa senha1 com o valor de "*"
movlw .11
movwf senha4 ;inicializa senha1 com o valor de "*"
movlw .4
movwf digito ;inicializa digito com o valor 4
movlw .11
movwf Tempsenha ;inicializa Tempsenha com o valor de "*"
return
;*************************************************************************************************************
; Subrotina de atraso de aproximadamente 15 ms
;*************************************************************************************************************
Delay_15ms
movlw 50 ;move 50 para o acumulador
movwf TEMP1 ;move o valor do acumulador para TEMP1
Loop1
movlw 10 ;move 10 para o acumulador
movwf TEMP2 ;move o valor do acumulador para TEMP2
Loop2
decfsz TEMP2,F ;decrementa TEMP2, skip se zero
goto Loop2 ;vai para o endereço Loop2
decfsz TEMP1,F ;decrementa TEMP1, skip se zero
goto Loop1 ;vai para o endereço Loop1
return
;*************************************************************************************************************
; Subrotina de atraso de aproximadamente 750 ms
;*************************************************************************************************************
Delay_750ms
movlw 50 ;move 50 para o acumulador
movwf TEMP3 ;move o valor do acumulador para TEMP3
decrementa
call Delay_15ms
decfsz TEMP3,F ;decrementa TEMP3, skip se zero
goto decrementa ;vai para o endereço LABEL3
return
;*************************************************************************************************************
; Subrotina de atraso de aproximadamente 15 ms
;*************************************************************************************************************
Delay_3us
nop
return
;*************************************************************************************************************
; Subrotina de atraso de aproximadamente 1 segundo
;*************************************************************************************************************
Delay_1s
movlw 10 ;move 10 para o acumulador
movwf TEMP1 ;move o valor do acumulador para TEMP1
LABEL1
movlw 50 ;move 50 para o acumulador
movwf TEMP2 ;move o valor do acumulador para TEMP2
LABEL2
movlw 50 ;move 50 para o acumulador
movwf TEMP3 ;move o valor do acumulador para TEMP3
LABEL3
decfsz TEMP3,F ;decrementa TEMP3, skip se zero
goto LABEL3 ;vai para o endereço LABEL3
decfsz TEMP2,F ;decrementa TEMP2, skip se zero
goto LABEL2 ;vai para o endereço LABEL2
decfsz TEMP1,F ;decrementa TEMP1, skip se zero
goto LABEL1 ;vai para o endereço LABEL1
return
end ;diretiva de fim do programa
-
Interrupção externa para o encoder ....
-
Valeu pessoal.
Obrigado pela ajuda!