Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
7 years, 4 months ago.
Unable to set x,y position for Nokia 5110 LCD
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 :(
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
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?
main.c
#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
#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 */ }
main.c
#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
1 Answer
6 years, 2 months ago.
Hi, I was confronted to the same problem of fancy positionning, I would suggest :
void PositionXY(char X, char Y)
{
CS = 1; chip deselect
SendCommand(0x80 + X); /* X position */
SendCommand(0x40 + Y); /* Y position */
CS = 0;/* chip select*/
DC = 1;/* mode data*/
}
Best Regards F. D.