Autor Tema: LCD con I2C  (Leído 5098 veces)

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

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
LCD con I2C
« en: 31 de Octubre de 2012, 12:32:57 »
Hola amigos del foro, estoy utilizando un PIC32MX795F512L y tengo un LCD I2C de referencia "NHD-C0216CiZ-FSW-FBW-3V3" (Datasheet), estoy utilizando el ejemplo de Suky (link), pero no hace nada el LCD, la verdad es que nunca he trabajado por I2C, el esquemático lo dejo adjunto en una imagen... el programa compila y se ejecuta pero en el LCD no me aparece nada de nada... Aquí esta el programa:

Código: [Seleccionar]
#define SDA _LATA3
#define SCL _LATA2
#define Slave 0x7C

#pragma config FPLLODIV=DIV_1, FPLLIDIV=DIV_2, FPLLMUL=MUL_20, FPBDIV=DIV_1
#pragma config FWDTEN=OFF, FCKSM=CSDCMD, POSCMOD=XT, FNOSC=PRIPLL
#pragma config CP=OFF, BWP=OFF, PWP=OFF

#define GetSystemClock() (80000000ul) // Hz
#define GetInstructionClock() (GetSystemClock()/1) // Normally GetSystemClock()/4 for PIC18, GetSystemClock()/2 for PIC24/dsPIC, and GetSystemClock()/1 for PIC32.  Might need changing if using Doze modes.
#define GetPeripheralClock() (GetSystemClock()/1)

int main(){

        mJTAGPortEnable(0); // JTAG des-habilitado
SYSTEMConfigPerformance(GetSystemClock()); // Activa pre-cache.-

TRISAbits.TRISA0=0;TRISAbits.TRISA1=0;TRISDbits.TRISD1=0;TRISDbits.TRISD2=0;TRISDbits.TRISD3=0;
        _LATA0=1;_LATA1=1;_LATD1=0;_LATD2=0;_LATD3=0;

vInitLCD();_LATD1=1;
vLcdInitCgram();_LATD2=1; // Incializa Memoria CGRAM.-
// vPutrs_LCD("Libreria generica..\nLCD 2x20, 4x20..\nBus 4-bits o 3-pines\npor Suky...");
        vWriteLCD(0x0F,LCD_COMMAND);DelayMs(1000);_LATD3=1;while(1);
        vPutrs_LCD("Libreria");
DelayMs(1000);_LATD3=1;
vLCD_Putc('\f');
PORTSetPinsDigitalOut(PORT_LED1, PIN_LED1);
PORTSetPinsDigitalOut(PORT_LED3, PIN_LED3);
PORTSetPinsDigitalOut(PORT_LED4, PIN_LED4);
PORTSetPinsDigitalIn(PORT_SW1,PIN_SW1);
PORTSetPinsDigitalIn(PORT_SW2,PIN_SW2);
while(1){
if(PORTReadBits(PORT_SW1,PIN_SW1)==0){
PORTSetBits(PORT_LED1,PIN_LED1);
vGotoxyLCD(1,1);
vPutrs_LCD("SW1:");
vLCD_Putc(1);
}else{
PORTClearBits(PORT_LED1,PIN_LED1);
vGotoxyLCD(1,1);
vPutrs_LCD("SW1:");
vLCD_Putc(0);
}
if(PORTReadBits(PORT_SW2,PIN_SW2)==0){
PORTSetBits(PORT_LED3,PIN_LED3|PIN_LED4);
vGotoxyLCD(1,2);
vPutrs_LCD("SW2:");
vLCD_Putc(1);
}else{
PORTClearBits(PORT_LED3,PIN_LED3|PIN_LED4);
vGotoxyLCD(1,2);
vPutrs_LCD("SW2:");
vLCD_Putc(0);
}
}
}

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: LCD con I2C
« Respuesta #1 en: 31 de Octubre de 2012, 13:48:37 »
Y donde esta en tu codigo el include a la libreria del LCD ?? :mrgreen: :mrgreen:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: LCD con I2C
« Respuesta #2 en: 31 de Octubre de 2012, 13:50:58 »
jajajajajajajajaj se me olvido colocarlo aquí, pero en el programa si esta...

