Ir ao conteúdo
  • Cadastre-se

PIC 16F628 e LCD


junior_jr_rj

Posts recomendados

Ola estou usando o arquivo PICC como compilador. Eu to tentando usar o drive de LCD do programa mas n consigo escrever nada no LCD.

Se alguem puder me ajudar.

Os pinos do são:

PIC ------------------------ LCD

RB0,RB1,RB2,RB3 ------------ Dados

RB4 ------------------------ Enable

Rb5 ------------------------ RS

gnd ------------------------ R/W

LCD de 2 linhas

PIC 16F628

texto "Clube do Hardware"

alguem pode criar esse código e comentar??? abraços!!!

Link para o comentário
Compartilhar em outros sites

Colega junior_jr_rj, por coincidência encontrei esses dias pra tras uma rotina do jeito que você precisa. Mas ela necessita que você utilize o Compilador CCS. Por definição, o compilador já vem com uma rotina de LCD chamada LCD.C.

No forum do compilador um membro modificou tal driver, chamando-o de LCD_flex. Funciona direitinho. A única coisa que você deve fazer é modificar no inicio do código do lcd_flex a definição das portas utilizadas, bem simples.

Vou passar o link do fórum, para não ter que transcrever tudo p cá. Tudo em inglês. :D

http://www.ccsinfo.com/forum/viewtopic.php?t=24661

Mas caso queira, o código está abaixo:



// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.

#define LCD_DB4 PIN_D0
#define LCD_DB5 PIN_D1
#define LCD_DB6 PIN_D2
#define LCD_DB7 PIN_D3

#define LCD_E PIN_A1
#define LCD_RS PIN_A3
#define LCD_RW PIN_A2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW 1

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

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 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_LCD_RW
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_cycles(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);

return(retval);
}
#endif

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

#ifdef USE_LCD_RW
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_LCD_RW
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_LCD_RW
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;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

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 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}

}

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

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

if(y != 1)
address = lcd_line_two;
else
address=0;

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

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

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

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

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

//------------------------------
#ifdef USE_LCD_RW
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_lcd.c

Para utilizar o código, copie e cole o código acima em novo source code no CCS e salve como .C. Não precisa complilar. Ponha na pasta junto dos outros drivers.

No seu programa, faça um #include <lcd_flex.c>. Pronto. funciona q é uma beleza.

Usei o 16F628A porq é o q o proteus tem mais perto do seu. Altere o código para seu caso.

Como você ta colocando o RW do lcd no ground, você precisa comentar (//) a linha #define USE_LCD_RW 1

Teste p o código:

O inicio do meu LCD_flex ficou assim:



// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.

#define LCD_DB4 PIN_B0 //Definição das portas aqui!
#define LCD_DB5 PIN_B1
#define LCD_DB6 PIN_B2
#define LCD_DB7 PIN_B3

#define LCD_E PIN_B4
#define LCD_RS PIN_B5
//#define LCD_RW PIN_B6

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW 1 //comente se usar em nivel baixo

// flex_lcd.c

Código de teste para o 16F628A:


#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection

#use delay(clock=4000000) // O clock

#include <lcd_flex.C> // Drive de LCD modificado

void main()
{
lcd_init (); //Sempre chame essa rotina para o LCD!

while (TRUE) //Forever!
{
lcd_gotoxy (5,1); //Ir para a coluna 5 na linha 1 do LCD.
lcd_putc ("Clube do"); //Escreve no LCD.
lcd_gotoxy (5,2); // Ir para a coluna 5 da linha 2 do LCD.
lcd_putc ("Hardware"); //Escreve.
delay_ms (1000); //Pausa de 100 milisegundos
lcd_putc ("\f"); //Apaga o LCD.
delay_ms (500);
}
}
#include <16F628A.h>   //Seu PIC

Imagem:

semttuloon.jpg

flws

Link para o comentário
Compartilhar em outros sites

Amigo, se você estiver ligando o R/W somente no GND, o LCD não funciona mesmo pois é um pino de controle interno do LCD.

O LCD que tenho para realizar testes é esse, MGD1602B (16x2):

Pino no uC Pino no LCD

RB1 ----------- RS

RB2 ----------- R/W << CONTROLE

RB0 ----------- ENABLE

RB4 ----------- DB4

RB5 ----------- DB5 << DADOS

RB6 ----------- DB6

RB7 ----------- DB7

Exemplo:

#include <16f628.h>

#use delay(clock=4000000)

#fuses NOWDT,PUT,NOPROTECT,MCLR,NOBROWNOUT,NOLVP,INTRC_IO

#define use_portb_lcd TRUE

#include <lcd.c>

void main()

{

lcd_init(); //Inicialização do LCD

While (TRUE)

{

printf(lcd_putc,"\fClube do Hardware");

delay_ms(500);

printf(lcd_putc,"\fTeste LCD");

}

}

Esse é o exemplo mais simples e de uso mais direto, funciona diretamente com os parametros do CCS.

Link para o comentário
Compartilhar em outros sites

Boa felipe-zero.

Não conhecia o comando #define use_portb_lcd TRUE. Com ele consigo mudar as portas utilizadas pelo LCD.C. Interessante.

No entanto, o objetivo do lcd_flex é no caso de alguem pecisar utilizar outras portas em conjunto. Tipo umas PortB, umas Portc, umas PORTa.... por exemplo, tudo ao mesmo tempo. E com ele você pode usar o RW em ground.

Ele é ....digamos que mais versátil doq o LCD.c padrão.

valeu

Link para o comentário
Compartilhar em outros sites

Ae galerinha.

O pino R/W do lcd pode ir sim direto ao GND, desde que você só realize operações de escrita no LCD. Algo que pode ser a fonte do erro é que quando você configura o LCD pra 4 bits você deve enviar duas vezes o comando que configura ele desse modo (em assembly você manda o dado 0x28 (hexa))

Espero ajudar =]

