Need help in solving issue with LCD Nokia5110 (PCD8544)

Thread Starter

phetal

Joined Jun 18, 2017
5
I have been scratching my head since couple of days to solve a lcd display issue.

Problem-1: As I read from the datasheet of PCD8544, I can set x, y position to (0, 0) by writing command 0x80 and 0x40. However upon restart when I write these commands and then display any pattern, it seem to be displaying at different location (almost at x=73, y = 0) when I keep on writing then after it continue to write till last pixel (bottom right corner) and then rolls back to top left. If i write exactly 504 data, it covers whole LCD but the start position is not as expected (0,0). Any clue or pointer what could be going wrong? PS: If I don't write (0,0) upon restart and directly start writing data, it starts writing from the first pixel of the lcd as expected :(

pls see the Scenario1 image

Problem-2: If I want to write some data i.e. write data to first byte of first row, second byte of second row, third byte of third row and so on....
If I dont set the x,y position at start up (first set_xy_pos(0,0)) and only set the Y position within while loop.

I see that it starts to display from first pixel but does not display all the rows.
It just displays 1st, 2nd and 4th rows only rest remains blank

Pls see Scenario2 image


Any clue why it does not display any data on 3rd, 5th and 6th row when I explicitly set the y position?

Problem-3: upon restart if I write data 0x01, it makes two pixel ON. MSB and LSB as if I have written 0x81, any clue?
Pls see Scenario3 image
 

Attachments

GopherT

Joined Nov 23, 2012
8,009
I have been scratching my head since couple of days to solve a lcd display issue.

Problem-1: As I read from the datasheet of PCD8544, I can set x, y position to (0, 0) by writing command 0x80 and 0x40. However upon restart when I write these commands and then display any pattern, it seem to be displaying at different location (almost at x=73, y = 0) when I keep on writing then after it continue to write till last pixel (bottom right corner) and then rolls back to top left. If i write exactly 504 data, it covers whole LCD but the start position is not as expected (0,0). Any clue or pointer what could be going wrong? PS: If I don't write (0,0) upon restart and directly start writing data, it starts writing from the first pixel of the lcd as expected :(

pls see the Scenario1 image

Problem-2: If I want to write some data i.e. write data to first byte of first row, second byte of second row, third byte of third row and so on....
If I dont set the x,y position at start up (first set_xy_pos(0,0)) and only set the Y position within while loop.

I see that it starts to display from first pixel but does not display all the rows.
It just displays 1st, 2nd and 4th rows only rest remains blank

Pls see Scenario2 image


Any clue why it does not display any data on 3rd, 5th and 6th row when I explicitly set the y position?

Problem-3: upon restart if I write data 0x01, it makes two pixel ON. MSB and LSB as if I have written 0x81, any clue?
Pls see Scenario3 image
I don't open zip files. Post your code as text inside tags as follows (replace quote marks with square brackets)
"code"
(Place program code here)
"/code"
 

Thread Starter

phetal

Joined Jun 18, 2017
5
I don't open zip files. Post your code as text inside tags as follows (replace quote marks with square brackets)
"code"
(Place program code here)
"/code"
Here is the code....

======= main.c ============
"code"
#include <pic18f45k40.h>
#include "config.h"
//#include "switch_matrix.h"
//#include "queue.h"
#include "lcd.h"

#define LED1_LATBIT LATAbits.LATA1
#define LED1_PORTBIT PORTAbits.RA1

#define LED2_LATBIT LATAbits.LATA2
#define LED2_PORTBIT PORTAbits.RA2

void main(void) {

OSCFRQbits.HFFRQ = 0b0011; //8MHZ clock

LATDbits.LATD2 = 1; //LCD_POWER_ON_OFF

// INTCONbits.PEIE = 1; //peripheral interrupt enable
// INTCONbits.GIE = 1;

init_lcd_if();
unsigned char y_pos = 0;
unsigned char x_pos = 0;

__delay_ms(100);
set_xy_pos(0, 0);

while (1)
{
//buf full, read and flush
proc_lcd_data();
__delay_ms(100);

x_pos++;

if(x_pos > 83) {
x_pos = 0;
y_pos++;

if(y_pos > 5) {
y_pos = 0;
}
}
set_xy_pos(x_pos, y_pos);
}
return;
}
"/code"

