LCD 44780 4-bits para PIC16F, driver y ejemplo.

Página 1 de 2. 1, 2  Siguiente

Ver el tema anterior Ver el tema siguiente Ir abajo

LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por arcachofo el Jue 27 Nov 2008 - 3:24

Con este driver se puede manejar un LCD compatible con 44780 en modo 4-bits, su funcionamiento es independiente de la velocidad de reloj, que tiene que estar definida en el programa principal: #define FREQ 8000 //para 8MHz.

El caso es que todavía no he conseguido que funcione a 4 MHz, pero lo he probado desde 8 a 20 MHz con PIC16f876A y PIC16F627A, se agradería confirmación de que funciona con otros PIC16F... o de no funciona...claro.

En el driver hay una seción donde se definen los pines a utilizar, la cosa es copiarla, pegarla en el programa principal y ajustar los datos a tus necesidades, además hay información sobre las funciones implementadas. El driver tiene sus propias funciones de retardo, utilizables en el programa principal: espera_ms() y pausa()

Este es el driver (lcd_sdcc_sgr.h):

Código:
 

/*****************************************************************************
******************************************************************************
****                                                                      ****
****            --- DRIVER LDC 44780 4-BITS para PIC16F ---              ****
****                                                                      ****
******************************************************************************
******************************************************************************

// This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


                            FUNCIONES DISPONIBLES:
------------------------------------------------------------------------------
lcd_car()        //envia un caracter, ejemplo: lcd_car("A");
lcd_dato()        //envía byte, ejemplo: char a= 0xE5; lcd_dato(a); lcd_dato(0xE5)
lcd_comand()        //envía comando, ejemplo: lcd_comand(linea2); lcd_comand(0x0E)
lcd_num()        //envía número entero (int), ejemplo: lcd_num(1756);
lcd_clear()        //borra display.
lcd_init()        //inicializa lcd.
espeara_ms()        //delay milisegundos, ejemplo: espera_ms(10);
pausa()            //delay 4xValor+1 µs, ejemplo: pausa(2); pausa de 9 µs.

********************************************************************************
********************************************************************************

        EN EL PROGRAMA PRINCIPAL DONDE VAYA A USAR LAS FUNCIONES LCD
INSERTAR LAS SIGUIENTES LINEAS CON LAS DEFINICIONES DE PUERTO Y RELOJ USADOS:

//---------------------------- PUERTO LCD --------------------------------
//------------------------------------------------------------------------

#define RS RC1            //PIN PARA RS.
#define RW RC2            //PIN PARA RW.
#define EN RC3            //PIN PARA ENABLE.
#define DATOT TRISC        //TRIS DE DATOS, PINES 4, 5, 6, 7 DEL PUERTO.
#define DATOP PORTC        //PORT DE DATOS, MISMO PUERTO.

#define FREQ 8000        // 8000 KHz = 8 Mhz, LA FRECUENCIA EN KHz.

#include "lcd_sdcc_sgr.h"


********************************************************************************
*******************************************************************************/


//----------------------------- ACCIONES ---------------------------------
//------------------------------------------------------------------------
#define write  RW = 0; pausa(u9); DATOT &= 0x0F; pausa(u9)
#define read  DATOT |= 0xF0; pausa(u9); RW = 1; pausa(u9)
#define EN0 EN = 0; pausa(u9)
#define EN1 EN = 1; pausa(u9)

//--------------------------- COMANDOS LCD -------------------------------
//------------------------------------------------------------------------
#define clear                0x01 // Clear Display
#define home              0x02 // Cursor a Home
#define normal            0x06 // Normal
#define rev            0x04 // Normal-reverse
#define scroll            0x07 // con scroll
#define scroll_rev        0x05 // Reverse
#define d8_bit            0x38 // 8 bit 2 lineas ( 5x7 font )
#define d4_bit            0x28 // 4 bit 2 lineas ( 5x7 font )
#define reset            0x30 // Reset
#define dis_on                0x0C // Display on modo 2 lineas
#define dis_off              0x08 // Display off
#define linea1              0x80 // Linea 1 posicion 1
#define linea2              0xC0 // Line 2 posicion 1
#define cursor_on            0x0E // Cursor on
#define cursor_off            0x0C // Cursor off
#define blink_on          0x0F // Cursor blink
#define cursor_der        0x14 // Mover cursor derecha
#define cursor_izq        0x10 // Mover cursor izquierda
#define display__der        0x1C // Scroll display derecha
#define display__izq        0x18 // Scroll display izquierda
#define cg_addr            0x40 //

