Autor Tema: Porblema LCD y sensor digital  (Leído 2266 veces)

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

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
Porblema LCD y sensor digital
« en: 15 de Febrero de 2005, 06:55:00 »
Tengun problemilla y no se muy bien como resolverlo. Estoy utilizando un LCD de 20x4, con 4bits, y señales de E/RS/RW, tengo conectado al puertoA la linea de datos, y las lineas de control al puertoC, en el PA tengo tambien conectado un sensor digital (SHT-11), el problema es que hace una medición (correcta), y a continuación las demas son erroneas, este problema me lo da a veces, solo deja de darmelos cuando compilo el programa sin el uso del LCD (para saber que está funcionando como debe lo compruebo via RS232), deduzco que el problema está en la librería, esta es la que estoy usando...
Codigo:

////////////////////////////////////////////////////////////////////////////
////                             LCD_MOD.C                              ////
////                 Driver para módulos LCD microcontrolados           ////
////                                                                    ////
////  Inspirado en librería CCS                                          ////
////  Adaptado por Fernando Nuño García y Miguel Ángel José Prieto para ////
////  funcionamiento con el LCD integrado en la placa PICDEM-2-PLUS.    ////
////  Adaptado por Jaime Fernández-Caro para usar LCD de 20x4           ////
////                                                                    ////
////  Funciones definidas                                               ////
////                                                                    ////
////  lcd_init()   Inicialización,llamar antes de cualquier otra función////
////                                                                    ////
////  lcd_putc(c)  Muestra c en la posicion siguiente del LCD.          ////
////                  Caracteres de control:                            ////
////                   f  Borra display                                ////
////                  
  Sitúa cursor al comienzo de la línea 2       ////
////                     Retrocede el cursor una posición             ////
////                        Avanza el cursor una posición                ////
////                    Retrocede una posición la pantalla visible   ////
////                   v  Avanza una posición la pantalla visible      ////
////                                                                     ////
////                                                                    ////
////  lcd_gotoxy(x,y) Sitúa escritura en posición del LCD               ////
////    (posición 1,1: arriba a la izquierda)                              ////
////                                                                    ////
////  lcd_getc(x,y)   Devuelve carácter en posición x,y del LCD         ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,1997 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.                                ////
////////////////////////////////////////////////////////////////////////////

// Conexión a 7 pines del MCU: 3 de control / interface de datos de 4 bits:
//
//    Líneas de control asignadas
//     RC0  enable
//     RC1  rw
//     RC2  rs
//
//    Líneas de Datos
//     RA0  D4
//     RA1  D5
//     RA2  D6
//     RA3  D7
//
//

struct lcd_pines_control {   // Estructura que se define para facilitar acceso

           boolean enable;   // y asociarlos a los 3 bits más bajos del PORTC
           boolean rw;      // asignamos luego a esta estructura el PORTC
           boolean rs;      // rs (1º corresponde al menos significativo
           boolean nada;   // a los pines de control del LCD
           int     otros:4;
        } lcd_control;

struct lcd_pines_datos {   // Hacemos lo mismo con esta estructura para el PORTA
           int     datos:4;   // los 4 bits más bajos son los de datos
           int     no_usados:4;
       } lcd_datos;


#byte lcd_control = 0xF82            // Ponemos la estructura entera en el PORTC
#byte trisc = 0xF94               // Registro de dirección de datos

#byte lcd_datos = 0xF80               // Lo mismo para los datos, en el PORTA
#byte trisa = 0xF92               // Registro de dirección de datos




//Prototipos de las funciones posteriores

void lcd_init();
byte lcd_read_byte();
void lcd_send_nibble(byte n);
void lcd_send_byte(byte address, byte n);
void lcd_gotoxy(byte x, byte y);
void lcd_putc(char c);
char lcd_getc(byte x, byte y);
void lcd_clr_line(char fila);


///////////////////////////////////////////////////////////////////////////////////////////
/// Función que inicializa el LCD, se deberían cambiar bits para cambiar configuracion
///////////////////////////////////////////////////////////////////////////////////////////

void lcd_init() {
    byte i;

    trisc&=0b11111000; // Asignamos salidas en RC0, RC1 y RC2, resto puerto como estaba

    trisa&=0b11110000; // Lo mismo para RA0 a RA3
    lcd_control.rs = 0;
    lcd_control.rw = 0;
    lcd_control.enable = 0;
    delay_ms(15);

    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);

    lcd_send_byte(0,0b00101000); ///Se envía Function set   0 0 1 DL N F  -  -
    lcd_send_byte(0,0b00001100); ///Se envía Display on/off 0 0 0 0  1 D  C  B
    lcd_send_byte(0,0b00000001); //Se envía Clear Display
    lcd_send_byte(0,0b00000110); //Se envía Entry Mode set  0 0 0 0  0 1 I/D S//