=========== lcd.c ====================
"code"


#include <pic18f45k40.h>
#include "config.h"
#include "lcd.h"
//#include "queue.h"

#define LCD_COMMAND LATDbits.LATD1 = 0;
#define LCD_DATA LATDbits.LATD1 = 1;
#define LCD_CS(level) LATAbits.LA5 = level;

#define HIGH 1
#define LOW 0

static void send_lcd_cmd(unsigned char cmd);
void SPI_Write(unsigned char x);

void init_lcd_if(void)
{
ANSELDbits.ANSELD1 = 0; //MODE Select, 0:Cmd, 1:Data
TRISDbits.TRISD1 = 0;

ANSELDbits.ANSELD2 = 0; //LCD_ON_OFF
TRISDbits.TRISD2 = 0;

ANSELDbits.ANSELD3 = 0; //RESET, Active low
TRISDbits.TRISD3 = 0;
// LATDbits.LATD3 = 1;

ANSELCbits.ANSELC3 = 0; //CLK
TRISCbits.TRISC3 = 0;

ANSELCbits.ANSELC5 = 0; //MOSI
TRISCbits.TRISC5 = 0;

ANSELAbits.ANSELA5 = 0; //CS, Active low
TRISAbits.TRISA5 = 0;

//MOSI
RC5PPS = 0b10000;
//CLK
RC3PPS = 0b01111;

//config SPI registers

SSP1STATbits.SMP = 1;
SSP1CON1bits.WCOL = 0; //no collision
SSP1CON1bits.SSPOV = 0; //no overflow

SSP1CON1bits.CKP = 0; //idle state for the clock is a low level
// SSP1CON1bits.SSPM = 0b0010; //clock = FOSC/64
SSP1CON1bits.SSPM = 0b0001; //clock = FOSC/16
// SSP1CON1bits.SSPM = 0b0000; //clock = FOSC/4

SSP1CON3bits.PCIE = 1;


SSP1CON1bits.SSPEN = 1;

// PIE3bits.SSP1IE = 1; //SPI int enabled
SSP1BUF = 0x00;
// SPI_Write(0x00);
//SS bit always on, SP_DEBUG
LCD_CS(HIGH);
__delay_ms(10);
LCD_CS(LOW); //Keep the CS enabled always

LATDbits.LATD3 = 0; //LCD_RESET
__delay_ms(100);
LATDbits.LATD3 = 1; //LCD_RESET

PIR3bits.SSP1IF=0;

SPI_Write(0x00);

LCD_COMMAND;

send_lcd_cmd(0x21);
send_lcd_cmd(0x13);
send_lcd_cmd(0x07);
send_lcd_cmd(0x80);
send_lcd_cmd(0x20);
send_lcd_cmd(0x0C); //Normal mode

clear_lcd_disp();
}

static void send_lcd_cmd(unsigned char cmd)
{
LCD_CS(LOW);
LCD_COMMAND;
SPI_Write(cmd);
LCD_CS(HIGH);
}

void send_lcd_data(unsigned char data)
{
LCD_CS(LOW);
LCD_DATA;
SPI_Write(data);
LCD_CS(HIGH);
}

void set_display_off()
{
send_lcd_cmd(0x08); //Normal mode
}

void set_display_on()
{
send_lcd_cmd(0x0C); //Normal mode
}
void clear_lcd_disp(void)
{
LCD_DATA;
LCD_CS(LOW);
for(int i = 0; i < 504; i++) {
SPI_Write(0x00);
}
LCD_CS(HIGH);
}

void proc_lcd_data(void)
{
LCD_CS(LOW);
LCD_DATA;
SPI_Write(0xFC);
LCD_CS(HIGH);
}

void set_xy_pos(unsigned char x, unsigned char y)
{
// send_lcd_cmd(0x40 | y);
// send_lcd_cmd(0x80 | x);
}

void SPI_Write(unsigned char x)
{
unsigned char data_flush;
SSP1BUF=x; /* Copy data in SSBUF to transmit */
while(!PIR3bits.SSP1IF); /* Wait for complete 1 byte transmission */
PIR3bits.SSP1IF=0; /* Clear SSPIF flag */
data_flush=SSP1BUF; /* Flush the data */
}
"/code"

=============== lcd.h =====================
"code"