//----------------------- CONFIGURAR VARIABLES ---------------------------
//------------------------------------------------------------------------
unsigned char d;
unsigned char n;
unsigned char coms = FREQ / 4000;
unsigned char u9 = FREQ / 2000;
unsigned char pa = FREQ / 400;

//----------------------------- FUNCIONES --------------------------------
//------------------------------------------------------------------------

void pausa( unsigned char a )           
{    a;                //tiempo = (4a + 1)µs a>=2, para 4MHz
    _asm                // "a" ya está en w
    sublw 1   
    bucle:
    addlw 1
    btfss STATUS,0
    goto bucle
    _endasm;
}

void espera_ms( unsigned int ms )
{
    ms = ms * coms;
    while (ms > 0 )
    {
        pausa(247);
        ms--;
    }
}

char lcd_read()
{
    read;                //modo lectura
   
    EN1;
    d = DATOP & 0xF0;        //lee nibble alto
    EN0;
   
    EN1;
    d |= DATOP >> 4;        //lee nibble bajo
    EN0;
   
    return d;
}
   
char lcd_busy()
{
    RS = 0;
    lcd_read();
   
    d = d & 0x80;            //aisla bit busy
   
    if( d == 0x80 )        //comprueba si está ocupado
        return(1);
    else   
        return(0);
}   

void write_n( char dat )
{
    write;                //modo escritura
   
    DATOP &= 0x0F;
    DATOP |= dat & 0xF0;        //escribe nibble alto
    EN1;
    EN0;
   
    dat <<= 4;
   
    DATOP &= 0x0F;
    DATOP |= dat & 0xF0;        //escribe nibble bajo
    EN1;
    EN0;
    pausa(pa);
}

void lcd_dato( char dato )
{
    while( lcd_busy() == 1 );    //leer bit busy hasta que sea 0
    RS = 1;                //modo datos
    write_n( dato );
}

void lcd_comand( char comand )
{
    RS = 0;                //modo comandos
    write_n( comand );
}

void lcd_clear()
{
    lcd_comand( clear );
    lcd_comand( home );
}

void lcd_init( void )
{
    DATOT = 0;            //todo a salidas
    DATOP = 0;            //todo a 0
    espera_ms(20);
    write_n( reset );        //secuancia de reset
    espera_ms(10);
    write_n( reset );
    pausa(pa);
    write_n( reset );
    pausa(u9);            //secuencia de inicio:
    lcd_comand( d4_bit );        //0x28 modo 4 bits 2 lineas
    lcd_comand( normal );        //0x06 entrada normal hacia adelante
    lcd_comand( dis_on );        //0x0c display on
    lcd_comand( linea1 );        //0x80 linea 1 posicion 1
}

void lcdh( char a )
{
    if (a > 9)
        a += 55;
    else
        a += 48;
    lcd_dato(a);
}


void lcd_hex( char nb )
{
    char n;
    n = ( nb >> 4 ) & 0x0f;
    lcdh(n);
    n = nb & 0x0f;
    lcdh(n);
}

void lcd_num( int num )
{
    lcd_hex( num >> 8 );
    lcd_hex( num & 0xff );
}

void lcd_car( unsigned char *car )
{
    char n = 0;
    while( car[n])
    {
        lcd_dato( car[n] );
        n++;
    }
}



guardarlo con el nombre: lcd_sdcc_sgr.h. o con otro nombre y cambiar la linea include en el programa principal.


Este es un ejemplo de uso para PIC16F628A, aunque se puede cambiar la defición del pic y los bits de configuración para usarlo con otros PIC16F (lcd_Hola_Mundo.c):
Código:


/*------------------------- lcd_Hola_Mundo.c --------------------------*/
/* ----------------------------------------------------------------------- */

/* Template source file generated by piklab */

#include    //nomre del pic a usar

/* ----------------------------------------------------------------------- */
/* Bits de configuración: adapte los parámetros a su necesidad */

typedef unsigned int word;
word at 0x2007 CONFIG = _WDT_OFF & _PWRTE_ON & _HS_OSC & _MCLRE_OFF & _BOREN_OFF & _LVP_OFF & _DATA_CP_OFF & _CP_OFF;



