Autor Tema: Problema LCD con RW  (Leído 1840 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado weten

  • PIC10
  • *
  • Mensajes: 6
Problema LCD con RW
« en: 09 de Junio de 2014, 16:00:41 »
Hola a todos.
Os comento mi caso que ya que estoy un poco mosqueado. Estoy programando una LCD 16x2 con un pic 18f2550, para ello fui haciendo diferentes versiones de programas, de tal manera que al principio usaba la libreria LCD.C que viene con PIC C, usando la patilla RW y conectandola al PORTB del pic. Al querer usar el PORTB para las interrupciones, quise cambiar al PORTC la LCD y para ello uso la libreria "flex_lcd.c", resulta que esta libreria es configurable, asique por definido biene la patilla RW como desbilitada, y por tanto hay que ponerla a GND. cuando pruebo el programa en PROTEUS funciona perfectamente, pero resulta que cuando lo cargo en mi pic fisico, no funciona. Estoy seguro de que es la patilla RW porque cuando vuelvo a probar el programa anterior con el PORTB y usando RW, si funciona.

He probado a habilitar la RW en la libreria y configurarla en C7 pero no funciona. ¿Podeis ayudarme?

Gracias! Adjunto fotos para que veais






LIBRERIA 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_D4  PIN_C0
#define LCD_D5  PIN_C1
#define LCD_D6  PIN_C2
#define LCD_D7  PIN_C4
#define LCD_RS  PIN_C5
#define LCD_EN  PIN_C6
#define LCD_RW  PIN_B1// esta patilla no está usada, por eso pongo aquí esta definición que en realidad nunca se usará pq RW del LDC está puesta a masa en el esquema.

// 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// Tal como dice el comentario en inglés, si no va a ser usada se le pone '//' pq esa patilla está a masa en el esquema.   

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

#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_D4, !!(nibble & 1));
  output_bit(LCD_D5, !!(nibble & 2));
  output_bit(LCD_D6, !!(nibble & 4));
  output_bit(LCD_D7, !!(nibble & 8));

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

//-----------------------------------
// 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_EN);
  delay_cycles(1);

  retval_0 = input(LCD_D4);
  retval_1 = input(LCD_D5);
  retval_2 = input(LCD_D6);
  retval_3 = input(LCD_D7);

  output_low(LCD_EN);

  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_EN);

  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_EN);

  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);

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

void lcd_setcursor_vb(short visible, short blink) {
  lcd_send_byte(0, 0xC|(visible<<1)|blink);
}


PROGRAMA

#include <18F2550.h>
#device adc=8
//#include <math.h>
//Libreria del pic utilizado
//Conexiones LCD:
// C4 -> RS
// C5 -> RW
// C0 -> D4
// C1 -> D5
// C2 -> D6
// C3 -> D7
//libreria de nuestro pic y lcd
//configura fusibles de configuración
//#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOMCLR
#fuses INTRC_IO, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=4800000)
//CLOCK DE 4 MHZ
//DIRECCION DE LOS REGISTROS
#BYTE TRISC = 0xF94
#BYTE PORTC = 0xF82
#BYTE TRISB = 0XF93
#BYTE PORTB = 0XF81
#BYTE OSCON = 0XFD3
#BYTE OSCON = 0XFD3
#BYTE INTCON= 0XFF2
#BYTE INTCON2=0XFF1
#BYTE INTCON3=0XFF0


#include <flex_lcd.c>
//libreria lcd
#define use_portc_lcd TRUE //definir portc lcd


int k=0;
int8 temp1;
float temp;
#INT_EXT

void interruptRB0() //funcion de la interrupcion por RB0
{
 //     lcd_gotoxy(1,1);
      delay_ms (1000);
      lcd_putc("\f");
      lcd_putc("\n");
      lcd_putc("\f");
      lcd_putc("\b");
      lcd_putc("\f");
      delay_ms(100);
      k++;
      if (k>4)
      {
      k=0;
      } 
}

void temperatura()
{
      lcd_gotoxy(1,1);                      //COLOCA EL CURSOR EN COLUMNA 1 FILA 1
      lcd_putc("TEMPERATURA");    //IMPRIME EN PANTALLA                                       
      lcd_gotoxy(6,2);                      //COLOCA EL CURSOR EN COLUMNA 4 FILA 2
      printf(lcd_putc,"%2.2f C",temp);  //MUESTRA EN EL LCD EL VALOR DE TEMPERATURA
      delay_ms (1);
}

