Autor Tema: Problema con el PORT_A y LCD  (Leído 2119 veces)

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

Desconectado juanelete

  • PIC12
  • **
  • Mensajes: 74
Problema con el PORT_A y LCD
« en: 16 de Diciembre de 2007, 08:45:09 »
Hola a tod@s

Quiero usar las lineas RA0-RA3 de un 16f876 para conectar el bus de datos de un LCD, y no hay forma de que funcione.

Conozco perfectamente el funcionamiento del driver de inicializacion del LCD, de hecho tengo varios drivers modificados y adaptados a mis necesidades, funcionando perfectamente tanto con 4, como con 8 bits. El driver que quiero utilizar funciona perfectamente siempre y cuando no intente utilizar el puerto A como bus de datos.

Hay algun problema para utilizar RA0-RA3 como bus de datos?, hay que tener algo en cuenta?, aparte de declarar los pines como digitales y ponerlos como salidas.

Aqui teneis el driver para 4 bit

Código: [Seleccionar]
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//               Libreria  LCD_4B20x4.lib.C                         
//                                                                                                                                   
//  Bus 4 bits datos, lineas 4x20, Datos en PORT_A (RA0-RA3) y Control en PORT_C (RC0,RC1),
//  sin utilizar R/W (Bussy Flag) y con retardos, en total 6 lineas
//                                                                 
//  Funciones:                     
//                                                                   
//  lcd_init()   Must be called before any other function.           
//                                                                   
//  lcd_putc(c)  Will display c on the next position of the LCD.     
//                     The following have special meaning:         
//                      \f  Clear display                           
//                      \n  Go to start of second line               
//                      \b  Move back one position                   
//                                                                   
//  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)   
//                                                                   
//  (NO) lcd_getc(x,y)   Returns character at position x,y on LCD         
//           
//  PINES PIC           PINES LCD
//  1                                                Masa
//  2                                                VDD 5V
//  3                                                Contraste
//  2-5   RA0-RA3       11-14  D4-D7
//  11    RC0              4        RS
//  5      R/W                                    Masa=0
//  12    RC1              6        E
// 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////


// Configurar puertos segun el PIC utilizado
#define PORT_A 0x05
#define PORT_B 0x06
#define PORT_C 0x07
#define PORT_D 0x08
#define PORT_E 0x09

#define LCD_TRIS_WRITE 0b00000000
#define LCD_TRIS_READ  0b11111111

#define LCD_RS_COMANDO     0     //RS
#define LCD_RS_CARACTER    1     //RS

struct lcd_bus_dat        // Declaro la structura que va a contener los bits de datos del LCD
{
   int nibble_bajo : 4;       // Nible bajo (Solo se usa en bus datos 8 bits, junto con el nible alto)
   int nibble_alto : 4;       // Nible alto, Bus de datos del LCD de 4 bits
} lcd;


#byte lcd = PORT_A        // Aqui hay que elegir el puerto para el bus de datos (PORT_B, PORT_C,...)

// Ahora vamos a elegir donde conectaremos los pines de control del LCD.
#bit lcd_rs     = PORT_C.0    //11
#bit lcd_enable = PORT_C.1    //12

#define set_tris_lcd(x) set_tris_A(x)

#define FUN_SET          32     // Funcion SET. Solo se puede utilizar en la inicializacion
#define LCD_FUENTE      0     // 0=5x7, 4=5x10
#define LCD_LINEAS      8     // 0=1 Linea, 2=2 Lineas, 8=2 Lineas ó mas.
#define LCD_BUS           0     // 0=4 Bits (D4-D7), 16=8 Bits (D0-D7)

#define DISPLAY_CTRL    8     // Funcion Display control
#define LCD_BLINK         0     // Parpadeo cursor 'ƒ'.  0=Off, 1=On
#define LCD_CURSOR      0     // Visualizacion cursor '_'.  0=Off, 2=On
#define LCD_DISPLAY      4     // Display encendido o apagado.  0=Off, 4=On ** ojo, mientras este Off no veras nada **

#define CLEAR_DISPLAY   1     // Funcion Borrar pantalla

#define ENTRY_MODE          4     // Funcion Modo entrada
#define DESPLAZ_TXT         0     // 0=Off, 1=On   Desplazamiento del texto al escribir un nuevo caracter
#define INC_DEC_CURSOR  2     // 0=Decremento, 2=Incremento  Incr/Decr autoamtico de la pos. del cursor

