Nokia 3310 Display (Philips PCD8544)

www.erazor-zone.de_ez_projects_ezusb_nokia_3310_display_pcd8544_nddnok3310.jpg

Some examples how to talk to a LC-Display using SPI.

The main part is the PCD8544 used on Nokia 3310 displays.

EZ-USB assembly example

file: http://darcs.erazor-zone.de/ezusb/as31/pcd8544/main.asm

; Copyright (C) 2004,  Alexander 'E-Razor' Krause
;                      admin@erazor-zone.de
;                      http://projects.erazor-zone.de/ezusb
; 
;       writing to a pcd8544                    v0.1    
;       based on max7219        
;  using this code for any non-commercial stuff is allowed
;  please respect this, it took's me a some time writing this code
 
.inc ../ezusb_reg_inc.asm
 
.equ LCD,               0x20
.equ LCD_RESET,         0x00                    ;!RESET
.equ LCD_SCE,           0x01
.equ LCD_D,             0x02                    ;D/!C
.equ LCD_SDIN,          0x03
.equ LCD_SCLK,          0x04
 
init:
  ;PORTB Setup
  ;all bit's from port c are io's
  mov dptr,#PORTCCFG
  mov A,#00000000b
  movx @dptr,A
 
  ;output only
  mov dptr,#OEC
  mov A,#11111111b
  movx @dptr,A
 
 
initLCD:
  mov LCD,#0x00h
 
  mov dptr,#OUTC
 
  mov A,LCD                               ;reset
  movx @dptr,A
 
  setb LCD_RESET
  mov A,LCD                               ;no reset
  movx @dptr,A
 
  setb LCD_SCE                            ;dissable serial interface
 
setupLCD:
  clr LCD_SCE                             ;enable serial interface
 
  ;example code from manual
  clr LCD_D                               ;Databytes
  mov r0,#00100001b                       ;extended instruktion set
  lcall sendb
 
  mov r0,#10010000b                       ;V_{OP}=+16     (contrast)
  lcall sendb
 
  mov r0,#00010111b                       ;Bias Setup
  lcall sendb                             ;MUX RATE (1:10/1:9/1:8)
 
  mov r0,#00100000b                       ;function set, normal instruktion set
                                          ;PD=0 V=0 H=0
  lcall sendb
 
  mov r0,#00001100b                       ;display control set, normal mode
                                          ;D=1 E=0
  lcall sendb
  setb LCD_SCE                            ;dissable serial interface
 
clearLCD:
  clr LCD_SCE                             ;enable serial interface
 
  setb LCD_D                              ;Databytes
 
  mov r1,#252                             ;clears everything and returns to last position
  mov r0,#0
  clearLCDl:
    lcall sendb
    lcall sendb
  djnz r1,clearLCDl
 
 
  setb LCD_SCE                            ;dissable serial interface
 
writeLCD:
  clr LCD_SCE                             ;enable serial interface
 
  setb LCD_D                              ;Databytes
  mov r0,#00011111b
  lcall sendb
 
  mov r0,#00000101b
  lcall sendb
 
  mov r0,#00000111b
  lcall sendb
 
  mov r0,#00000000b
  lcall sendb
 
  mov r0,#00011111b
  lcall sendb
 
  mov r0,#00000100b
  lcall sendb
 
  mov r0,#00011111b
  lcall sendb
 
  setb LCD_SCE                            ;dissable serial interface
  mov A,LCD
  movx @dptr,A
 
mainl:
ljmp mainl
 