//--------------------------- DEFINICIONES -------------------------------
//------------------------------------------------------------------------
#define RS RB1
#define RW RB2
#define EN RB3
#define DATOT TRISB
#define DATOP PORTB

#define FREQ 8000        // 8 Mhz

#include "lcd_sdcc_sgr.h"


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

void main()
{   
    char frase[] = "Hola";
    char lin[] = "Mundo";
    unsigned char n;
   
    lcd_init();
   
    while(1)
    {
        lcd_clear();
        lcd_comand( linea1 );
        espera_ms(1000);
       
        n = 0;
        while( frase[n] )
        {
            lcd_dato(frase[n]);
            n++;
        }
        espera_ms(1000);
        lcd_comand( linea2 );
       
        n = 0;
        while( lin[n] )
        {
            lcd_dato(lin[n]);
            n++;
        }
        espera_ms(1000);       
    }

}


avatar
arcachofo
Participante Activo
Participante Activo

Mensajes : 91
Fecha de inscripción : 26/11/2008

Volver arriba Ir abajo

Rutina de LDC hd44780

Mensaje por pentax33 el Dom 28 Dic 2008 - 23:46

Hola gente i felices fiestas

Por fin he podido dedicar un tiempo a mi hobby i he localizado esta libreria de funcionamiento de un LCD dejo el enlace para que la visiten.

http://www.warpedlogic.co.uk/?q=node/10

Seguire investigando.

pentax33
Participante
Participante

Mensajes : 11
Fecha de inscripción : 28/11/2008

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Sáb 16 Ene 2010 - 0:09

Hola a todos..
Estoy probando esta libreria, consulta la has probado con un osc de 4mhz.. la estoy probando con un pic. 16f876A, pero no consigo que trabaje correctamente. Pero aun estoy revisando para descartar aun error externo (de esos errores no previstos)..

RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 16 Ene 2010 - 2:38

Estoy probando esta libreria, consulta la has probado con un osc de 4mhz..

No... precisamente, a 4 MHz no me funcionaba y no sé porqué, seguramente problemas algún tiempo, pero nunca llegué a encontrar solución, recuerdo que hice bastantes pruebas, pero no hubo manera...

Pero desde 8 a 20 MHz prové con varios relojes y funcionaba bién:
El caso es que todavía no he conseguido que funcione a 4 MHz, pero lo he probado desde 8 a 20 MHz con PIC16f876A y PIC16F627A,

Quizás puedas probarlo a mayor velocidad.

En el enlace que puso pentax33 el un mensaje anterior hay una librería que es para pic18f, pero está muy bién comentada, con los tiempos necesarios en cada momento, quizás habría que repasar el código y ver donde no se cumplen los tiempos en el caso de 4MHz.


Saludos.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Sáb 16 Ene 2010 - 19:47

Gracias...
Por lo menos mi problema le a pasado a otro.. es un consuelo.. para saber que va por el codigo el problema, si debe ser algo con los tiempos, Consulta? sabes mas menos cuales son los pasos para iniciar LCd en 4bit, he encontrado algo de informacion ,ademas para despues enviar datos de 8 bit, entiendo que se envia primero los 4bit de mayor peso y despues los otros pero como se diferencias, nose si hay que esperar un tiempo o existe algun pin como de sincronismo, al parece es con En (segun la libreria). pero no estoy seguro..


Voy a hacer lo mejor .. que es pruebas tras pruebas..

RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 16 Ene 2010 - 21:25

Mira, aquí tienes información sobre la inicialización: http://www.geocities.com/dinceraydin/lcd/initalization.htm
y aquí más sobre lcd (la anterior està dentro de esta): http://www.geocities.com/dinceraydin/lcd/index.html

Pero hay al menos dos maneras de inicializar, la que se usa el la librería de este tema (3 resets) es distinta a la que usa el tipo del enlace del mensaje de Pentax.

Respecto a los nibles, yo no le puse ninguna pausa, el tema es que funciona con relojes rápidos, pero nó con 4 MHz.

Código:

void write_n( char dat )
{
    write;                //modo escritura
   
    DATOP &= 0x0F;
    DATOP |= dat & 0xF0;        //escribe nibble alto
    EN1;
    EN0;
   
    dat <<= 4;
   
    DATOP &= 0x0F;
    DATOP |= dat & 0xF0;        //escribe nibble bajo
    EN1;
    EN0;
    pausa(pa);
}


