I've recently made a WS0010 driver (only 8 bit mode done).
Here's how I've done it.
First thing I did, is I made a "sendByte" function that is able to send instructions, as well as data to be written on the LCD.
So my function looked something like this:
Code: Select all
/*
u8 = unsigned 8 bit value (unsigned char)
CONTROL_PORT is the port where you connected the RS, RW and EN pins
DATA_PORT is the port where you connected the DB0~7 pins
RS_BIT is the pin number where you attached your RS pin on the microcontroller
RW_BIT ...
EN_BIT ...
*/
int sendByte(u8 RS, u8 RW, u8 data)
{
if (RW != 0)
return -1; // RW need to be 0 to write something to the controller
else
clear_bit(CONTROL_PORT, RW_BIT);
// If it's data, set to 1, if not, set to 0
if (RS != 0)
set_bit(CONTROL_PORT, RS_BIT);
else
clear_bit(CONTROL_PORT, RS_BIT);
DATA_PORT = data
// Set your data BEFORE your enable bit
set_bit(CONTROL_PORT, EN_BIT);
delay_ms(1);
// Once you set your enable bit, give the controller a little bit of time and then clear every bit you set
clear_bit(CONTROL_PORT, EN_BIT);
clear_bit(CONTROL_PORT, RS_BIT);
return 0;
}
Second thing to do is make a "readBusyFlag" function. Every controller, when an instruction is sent to it, sets its DB7 bit high (RS & RW need to be set to "01") whenever it's busy processing an instruction.
You could leave this only if you give the controller enough time to process the instructions and you are sure it has done processing data.
Code: Select all
/*
retval is the value of DB7 (either 0 or 1)
DATA_TRIS is the TRIS register of the data port to set a pin as input or output
CONTROL_TRIS is the TRIS register of the control port
*/
u8 readBusyFlag(void)
{
u8 retval = 0;
set_bit(DATA_TRIS, 7); // set data port pin 7 to an input
clear_bit(CONTROL_PORT, RS_BIT); // clear RS bit
set_bit(CONTROL_PORT, RWB_BIT); // set RW bit (read-mode)
delay_ms(1);
set_bit(CONTROL_PORT, EN_BIT); // set enable bit
delay_ms(1); // wait for a ms
retval = GETBIT(DATA_PORT, 7); // read pin 7 (DB7)
clear_bit(CONTROL_PORT, EN_BIT); // disable the controller
clear_bit(DATA_TRIS, 7); // set pin 7 back to output
clear_bit(CONTROL_PORT, RWB_BIT); // clear the RW bit (write mode)
return retval; // return the value of DB7
}
Now you can use both those function to either send instruction or data and wait for the controller to process that information.
Your next step will be to make an initialization function. This consist in using the sendByte function, readBusyFlag function and delay_ms function.
Based on page 63 of your KS0073 datasheet, this is what your initialization code could look like:
(1) Note that in the function set, setting the LCD to 1 or 2 lines doesn't really matter because you're going to use the extended function set to set it to 4 lines.
But you have to use the function set first, because this is what determines if you're using 8 bit mode or 4 bit mode.
(2) Don't forget that not all the instruction can be executed when the extended register is set. Take a look at Display ON/OFF Control instruction. RE needs to be 0 for it to be recognized and processed the way it should!
Code: Select all
void initLCD(void)
{
delay_ms(25); // wait more than 20 ms after power up
// Set Extended Register to 1
// Function Set (check datasheet p.27)
sendByte(0, 0, 0b00111100); // send instruction (RS=0, RW=0) Function Set: 8 bit mode (1), 2 lines (1), extended register enable (1)
while (readBusyFlag()); // while busy flag is set, do nothing
delay_ms(1); // wait for a ms
//Extended Function Set (check datasheet p.26)
sendByte(0, 0, 0b00001001); // send instruction Ext. Function Set: 5-dot font (0), cursor blink invert disabled (0), 4 line display mode (1)
while (readBusyFlag()); // while busy flag is set, do nothing
delay_ms(1); // wait for a ms
// Clear Extended Register
// Function Set (check datasheet p.27)
sendByte(0, 0, 0b00111000); // send instruction (RS=0, RW=0) Function Set: 8 bit mode (1), 2 lines (1), extended register enable (0)
while (readBusyFlag()); // while busy flag is set, do nothing
delay_ms(1); // wait for a ms
// Display ON/OFF control (datasheet p.26)
sendByte(0, 0, 0b00001100); // set display on (1), cursor off (0), blink off (0)
while (readBusyFlag()); // while busy flag is set, do nothing
delay_ms(1); // wait for a ms
// Clear Display
sendByte(0, 0, 0b00000); // send instruction clear display
while (readBusyFlag()); // while busy flag is set, do nothing
delay_ms(2); // wait for more than 1.53 ms
// Entry mode set
sendByte(0, 0, 0b00000110); // set cursor increment (1), disable shift (0)
while (readBusyFlag()); // while busy flag is set, do nothing
delay_ms(1); // wait for a ms
}
Check out p.28 to set the DDRAM address and to write data to that address (RS=1, RW=0).
I think I've said enough for you to continue.
PS: I don't think using the LCD macro's from flowcode will work with your LCD.