#define RETURN_HOME        2     // Funcion Poner el cursor en 0,0

#define CURSOR_DISPLAY   16    // Funcion para controlar los desplazamientos del cursor y la pantalla
#define LCD_RL                    0     // 0=Izquierda,  4=Derecha
#define LCD_SC                   0     // 0=Solo cursor, 8=Cursor y DDRAM

#define LCD_GOTO_XY       128     // Funcion para situar el cursor en la pos. deseada


int8 lcd_linea=1;           //Numero de linea donde estamos (necesario para el comando \n)


// Envia el nibble al LCD
void lcd_send_nibble(int8 dato)  // Formato n -> 0000 DDDD    DDDD = nibble a enviar
{
   lcd.nibble_alto = dato;                      //Como cargo un byte en una variable de 4 bits se pierde la parte alta del byte
   delay_cycles(1);
   lcd_enable = 1; 
   delay_us(2);
   lcd_enable = 0;
}

// Esta funcion descompone el dato en dos nibbles y los mete en sendos bytes para enviarlos a LCD
void lcd_send_byte( int8 modo, int8 dato )   // RS=0 ó 1    RW=0 ESCRIBIR
{
   lcd_rs = modo;                                       // 0 = Modo comando,  1 = Modo caracter
   delay_cycles(1);                                     
   lcd_enable = 0;             
   lcd_send_nibble(dato >> 4);                    // Elimino la parte baja y envio la parte alta con este formato: 0000 AAAA
   lcd_send_nibble(dato & 0xf);                   // Pongo a cero la parte alta y solo envio la parte baja 0000 BBBB
   if(modo==LCD_RS_CARACTER)
        delay_us(40);               //Retardo necesario modo caracter (No se comprueba Bussy Flag)
   else
        delay_ms(2);                //Retardo necesario modo comando
}



// Antes de nada hay que inicializar el LCD segun una secuencia determinada por el fabricante
void lcd_init()   // 4 Bit
{
    int8 i;

    set_tris_lcd(LCD_TRIS_WRITE);                  //Pines puerto datos como salida
    set_tris_c(0b00000000);                            //Pines puerto control como salida

    lcd_enable = 0;               
    lcd_rs = LCD_RS_COMANDO;                   //Modo comando
    delay_ms(15);                   

    for(i=0;i<3;i++)                                     //3 veces
    {
        lcd_send_nibble(0b0011);                   //0011 Segun Datasheet
        delay_ms(5);               
    }
    lcd_send_nibble(0b0010);                      //0010 Segun Datasheet

   lcd_send_byte(LCD_RS_COMANDO,FUN_SET | (LCD_FUENTE + LCD_LINEAS + LCD_BUS));
   lcd_send_byte(LCD_RS_COMANDO,DISPLAY_CTRL | (LCD_DISPLAY + LCD_CURSOR + LCD_BLINK));
   lcd_send_byte(LCD_RS_COMANDO,CLEAR_DISPLAY);
   lcd_send_byte(LCD_RS_COMANDO,ENTRY_MODE | (DESPLAZ_TXT + INC_DEC_CURSOR));
   lcd_send_byte(LCD_RS_COMANDO,RETURN_HOME);
}


void lcd_gotoxy( byte x, byte y)
{
   int8 pos;

   switch(y)
   { 
      case 1 : pos=0x80; break;     
      case 2 : pos=0xc0; break;     
      case 3 : pos=0x94; break;     
      case 4 : pos=0xd4; break;           
   }

   lcd_send_byte(LCD_RS_COMANDO,LCD_GOTO_XY | pos+x-1); //Las direcciones de la DDRAM empiezan por 1xxxxxxx

   // 1DDDDDDD Comando Desplazamiento cursor
   // 0x80 = 10000000  Osea que para poner el valor del desplazamiento en el comando, hay que hacer OR con 0x80
   // Ejemplo: Col=8 y Lin=2 => address=0x40 + 0x08 - 0x01 = 0x47 = 01000111 Este seria el desplazamiento
   // Ahora hay que poner (hacer OR) en el byte comando el valor del desplazamiento: 10000000 OR 01000111 = 11000111
}


