Ir ao conteúdo

Problema com montagem! 877A e C.


Andask

Posts recomendados

Postado

Bom dia pessoal....

Bom, estou tendo um pequeno problema aqui com o 877A e o CCS....

Fiz esse pequeno código para testes, no Proteus funciona perfeitamente bem mas quando passo pro PIC, é uma tristeza só..

Fica aparecendo um monte de números sem sentido no LCD, mesmo com todos os pinos dos botões deligados! :eek:

Já tentei tudo quando foi coisa que me veio a cabeça, e nada.....

To meio desesperado porque isso vai se tornar uma aplicação bem maior, umas 400 linhas no main.c pra ser entregue dia 27 instalada já e fica dando essa zica.. =/

Vou colar o código de todos os arquivos utilizados pra compilação...

Edit: Lembrando que no MPSIM, o fluxo do programa é perfeito também!

main:


#include <16f877a.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOLVP,NOBROWNOUT,NOPROTECT
#include <mod_lcd.c>
#include <funcs.h>

int x;

void main ()
{
lcd_ini();
lcd_escreve('\f');
printf(lcd_escreve,"Teste");

while(true)
{
lcd_escreve('\f');
x = leitura(0);
printf(lcd_escreve,"%u",x);
delay_ms(500);
}
}

mod_lcd:


/************************************************************************/
/* MOD_LCD.C - Biblioteca de manipulação de módulo LCD */
/* */
/* Autor: Fábio Pereira */
/* */
/************************************************************************/

// As definições a seguir são utilizadas para acesso aos pinos do display
// caso o pino RW não seja utilizado, comente a definição lcd_rw
#ifndef lcd_enable
#define lcd_enable pin_e1 // pino enable do LCD
#define lcd_rs pin_e0 // pino rs do LCD
//#define lcd_rw pin_e2 // pino rw do LCD
#define lcd_d4 pin_d4 // pino de dados d4 do LCD
#define lcd_d5 pin_d5 // pino de dados d5 do LCD
#define lcd_d6 pin_d6 // pino de dados d6 do LCD
#define lcd_d7 pin_d7 // pino de dados d7 do LCD
#endif

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 linhas
#define lcd_seg_lin 0x40 // Endereço da segunda linha na RAM do LCD

// a constante abaixo define a seqüência de inicialização do módulo LCD
byte CONST INI_LCD[4] = {0x20 | (lcd_type << 2), 0xf, 1, 6};

byte lcd_le_byte()
// lê um byte do LCD (somente com pino RW)
{
byte dado;
// configura os pinos de dados como entradas
input(lcd_d4);
input(lcd_d5);
input(lcd_d6);
input(lcd_d7);
// se o pino rw for utilizado, coloca em 1
#ifdef lcd_rw
output_high(lcd_rw);
#endif
output_high(lcd_enable); // habilita display
dado = 0; // zera a variável de leitura
// lê os quatro bits mais significativos
if (input(lcd_d7)) bit_set(dado,7);
if (input(lcd_d6)) bit_set(dado,6);
if (input(lcd_d5)) bit_set(dado,5);
if (input(lcd_d4)) bit_set(dado,4);
// dá um pulso na linha enable
output_low(lcd_enable);
output_high(lcd_enable);
// lê os quatro bits menos significativos
if (input(lcd_d7)) bit_set(dado,3);
if (input(lcd_d6)) bit_set(dado,2);
if (input(lcd_d5)) bit_set(dado,1);
if (input(lcd_d4)) bit_set(dado,0);
output_low(lcd_enable); // desabilita o display
return dado; // retorna o byte lido
}

void lcd_envia_nibble( byte dado )
// envia um dado de quatro bits para o display
{
// coloca os quatro bits nas saidas
output_bit(lcd_d4,bit_test(dado,0));
output_bit(lcd_d5,bit_test(dado,1));
output_bit(lcd_d6,bit_test(dado,2));
output_bit(lcd_d7,bit_test(dado,3));
// dá um pulso na linha enable
output_high(lcd_enable);
output_low(lcd_enable);
}


void lcd_envia_byte( boolean endereco, byte dado )
{
// coloca a linha rs em 0
output_low(lcd_rs);
// aguarda o display ficar desocupado
//while ( bit_test(lcd_le_byte(),7) ) ;
// configura a linha rs dependendo do modo selecionado
output_bit(lcd_rs,endereco);
delay_us(100); // aguarda 100 us
// caso a linha rw esteja definida, coloca em 0
#ifdef lcd_rw
output_low(lcd_rw);
#endif
// desativa linha enable
output_low(lcd_enable);
// envia a primeira parte do byte
lcd_envia_nibble(dado >> 4);
// envia a segunda parte do byte
lcd_envia_nibble(dado & 0x0f);
}