Link para o comentário
Compartilhar em outros sites

  • 9 meses depois...

Ola Pessoal, O Poste é antigo mas se ajudar tenho um programa escrito no ccs em c ,que modifiquei en vez de 16x4 coloquei um lcd 20x2 com rw aterrado e funciona no meu aparelho diretinho, n sei como colocar o codigo aqui nem as imagens do proteus, mas se alguem se despor a me ensinar a usar bem o forum ,eu gostaria de contribuir ...até+...

Link para o comentário
Compartilhar em outros sites

Para você colocar o código aqui você copia ele do CCS e coloca ele aqui assim:

seu codigo fica entre esses dois comandos[.code] Onde você substitui o .(ponto) por /(barra).

As imagens, você tira uma screenshot com o botão print screen do seu teclado e cola no paint, salva e hospeda em algum site tipo esse: http://imgur.com/

Aí você copia o endereço que você pegou nesse site e cola aqui assim:

[img]endereço da sua imagem aqui[.img]. Novamente, substitua o .(ponto) por /(barra).

Falou

Link para o comentário
Compartilhar em outros sites

  • 3 meses depois...

Utilize algo do tipo:

#include <lcd.C>

void lcd_scroll_right(void)
{
lcd_send_byte(0, 0x1E);
delay_ms(400); // scroll delay
}

void lcd_scroll_left(void)
{
lcd_send_byte(0, 0x18);
delay_ms(400); // scroll delay
}



void main()
{
lcd_init ();

while (true)
{
printf(lcd_putc,"\fteste");
delay_ms (500);
printf(lcd_putc,"\n18f4550");
delay_ms (500);

for(i = 0; i < 15 ; i++)
{
lcd_scroll_left();
}
}
}

Qualquer dúvida, só perguntar.

Falou

Link para o comentário
Compartilhar em outros sites

  • 9 meses depois...

gente.. no código que eu peguei ta dando erro nessa linha

int8 const LCD_INIT_STRING[4] =

o que tem de errado aí? preciso muito de uma ajuda pra terminar meu trabalho!

gente.. no código que eu peguei ta dando erro nessa linha

int8 const LCD_INIT_STRING[4] =

o que tem de errado aí? preciso muito de uma ajuda pra terminar meu trabalho!

Link para o comentário
Compartilhar em outros sites

  • 3 meses depois...

Ôla PEssoal, tenho acompanhado os Foruns aqui do Clube do Hardware a um tempo e mesmo sendo vastos não consigo encontrar a solução para o meu problema:

Estou tentando escrever em um LCD utilizando o seguinte codigo:

#include <16f870.h>           

#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT

//#define LCD_E PIN_B1
//#define LCD_RS PIN_B2
//#define LCD_RW PIN_B3
//#define LCD_DB4 PIN_B4
//#define LCD_DB5 PIN_B5
//#define LCD_DB6 PIN_B6
//#define LCD_DB7 PIN_B7


#include <lcd_flex.c> // Drive de LCD modificado

void main()
{
delay_ms(100);
lcd_init() ; //Sempre chame essa rotina para o LCD!
delay_ms(100);
while (TRUE) //Forever!
{

//printf(lcd_putc,"\foi");
lcd_gotoxy(1,1); //Ir para a coluna 5 na linha 1 do LCD.
lcd_putc("alexandre"); //Escreve no LCD.
lcd_gotoxy(1,2); // Ir para a coluna 5 da linha 2 do LCD.
lcd_putc("gangorra"); //Escreve.
delay_ms(1000); //Pausa de 100 milisegundos
lcd_putc("\f"); //Apaga o LCD.
delay_ms(500);
output_high(pin_c3);
delay_ms(100);
output_low(pin_c3);
delay_ms(100);
}
}

Os defines estão comentados pois como a biblioteca Flex_lcd ja os tem o CCS acusa duplicidade.

O trexo Abaixo serve para acender um LEd,

      output_high(pin_c3);
delay_ms(100);
output_low(pin_c3);
delay_ms(100);

Usei unicamente porque quando eu tentava utilizar a Biblioteca LCD.C o programa não acusava erro ao compilar porém travava na linha lcd_putc;

O Led pisca porém o LCD exibe apenas a primeira linha com todas as colunas preenchidas;

Para tester estou usando uma placa Universal Lab Master da personal pic

O mais interessante é que na simulação no ISIS o programa funciona certinho;

DEsde ja Obrigado

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para 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...