Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD Sunfounder 1602 for PIC24FJ128GA110

Status
Not open for further replies.

JJReyes

Newbie
Newbie level 2
Joined
Jul 25, 2023
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
41
Hello everyone,
I have bought a LCD Sunfounder 1602 (LCD + PCF8574T to be exact). My goal is to display data from the PIC24FJ128GA110 to the LCD, I have written an I2C library that seems to work (tested it with an ADC and I got pretty much what I wanted). So I connect the LCD (4 pins : VDD, GND, SCL and SDA), and when I observe with my scope, I can indeed see the signals SCL and SDA on the pins of the LCD. But else, nothing is being displayed on the LCD and I don't really know why. I have done continuity testing, to check that the software driver matches the port assignments and it was fine. I suspect a problem in the code, (maybe the LCD initialization that is not correct ?), but as I am quite new with microcontrollers, I don't know what could be wrong to be honest. I am including the I2C and LCD libraries in case someone had already worked with one of those LCD.


LCD Lib :
C:
#include <xc.h>
#include "lcd.h"
#include "i2c1.h"
#include <string.h>

#ifndef _XTAL_FREQ
#define _XTAL_FREQ  8000000UL
#endif

#ifndef FCY
#define FCY _XTAL_FREQ/2
#endif


#include <libpic30.h>


void lcd_init() {
    // Initialization sequence for 16x2 LCD
    lcd_send_command(0x33); // Initialize the LCD in 8-bit mode
    __delay_ms(5);
    lcd_send_command(0x32); // Initialize the LCD in 4-bit mode then
    __delay_ms(5);
    lcd_send_command(0x28); // 2 lines, 5x7 matrix
    __delay_ms(5);
    lcd_send_command(0x0C); // Display ON, Cursor OFF, Blink OFF
    __delay_ms(5);
    lcd_clear(); // Clear the LCD
}

void lcd_clear() {
    lcd_send_command(0x01); // Clear display command
    __delay_ms(5); // Delay to allow the LCD to process the command
}

void write_word_lcd(int data){
    int temp = data;
    temp |= 0x08;
    send_i2c1_byte(LCD_ADDRESS);
    send_i2c1_byte(temp);
}

void lcd_send_command(unsigned int command) {
  
    //send_i2c1_byte(LCD_ADDRESS << 1); //RW = 0
    //send_i2c1_byte(command);
    int buffer;
  
    //Write bit 7 to 4
    buffer = command & 0xF0;
    buffer |= 0x04;                     // RS = 0, RW = 0, EN = 1
    write_word_lcd(buffer);
    __delay_ms(50);
    buffer &= 0xFB;
    write_word_lcd(buffer);
  
    //Write bit 3 to 0
    buffer = (command & 0x0F) << 4;
    buffer |= 0x04;                    // RS = 0, RW = 0, EN = 1
    write_word_lcd(buffer);
    __delay_ms(50);
    buffer &= 0xFB;                    // EN = 0
    write_word_lcd(buffer);
  
}

void lcd_send_data(unsigned char data) {
    // Set RS high (0x80) for data, and send data byte to LCD
    //send_i2c1_byte((LCD_ADDRESS << 1) | 0x01); // Set R/W bit high for Write
    //send_i2c1_byte(data);
  
    int buffer;
  
  
    //Write bit 7 to 4
    buffer = data & 0xF0;
    buffer |= 0x05;                    // RS = 1, RW = 0, EN = 1
    write_word_lcd(buffer);
     __delay_ms(50);
    buffer &= 0xFB;                    // EN = 0
    write_word_lcd(buffer);

    //Write bit 3 to 0
    buffer = (data & 0x0F) << 4;
    buffer |= 0x05;                    // RS = 1, RW = 0, EN = 1
    write_word_lcd(buffer);
     __delay_ms(50);
    buffer &= 0xFB;                    // EN = 0
    write_word_lcd(buffer);
}

void write(int x, int y, char data[]){
    int addr, i;
    int temp;
    if (x < 0)  x = 0;
    if (x > 15) x = 15;
    if (y < 0)  y = 0;
    if (y > 1)  y = 1;

    // Move cursor
    addr = 0x80 + 0x40 * y + x;
    lcd_send_command(addr);

    temp = strlen(data);
    for (i = 0; i < temp; i++){
        lcd_send_data(data[i]);
    }
}

 
/*
void lcd_set_cursor(unsigned char row, unsigned char col) {
    unsigned char address = (0x80 | (row << 6) | col); // Calculate the DDRAM address
    lcd_send_command(address);
}
*/
/*
void lcd_display_string(const char *str) {
    while (*str) {
        lcd_send_data(*str);
        str++;
    }
}
*/

I2C Lib :
C:
#include <xc.h>
#include "i2c1.h"

#ifndef _XTAL_FREQ
#define _XTAL_FREQ  8000000UL
#endif

#ifndef FCY
#define FCY _XTAL_FREQ/2
#endif


#include <libpic30.h>