#ifndef LCD_H
#define LCD_H

#ifdef __cplusplus
extern "C" {
#endif

typedef enum LCD_STATE
{
LCD_INIT = 0,
LCD_IDLE,
LCD_DATA_WRITE,
LCD_CMD_WRITE,
};


void init_lcd_if(void);
void clear_lcd_disp(void);
void write_lcd_cmd(void);
void send_lcd_data(unsigned char data);
void set_display_off();
void set_display_on();
void set_xy_pos(unsigned char x, unsigned char y);

void proc_lcd_data(void);



#ifdef __cplusplus
}
#endif

#endif /* LCD_H */

"/code"
 

GopherT

Joined Nov 23, 2012
8,009
Unreadable without formatting.

Inset your code by clicking as follows and selecting "code" when you make a new post.
image.jpeg
 

Thread Starter

phetal

Joined Jun 18, 2017
5
Unreadable without formatting.

Inset your code by clicking as follows and selecting "code" when you make a new post.
View attachment 129524
======= main.c =================

Code:
#include <pic18f45k40.h>
#include "config.h"
//#include "switch_matrix.h"
//#include "queue.h"
#include "lcd.h"

#define LED1_LATBIT LATAbits.LATA1
#define LED1_PORTBIT PORTAbits.RA1

#define LED2_LATBIT LATAbits.LATA2
#define LED2_PORTBIT PORTAbits.RA2

void main(void) {

   OSCFRQbits.HFFRQ = 0b0011;   //8MHZ clock

    LATDbits.LATD2 = 1;     //LCD_POWER_ON_OFF
   
//    INTCONbits.PEIE = 1;    //peripheral interrupt enable
//    INTCONbits.GIE = 1;
   
    init_lcd_if();
 
    unsigned char y_pos = 0;
    unsigned char x_pos = 0;
   
    __delay_ms(100);
    set_xy_pos(0, 0);

    while (1)
    {
        //buf full, read and flush
        proc_lcd_data();
        __delay_ms(100);

        x_pos++;

        if(x_pos > 83) {
            x_pos = 0;
            y_pos++;

            if(y_pos > 5) {
                y_pos = 0;
            }
        }
        set_xy_pos(x_pos, y_pos);
    }
    return;
}
===================== lcd.c ===================

Code:
#include <pic18f45k40.h>
#include "config.h"
#include "lcd.h"
//#include "queue.h"

#define LCD_COMMAND LATDbits.LATD1 = 0;
#define LCD_DATA LATDbits.LATD1 = 1;
#define LCD_CS(level) LATAbits.LA5 = level;

#define HIGH 1
#define LOW  0

static void send_lcd_cmd(unsigned char cmd);
void SPI_Write(unsigned char x);

void init_lcd_if(void)
{
    ANSELDbits.ANSELD1 = 0;     //MODE Select, 0:Cmd, 1:Data
    TRISDbits.TRISD1 = 0;
   
    ANSELDbits.ANSELD2 = 0;     //LCD_ON_OFF
    TRISDbits.TRISD2 = 0;
   
    ANSELDbits.ANSELD3 = 0;     //RESET, Active low
    TRISDbits.TRISD3 = 0;
//   LATDbits.LATD3 = 1;

    ANSELCbits.ANSELC3 = 0;     //CLK
    TRISCbits.TRISC3 = 0;
   
    ANSELCbits.ANSELC5 = 0;     //MOSI
    TRISCbits.TRISC5 = 0;
   
    ANSELAbits.ANSELA5 = 0;     //CS, Active low
    TRISAbits.TRISA5 = 0;
   
    //MOSI
    RC5PPS = 0b10000;
    //CLK
    RC3PPS = 0b01111;
   
    //config SPI registers
   
    SSP1STATbits.SMP = 1;
    SSP1CON1bits.WCOL = 0;  //no collision
    SSP1CON1bits.SSPOV = 0; //no overflow
   
    SSP1CON1bits.CKP = 0;   //idle state for the clock is a low level
//    SSP1CON1bits.SSPM = 0b0010;  //clock = FOSC/64
    SSP1CON1bits.SSPM = 0b0001;  //clock = FOSC/16
//    SSP1CON1bits.SSPM = 0b0000;  //clock = FOSC/4
   
    SSP1CON3bits.PCIE = 1;


    SSP1CON1bits.SSPEN = 1;
   
//    PIE3bits.SSP1IE = 1;       //SPI int enabled
    SSP1BUF = 0x00;
//    SPI_Write(0x00);
    //SS bit always on, SP_DEBUG
    LCD_CS(HIGH);
    __delay_ms(10);
    LCD_CS(LOW);        //Keep the CS enabled always
   
    LATDbits.LATD3 = 0;     //LCD_RESET
    __delay_ms(100);
    LATDbits.LATD3 = 1;     //LCD_RESET
   
    PIR3bits.SSP1IF=0;

    SPI_Write(0x00);
   
    LCD_COMMAND;

    send_lcd_cmd(0x21);
    send_lcd_cmd(0x13);
    send_lcd_cmd(0x07);
    send_lcd_cmd(0x80);
    send_lcd_cmd(0x20);
    send_lcd_cmd(0x0C);     //Normal mode
   
    clear_lcd_disp();
}

