Sie sind auf Seite 1von 6

This is the code I wrote to drive a 128x64 pixel graphic LCD module based on the KS0107 and KS0108

controllers. The biggest problem with interfacing this module is the terrible datasheet quality- the timing sequence diagrams are very ambiguous, to say the least. You'll likely want to change the duration of the delay in the _lcd_enable() function to match your chip. The code is for 18F452 @ 22.118 MHz, and written in Microchip C18. I don't think it'd be too hard to port to other compilers, but YMMV. I've reluctantly removed the font data, since I do not own it, and cannot freely distribute it. There are many starts for fonts available on this site here:http://piclist.com/techref/datafile/charsets.htm . The functions that start _lcd* are intended to be for internal use by the library, whereas lcd* are for your use. Of course, that doesn't limit you in what you do at all.

glcd.h #include <p18cxxx.h> #include <delays.h> #define LCD_TRIS TRISB #define LCD_DATA PORTB #define ENABLE PORTDbits.RD7 #define RW PORTDbits.RD6 #define DI PORTDbits.RD5 #define RESET PORTDbits.RD4 #define CS1 PORTDbits.RD2 #define CS2 PORTDbits.RD3 #define LEFT 0b01 #define RIGHT 0b10 #define BOTH 0b11 #define NONE 0b00 // internal function prototypes // // you would not normally call these directly. but you can // if you like. void _lcd_enable(void); unsigned char _lcd_status(void); void _lcd_reset(void); void _lcd_waitbusy(void); // public function prototypes // // call these all you want ! void lcd_screenon(unsigned char on);

void lcd_cls(void); void lcd_setpage(unsigned char page); void lcd_setyaddr(unsigned char y); void lcd_selectside(unsigned char sides); void lcd_write (unsigned char data); unsigned char lcd_read (void); void lcd_plotpixel(unsigned char rx, unsigned char ry); void lcd_putchar(char c); void lcd_puts(char *string); void lcd_putrs(const rom char *string); And now glcd.c :#include <p18cxxx.h> #include "glcd.h" const rom char font[]= { /* add your own font data each char is 3x8 pixels. 3 bytes per char. left column, middle column, right column */ }; void _lcd_enable(void) { Delay10TCYx(1); ENABLE=1; Delay10TCYx(1); ENABLE=0; Delay10TCYx(1); } unsigned char _lcd_status(void) { // returns the lcd status & maintains the TRIS state of the // lcd data port unsigned char _lcd_tris, _status; // save the tris value _lcd_tris = LCD_TRIS; // read the status LCD_TRIS=0xFF; // all inputs DI=0; RW=1; // command/read _lcd_enable(); _status = LCD_DATA; // restore the tris value LCD_TRIS = _lcd_tris;

return _status; } void _lcd_reset(void) { // reset the lcd module // datasheet says reset must be low for minimum of 1us // after Vdd clears 4.5v. // from experimentation, this is bullshit. this seems to // work though. Delay10TCYx(250); // actually .5 ms RESET=1; Delay10TCYx(250); // actually .5 ms RESET=0; // check status, and wait if necessary while (_lcd_status() & 0b00010000) { Delay10TCYx(250); // .5 ms } } void lcd_screenon(unsigned char on) { // turn the display on or off LCD_TRIS=0; // all outputs RW=0; DI=0; LATB = 0b00111110 | (on & 0b00000001); // main screen turn on! _lcd_enable(); } void lcd_cls(void) { unsigned char x,y; for (x=0; x<8; x++) { // set the page (x) lcd_setpage(x); // set the y address to 0 lcd_setyaddr(0); // setup for data LCD_DATA=0; RW=0; DI=1; // clear the row for (y=0; y<64; y++)

{ _lcd_enable(); //Delay10TCYx(1); } } } void lcd_setpage(unsigned char page) { _lcd_waitbusy(); DI=0; RW=0; LCD_DATA = 0b10111000 | page; _lcd_enable(); } void lcd_setyaddr(unsigned char y) { _lcd_waitbusy(); DI=0; RW=0; LCD_DATA = 0b01000000 | (y & 0b00111111); _lcd_enable(); } void _lcd_waitbusy(void) { while (_lcd_status() & 0b10000000) { Delay10TCYx(250); // .5 ms } } void lcd_write (unsigned char data) { _lcd_waitbusy(); DI=1; RW=0; LCD_TRIS=0; LCD_DATA = data; _lcd_enable(); } void lcd_selectside(unsigned char sides) { // set a CS pin low to enable it if (sides & LEFT)

CS1 = 0; else CS1 = 1; if (sides & RIGHT) CS2 = 0; else CS2 = 1; } unsigned char lcd_read (void) { unsigned char _data; LCD_TRIS=0xFF; RW = 1; DI=1; _lcd_enable(); _data = LCD_DATA; LCD_TRIS=0x00; return _data; } void lcd_plotpixel(unsigned char rx, unsigned char ry) { unsigned char data; //lcd_waitbusy(); // select the correct side if (rx & 64) lcd_selectside(RIGHT); else lcd_selectside(LEFT); lcd_setpage( ry >> 3); lcd_setyaddr( rx & 0b00111111); data = lcd_read(); // dummy read needed here data = lcd_read(); lcd_setyaddr( rx & 0b00111111); lcd_write (data | (1 << (ry & 0b111))); } void lcd_putchar(char c) { int base; base = c - 32; base *= 3; lcd_write(font[base]);

lcd_write(font[base + 1]); lcd_write(font[base + 2]); lcd_write(0); } void lcd_putrs(const rom char *string) { char i=0; while (string[i] != 0) lcd_putchar(string[i++]); } void lcd_puts(char *string) { char i=0; while (string[i] != 0) lcd_putchar(string[i++]); }

Das könnte Ihnen auch gefallen