Código: [Seleccionar]
#include "../HardwareProfileSkP32.h"
#include "../LCDGeneric.h"

#if defined (__PIC32MX__)
#include <p32xxxx.h>
#include "../TimeDelay.h"
#define __delay_1Cycle() {Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();}
#define __delay_1us() {UINT8 k; for(k=0;k<50;k++){Nop();}}
#define __delay_100us() Delay10us(10)
#define __delay_2ms() DelayMs(2)
#endif
// *--------------------------------------------------------------------------------*
const char CharactersCGRAM[16]={0,0,0x0E,0x1F,0x0A,0x0A,0x0A,0x11,0,0,0,0,0x0E,0x1F,0x0A,0x11};
// *--------------------------------------------------------------------------------*
// Guarda en la CGRAM el caracter en el banco seleccionado.-
// <Caracter> es la dirección de la primer fila del caracter a enviar.-
void vLcdWriteCgram(unsigned char Bank,char Character){
unsigned char AddressBank,i;
 
AddressBank=0x40+0x08*Bank;
vWriteLCD(AddressBank,0);
// Cargamos los 8 registros.-
for(i=0;i<8;i++){
vWriteLCD(CharactersCGRAM[Character + i],1);
}
vWriteLCD(0x80,0); // Se da por terminada la escritura.-
}
 
// Incializa Memoria CGRAM.-
void vLcdInitCgram(void){
unsigned char j;

for(j=0;j<2;j++){
vLcdWriteCgram(j,j*8);   
}
}

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: LCD con I2C
« Respuesta #3 en: 31 de Octubre de 2012, 14:01:55 »
Una:
Las resistencias pullup del bus, siempre las puse de 4,7K.
Creo que lei que debe ser asi.

Dos:
Tanto el capacitor en el pin Vout como en los pines C1+ y C1-, deben ser electroliticos de 1 uF.

Pin Description and Wiring Diagram
Pin No. Symbol External
Connection
Function Description
1 RST MPU Active LOW Reset Signal
2 SCL MPU Serial clock
3 SDA MPU Input Data
4 Vss Power Supply Ground
5 VDD Power Supply Power supply for logic for LCD (3.0V)
6 VOUT Power Supply DC/DC voltage converter. Connect to 1uF capacitor to VDD
7 C1+ CAP Voltage booster circuit. Connect to 1uF cap to PIN8
8 C1- CAP Voltage booster circuit. Connect to 1uF cap to PIN7

A LED+ Power Supply Power supply for Backlight(3.0V)
K LED- Power Supply Backlight Ground
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: LCD con I2C
« Respuesta #4 en: 31 de Octubre de 2012, 15:02:56 »
Hola! Pero adaptaste la librería? Porque de I2C no tiene nada  :mrgreen: Aparte, al ser I2C, no se trabaja con otros comandos más específicos? Pienso, no tengo la certeza.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: LCD con I2C
« Respuesta #5 en: 31 de Octubre de 2012, 15:10:13 »
Una:
Las resistencias pullup del bus, siempre las puse de 4,7K.
Creo que lei que debe ser asi.

Dos:
Tanto el capacitor en el pin Vout como en los pines C1+ y C1-, deben ser electroliticos de 1 uF.

Pin Description and Wiring Diagram
Pin No. Symbol External
Connection
Function Description
1 RST MPU Active LOW Reset Signal
2 SCL MPU Serial clock
3 SDA MPU Input Data
4 Vss Power Supply Ground
5 VDD Power Supply Power supply for logic for LCD (3.0V)
6 VOUT Power Supply DC/DC voltage converter. Connect to 1uF capacitor to VDD
7 C1+ CAP Voltage booster circuit. Connect to 1uF cap to PIN8
8 C1- CAP Voltage booster circuit. Connect to 1uF cap to PIN7

A LED+ Power Supply Power supply for Backlight(3.0V)
K LED- Power Supply Backlight Ground

Eso me di cuenta y los cambie pero nada de nada.

Hola! Pero adaptaste la librería? Porque de I2C no tiene nada  :mrgreen: Aparte, al ser I2C, no se trabaja con otros comandos más específicos? Pienso, no tengo la certeza.


Saludos!

Es que no tengo ni idea de como se trabaja I2C, la librería que tu hiciste es I2C???


 :(

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: LCD con I2C
« Respuesta #6 en: 31 de Octubre de 2012, 19:43:53 »
Hola! Pero adaptaste la librería? Porque de I2C no tiene nada  :mrgreen: Aparte, al ser I2C, no se trabaja con otros comandos más específicos? Pienso, no tengo la certeza.


Saludos!

Es que no tengo ni idea de como se trabaja I2C, la librería que tu hiciste es I2C???


 :(

No, para nada... No se de donde sacaste la idea, si en ningún lado dice que se implementa por I2C  :shock: Estudia un poco el tema, ya has implementado varias cositas interesante con el PIC32, I2C no debería ser un reto  ;-) Lo que si necesitas es el datasheet del LCD.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: LCD con I2C
« Respuesta #7 en: 01 de Noviembre de 2012, 00:31:00 »
Ahora entiedo!!! Agarraste esa libreria de Suky de tres hilos, pero se hace con un registro de desplazamiento!!! :D :D :D
Si, hay muchos ejemplos de uso de I2C, creo que adaptaras muy rapido algunos para memorias eeprom externas...
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: LCD con I2C
« Respuesta #8 en: 01 de Noviembre de 2012, 09:54:02 »
 :( :( :( :( :( Tenia la esperanza  :( :( :( :(  :D :D :D :D

Bueno ya encontré el datasheet del lcd, y también encontré un programa del mismo fabricante pero me parece que hacen el spi por software, entonces que me recomiendan, utilizar las librerías de microchip o utilizar esta librería por software????

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: LCD con I2C
« Respuesta #9 en: 01 de Noviembre de 2012, 11:31:28 »
 :-/ :-/ :-/ :-/ :-/ Ya funcionoooooooooooooooooooooooooooooooooo

Código: [Seleccionar]
#include <plib.h>   // Peripheral Library
#include <p32xxxx.h>
#include "Analog_PIC32/HardwareProfile.h"
#include "Analog_PIC32/p32mx795f512l.h"
#include "Analog_PIC32/ppic32mx.h"


#pragma config UPLLEN   = ON        // USB PLL Enabled
#pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider
#pragma config WDTPS    = PS16384//PS1048576           // Watchdog Timer Postscale
#pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
#pragma config OSCIOFNC = OFF           // CLKO Enable
#pragma config IESO     = OFF           // Internal/External Switch-over
#pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable (KLO was off)
#pragma config CP       = OFF           // Code Protect
#pragma config BWP      = OFF           // Boot Flash Write Protect
#pragma config PWP      = OFF           // Program Flash Write Protect
#pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select
#pragma config DEBUG    = ON            // Background Debugger Enable

#pragma config FNOSC    = PRIPLL//Oscilador Interno con PPL
#pragma config POSCMOD  = XT //Oscilador externo apagado
#pragma config FPBDIV   = DIV_1//divisor Bus Periféricos
#pragma config FWDTEN   = OFF//Wachdog deshabilitado
#pragma config FPLLODIV = DIV_1//Pos-Divisor PPL 1/1
#pragma config FPLLIDIV = DIV_2//Pre-Divisor PPL 1/2
#pragma config FPLLMUL  = MUL_20// 20xPPL

// Clock Constants
#if defined (__32MX460F512L__) || defined (__32MX360F512L__) || defined (__32MX795F512L__)
#define SYS_CLOCK (80000000L)
#elif defined (__32MX220F032D__) || defined (__32MX250F128D__)
#define SYS_CLOCK (40000000L)
#endif
#define GetSystemClock()            (SYS_CLOCK)
#define GetPeripheralClock()        (SYS_CLOCK/2)
#define GetInstructionClock()       (SYS_CLOCK)
#define I2C_CLOCK_FREQ              5000

// EEPROM Constants
#define EEPROM_I2C_BUS              I2C2
#define EEPROM_ADDRESS             0x7C        // 0b1010000 Serial EEPROM address

#if defined (__PIC32MX__)
#include <p32xxxx.h>
#include "Analog_PIC32/TimeDelay.h"
#define __delay_1Cycle() {Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();Nop();}
#define __delay_1us() {UINT8 k; for(k=0;k<50;k++){Nop();}}
#define __delay_100us() Delay10us(10)
#define __delay_2ms() DelayMs(2)
#endif

#define DESIRED_BAUDRATE     (115200)      //The desired BaudRate

// ****************************************************************************
// ****************************************************************************
// Local Support Routines
// ****************************************************************************
// ****************************************************************************


/*******************************************************************************
  Function:
    BOOL StartTransfer( BOOL restart )

  Summary:
    Starts (or restarts) a transfer to/from the EEPROM.

  Description:
    This routine starts (or restarts) a transfer to/from the EEPROM, waiting (in
    a blocking loop) until the start (or re-start) condition has completed.

  Precondition:
    The I2C module must have been initialized.

  Parameters:
    restart - If FALSE, send a "Start" condition
            - If TRUE, send a "Restart" condition

  Returns:
    TRUE    - If successful
    FALSE   - If a collision occured during Start signaling

  Example:
    <code>
    StartTransfer(FALSE);
    </code>

  Remarks:
    This is a blocking routine that waits for the bus to be idle and the Start
    (or Restart) signal to complete.
  *****************************************************************************/

BOOL StartTransfer( BOOL restart )
{
    I2C_STATUS  status;

    // Send the Start (or Restart) signal
    if(restart)
    {
        I2CRepeatStart(EEPROM_I2C_BUS);
    }
    else
    {
        // Wait for the bus to be idle, then start the transfer
        while( !I2CBusIsIdle(EEPROM_I2C_BUS) );

        if(I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
        {
            DBPRINTF("Error: Bus collision during transfer Start\n");
            return FALSE;
        }
    }

    // Wait for the signal to complete
    do
    {
        status = I2CGetStatus(EEPROM_I2C_BUS);

    } while ( !(status & I2C_START) );

    return TRUE;
}


/*******************************************************************************
  Function:
    BOOL TransmitOneByte( UINT8 data )

  Summary:
    This transmits one byte to the EEPROM.

  Description:
    This transmits one byte to the EEPROM, and reports errors for any bus
    collisions.

  Precondition:
    The transfer must have been previously started.

  Parameters:
    data    - Data byte to transmit

  Returns:
    TRUE    - Data was sent successfully
    FALSE   - A bus collision occured

  Example:
    <code>
    TransmitOneByte(0xAA);
    </code>

  Remarks:
    This is a blocking routine that waits for the transmission to complete.
  *****************************************************************************/

BOOL TransmitOneByte( UINT8 data )
{
    // Wait for the transmitter to be ready
    while(!I2CTransmitterIsReady(EEPROM_I2C_BUS));

    // Transmit the byte
    if(I2CSendByte(EEPROM_I2C_BUS, data) == I2C_MASTER_BUS_COLLISION)
    {
        DBPRINTF("Error: I2C Master Bus Collision\n");
        return FALSE;
    }

    // Wait for the transmission to finish
    while(!I2CTransmissionHasCompleted(EEPROM_I2C_BUS));

    return TRUE;
}


/*******************************************************************************
  Function:
    void StopTransfer( void )

  Summary:
    Stops a transfer to/from the EEPROM.

  Description:
    This routine Stops a transfer to/from the EEPROM, waiting (in a
    blocking loop) until the Stop condition has completed.

  Precondition:
    The I2C module must have been initialized & a transfer started.

  Parameters:
    None.

  Returns:
    None.

  Example:
    <code>
    StopTransfer();
    </code>

  Remarks:
    This is a blocking routine that waits for the Stop signal to complete.
  *****************************************************************************/

void StopTransfer( void )
{
    I2C_STATUS  status;

    // Send the Stop signal
    I2CStop(EEPROM_I2C_BUS);

    // Wait for the signal to complete
    do
    {
        status = I2CGetStatus(EEPROM_I2C_BUS);

    } while ( !(status & I2C_STOP) );
}

// ****************************************************************************
// ****************************************************************************
// Application Main Entry Point
// ****************************************************************************
// ****************************************************************************


int main(){

    DDPCONbits.JTAGEN=0;
    SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    configuracion_uart1();

    // configure for multi-vectored mode
    INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

    // enable interrupts
    INTEnableInterrupts();

    UINT8               i2cData[10];
    I2C_7_BIT_ADDRESS   SlaveAddress;
    int                 Index;
    int                 DataSz;
    UINT32              actualClock;
    BOOL                Acknowledged;
    BOOL                Success = TRUE;
    UINT8               i2cbyte;

    TRISAbits.TRISA0=0;TRISAbits.TRISA1=0;TRISDbits.TRISD1=0;TRISDbits.TRISD2=0;TRISDbits.TRISD3=0;
    _LATA0=1;_LATA1=1;_LATD2=0;_LATD3=0;

    actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(), I2C_CLOCK_FREQ);
    if ( abs(actualClock-I2C_CLOCK_FREQ) > I2C_CLOCK_FREQ/10 )
    {
        WriteString_U1("\r\nError: I2C1 clock frequency error exceeds 10.\r\n");
    }
    // Enable the I2C bus
    I2CEnable(EEPROM_I2C_BUS, TRUE);
    //
    // Send the data to EEPROM to program one location
    //
    // Initialize the data buffer
    i2cData[0] = EEPROM_ADDRESS;//SlaveAddress.byte;
    i2cData[1] = 0x00;              // command
    i2cData[2] = 0x38;              // Off LCD 0X08 APAGA EL LCD
    i2cData[3] = 0x39;              // On LCD 0X0E ENCIENDE EL LCD
    i2cData[4] = 0x14;              // LIMPIA
    i2cData[5] = 0x76;              // CONTRASTE
    i2cData[6] = 0x5D;              //
    i2cData[7] = 0x6D;              //
    i2cData[8] = 0x01;              //
    i2cData[9] = 0x06;              //

    DataSz = 10;

    while(1){     
        // Start the transfer to write data to the EEPROM
        if( !StartTransfer(FALSE) )
        {
            WriteString_U1("\r\nError: !StartTransfer(FALSE).\r\n");
        }
        else{
            WriteString_U1("\r\nStartTransfer: OK.\r\n");

            // Transmit all data
            Index = 0;
            while( Success && (Index < DataSz) )
            {
                // Transmit a byte
                if (TransmitOneByte(i2cData[Index]))
                {
                    // Advance to the next byte
                    Index++;

                    // Verify that the byte was acknowledged
                    if(!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
                    {
                        WriteString_U1("\r\nError: Sent byte was not acknowledged\r\n");
                        Success = FALSE;
                    }
                    else{WriteString_U1("\r\nSent byte was acknowledged.\r\n");}
                }
                else
                {
                    Success = FALSE;
                }
            }

            // End the transfer (hang here if an error occured)
            StopTransfer();

            DelayMs(5000);
            
            if(!Success)
            {
                WriteString_U1("\r\nError: !Success\r\n");
                WriteString_U1("\r\nRetrying...\r\n");
                Success = TRUE;
            }
            else{
                    i2cData[0] = EEPROM_ADDRESS;//SlaveAddress.byte;
                    i2cData[1] = 0x40;              // command
                    i2cData[2] = 'H';              // Off LCD 0X08 APAGA EL LCD
                    i2cData[3] = 'O';              // On LCD 0X0E ENCIENDE EL LCD
                    i2cData[4] = 'L';              // LIMPIA
                    i2cData[5] = 'A';              // CONTRASTE
                    i2cData[6] = ' ';              //

                    DataSz = 7;
            }
        }
    }
    while(1);
}


Ahora toca es mirar como bajarle el contraste al lcd por hardware, por que por software no baja mucho... gracias.
« Última modificación: 01 de Noviembre de 2012, 16:51:23 por IngRandall »

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: LCD con I2C
« Respuesta #10 en: 01 de Noviembre de 2012, 12:02:15 »
Aleluya !!!   :-/ :-/ :-/ ((:-)) ((:-)) ((:-)) ((:-))
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: LCD con I2C
« Respuesta #11 en: 01 de Noviembre de 2012, 16:58:40 »
Ya le baje el contraste  :-/ :-/ :-/ :

Este tipo de lcd puede cambiar el contraste por software y tiene dividido el control en dos bytes, que se muestran en la imagen y en el código que subí anteriormente ya están corregidos.

Gracias  por la ayuda :-/ :-/ :-/ :-/


Ahora a seguir con la uSD que no me funciona  :( :( :( :(