Ir ao conteúdo
  • Cadastre-se

Não consigo usar o LCD 20x4 no CCS


Posts recomendados

Amigos, já usei sem problemas o LCD 16x2 em conjunto com um PIC 877 através do compilador CCS. Estou tentando agora fazer o LCD 20x4 funcionar, mas creio eu que estou fazendo algum erro por ele simplesmente não funciona. Eu até posso usa-lo com a biblioteca do LCD normal, mas ele não acessa as linhas seguintes, só as linhas 1 e 2, a 3 e 4 ficam em branco.

O programa que estou fazendo é esse ai que se segue. Será que alguem pode me dizer aonde ou o que devo modificar para que ele passe a aceitar o novo LCD?


#include <Leitor de Salinidade e Temp com int.h>

#define LCD_ENABLE_PIN PIN_B3
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
#include <lcd.c>


int salcal;
int tempcal;
int salatual;
int tempatual;
int sallcdatual;
int templcdatual;
int sallcdcal;
int templcdcal;

#int_EXT
void EXT_isr(void)
{

lcd_init();
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_DIV_4);
set_pwm1_duty(0);


if (input(pin_c4))
{
set_adc_channel(0);
salcal= read_adc();
sallcdcal=salcal;
set_adc_channel(1);
tempcal= read_adc();
templcdcal =(tempcal)/2;
lcd_putc("\f Calibrando...");
delay_ms(2000);
printf(lcd_putc,"\f Sal. Cal %u", sallcdcal);
printf(lcd_putc,"\n Temp. Cal %u", templcdcal);
delay_ms(3000);
if (tempcal <= 20 || salcal <= 40){lcd_putc("\fCalibragem \nIncorreta."); delay_ms(3000);}
else {lcd_putc ("\f Calibragem \n Concluida!");delay_ms(3000);}
}

while(input(pin_c3))
{
tempcal=tempcal-1;
templcdcal=(tempcal)/2;
lcd_gotoxy(1,1);
printf(lcd_putc,"Temperatura \n %u graus",templcdcal);
if (tempcal==21) {set_adc_channel(1);tempcal= read_adc();}
delay_ms(100);
output_high(pin_c6);
delay_ms(100);
output_low(pin_c6);

}
while(input(pin_c5)){
printf(lcd_putc,"\fSal. Cal. %u ", sallcdcal);
printf(lcd_putc,"\nTemp. Cal. %u", templcdcal);
delay_ms(2000);}
}


void main()
{
lcd_init();
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_DIV_4);
set_pwm1_duty(0);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);

lcd_putc ("\fSistema controle \n Temp. e Sal.");// ...

Obrigado!

Link para o comentário
Compartilhar em outros sites

Matheus, eu ainda continuo com dificuldade mesmo depois de tentar de diversas formas. Devo estar errando em alguma coisa no meio do caminho.

Eu fiz o seguinte, copiei o code para um arquivo chamado flex_lcd420.c e coloquei esse arquivo dentro da pasta de drivers do PICC. Fiz a mudança no código do programa principal de #include <lcd.c> para #include <flexlcd420.c> mas o LCD no proteus não responde de jeito nenhum.

Eu sou um usuario novato do PICC e ainda começo a minha programação usando o Pic Wizard :P, por isso eu não tenho muito ideia dessas configurações mais avançadas.

Se voce puder me fazer um exemplo de um programa que funcione aqui pra eu copiar e testar modificações ou um passo a passo de como utilizar esse driver novo ficarei muito agradecido.

Abs!

Link para o comentário
Compartilhar em outros sites

Código de teste:

#include <16F877a.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)

#include <lcd_204.c>

//===================================
void main()
{
lcd_init();

printf(lcd_putc, "\f");
delay_ms(500);

while(1)
{
printf(lcd_putc, "\fLinha 1");
printf(lcd_putc, "\nLinha 2");
printf(lcd_putc, "\nLinha 3");
printf(lcd_putc, "\nLinha 4");
delay_ms(1000);
printf(lcd_putc, "\f");
delay_ms(1000);
}
}

Meu arquivo FLEX_20x4.c configurado:



// These pins are for my Microchip PicDem2-Plus board,
// which I used to test this driver.
// An external 20x4 LCD is connected to these pins.
// Change these pins to match your own board's connections.

#define LCD_DB4 PIN_D4
#define LCD_DB5 PIN_D5
#define LCD_DB6 PIN_D6
#define LCD_DB7 PIN_D7

#define LCD_RS PIN_D0
#define LCD_RW PIN_D1
#define LCD_E PIN_D2