void lcd_putc( char c)
{
   switch (c)
   {
      case '\f': lcd_send_byte(LCD_RS_COMANDO,CLEAR_DISPLAY);
                 lcd_linea=1;   //El cursor esta en la primera linea
                 break;
      case '\n': lcd_gotoxy(1,++lcd_linea); // Desplaza cursor siguiente linea
                 break;
                                        // 00010000 Comando desplazar cursor, sin alterar ddram, Izquierda
      case '\b': lcd_send_byte(LCD_RS_COMANDO,CURSOR_DISPLAY | (LCD_RL + LCD_SC));
                 break;         
      default  : lcd_send_byte(LCD_RS_CARACTER,c);             // Envio byte en modo caracter
                 break;
   }
}


Y el programa de prueba

Código: [Seleccionar]
////////////////////////////////////////////////////////////////////////////////
//                        pruLCD4B20x4v4.c
//                                                                           
// PIC: 16F876
// Programa de prueba para probar la libreria LCD_4B20x4v4.lib.c
//
////////////////////////////////////////////////////////////////////////////////

#INCLUDE <16F876.H>

#fuses HS,NOWDT,NOPROTECT,NOLVP

#use delay(clock=20000000)

#include <LCD_4B20x4v4.lib.C> 


void main()
{
    char c;
   
    setup_adc_ports( NO_ANALOGS );  //Todos los puertos digitales
    set_tris_A(0b00000000);               //Puerto A como salidas
    delay_ms(100);

    lcd_init();
    lcd_putc("\fPreparado...\n");
   
    while(1);
}


Decime si se os ocurre algo.

Gracias anticipadas   :mrgreen:

Saludos a tod@s


Desconectado maxluis

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 129
Re: Problema con el PORT_A y LCD
« Respuesta #1 en: 16 de Diciembre de 2007, 10:35:15 »
Estimado Juanelete: Revisa la pagina del Amigo Redpic ahi tiene una libreria "flexible" para los LCDs`
saludos.
Maxluis.

Desconectado juanelete

  • PIC12
  • **
  • Mensajes: 74
Re: Problema con el PORT_A y LCD
« Respuesta #2 en: 16 de Diciembre de 2007, 15:08:10 »
Hola maxluis

La conozco, y se que funciona perfectamente.

Pero quiero saber porque no funciona esta con el puerto A y si funciona con cualquier otro puerto.

Gracias por responder.   :)

Saludos a tod@s

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Problema con el PORT_A y LCD
« Respuesta #3 en: 16 de Diciembre de 2007, 15:42:52 »
He estado dándole un vistazo y no veo tampoco cuál puede ser el problema. He visto que al reset el 18F876 configura el PORTA como entradas analógicas, pero eso debería estar solucionado con tu setup_adc_ports( NO_ANALOGS );  :shock:

Añádele por si acaso también el SETUP_ADC(ADC_OFF); 

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado juanelete

  • PIC12
  • **
  • Mensajes: 74
Re: Problema con el PORT_A y LCD
« Respuesta #4 en: 16 de Diciembre de 2007, 16:35:15 »
Hola a tod@s

!!!! SOLUCIONADO  !!!!!   :-/

He estado revisando el codigo y al final he encontrado el problema, a saber:

!! MI IGNORANCIA !! (90%)  y la casualidad (10%)  :?

Me explico:

Este driver lo hice hace ya mas de un año, y ha estado funcionado perfectamente, hasta ahora, porque casualmente siempre he utilizado el nibble alto de un puerto para el bus de datos del LCD. Pero en el momento que lo he configurado para utilizar el nibble bajo para el bus, no funciona :(  ,  porque tal y como esta programado siempre saca el dato por el nibble alto del puerto.

Hare la correspondiente modificacion para arregarlo.

Gracias a todos  :mrgreen:

Saludos

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Problema con el PORT_A y LCD
« Respuesta #5 en: 16 de Diciembre de 2007, 18:34:21 »
Bien está lo que bien acaba.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado telojurito

  • PIC12
  • **
  • Mensajes: 55
Re: Problema con el PORT_A y LCD
« Respuesta #6 en: 23 de Septiembre de 2008, 21:59:16 »
Amigo Juanelete,

Podrias pasarme el código a 8 bits para un LCD 4x20?

Yo tengo uno con el controlador PCM2004A y usa el controlador S6A0069. Te lo pido ya que tengo problemas tanto para inicializarlo a 4 lineas y para escribir caracteres. Estoy usando un PIC16F76 con cristal de 8MHz y si lo tuvieras en assembler magnifico ya que no uso el C o en una especie de diagrama a bloques seria suficiente. Ahora que si solo lo tienes en C, pues venga ya me las arreglare para entenderloy pasarlo a assembler.

saludos y gracias de antemano


 

anything