// DL: datos 4 bits(0); 8 bits (1) / N: 2 líneas (1); 1 línea (0) / F: 5x10 (1); 5x8 (0)
// D: display on (1); off (0) / C: cursor on (1); off (0) / B: parpadeo pos.cursor (1); no (0)
// I/D: incremento en R/W (1) o decremento (0) / S: acompaña desplaz.display (1); no (0)
}



/////////////////////////////////////////////////////////////////////////////////////////////
// Lee el byte señalado por el puntero, 1º parte alta, 2º parte baja
// Si al llamar a esta función rs=0, devuelve busy flag (+signif.) y dirección actual
/////////////////////////////////////////////////////////////////////////////////////////////

byte lcd_read_byte()
{
      byte low,high;

      trisc&=0b11111000; //Las señales de control siguen siendo salidas, el resto lo que sean
      trisa|=0b00001111; //Las de datos pasan a ser entradas, las demas igual

      lcd_control.rw = 1;
      delay_cycles(1);
      lcd_control.enable = 1;
      delay_cycles(1);
      high = lcd_datos.datos;
      lcd_control.enable = 0;
      delay_cycles(1);
      lcd_control.enable = 1;
      delay_us(1);
      low = lcd_datos.datos;
      lcd_control.enable = 0;

      trisa&=0b11110000; // Dejamos RD0 a RD3 como salidas

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



/////////////////////////////////////////////////////////////////////////////////////////////
// Envía medio byte, los 4 bits más bajos de n
// Necesario poner rs y rw de modo adecuado y entrar con enable=0
/////////////////////////////////////////////////////////////////////////////////////////////

void lcd_send_nibble( byte n )
{
      lcd_datos.datos = n;
      delay_cycles(1);
      lcd_control.enable = 1;
      delay_us(2);
      lcd_control.enable = 0;
}



/////////////////////////////////////////////////////////////////////////////////////////////
// Envía un byte (n) al registro de instrucciones (si address=0) o reg. de datos (address=1)
// Utiliza lcd_send_nibble(n) enviando primero nibble alto del byte
/////////////////////////////////////////////////////////////////////////////////////////////

void lcd_send_byte( byte address, byte n )
{
      lcd_control.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ; //Mientras esté ocupado el LCD, espera
      lcd_control.rs = address;
      delay_cycles(1);
      lcd_control.rw = 0;
      delay_cycles(1);
      lcd_control.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0x0F);
}



/////////////////////////////////////////////////////////////////////////////////////////////
// Sitúa el contador de direcciones en la DDRAM (para lectura o escritura posterior)
// x puede ir de 1 a 40, posición dentro de una línea (16 visibles)
// y puede ser 1 (línea 1) o 2 (línea 2)
/////////////////////////////////////////////////////////////////////////////////////////////

void lcd_gotoxy( byte x, byte y)
{
   byte posicion;

   switch(y)
   {
     case 1 : posicion=0x80;break;
     case 2 : posicion=0xc0;break;
     case 3 : posicion=0x94;break;
     case 4 : posicion=0xd4;break;
   }
   posicion+=x-1;
   lcd_send_byte(0,0x80|posicion); //Las direcciones de la DDRAM empiezan por 1xxxxxxx
}



////////////////////////////////////////////////////////////////////////////////////////////
// Envía un carácter c a la DDRAM del LCD, también algunos caracteres de control
////////////////////////////////////////////////////////////////////////////////////////////

void lcd_putc( char c)
{
   switch (c)
   {
     case "f"   : lcd_send_byte(0,1);    //Limpia la pantalla
                   delay_ms(2);
                   break;
     case "
"   : lcd_gotoxy(1,2);       //Coloca puntero en 1ª posicion de la 2ª línea
                   break;
     case ""   : lcd_send_byte(0,0x10); //Retrocede una posición el cursor
                   break;
     case "   "   : lcd_send_byte(0,0x14); //Avanza una posición el cursor
                   break;
     case ""   : lcd_send_byte(0,0x18); //Retrocede una posición la pantalla visible
                   break;
     case "v"   : lcd_send_byte(0,0x1C); //Avanza una posición la pantalla visible
                   break;
     default     : lcd_send_byte(1,c);    //Envía caracter a DDRAM,
                   break;                 //Si es una tira, los envía todos uno a uno
   }
}