static void send_lcd_cmd(unsigned char cmd)
{
    LCD_CS(LOW);
    LCD_COMMAND;
    SPI_Write(cmd);
    LCD_CS(HIGH);   
}

void send_lcd_data(unsigned char data)
{
    LCD_CS(LOW);
    LCD_DATA;
    SPI_Write(data);
    LCD_CS(HIGH);
}

void set_display_off()
{
    send_lcd_cmd(0x08);     //Normal mode
}

void set_display_on()
{
    send_lcd_cmd(0x0C);     //Normal mode
}
void clear_lcd_disp(void)
{
    LCD_DATA;
    LCD_CS(LOW);
    for(int i = 0; i < 504; i++) {
        SPI_Write(0x00);
    }
    LCD_CS(HIGH);
}

void proc_lcd_data(void)
{
    LCD_CS(LOW);
    LCD_DATA;
    SPI_Write(0xFC);
    LCD_CS(HIGH);
}

void set_xy_pos(unsigned char x, unsigned char y)
{
//    send_lcd_cmd(0x40 | y);
//    send_lcd_cmd(0x80 | x);
}

void SPI_Write(unsigned char x)
{
    unsigned char data_flush;
    SSP1BUF=x;                /* Copy data in SSBUF to transmit */
    while(!PIR3bits.SSP1IF);    /* Wait for complete 1 byte transmission */
    PIR3bits.SSP1IF=0;        /* Clear SSPIF flag */
    data_flush=SSP1BUF;        /* Flush the data */
}
=========== lcd.h =============================
Code:
#ifndef LCD_H
#define    LCD_H

#ifdef    __cplusplus
extern "C" {
#endif

    typedef enum LCD_STATE
    {
        LCD_INIT = 0,
        LCD_IDLE,
        LCD_DATA_WRITE,
        LCD_CMD_WRITE,
    };

   
    void init_lcd_if(void);
    void clear_lcd_disp(void);
    void write_lcd_cmd(void);
    void send_lcd_data(unsigned char data);
    void set_display_off();
    void set_display_on();
    void set_xy_pos(unsigned char x, unsigned char y);
   
    void proc_lcd_data(void);



#ifdef    __cplusplus
}
#endif

#endif    /* LCD_H */
 

GopherT

Joined Nov 23, 2012
8,009
Read the data sheet for the LCD driver chip, there is something about automatically increment into the current register to the next pixel after a write event.
 

Thread Starter

phetal

Joined Jun 18, 2017
5
Read the data sheet for the LCD driver chip, there is something about automatically increment into the current register to the next pixel after a write event.
Yes, it says it will automatically increment based on the selection (V=0 or V=1). In my case I have it V=0 and also I am facing problem when I explicitly set the x n y position to 0 at start up.
So, I wonder could there be any other issue?
 

jjw

Joined Dec 24, 2013
823
In the set_xy_pos ( ) you have commented out the commands:
send _lcd_cmd ( 0x80|x) ...
 
Last edited:

Thread Starter

phetal

Joined Jun 18, 2017
5
In the set_xy_pos ( ) you have commented out the commands:
send _lcd_cmd ( 0x80|x) ...
As I have mentioned three problems, I face the problem when I do not comment this line (basically setting x,y position to '0' at startup). However it was comment to test other problem scenarios
 
Top