Voy a hacer lo mejor .. que es pruebas tras pruebas..
Si... el tema es que no recuerdo.. si inicializaba bien y fallaba al mandar caracteres o ni siquiera inicializaba.
Sería cuestión de ver el cursor, no recuerdo si después de inicializar estaba en modo cursor parpadeante o no.. sinó se puede poner (hay un comando)
Quizás hacer un programa que solo inicialice o que espere un tiempo antes de mandar nada y ver si el cursor parpadea.. digo para ver si inicia bién o no.



Saludos.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Sáb 16 Ene 2010 - 22:43

Gracias por la informacion.. Segun pruebas que he realizado con esta libreria, tengo problemas con lo que respecta la iniciación

Código:

lcd_init();

Si Correcto segun lo que analizo de esta lib. realiza tres reset y ademas manipula el bit EN. cada vez que los envia
Código:

void lcd_init( void )
{
    DATOT = 0;            //todo a salidas
    DATOP = 0;            //todo a 0
    espera_ms(20);
    write_n( reset );        //secuencia de reset envia 30h ,en cada reset se ejecuta
                                    //  RW = 0; pausa(u9); DATOT &= 0x0F; pausa(u9)
    espera_ms(10);
    write_n( reset );
    pausa(pa);
    write_n( reset );
    pausa(u9);            //secuencia de inicio:
    lcd_comand( d4_bit );        //0x28 modo 4 bits 2 lineas
    lcd_comand( normal );        //0x06 entrada normal hacia adelante
    lcd_comand( dis_on );        //0x0c display on
    lcd_comand( linea1 );        //0x80 linea 1 posicion 1
}

Pero despues de ejecutar Clear y Enviar un Cadena Caracteres para que lo imprima en Linea 1 , este solo imprime caracteres sin sentido. Pero lo curioso despues de hacer esto , procedo a Resetear el Pic (Pulsador entre MCLR y GND). el Lcd comienza a trabajar normalmente. por esto pienso que hay algún problema con algún tiempo o algo en la Iniciación o otra cosa rara.
Bueno ademas he probado iniciarlo de otra manera como modificando la lib.

Código:


void lcd_init( void )
{
    DATOT = 0;            //todo a salidas
    DATOP = 0;            //todo a 0
    espera_ms(20);
    EN0;
 for(i=0 ;i < 3; i++)      // 3 pero solo a los bit d4-d7 durante muchos ms
  {
DATOP &= 0x0F;
DATOP |= 0x30 & 0xF0;
espera_ms(20);
  }
    lcd_comand( d4_bit );        //0x28 modo 4 bits 2 lineas
    lcd_comand( normal );        //0x06 entrada normal hacia adelante
    lcd_comand( dis_on );        //0x0c display on
    lcd_comand( linea1 );        //0x80 linea 1 posicion 1
}

Esto funciona pero con el mismo efecto, tengo que restear el Pic para que comience a visualizar los datos que les envio.

Bueno seguire probando y revisando, estoy seguro que hay algun detalle que aun no visualizo..

Atte.
RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Dom 17 Ene 2010 - 16:12

Pero lo curioso despues de hacer esto , procedo a Resetear el Pic
(Pulsador entre MCLR y GND). el Lcd comienza a trabajar normalmente.

Esto me hace pensar que el problema no es de la secuencia: si funciona bién despues de un reset del PIC, entonces quizás el problema es otro.. quizás un tema de voltajes: En el primer enlace de mi mensaje anterior habla de eso y dice que con los 3 reset se debería solucionar esto; el caso es que la tensión tiene que estar en un punto estable > 4.5 V (o algo así), si la fuente que usas tarda un poco en alcanzar la tensión nominal, o el circuito tiene condensadores grandes... o lo que sea que retrase un poco la tensión estable, quizás falle...

No sé.. pero por probar, se podría probar a inicializar el LCD después de un par de segundos (o lo que sea) para estar seguros de que no hay problemas de este tipo.

Si el problema es de este tipo, quizás habria que subir el primer delay:
Código:
void lcd_init( void )
{
    DATOT = 0;            //todo a salidas
    DATOP = 0;            //todo a 0
    espera_ms(20);  //*******************ESTE

Por decir cosas: otra cosa a probar sería llamar la rutina de inicio del LCD dos veces... a ver que pasa.

Otra cosa: no sé si es cuestión de velocidades (funciona con 8-20 MHZ pero no con 4MHz) o cuestion de oscilador interno/externo; otra cosa a probar sería reloj externo de 4MHz.


Saludos.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Dom 17 Ene 2010 - 23:34

Gracias Pikitin.. por sus consejos ...

Es bastante bueno compartir experiencias y opiniones, mas aun ya que estos temas no son comunes donde vivo..

Bueno, sobre esperar que la tension del LCD se estabilice lo he prodabo hasta puntos absurdos osea por ejemplo. Todos los pines que van al LCd E.RW.Rs, d4-d7 en 0 y espero como 10seg y recién comienzo a función de iniciar LCD. pero el mismo efecto. ademas probé con alimentar antes el LCD y después el Pic para ver si era un tema de voltaje pero nada.. ademas he probado con ejecutar la rutina iniciación cada vez que pulso un pulsador y esto responde pero no al primer intento.

Código:
if (RB5==0){
delay_ms(100);
lcd_init();
}


Bueno estoy ya un poco frustrado.. pero son por estas situaciones que me gusta la electrónica, sigo buscando una una respuesta a este problema..

Atte.
RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Dom 17 Ene 2010 - 23:36

Ademas el LCD que estoy usando no es un HD 44780, sino un GMD1602H, segun el Datasheet es compatible el protocolo de comunicacion...


Risanti.
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Lun 18 Ene 2010 - 0:30

Quizás esto te pueda ser util: http://www.8051projects.net/lofiversion/t16483/Problem-with-LCD-1602.html
Usa el GMD1602B y sin librería, así que puedes ver la rutina de inicio (la última es la que dice que funciona).

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Mar 23 Mar 2010 - 19:30

Disculpa por no seguir con este tema. Básicamente mi trabajo me quita mucho tiempo.. jjaaj pero para esta semana retome este tema básicamente con otro LCD 16x02 que compre. mira lo raro es que con este display funciona como debería funcionar. la libreria es operativa , creo que el otro display quizá tenga algun daño, aunque solo es durante la iniciación ya que se se intenta reiteradas veces el lcd se inicia y trabaja normalmente. raro..

bueno por lo menos tengo una que funciona bien.. jajaaj

atte.
RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Lun 29 Mar 2010 - 3:40

Ok.. gracias por la información.

Por cierto.. te ha funcionado a 4Mhz??

Con oscilador interno o externo??


Saludos.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Risanti el Lun 29 Mar 2010 - 5:42

Bueno pikitin..
Estoy usando Pic16f876 a 4MHZ sin problemas.. Gracias
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Problemas al compilar

Mensaje por mentes el Vie 1 Oct 2010 - 11:05

Hola,

Al intentar compilar la librería me da un error que no he conseguido encontrar qué significa.

Código:
message: using default linker script "/usr/share/gputils/lkr/16f84a.lkr"
warning: relocation of section "UDL__mulint_0" failed, relocating to a shared memory location
error: linker script has no definition that matches the type of section "UDL__mulint_0"

Estoy utilizando un 16F84A y he puesto los fuses de este modelo

Código:
#include  <pic16f84a.h>
typedef unsigned int word;
word at 0x2007 CONFIG = _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF;

La versión de SDCC es la siguiente:

SDCC : avr/pic16/pic14/xa51 2.8.0 #5117 (Jun 2 2008) (UNIX)

mentes
Nuevo Usuario
Nuevo Usuario

Mensajes : 9
Fecha de inscripción : 01/10/2010

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Vie 1 Oct 2010 - 20:36

Hola mentes.

Es un error del linker, pero creo que solo pasa con 16f84 y 16f84a; prueba a compilarlo con otro pic para confirnarlo.

El fallo es de gputils, googlea un poco a ver que encuentras.


Saludos.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por mentes el Sáb 2 Oct 2010 - 0:33

Efectivamente cambiando el modelo a la hora de ejecutar el compilador desaparece el error. Además del 16F84 también ocurre con 16C711 que es equivalente al 16F84 en cuanto a Memoria, Ram y número de I/O.

He compilado otros programas para el 16F84 así que el problema está en esta librería. ¿Tienes idea que parte del código es la que produce el error?

También he probado a grabar el .hex compilado con otros modelos, y el LCD no inicia, supongo que en este caso el problema es por generar un .hex que no es para un 16F84.

He conseguido iniciar el LCD con la siguiente librería, pero soy incapaz de escribir algo coherente, sólo salen letras y símbolos aleatorios. No tengo muy claro como ejecutar la función para que escriba correctamente.

Código:
#ifndef LCD_H
#define LCD_H

#define LCD_DATA                PORTB // Puerto de datos
#define LCD_DATA_TRIS          TRISB // Control del puerto de datos
#define LCD_RS                  RB2  // Modo
#define LCD_ENABLE              RB3  // Habilitación/deshab. en envíos de datos al lcd.
#define LCD_CLEAR                0x01 // Clear Display
#define LCD_HOME                0x02 // Cursor a Home
#define LCD_NORMAL              0x06 // Cursor en modo incrementar.
#define LCD_REV                  0x04 // Normal-reverse
#define LCD_SCROLL              0x07 // Usa scroll
#define LCD_SCROLL_REV          0x05 // Reverse
#define LCD_D8_BIT              0x38 // 8 bit 2 lineas ( 5x7 font )
#define LCD_D4_BIT_CONF          0x20 // 4 bit
#define LCD_D4_BIT              0x28 // 4 bit 2 lineas ( 5x7 font )
#define LCD_RESET                0x30 // Reset
#define LCD_DIS_ON              0x0C // Display on modo 2 lineas
#define LCD_DIS_OFF              0x08 // Display off
#define LCD_LINE1                0x80 // Linea 1 posicion 1
#define LCD_LINE2                0xC0 // Linea 2 posicion 1
#define LCD_CURSOR_ON            0x0E // Cursor on
#define LCD_CURSOR_OFF          0x0C // Cursor off
#define LCD_BLINK_ON            0x0F // Cursor blink
#define LCD_CURSOR_DER          0x14 // Mover cursor derecha
#define LCD_CURSOR_IZQ          0x10 // Mover cursor izquierda
#define LCD_DISPLAY__DER        0x1C // Scroll display derecha
#define LCD_DISPLAY__IZQ        0x18 // Scroll display izquierda
#define LCD_CHARMODE            0x01
#define LCD_COMMANDMODE          0x00

void lcd_send_quartet( char mode, char dato );
void lcd_send( char mode, char dato );
void lcd_init (void);
void lcd_message ( char * mess );
char lcd_hexa(char a);

#endif

Código:
#include <pic16f84a.h>
#include "lcd.h"

// tiempo = (5a+1)µs a>=2  basado en micro a 20mhz

void delay_us ( char a ){
   a;
   _asm                // a ya está cargado en el registro w
   sublw 1          //(1-a)
   bucle:
   ADDLW 1
   btfss 0x03,0        //test si w=0 carry=1
   goto bucle
   _endasm;
}

void delay_ms(int ms){
    unsigned int j;
    unsigned int k = ms * 10;
    for (j=0; j<k; j++)
    delay_us (33);      //101µs
}

void lcd_send_quartet( char mode, char dato ){
    LCD_RS = mode;
    PORTB = dato  | (PORTB & 0x0f) ;
    LCD_ENABLE = 1;
    _asm                              // delay de 4µs
    nop
    nop
    nop
    nop
    _endasm;
    LCD_ENABLE = 0;
}

void lcd_send( char mode, char dato ){

    unsigned int j;
    char dat = dato;
    LCD_RS = mode;
    dat = dato & 0xf0;
    PORTB = dat | (PORTB & 0x0f) ;
    LCD_ENABLE = 1;
    _asm                              // delay de 4µs
    nop
    nop
    nop
    nop
    _endasm;
    LCD_ENABLE = 0;
    dat = ((dato<<4)& 0xf0);
    PORTB = dat | (PORTB & 0x0f) ;
    LCD_ENABLE = 1;
    _asm                              // delay de 4µs
    nop
    nop
    nop
    nop
    _endasm;
    LCD_ENABLE = 0;
    for (j=0; j<30; j++){            // delay de 41µs
      _asm
      nop
      _endasm;
    }
}

void lcd_init (void){
   LCD_DATA_TRIS &= 0x03;
   //LCD_DATA = 0x00;
   delay_ms(15);
   lcd_send_quartet(LCD_COMMANDMODE, LCD_RESET);
   delay_ms(5);
   lcd_send_quartet(LCD_COMMANDMODE, LCD_RESET);
   delay_us(25);
   lcd_send_quartet(LCD_COMMANDMODE, LCD_RESET);
   delay_us(25);
   lcd_send_quartet(LCD_COMMANDMODE, LCD_D4_BIT_CONF);
   delay_us(25);
   lcd_send(LCD_COMMANDMODE, LCD_D4_BIT);
   delay_us(25);
   lcd_send(LCD_COMMANDMODE, LCD_CLEAR);
   delay_ms(2);
   lcd_send(LCD_COMMANDMODE, LCD_CURSOR_OFF);
   delay_ms(2);
   lcd_send(LCD_COMMANDMODE, LCD_NORMAL);
   delay_us(10);
   lcd_send(LCD_COMMANDMODE, LCD_DIS_ON);
   delay_us(10);
}

void lcd_message ( char * mess ){
  while ( *mess ){
    lcd_send(LCD_CHARMODE, *mess ) ;
    mess++ ;
  }
}

char lcd_hexa(char a){
    if (a >9)
        a+=55;
    else
        a+=48;
    return a;
}

Y la función main() que yo he añadido es:

Código:
void main() {
   char *m_ptr = "Hola";
   lcd_init();
    lcd_message(m_ptr);
}

* Para ahorrar espacio he eliminado algunos comentarios del código, el autor de la librería es http://sergiols.blogspot.com/

mentes
Nuevo Usuario
Nuevo Usuario

Mensajes : 9
Fecha de inscripción : 01/10/2010

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 2 Oct 2010 - 3:15

Es raro el error este...

He compilado otros programas para el 16F84 así que el problema está en esta librería. ¿Tienes idea que parte del código es la que produce el error?
El error es del linker y no se refiere a ninguna función de la librería lcd, se refiere a la función UDL__mulint_0 que parece ser una funcion de multiplicación de int, pero tampoco es un problema de esa función, sino de que el linker no consigue posicionarla correctamente en memoria y luego no la encuentra cuando tiene que usarla.... o algo así, tampoco controlo mucho como funciona el linker.

Prueba a compilar en "Compilar archivo" con tu archivo.c como ventana activa en vez de "Construir proyecto" a ver que pasa.


He conseguido iniciar el LCD con la siguiente librería, pero soy incapaz de escribir algo coherente, sólo salen letras y símbolos aleatorios. No tengo muy claro como ejecutar la función para que escriba correctamente.
Esa librería solo sirve para 16f84A a 4MHz (es ese el problema?), lo bueno de esta es que puedes adaptarlo a distintas velocidades de reloj.

Pero es extraño que con la librería de sergiols no haya problema y con esta sí... evidentemente algo pasa con esta. Pero no creo que sea problema de código, además funciona en otros pic.


Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por mentes el Sáb 2 Oct 2010 - 3:31

He compilado varios programas, así que algo tiene este código que al linker no le gusta.

Deduces que utilizo algún IDE, pero compilo y grabo desde la consola.

Código:
sdcc --debug -mpic14 -p16f84a archivo.c
picprog --input archivo.hex --burn -d pic16f84a --pic /dev/ttyS0

La librería de sergiols sirve para varios pic, y por ejemplo yo la estoy utilizando con un cristal de 8Mhz.

La ventaja de la sgr es que tiene la opción de Read, está más comentada y hay ejemplos de como utilizar las funciones. Con la de sergiols no he conseguido escribir nada en el LCD y no sé si estoy utilizando mal las funciones o hay otro problema.

mentes
Nuevo Usuario
Nuevo Usuario

Mensajes : 9
Fecha de inscripción : 01/10/2010

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 2 Oct 2010 - 4:03

He compilado varios programas, así que algo tiene este código que al linker no le gusta.
Si... algo pasa.

Deduces que utilizo algún IDE, pero compilo y grabo desde la consola.
OK... si, no sé porqué suponía que usabas piklab.

Entonces prueba esto:
Código:
sdcc -mpic14 -p16f84a -V --debug -c tu_archivo.c


Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 2 Oct 2010 - 4:21

Vaya.. fui a previsualizar el mensaje y creo que le di a enviar.

La librería de sergiols sirve para varios pic, y por ejemplo yo la estoy utilizando con un cristal de 8Mhz.
Si, sirve para varios pic, eso lo decía por esto:
Código:
#include <pic16f84a.h>
#include "lcd.h"

y quizás funcione a 8 MHz, pero parece que está hecha para 4 MHz:
Código:

void delay_ms(int ms){
    unsigned int j;
    unsigned int k = ms * 10;
    for (j=0; j<k; j++)
    delay_us (33);      //101µs **** Aunque a mi me salen 133 µs
}
................
................
    _asm                              // delay de 4µs
    nop
    nop
    nop
    nop
    _endasm;

Quizás esté relacionado con la cantidad de memoria y el modo "realocatable" (o algo así) que creo que usa el linker.

Si por ejemplo copias el contenido de la librería y lo pegas en tu archivo en lugar de #include "lcd_sdcc_sgr.h" también debería funcionar sin el "-c" al lanzar sdcc.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 2 Oct 2010 - 5:31

Definitivamente es un problema de cantidad de memoria.

Si se compila con la opción "-c" (no linkear) compila bien y genera el asm.

Si ahora llamamos al linker sin la opción "-r" que biene por defecto para usar memoria compartida, que el pic no tiene... no?, da el verdadero error :
$ /usr/bin/gplink -I/usr/bin/../share/sdcc/lib -I/usr/share/sdcc/lib -I/usr/bin/../share/sdcc/lib/pic -I/usr/share/sdcc/lib/pic -c -m -w -o lcd_Hola_Mundo.hex lcd_Hola_Mundo.o libsdcc.lib pic16f84a.lib

message: using default linker script "/usr/share/gputils/lkr/16f84a.lkr"

error: no target memory available for section "UDL__divuint_0"

La libreria de sergiols es más pequeña y entonces debe entrar bien en memoria.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por mentes el Sáb 2 Oct 2010 - 13:34

¡Acertaste!

Hay un problema de espacio. He comentado lcd_num() lcd_car() y compila, graba y ¡funciona!

¿Eso quiere decir que ahí se acaba la memoria del PIC, ya no puedo añadir más funciones al programa?

¿Existe alguna manera de calcular cuanto espacio va a necesitar un programa?

Supongo que el problema es de Ram ya que sólo tiene 68 bytes.

mentes
Nuevo Usuario
Nuevo Usuario

Mensajes : 9
Fecha de inscripción : 01/10/2010

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Pikitin el Sáb 2 Oct 2010 - 14:14

Bien! al menos mis divagaciones sirvieron para algo Laughing

Hay un problema de espacio. He comentado lcd_num() lcd_car() y compila
De todas formas esas dos funciones no sirven para nada.

Creo que tambien podrías comentar lcd-busy y la linea while(lcd_busy... en lcd_data... creo que tampoco son imprescincibles.

y si no las vas a usar lcd-hex y la otra que está encima... lcdh o algo así.


¿Eso quiere decir que ahí se acaba la memoria del PIC, ya no puedo añadir más funciones al programa?
Pues por lo visto no...
Es que ese pic tiene muy poca flash, y sdcc solo para las rutinas de inicio se come unos 300 bytes, osea que queda muy poco libre.
Yo usaría como mínimo un 16f628a o por ahí.


¿Existe alguna manera de calcular cuanto espacio va a necesitar un programa?
Pues a priori creo que no hay manera, además también depende de las optimizaciones del compilador que se usen, sdcc tiene unas pocas, alguna de ellas que influyen en el tamaño del código generado.


Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por mentes el Sáb 2 Oct 2010 - 14:28

De momento esto me va a servir para entender como se maneja el LCD, pero por lo que veo para la aplicación final voy a necesitar algo con más memoria como me indicas.

Voy a ir viendo como trabaja cada función y quitando lo que no sea imprescindible. Cuando lo tenga pondré aquí una versión reducida de la librería para el 16F84.

Tus comentarios me han sido de gran ayuda, gracias.

mentes
Nuevo Usuario
Nuevo Usuario

Mensajes : 9
Fecha de inscripción : 01/10/2010

Volver arriba Ir abajo

Re: LCD 44780 4-bits para PIC16F, driver y ejemplo.

Mensaje por Contenido patrocinado


Contenido patrocinado


Volver arriba Ir abajo

Página 1 de 2. 1, 2  Siguiente

Ver el tema anterior Ver el tema siguiente Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.