///////////////////////////////////////////////////////////////////////////////////////////
// Devuelve el carácter situado en la posición x,y de la DDRAM
///////////////////////////////////////////////////////////////////////////////////////////

char lcd_getc( byte x, byte y) {
   char value;

    lcd_gotoxy(x,y);
    lcd_control.rs=1;
    value = lcd_read_byte();
    lcd_control.rs=0;
    return(value);
}



////////////////////////////////////////////////////////////////////////////////////
// Limpia la linea correspondiente y se situa al principio de la misma            //
////////////////////////////////////////////////////////////////////////////////////

void lcd_clr_line(char fila)
{
   int j;

   lcd_gotoxy(1,fila);
    for (j=0;j<40;j++) lcd_putc(" ");

    lcd_gotoxy(1,fila);
}



No se muy bien como afrontarlo, creo q es akí:
trisc&=0b11111000; // Asignamos salidas en RC0, RC1 y RC2, resto puerto como estaba

    trisa&=0b11110000; // Lo mismo para RA0 a RA3

es decir, la forma que tiene de configurar el puerto, ya q el sensor tiene 2 lineas, una de datos (bidireccional), y la del reloj, y al configurar el LCD cuelga al sensor...

Lo que creo debo hacer es (esto no se si funcionará) desabilitar el LCD mientras se esté leyendo el sensor... esto no se como hacerlo.
Otra solución es poner el LCD el solo en el puerto A(solo dispongo de este completo, ya q el sensor puedo ponerlo en el lugar q ocupan actualmente las lineas de control), el problema esq estoy haciendo uso de 7 lineas, y el puerto A solo tiene 6, por lo que habia pensado en deshabilitar la linea RW, ya que en mi diseño no voy a hacer uso de esta linea, debería ponerla a GND, el problema esq la librería si hace uso de ella...y no se como readaptarlo
Otra opción pasa por readaptar la librería xlcd.c (del C18) para que funcione con el CCS, pero parece algo complejo.

Se os curre algo???, lo deseable sería la primera solución, e incluso la segunda :p

Gracias y Un Saludo ;)

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: Porblema LCD y sensor digital
« Respuesta #1 en: 15 de Febrero de 2005, 07:18:00 »
vaya acabo de ver justito debajo de este post, uno donde postean una librería que es como lo q andaba buscando... voy a probarlo y os cuento

Salu2!

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: Porblema LCD y sensor digital
« Respuesta #2 en: 15 de Febrero de 2005, 10:20:00 »
vale problema resuelto Sonrisa aparte del lcd parece que tenia un problema la linea de datos, con una pullup se ha solucionado, os pongo el código del LCD por si os interesa

Codigo:

//include LCD para CCS

// La ventaja de este codigo es que puedes trabajar si lo quieres con pines
// dispersos es decir no estas sujeto a la mitad de un puerto

// Registros de Puertos A
#define PORTA 0xf80 // Puerto A
#define TRISA 0xf92 // Tris A

// Definición de Puertos Pantalla LCD 40x20 Hitachi 44780
#bit lcd_db4 = PORTA.0
#bit tris_lcd_db4 = TRISA.0
#bit lcd_db5 = PORTA.1
#bit tris_lcd_db5 = TRISA.1
#bit lcd_db6 = PORTA.2
#bit tris_lcd_db6 = TRISA.2
#bit lcd_db7 = PORTA.3
#bit tris_lcd_db7 = TRISA.3
#bit lcd_en = PORTA.4
#bit tris_lcd_en = TRISA.4
#bit lcd_rs = PORTA.5
#bit tris_lcd_rs = TRISA.5


// lcd_init() Inicialización del LCD (debe utilizarse al principio,
// antes de trabajar con el LCD).
//
// lcd_putc(c) Imprime un caracter en el LCD.
//
// lcd_gotoxy(x,y) Selecciona la nueva posicion de escritura en el LCD.
// (la esquina superior izquierda es 1,1)
//
// lcd_getc(x,y) Devuelve el caracter de la posicion x,y del LCD.
//
// void lcd_erase_line(x) Borra una cantidad de caracter hacia la derecha

// Conexion a la pantalla LCD 40x4
// RA0 <---> LCD DB4
// RA1 <---> LCD DB5
// RA2 <---> LCD DB6
// RA3 <---> LCD DB7
// RA5 <---> LCD ENABLE
// RA4 <---> LCD RS
//

#define LCD_DATO 1
#define LCD_INST 0

#define LCD_LINEA1 0x80 // Direccion de memoria para la 1 linea
#define LCD_LINEA2 0xc0 // Direccion de memoria para la 2 linea
#define LCD_LINEA3 0x94 // Direccion de memoria para la 3 linea
#define LCD_LINEA4 0xd4 // Direccion de memoria para la 4 linea



// 7 6 5 4 3 2 1 0
// Function Set 0b 0 0 1 B L F 0 0
// Bus size, B:0=4 bits, B:1=8 bits
// Line Number, L:0=1 Line, L:1=2 Lines
// Font size F:0=5x8, F:1=5x10
#define LCD_FUNCTION_SET 0b00101000 // Bus=4bit, Line=2 & Font=5x8

// 7 6 5 4 3 2 1 0
// Display/Cursor 0b 0 0 0 0 1 D U B
// Set Display on/off, D:0=off, D:1=on
// Underline cursor, U:0=off, U:1=on
// Blinking cursor, B:0=off, B:1=on
#define LCD_DISPLAY_CURSOR 0b00001100 // Display=on, Scroll=off, Blinkin=off

// 7 6 5 4 3 2 1 0
// Entry Mode 0b 0 0 0 0 0 1 M S
// Cursor direction, M:0=left, 1=right
// Display Scroll, S:0=no scroll, S:1=scroll
#define LCD_ENTRY_MODE 0b00000110 // Increment cursor, no disp shift

#define LCD_CLEAR_DISPLAY 0b00000001 // Clear Display

void lcd_set_write()
{
   tris_lcd_db4 = 0; //
   tris_lcd_db5 = 0; //
   tris_lcd_db6 = 0; //
   tris_lcd_db7 = 0; //---> Set porta RA0-RA3 mode output
}


void lcd_send_nibble(int8 n)
{
   if (bit_test(n,0)) //
      lcd_db4 = 1; //
   else //
      lcd_db4 = 0; //
   if (bit_test(n,1)) //
      lcd_db5 = 1; //
   else //
      lcd_db5 = 0; //
   if (bit_test(n,2)) //
      lcd_db6 = 1; //
   else //
      lcd_db6 = 0; //
   if (bit_test(n,3)) //
      lcd_db7 = 1; //
   else //
      lcd_db7 = 0; //---> Set data nibble
   delay_cycles(1); // nop
   lcd_en = 1; // Habilita LCD Enable __
   delay_us(2); // Espera 2 uSeg. | |
   lcd_en = 0; // Desabilita LCD Enable __| |__
}

void lcd_send_byte (int1 select, int8 n)
{
   lcd_rs = 0; // Modo de instruccion
   lcd_rs = select; // Escoje entre RS=0 : Instruccion & RS=1 : Data
   delay_cycles(5); // nop
   lcd_en = 0; // Desabilita LCD Eneable
   lcd_send_nibble(n >> 4); // Envia los datos superiores MSB
   lcd_send_nibble(n); // Envia los datos inferiores LSB
}

void lcd_init()
{
   int8 i, count=0;
   lcd_set_write(); // Prepara el puerto DB4-DB7 como salida
   tris_lcd_en = 0; //
   tris_lcd_rs = 0; //---> Set porta RA0, RA1 & RA2 mode output
   lcd_en = 0; //
   lcd_rs = 0; //---> Clear LCD_EN, LCD_RW & LCD_RS
   delay_ms(15);
//   retry:
   for(i=1; i<=3; ++i)
   {
      lcd_send_nibble(0b0011); // 8 bit mode 3 times
      delay_ms(5);
   }
   lcd_send_nibble(0b0010); // 4 bit mode
   lcd_send_byte(LCD_INST, LCD_FUNCTION_SET); // Function Set
   lcd_send_byte(LCD_INST, LCD_DISPLAY_CURSOR); // Display Cursor
   lcd_send_byte(LCD_INST, LCD_ENTRY_MODE); // Entry Mode
   lcd_send_byte(LCD_INST, LCD_CLEAR_DISPLAY); // Clear Display
}

void lcd_gotoxy(int8 x, int8 y)
{
   int8 const address[4]={LCD_LINEA1,LCD_LINEA2,LCD_LINEA3,LCD_LINEA4};
   int8 pos;
   pos=address[y-1]+(x-1);
   lcd_send_byte (LCD_INST, pos);
}

void lcd_putc(char c)
{
   lcd_send_byte(LCD_DATO,c);
}

void lcd_clear()
{
   lcd_send_byte(LCD_INST,0x01);
}

void lcd_home()
{
   lcd_send_byte(LCD_INST,0x02);
}

void lcd_erase_line(int8 x)
{
   int8 i;
   for(i=1;i<=x;++i)
   {
      lcd_send_byte(LCD_DATO,32);
   }
}



Salu2!


 

anything