void fan1()
{
      lcd_gotoxy(1,1);
      if (bit_test(portb,2) == 1)
      {
      printf(LCD_PUTC, "Fan 1=  ON");
      lcd_gotoxy(1,2);
      lcd_putc("Modo: AUTOMATICO");
      delay_ms (10);
      }
      else
      printf(LCD_PUTC, "Fan 1= OFF");
      delay_ms (10);

     
}
void fan2()
{
      lcd_gotoxy(1,1);
      if (bit_test(portb,3) == 1)
      {
      printf(LCD_PUTC, "Fan 2=  ON");
      lcd_gotoxy(1,2);
      lcd_putc("Modo: AUTOMATICO");
      delay_ms (10);
      }
      else
      printf(LCD_PUTC, "Fan 2= OFF");
      delay_ms (10);
}
void fan3()
{
      lcd_gotoxy(1,1);
    //  printf(LCD_PUTC, "fan1=%d",k);
      if (bit_test(portb,4) == 1)
      {
      printf(LCD_PUTC, "Fan 3=  ON");
      lcd_gotoxy(1,2);
      lcd_putc("Modo: AUTOMATICO");
      delay_ms (10);
      }
      else
      printf(LCD_PUTC, "Fan 3= OFF");
      delay_ms (10);
}
void fan4()
{
      lcd_gotoxy(1,1);
    //  printf(LCD_PUTC, "fan1=%d",k);
      if (bit_test(portb,5) == 1)
      {
      printf(LCD_PUTC, "Fan 4=  ON");
      lcd_gotoxy(1,2);
      lcd_putc("Modo: AUTOMATICO");
      delay_ms (10);
      }
      else
      printf(LCD_PUTC, "Fan 4= OFF");
      delay_ms (10);
}
void main()
{
   enable_interrupts(GLOBAL);//habilitacion de interrupciones generales
   enable_interrupts(int_ext);//habilitacion de interrupcions por RB0
   ext_int_edge(H_TO_L);//flanco de bajada interrupcion RB0
   INTCON=0xD8;//registro de control de interrupciones
   //GIE=1,PEIE=1
   INTCON2=0x80;//registro de control de interrupcion 2
   //nRBPU=0
   INTCON3=0x00;//registro de control de interrupcion 3
   TRISC=0x00;
   PORTC=0x00;
   TRISB=0x01;
   PORTB=0x00;
   lcd_init(); //inicializa lcd
   
   lcd_gotoxy(1,1);
   printf(LCD_PUTC, " Calculando...");
   lcd_gotoxy(1,2);
   printf(LCD_PUTC, "  ...ESPERE");
   delay_ms(500);
   lcd_putc("\b");
   lcd_putc("\f");
   
   while(1)
   {
      setup_adc(ADC_CLOCK_INTERNAL);
      Setup_adc_ports(AN0);          //PONE PUERTO RA0 ANALOGO
      set_adc_channel(0);                   // INDICA EL PIN A LEER RA0
      delay_us(20);       
      temp1=read_adc();                     //LEE EL VALOR DEL PIN
      temp=(temp1*0.01960784318*100);
      if (k==0)
      {
     /* lcd_gotoxy(1,1);
      printf(LCD_PUTC, "Temp=%d",k);*/
      temperatura();
      }
      if (k==1)
      {
      fan1();
      }
      if (k==2)
      {
      fan2();
      }
      if (k==3)
      {
      fan3();
      }
      if (k==4)
      {
      fan4();
      }
     
      if(temp>=25)
      {
         bit_set(PORTB,2);
         bit_set(PORTB,3);
         bit_set(PORTB,4);
         bit_set(PORTB,5);
      //   output_high(PIN_B3);
      }
      else if(temp<=20)
      {
         bit_clear(PORTB,2);
         bit_clear(PORTB,3);
         bit_clear(PORTB,4);
         bit_clear(PORTB,5);
      //   output_high(PIN_B3);
      }
   }
}



Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Problema LCD con RW
« Respuesta #1 en: 09 de Junio de 2014, 16:51:50 »
Intentaste habilitarla en la libreria y ponerla a GND en tu circuito?
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado weten

  • PIC10
  • *
  • Mensajes: 6
Re: Problema LCD con RW
« Respuesta #2 en: 09 de Junio de 2014, 17:00:33 »
Si, he probado de ambas maneras y nada...

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Problema LCD con RW
« Respuesta #3 en: 09 de Junio de 2014, 17:04:21 »
Sí no habilitas el pin WR la librería hace un retardo, tú no tienes bien configurado el oscilador interno
mira que el problema tiene que ser de ahí
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado weten

  • PIC10
  • *
  • Mensajes: 6
Re: Problema LCD con RW
« Respuesta #4 en: 09 de Junio de 2014, 17:28:07 »
Ok buena idea! AAlguna pista de como configurarlo? de todos modos voy a probar, Gracias de antemano

Desconectado weten

  • PIC10
  • *
  • Mensajes: 6
Re: Problema LCD con RW
« Respuesta #5 en: 09 de Junio de 2014, 18:45:56 »
Nada, he probado con todo y no soy capaz

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Problema LCD con RW
« Respuesta #6 en: 09 de Junio de 2014, 20:56:04 »
debes usar al principio del main setup_oscillator(OSC_INTRC|OSC_4MHZ);
ademas... en el #use delay(clock=4800000) no son 4800000 si no 4000000...

te recomendaria que setup_adc(ADC_CLOCK_INTERNAL); lo saques fuera del bucle while()...y que configures los pines y los voltajes de referencia del modulo ADC...

mas o menos asi...
void main(){
   setup_oscillator(OSC_INTRC|OSC_4MHZ);
   setup_adc_ports(AN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   .........
   .........  resto de las configuraciones e interrupciones y demas
   .........

por cierto, los pines C3,C4 y C5 no los puedes usar como salidas digitales... C3 es para la regulacion de voltaje del usb y los otros dos son las lineas D- y D+ del usb....
estas dos ultimas se pueden usar solo como entradas digitales...no como salidas.... el proteus debe de tener algun tipo de bug...
« Última modificación: 09 de Junio de 2014, 21:04:57 por ppyote »
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado weten

  • PIC10
  • *
  • Mensajes: 6
Re: Problema LCD con RW
« Respuesta #7 en: 10 de Junio de 2014, 08:35:43 »
Gracias ppyote, comprobé lo que me dijiste y tenias razon, C4 y C5 son d+ y d- y logicamente no se puede poner la lcd. con respecto a lo demas, tambien probé y algo mejoró lo cual agradezco tambien.

En definitiva, pos si a alguien le pasa, lo que hice fue cambiar los pines de la libreria:

RS  --> C0
E    --> C1
RW --> GND
D4  --> B4
D5  --> B5
D6  --> B6
D7  --> B7

Y FUNCIONA!!! GRACIAS!

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Problema LCD con RW
« Respuesta #8 en: 10 de Junio de 2014, 09:41:07 »
Me alegro que todo funcione bien...
Un saludo
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...