void i2c1_init() {

    I2C1BRG = 18; //8 7 4 = 300kH
    //I2C1CONbits.I2CEN = 0; // Disable I2C Mode
    // Clear Interrupt
    IFS3bits.MI2C2IF = 0;
    //Continue module operation in Idle mode
    I2C1CONbits.I2CSIDL = 0;
    //IPMIEN mode disabled
    I2C1CONbits.IPMIEN = 0;
    //Slew rate enabled
    I2C1CONbits.DISSLW = 0;
    //General call address disabled
    I2C1CONbits.GCEN = 0;
    //Disable SMBus input thresholds
    I2C1CONbits.SMEN = 0;
    //Software or receive call stretching disabled
    I2C1CONbits.STREN = 0;
    // Enable I2C Mode
    I2C1CONbits.I2CEN = 1;

}

void i2c1_wait(void) {
    //while(!IFS3bits.MI2C2IF);
    __delay_ms(500);
    IFS3bits.MI2C2IF = 0; // Reset flag
}

void i2c1_start(void) {
    I2C1CONbits.SEN = 1; //Initiate Start condition
    i2c1_wait();
}

void i2c1_restart(void) {
    I2C1CONbits.RSEN = 1; //Initiate restart condition
    i2c1_wait();
}

void i2c1_stop(void) {
    I2C1CONbits.PEN = 1; //Initiate Start condition
    i2c1_wait();
}

void reset_i2c1_bus(void) {
    I2C1CONbits.PEN = 1; //initiate stop bit
    while (I2C1CONbits.PEN);
    I2C1CONbits.RCEN = 0;
    IFS3bits.MI2C2IF = 0; // Clear Interrupt
    I2C1STATbits.IWCOL = 0;
    I2C1STATbits.BCL = 0;
}

char send_i2c1_byte(unsigned char data) {
    I2C1TRN = data; // load the outgoing data byte
    i2c1_wait();
    return (I2C1STATbits.ACKSTAT == 0); // return 1 if ACK 
}

unsigned char receive_i2c1_byte(char send_ack) {
    unsigned char data;

    if (send_ack)
        I2C1CONbits.ACKDT = 0;
    else
        I2C1CONbits.ACKDT = 1;

    I2C1CONbits.RCEN = 1; // Start reception
    //i2c1_wait();
    data = I2C1RCV; // Read data 
    I2C1CONbits.ACKEN = 1; // Send ACK/NAK
    //i2c1_wait();
    while (I2C1CONbits.ACKEN);
    return data;
}

unsigned char I2C1write(unsigned char dev, unsigned char reg, unsigned char value) {
    dev <<= 1; // RW=0
    i2c1_start(); // Send start
    if (!send_i2c1_byte(dev) || !send_i2c1_byte(reg)) { // Send device address and reg address
        i2c1_stop(); // Cancel if NACK
        return 0;
    }
    send_i2c1_byte(value); // Write data
    i2c1_stop(); // Send stop
    return 1;
}

char I2C1read(unsigned char dev, unsigned char reg) {
    unsigned char data;
    dev = (dev << 1); // RW=0 
    i2c1_start(); // Send start
    if (!send_i2c1_byte(dev) || !send_i2c1_byte(reg)) { // Send device address and reg address
        i2c1_stop(); // Cancel if NACK
        return 0;
    }
    dev |= 1;  // RW=1
    i2c1_restart(); // Send restart
    if (!send_i2c1_byte(dev)) { // Send device address
        i2c1_stop(); // Cancel if NACK
        return 0;
    }
    data = receive_i2c1_byte(0);
    i2c1_stop(); // Send stop
    return data; // Return read data
}

Main :
C:
    LED_IGN_TRIS = LED_OUTPUT;
    LED_IGN_LAT = LED_OFF;
      i2c1_init();
    //lcd_init();
    __delay_ms(500);
    i2c1_start();
    LED_IGN_LAT = LED_ON;


    while (1) {
        //write(0, 0, 'J');
    
        lcd_send_command(0x33);
        __delay_ms(50);
        lcd_send_command(0x32);
        __delay_ms(50);
        lcd_send_command(0x28); // 2 lines, 5x7 matrix
        __delay_ms(50);
        lcd_send_command(0x0C); // Display ON, Cursor OFF, Blink OFF
        __delay_ms(50);
        lcd_send_data('J');
        LED_IGN_LAT = LED_OFF;


I reckon I just don't really know what's wrong, because I thought the I2C was working, and because I can see the SCL and SDA signals on my scope. I work with the MPLABX IDE, so it's pretty hard to have a debug terminal, so usually try to debug with a LED (LED_IGN_LAT), and it seems that it never turns off as it's supposed to after I send the 'J' to the LCD, but it seems to be doing the initialization. As I said, my guess would be that something is wrong with the LCD library, but I don't quite know where to look... If anyone had an idea I'd gladly take it!
Thanks heaps !
 
Last edited:

Hello everyone, and my apologies for the second message.
I did continuity testing again, and I found out that the pin number 7 'P3' on the PCF8574 isn't connected to the parallel bit 'Backlight' (which is supposed to be bit 7 if we consider VSS the MSB on the LCD), and I read on an article that it was supposed to be the case...

I have also noticed that on the LCD, bit 15 and 16 are the anode and the cathode for the backlight. The anode (+5V) is connected to the VCC that powers the LCD, but the cathode (0V) isn't connected to the GND.
I want to precise that I didn't soldered anything or connected on the LCD and the PCF8574, it arrived in the mail like that.

Could these be reasons than prevent anything to be displayed on the LCD screen ?
https://www.openhacks.com/uploadsproductos/eone-1602a1.pdf : this is supposed to be the datasheet of the LCD that I have.
Thanks again for your time !
 
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top