void lcd_ini()
// rotina de inicialização do display
{
byte conta;
output_low(lcd_d4);
output_low(lcd_d5);
output_low(lcd_d6);
output_low(lcd_d7);
output_low(lcd_rs);
//#ifdef lcd_rw
// output_high(lcd_rw);
//#endif
output_low(lcd_enable);
delay_ms(15);
// envia uma seqüência de 3 vezes 0x03
// e depois 0x02 para configurar o módulo
// para modo de 4 bits
for(conta=1;conta<=3;++conta)
{
lcd_envia_nibble(3);
delay_ms(5);
}
lcd_envia_nibble(2);
// envia string de inicialização do display
for(conta=0;conta<=3;++conta) lcd_envia_byte(0,INI_LCD[conta]);
}

void lcd_pos_xy( byte x, byte y)
{
byte endereco;
if(y!=1)
endereco = lcd_seg_lin;
else
endereco = 0;
endereco += x-1;
lcd_envia_byte(0,0x80|endereco);
}

void lcd_escreve( char c)
// envia caractere para o display
{
switch (c)
{
case '\f' : lcd_envia_byte(0,1);
delay_ms(2);
break;
case '\n' :
case '\r' : lcd_pos_xy(1,2);
break;
case '\b' : lcd_envia_byte(0,0x10);
break;
default : lcd_envia_byte(1,c);
break;
}
}

char lcd_le( byte x, byte y)
// le caractere do display
{
char valor;
// seleciona a posição do caractere
lcd_pos_xy(x,y);
// ativa rs
output_high(lcd_rs);
// lê o caractere
valor = lcd_le_byte();
// desativa rs
output_low(lcd_rs);
// retorna o valor do caractere
return valor;
}


funcs:


#define col1 pin_b3
#define col2 pin_b2
#define col3 pin_b1

#define lin1 pin_b4
#define lin2 pin_b5
#define lin3 pin_b6
#define lin4 pin_b7

int tecla_temp, tecla;

#SEPARATE
int leitura(int y)
{

output_low(col1);
output_low(col2);
output_low(col3);

tecla_temp = 0;
tecla = 0;

ler:

while(true)
{
//Testar coluna 1, valores 1, 4, 7, 254;
output_high(col1);
if (input(lin1))
{

while (input(lin1)) {}

tecla_temp = 1;
break;
} else
if (input(lin2))
{

while (input(lin2)) {}

tecla_temp = 4;
break;
} else
if (input(lin3))
{

while (input(lin3)) {}

tecla_temp = 7;
break;
} else
if (input(lin4))
{

while (input(lin4)) {}

tecla_temp = 254;
break;
}

output_low(col1);

//Testar coluna 2, valores 2, 5, 8, 0;
output_high(col2);
if (input(lin1))
{

while (input(lin1)) {}

tecla_temp = 2;
break;
} else
if (input(lin2))
{

while (input(lin2)) {}

tecla_temp = 5;
break;
} else
if (input(lin3))
{

while (input(lin3)) {}

tecla_temp = 8;
break;
} else
if (input(lin4))
{

while (input(lin4)) {}

tecla_temp = 0;
break;
}

output_low(col2);

//Testar coluna 3, valores 3, 6, 9, 255;
output_high(col3);
if (input(lin1))
{

while (input(lin1)) {}

tecla_temp = 3;
break;
} else
if (input(lin2))
{

while (input(lin2)) {}

tecla_temp = 6;
break;
} else
if (input(lin3))
{

while (input(lin3)) {}

tecla_temp = 9;
break;
} else
if (input(lin4)) // enter
{

while (input(lin4)) {}

tecla_temp = 255;
break;
}

output_low(col3);

}

if (tecla_temp < 254)
{
tecla = tecla * 10;
tecla = tecla + tecla_temp;
}

if (tecla_temp == 255)
{
while (input(lin4)){};
if (tecla == 0) tecla = 255; else tecla = tecla;
return tecla;
}

if (tecla_temp == 254)
{
tecla = 254;
return tecla;
}
if (y == 1) printf(lcd_escreve,"%u",tecla_temp);
goto ler;
}


Postado

Alterei as bibliotecas e o código..

O programa no Proteus funciona perfeitamente, como dá pra ver na imagem.. (ultima coisa do tópico).

Quando eu passo pra protoboard, começam os problemas, as vezes eu aperto apenas uma vez um número, o '5' por exemplo, e no display aparece '55' ou até mesmo '555' (555 é mais raro, 55 aparece com alguma frequencia).

E a primeira coluna inteira não funciona...

Verifiquei as tensões dos pinos da coluna com o programa rodando e obtive os seguintes números:

Col 1 = 0,1 V

Col 2 = 0,5 V

Col 3 = 0,5 V

Alguém sabe o que pode ser?

main:


#include <16f877a.h>
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)

#include "flex_lcd.c"
#include <kbd.c>

void main()
{
char c;
lcd_init();
kbd_init();

while(TRUE)
{
c=kbd_getc();
if(c!=0)
if(c=='*')
lcd_putc('\f');
else
lcd_putc(c);
}
}

flex_lcd:


// flex_lcd.c

// 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_D4
#define LCD_DB5 PIN_D5
#define LCD_DB6 PIN_D6
#define LCD_DB7 PIN_D7

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

// 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

kcd.c


///////////////////////////////////////////////////////////////////////////
//// KBDD.C ////
//// Generic keypad scan driver ////
//// ////
//// kbd_init() Must be called before any other function. ////
//// ////
//// c = kbd_getc(c) Will return a key value if pressed or /0 if not ////
//// This function should be called frequently so as ////
//// not to miss a key press. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////

////////////////// The following defines the keypad layout on port D

// Un-comment the following define to use port B
define use_portb_kbd TRUE

// Make sure the port used has pull-up resistors (or the LCD) on
// the column pins


#if defined(__PCH__)
#if defined use_portb_kbd
#byte kbd = 0xF81 // This puts the entire structure
#else
#byte kbd = 0xF83 // This puts the entire structure
#endif
#else
#if defined use_portb_kbd
#byte kbd = 6 // on to port B (at address 6)
#else
#byte kbd = 8 // on to port D (at address 8)
#endif
#endif

#if defined use_portb_kbd
#define set_tris_kbd(x) set_tris_b(x)
#else
#define set_tris_kbd(x) set_tris_d(x)
#endif



//Keypad connection: (for example column 0 is B2)
// Bx:

#ifdef blue_keypad ///////////////////////////////////// For the blue keypad
#define COL0 (1 << 2)
#define COL1 (1 << 3)
#define COL2 (1 << 6)

#define ROW0 (1 << 4)
#define ROW1 (1 << 7)
#define ROW2 (1 << 1)
#define ROW3 (1 << 5)

#else ////////////////////////////////////////////////// For the black keypad
#define COL0 (1 << 5)
#define COL1 (1 << 6)
#define COL2 (1 << 7)

#define ROW0 (1 << 1)
#define ROW1 (1 << 2)
#define ROW2 (1 << 3)
#define ROW3 (1 << 4)

#endif

#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2)

// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};

#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second


void kbd_init() {
}

char kbd_getc( ) {
static BYTE kbd_call_count;
static int1 kbd_down;
static char last_key;
static BYTE col;

BYTE kchar;
BYTE row;

kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
switch (col) {
case 0 : set_tris_kbd(ALL_PINS&~COL0);
kbd=~COL0&ALL_PINS;
break;
case 1 : set_tris_kbd(ALL_PINS&~COL1);
kbd=~COL1&ALL_PINS;
break;
case 2 : set_tris_kbd(ALL_PINS&~COL2);
kbd=~COL2&ALL_PINS;
break;
}

if(kbd_down) {
if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
kbd_down=FALSE;
kchar=last_key;
last_key='\0';
}
} else {
if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
if((kbd & ROW0)==0)
row=0;
else if((kbd & ROW1)==0)
row=1;
else if((kbd & ROW2)==0)
row=2;
else if((kbd & ROW3)==0)
row=3;
last_key =KEYS[row][col];
kbd_down = TRUE;
} else {
++col;
if(col==3)
col=0;
}
}
kbd_call_count=0;
}
set_tris_kbd(ALL_PINS);
return(kchar);
}

schematic.jpg

Postado

Bom, mudei o valor do deboucing e agora parece que tá sossegado...

O problema continua a ser a primeira coluna que não funciona..

Fiz um video tentando mostrar o que acontece mas infelizmente a qualidade ficou um lixo...

Se eu pressionar todas as teclas em sequencia vai aparecer o seguinte no LCD:

235689# nenhuma tecla da primeira coluna (147*) funciona...

Experimentei inverter os fios da primeira coluna com os da segunda pra ver se era algum problema de mau contato ou coisas do tipo, mas o hardware da primeira coluna está funcionando normalmente....

Deve ser algum problema no software então... Mas o que? =[

Postado

Bom, imagino que seja o tempo de aquisição do LCD, tenta deixar 2ms entre cada clock no pino E dele, e quanto a não conseguir escrever na primeira coluna, esse é um probleminha que os compiladores C geralmente mostram com as bibliotecas padrões de LCD, o negócio é escrever sua própria biblioteca de envio para LCD, aí você sabe exatamente o que está enviando para o LCD. O bom é enviar caracter por caracter, não enviar texto completo que nunca consegui fazer funcionar direito...

Falou..

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

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!