Some examples how to talk to a LC-Display using SPI.
The main part is the PCD8544 used on Nokia 3310 displays.
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
#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; }
#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); } }
#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; }