/*
// To prove that the driver can be used with random
// pins, I also tested it with these pins:
#define LCD_DB4 PIN_D4
#define LCD_DB5 PIN_B1
#define LCD_DB6 PIN_C5
#define LCD_DB7 PIN_B5

#define LCD_RS PIN_E2
#define LCD_RW PIN_B2
#define LCD_E PIN_D6
*/

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line. Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD. It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit. Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.
#define USE_RW_PIN 1


// These are the line addresses for most 4x20 LCDs.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/


//========================================

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines(or more)

int8 lcd_line;

int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Set mode: 4-bit, 2+ lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));

delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_RW_PIN
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_us(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);
delay_us(1);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_RW_PIN
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);

delay_cycles(1);

#ifdef USE_RW_PIN
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------

void lcd_init(void)
{
int8 i;

lcd_line = 1;

output_low(LCD_RS);

#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif

output_low(LCD_E);

// Some LCDs require 15 ms minimum delay after
// power-up. Others require 30 ms. I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);

for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);

// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 50 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_RW_PIN
delay_ms(5);
#endif
}

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;


switch(y)
{
case 1:
address = LCD_LINE_1_ADDRESS;
break;

case 2:
address = LCD_LINE_2_ADDRESS;
break;

case 3:
address = LCD_LINE_3_ADDRESS;
break;

case 4:
address = LCD_LINE_4_ADDRESS;
break;

default:
address = LCD_LINE_1_ADDRESS;
break;

}

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
lcd_line = 1;
delay_ms(2);
break;

case '\n':
lcd_gotoxy(1, ++lcd_line);
break;

case '\b':
lcd_send_byte(0,0x10);
break;

default:
lcd_send_byte(1,c);
break;
}
}

//------------------------------
#ifdef USE_RW_PIN
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(LCD_RS);

return(value);
}
#endif
// Flex_LCD420.c

Circuito:

teste_LCD_20x4.jpg

Falou

Link para o comentário
Compartilhar em outros sites

  • 3 anos depois...

Alo pessoal, beleza?

 

Montei um projetinho de fim de semana prá usar o LCD 20x4 e precisei continuar com o 16x2.

 

Minha dúvida é a seguinte: Ao incluir essa biblioteca FLEX LCD eu poderei posicionar o cursor na última linha usando o comando LCD_GOTOXY(4,1); ou não?

 

Ainda, se puderem me ajudar como outro detalhe, agradeço muito, ou seja, coisa do CCS mesmo, estou trabalhando com variáveis FLOAT e gostaria que os números permanecessem apenas com uma casa após o ponto (vírgula), assim, 27,5 C, e não 27,58 C, ok?

 

Grato e obrigado pelas explicações.

 

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

pro caso de demorarem pra te responder, vamos aos chutes (sabendo-se que não uso o ccs)

-se colocares o argumento 4, provavelmente não vai aparecer nada no display. O que impede de colocar 2?

-se estiver usando o printf, ele tem muitos parâmetros de formatação. Dê uma olhada...

http://en.wikipedia.org/wiki/Printf_format_string

Boa sorte!

Link para o comentário
Compartilhar em outros sites

Alo Isadora Ferraz, tudo bom? Obrigado por sua atenção à minha dúvida, porém, errei o comando de exemplo.

 

Em tese, para que pudesse acessar qualquer posição de caractere e posição de linha eu utilizo (no LCD 16x2)o seguinte:

lcd_gotoxy(1,1);//acessar primeiro caractere da primeira linha

lcd_gotoxy(1,2);// 1. carac. da 2. linha

 

Assim, eu gostaria de usar ...........(1,3), (1,4) para a 3a. e 4a. linha do 20x4. Será possivel?

 

Grato.

Link para o comentário
Compartilhar em outros sites

Olá,

 Segue endereços das primeiras colunas das linhas do LCD 20x4:

 

 Linha 1: 0x80

 Linha 2: 0xC0

 Linha 3: 0x94

 Linha 4: 0xD4

 

 Não conheço essa biblioteca que você está usando, mas se ela tiver alguma função que envia comando ao LCD, se você enviar esses comandos, o LCD vai posicionar na primeira coluna das respectivas linhas.

 Como exemplo, no CCS para posicionar na linha 3 o comando ficaria assim, para a biblioteca que eu uso:

//O primeiro parâmetro, "0" - deixa o pino RS em nível baixo, para envio do comando.lcd_send_byte(0, 0x94); 

Att,

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@chacalpowers1

 

Se você observar no Driver que postei, tem no final dele, uma função assim:

void lcd_gotoxy(int8 x, int8 y){int8 address;...

Ou seja, pode ser usado sim!

 

Prova:

#include <16F877a.H>#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP#use delay(clock = 4000000) #include <lcd_204.c>    //===================================void main(){   lcd_init();      printf(lcd_putc, "\f");   delay_ms(500);         while(1)   {        lcd_gotoxy(5,1);      lcd_putc ("Linha 1");      lcd_gotoxy(10,2);      lcd_putc ("Linha 2");      lcd_gotoxy(15,3);      lcd_putc ("Linha 3");      lcd_gotoxy(20,4);      lcd_putc ("Linha 4");      delay_ms(1000);      lcd_putc ("\f");      delay_ms(1000);   }}
 
Circuito:
 
post-543152-0-54015900-1419544419_thumb.
 
No entanto. Você quer mostrar variáveis valores com vírgula. O problema é que a função lcd_putc não aceita variável. Você precisa usar a função printf. E nesse caso, a função printf não usa o comando lcd_gotoxy. Ou seja. Voltamos à estaca zero. 
 
Calma, que tem como resolver. Primeiro sobre o printf:
 
Sendo um float (valor com vírgula), usamos isso para formatar a saída:

%f

Se você colocar:

%2.0f

O CCS vai reservar duas casas antes da vírgula e vai eliminar depois da vírgula! Simples, não?
 
%1.1f   Uma casa antes e uma casa depois da vírgula.
%2.2f   Duas casa antes e uma duas depois da vírgula.
%2.3f   Duas casa antes e três casa depois da vírgula.
 
Aqui, o CCS trunca o número para eliminar casa depois da vírgula.
 
Para colocar o valor onde deseja, você pode usar o printf normalmente, apenas imprima espaços.
 
Exemplo:
 
#include <16F877a.H>#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP#use delay(clock = 4000000) #include <lcd_204.c>    float var1 = 1.5;float var2 = 2.35;float var3 = 3.53;float var4 = 4.55; //===================================void main(){   lcd_init();      printf(lcd_putc, "\f");   delay_ms(500);         while(1)   {        printf(lcd_putc, "\f     %f", var1);      printf(lcd_putc, "\n          %f", var2);      printf(lcd_putc, "\n               %f", var3);      printf(lcd_putc, "\n             %f", var4);      delay_ms(1000);      lcd_putc ("\f");      delay_ms(1000);   }}
 
Circuito:
 
post-543152-0-37279500-1419546679_thumb.
 
O mesmo resultado se consegue com uma linha de código apenas:
 
while(1)   {        printf(lcd_putc, "\f     %f\n          %f\n               %f\n             %f", var1, var2, var3, var4);            delay_ms(1000);      lcd_putc ("\f");      delay_ms(1000);   }

Seguinte, uma dica legal para quem ainda não sabe imprimir o símbolo de graus celcius (º):

apenas ponha na linha que deseja imprimir assim:

printf(lcd_putc," %c",0xdf);

Dessa forma, no LCd aparece isso:
º
 
Falou
Link para o comentário
Compartilhar em outros sites

Alo Matheus, td bom?

 

Desculpe por estender tanto o tópico, na verdade eu observei atentamente seu link e percebi que eu já havia passado por aqueles campos do CCSinfo e observei as instuções LCD-gotoxy//

 

Obrigado, igualmente, pelas suas valiosas dicas, principalmente o simbolo "graus".

 

Sim, estou trabalhando com variáveis float e não tenho dificuldade com o posicionamento de vírgulas para os decimais, tudo ok!

 

Apenas não lhe entendi quando você disse que " Você precisa usar a função printf. E nesse caso, a função printf não usa o comando lcd_gotoxy."

 

Eu estou usando em meu código da seguinte forma e os resultados são corretos:

 

 
///LEITURA DE TENSÃO PORT A1
 
   set_adc_channel(1);
   delay_ms(10);
   valorV=read_adc();
   volt1=valorV/48.81;
   lcd_gotoxy(3,1);
   printf(lcd_putc,"%.2f", volt1);  
   delay_ms(100);
   
 
Para resumir, estou trabalhando com um projeto de display (neste momento 16x2) para acoplar em fontes de alimentação de alta corrente, eu já produzo estas fontes regularmente (100A e acima), porém, quero deixar de usar os voltimetros "prontos" e estou desenvolvendo uma "central de monitoramento" embarcado no display, com leitura de tensão, temperatura, corrente, e potência. Ale´m das informações visuais, estou implementando controle de coolers, proteção de sobrevoltagem e sobre-corrente pelos PIC, baseado nas informações que ele já fez a leitura.
 
Aproveitando o feriado já desenvolvi a PCI no proteus e amanhã somente vou corroer no percloreto.
 
Inicialmente vou aferir a corrente através de shunt mas estou aguardando a chegada dos ACS da  Allegro para 100A e 150A, o que vai melhorar muito a a precisão da medição sem perdas com dissipação de calor.
 
Grande abraço e novamente obrigado.
 
Sandro
Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...