;send r0
sendb:
  mov r2,#8
  sendpl:
    dec r2
    mov A,r0
    rlc A
    mov r0,A
 
    clr LCD_SCLK                          ;!SCLK
    mov LCD_SDIN,C                        ; SDIN=C
 
    mov A,LCD
    movx @dptr,A
 
    setb LCD_SCLK                         ; SCLK (setb acc could save clk's)
    mov A,LCD
    movx @dptr,A
 
    clr LCD_SCLK                          ;!SCLK (same as above)
    mov A,LCD
    movx @dptr,A
 
    mov A,r2
 
    nop
    nop
    nop
    nop
    nop
    nop
  jnz sendpl
ret

AVR-C Example

main.c

#include <avr/io.h>
#include <string.h>
 
 
#include "pcd8544.c"
 
#define FIRMWARE_VERSION "0.1"
int main(void) {
    int test=0;
    char* test_str;
 
    lcd_init();
    lcd_clear(); 
    lcd_set_contrast(25);
    //lcd_test();
 
 
    lcd_print("e-evo ");
    lcd_print(FIRMWARE_VERSION);
 
    test_str=(char*)malloc(5);
 
    lcd_goto(0,1);
    lcd_print("counts: ");
    lcd_goto(0,2);
    lcd_print("ADC: ");
 
    //sbi(AIO,0);
    ADCSRA=(1<<ADEN)|(1<<ADFR)|(1<<ADSC);
    ADMUX=(1<<ADLAR);
 
    while (1) {
	lcd_goto(8*FONT_WIDTH,1);
	sprintf(test_str,"%05i",test);
	lcd_print(test_str);
 
	lcd_goto(5*FONT_WIDTH,2);
	sprintf(test_str,"%02x",ADCH);
 
	lcd_print(test_str);
 
	test++;
    }
    return 0;
}

pcd8544.c

#include <avr/io.h>
#include <string.h> 
 
#include "font-7x5.h"
 
#include "spi.c"
 
#define LCD_D PB1
#define LCD_RESET PB0
#define LCD_SCE PB2
 
#define LCD_DDR DDRB
#define LCD_PORT PORTB
 
#define LCD_MUX_CMD 0x17
 
void lcd_init(void) {
    unsigned char tmp;
 
    sbi(LCD_DDR,LCD_D);
    sbi(LCD_DDR,LCD_RESET);
 
    cbi(LCD_PORT,LCD_RESET);
 
    for (tmp=0;tmp<255;tmp++);
    spi_init();
    for (tmp=0;tmp<255;tmp++);
 
    sbi(LCD_PORT,LCD_RESET);
 
    //switch to instruction mode
    cbi(LCD_PORT,LCD_D);
 
    //extended instruction set 0010.0001b
    spi_send_byte(0x21);
 
    spi_send_byte(0x80|20);
 
    //set the MUX
    spi_send_byte(LCD_MUX_CMD);
 
    //switch to normal instruction set
    spi_send_byte(0x20);
 
    //display control set (normal mode)
    spi_send_byte(0x0c);
 
    //switch to data-mode
    sbi(LCD_PORT,LCD_D);
}
 
void lcd_test(void) {
    //print something
    unsigned char tmp,tmp2;
    for (tmp2=0;tmp2<42;tmp2++) {
	for (tmp=1;tmp<7;tmp++)                                                  
    	    spi_send_byte(1<<tmp);
	for (tmp=7;tmp>1;tmp--)                                                  
    	    spi_send_byte(1<<tmp);
 
    }
}
 
void lcd_set_contrast(unsigned char contrast) {
    //V_{OP}=+16 1001.0000
    cbi(LCD_PORT,LCD_D);
    if (contrast<128) {
	spi_send_byte(0x21);
	spi_send_byte(0x80|contrast);
	spi_send_byte(0x20);
    }
    sbi(LCD_PORT,LCD_D);
}
 
 
void lcd_goto(unsigned char x, unsigned char y){
    cbi(LCD_PORT,LCD_D);
    if (x<=83) spi_send_byte(0x80|x);
    if (y<=5) spi_send_byte(0x40|y);
    sbi(LCD_PORT,LCD_D);
}
 
 
void lcd_clear(void) {
    unsigned char tmp,tmp2;
    for (tmp=0;tmp<84;tmp++) {
	for (tmp2=0;tmp2<6;tmp2++) 
	    spi_send_byte(0x00);	
    }
    lcd_goto(0,0);
}
 
void lcd_print(char* string) {
    unsigned char ac_char,ac_col;
 
    for (ac_char=0;ac_char<strlen(string);ac_char++) {
	for (ac_col=0;ac_col<FONT_WIDTH;ac_col++)
	    spi_send_byte( font_ascii_table[string[ac_char]-FONT_OFFSET][ac_col] );
 
	spi_send_byte(0x00);
    }
 
}

spi.c

#include <avr/io.h>
 
#define SPI_MODE_MASTER
 
#define SPI_CLK 0
#define SPI_CLKx2 1
 
#define SPI_SS PB2
#define SPI_MOSI PB3
#define SPI_MISO PB4
#define SPI_SCK PB5
 
#define SPI_PORT PORTB
#define SPI_DDR DDRB
 
void spi_init(void) {
#ifdef SPI_MODE_MASTER
    /*User defined Pin's:
	MOSI
	SCK
	!SS
    */
    //MOSI is output
    sbi(SPI_DDR,SPI_MOSI);
 
    //SCK is output
    sbi(SPI_DDR,SPI_SCK);
 
    //SS is output
    sbi(SPI_DDR,SPI_SS);
 
    //enable SPI
    SPCR=(1<<SPE)|(1<<MSTR)|
	((1&SPI_CLK)<<SPR0)|
	((1&(SPI_CLK>>1))<<SPR1)|
	(SPI_CLKx2<<SPI2X);
#else
    /*User defined Pin's:
	MISO
    */
    //MISO is output
    sbi(SPI_DDR,SPI_MOSI);
 
    //enable SPI
    SPCR=(1<<SPE)|(1<<MSTR)|
	((1&SPI_CLK)<<SPR0)|
	(((2&SPI_CLK)>>1)<<SPR1)|
	(SPI_CLKx2<<SPI2X);
 
#endif
}
 
 
void spi_send_byte(unsigned char data) {
    cbi(SPI_PORT,SPI_SS);
    SPDR = data;
    while (!(SPSR & (1<<SPIF))) ;
    sbi(SPI_PORT,SPI_SS);
 
}
 
unsigned char spi_receive_byte(void) {                                         
    return 0;                                                    
}
 
wiki/projects/hardware/pcd8544.txt · Last modified: 2005/08/25 16:46 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki