|
|
View previous topic :: View next topic |
Author |
Message |
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
QL200 development board LCD display –128*64 lattice |
Posted: Thu Jul 23, 2009 2:06 pm |
|
|
Hello,
My family has recently offers to me the development board QL200 for my birthday.
I've in my possession the CCS compiler and I would like to know if there is one driver for the graphical LCD display ?
LCD DISPLAY DATASHEET
Thanks a lot, and sorry for my english. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Jul 23, 2009 3:33 pm |
|
|
You should look in the PICC->drivers directory.
There is a somewhat universal LCD library - but I don't think it applies to this one because it's graphical.
Look for something that talks about the ST7920 Graphical LCD controller.
You should really email the manufacturer and ask them for the LCD's communication protocol.
Then you'll be able to interface it appropriately into the CCS "universal" LCD driver.
Also, Microchip has a free Graphical LCD driver library that would interest you. Check their website and see if they have posted drivers for this LCD.
Regards,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 23, 2009 4:33 pm |
|
|
According to your LCD data sheet, it uses the ST7920 controller.
There's a driver posted here for it:
http://www.ccsinfo.com/forum/viewtopic.php?t=36857
The LCD pinout is shown on page 22 of the QL200 data sheet:
http://www.pic16.com/soft/QL200_user_a4_en.pdf
The driver in the link above uses Port B for the data, and pins C5-C7
for control signals. The QL200 schematic shows that Port D is used
the data lines, but I can't see which pins are used for the control signals.
But, the driver would have to be changed slightly to use the correct pins
for your board.
There's no guarantee that this driver will work. |
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Fri Jul 24, 2009 3:26 am |
|
|
Ok thanks.
I will try it and modify it in consequence.
In your document, it's wrote that it use PORT A as control bit and PORT D as data bit.
thanks again. |
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Fri Jul 24, 2009 12:44 pm |
|
|
Hello again.
I've received my QL200 development board and there is one cd into the box.
In the CD there is one file which look like a driver.
Code: | //THE experiment is to familiarity the use of 12864LCD
//12864LCD with the lib of chinese
//program to display company's logo and tel.
//the configration of hardware
//Tip:Please open RA4 pull UP, will S10'S NO.4 in the "on" ,Jump J14 all connect,
#include<pic.h>
__CONFIG(0x1832);
//__CONFIG _DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC
#define rs RA5 //COMMNAD/DATA SELECT
#define rw RA4 //READ/WRITE SELECT
#define e RA3 //ENABLE SIGNAL
#define psb RA2 //PARALLEL/SERIAL SELECT£¨H/L£©
#define rst RA0 //RESET SIGNAL
#define nop() asm("nop") //nop func
//ÉîÛÚǬÁúÊ¢µç×Ó
const unsigned char TAB1A[ ]={0xC9,0xEE,0xDB,0xDA,0xC7,0xAC,0xC1,0xFA,0xCA,0xA2,0xB5,0xE7,0xD7,0xD3};
//WWW.PIC16.COM
const unsigned char TAB1B[ ]={' ', ' ', 'W', 'W', 'W', '.', 'P', 'I', 'C', '1','6', '.', 'C', 'O', 'M', ' '};
//TEL0755-28187975
const unsigned char TAB1C[ ]={'T', 'E', 'L' ,'0' ,'7', '5' ,'5','-', '2', '8','1', '8' ,'7','9' ,'7','5'};
//FAX0755-28187976
const unsigned char TAB1D[ ]={'F', 'A', 'X', '0', '7', '5', '5', '-','2', '8','1', '8', '7', '9', '7', '6'};
unsigned int lcd_x; //X address
unsigned int lcd_y; //Y address
bit busy; //busy flag
void init(); //system init.
void lcd_init(); //LCD init
void clear_p(); //clear screen
void han_wr2a(); //company name.
void han_wr2b(); //company website.
void han_wr2c(); //company tel.
void han_wr2d(); //company fax.
void wr_zb(); //display setting mode.
void flash(); //lcd blink func.
void qushu(int counts,const unsigned char *ps); //search table.
void send_d(unsigned char x); //send data
void send_i(unsigned char x); //send command.
void chk_busy(); //check busy sub.
void delay(); //delay func, decide the speed of display.
void delay1(); //delay func, decide the speed of blink.
//-------------------------------------------
//main
void main()
{
while(1)
{
init(); //system init.
lcd_init(); //
clear_p(); //
han_wr2a(); //company name.
han_wr2b(); //company website.
han_wr2c(); //company tel.
han_wr2d(); //company fax.
delay(); //
flash(); //
clear_p(); //
}
}
//-------------------------------------------
//I/O¿Ú setting func.
void init()
{
TRISA=0X00; //A port as output
TRISD=0X00; //d port as output
ADCON1=0X06; //A port as ordinary i/o
}
//-------------------------------------------
//-------------------------------------------
void lcd_init()
{
rst=0; //reset LCD
delay();
rst=1; //LCD normal work.
nop();
psb=1; //8 bit as parrallel.
send_i(0x30); //basic operation instruction
send_i(0x01); //off display
send_i(0x06); //set the cursor's moving direction.
send_i(0x0c); //on display,off cursor,off blink
}
//-------------------------------------------
//company name.
void han_wr2a()
{
send_i(0x81); //set display position
qushu(0xe,TAB1A); //get data from table
}
//-------------------------------------------
//company website.
void han_wr2b()
{
send_i(0x90); //set display position
qushu(0x10,TAB1B); //get data from table
}
//-------------------------------------------
//company tel.
void han_wr2c()
{
send_i(0x88); //set display position
qushu(0X10,TAB1C); //get data from table
}
//-------------------------------------------
//company fax.
void han_wr2d()
{
send_i(0x98); //set display position
qushu(0X10,TAB1D); //get data from table
}
//display setting.
void wr_zb()
{
send_i(lcd_y);
send_i(lcd_x);
}
//-------------------------------------------
//blink
void flash()
{
send_i(0x08); //off display.
delay1(); //delay
send_i(0x0c); //on display
delay1();
delay1(); //delay
send_i(0x08); //off
delay1();
send_i(0x0c); //on
delay1();
delay1();
send_i(0x08); //off
delay1();
send_i(0x0c); //on
delay1();
delay1();
}
//-------------------------------------------
//clear screen
void clear_p()
{
send_i(0x1); //clear all
send_i(0x34); //extend.
send_i(0x30); //basic
}
//------------------------------------------
//search.
void qushu(int counts,const unsigned char *ps)
{
int i; //define loop count.
for(i=counts;i>0;i--) //
{
send_d(*ps); //
delay(); //
ps++; //get next.
}
}
//-------------------------------------------
//display the next.
void send_d(unsigned char x)
{
chk_busy(); //check busy.
rs=1; //data not commnad.
rw=0; //write not read.
PORTD=x; //data to bus.
e=1; //enable.
nop();
nop();
nop();
e=0; //disable.
}
//--------------------------------------------
//send command.
void send_i(unsigned char x)
{
chk_busy(); //check lcd if busy.
rs=0; //data not commnad.
rw=0; //write not read.
PORTD=x; //data to bus.
e=1; //enable.
nop();
nop();
nop();
e=0; //disable.
}
//-------------------------------------------
//check lcd busy.
void chk_busy()
{
busy=1; //set busy signal
TRISD=0XFF; //change the bus to input.
rs=0; //command not data.
rw=1; //read not write.
while(busy)
{
nop();
nop();
nop();
e=1; //enable.
nop();
nop();
nop();
if(!RD7) busy=0; //
nop();
nop();
nop();
e=0; //DISABLE.
}
e=0; //DISABLE.
TRISD=0X00; //bus as output.
}
//-------------------------------------------
//delay
void delay()
{
int i;
for(i=0;i<5000;i++)
{;}
}
//-------------------------------------------
//delay1
void delay1()
{
int i;
for(i=0;i<10;i++)
{
delay(); //call delay.
}
} |
In reality it's a program which display the name of a company, but it looks like a driver... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 24, 2009 2:26 pm |
|
|
You can convert that code to CCS. It would be a good way to
learn about the compiler and PICs. |
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Sat Jul 25, 2009 1:20 am |
|
|
Hello, I finally try to find a driver and just modify it.
I've found this one:
http://www.ccsinfo.com/forum/viewtopic.php?t=32819&highlight=st7920
But when I try to compile it, I've many error.
It says that in the test program, function:
Quote: | inicializarMicro (); // Inicializa los registros de configuración del MCU y perifericos.
inicializarSD (); // Inicializa las estructuras de datos utilizadas por el programa.
activarSalidas (); // Inicializar las salidas. |
are undefined...
and in mg1903a.h it's waiting for many declaration and indentifier.
So it refused to compile... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 25, 2009 2:00 am |
|
|
The programs are not complete. They didn't post a compilable test
program. To make it compile, you need to make the changes shown
in bold below.
This code requires an 18F-series PIC, because it has large "dots" array.
It won't compile with a 16F877.
I did not develop this code. There is no guarantee that it works.
I'm just helping you to get it to compile, and maybe work in a
minimal way.
Quote: |
#include <18F452.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#case // Add this line
#include "mg1903a.h"
#include <graphics.c> // Add this line
#include <math.h>
void main()
{
int1 warn = FALSE;
int16 adc = 0L, adc_old = 0L;
char voltText[] = "Volts", warning[] = "Warning", W[] = "W";
float theta = 0;
// Comment out these next 3 lines:
// inicializarMicro (); // Inicializa los registros de configuraciÿÿÿón del MCU y perifericos.
// inicializarSD (); // Inicializa las estructuras de datos utilizadas por el programa.
// activarSalidas (); // Inicializar las salidas.
glcd_rect(1, 5, 126, 15, NO, ON); // Outline the bar
glcd_text57(30, 18, voltText, 1, ON); // Display "Volts"
glcd_circle(145, 16, 10, NO, ON); // Draw the clock circle
while (TRUE)
{
// Comment out these next 2 lines:
// adc = entradaAnalogica.valor; // Read a value from the ADC
// displayVoltage (adc); // Display the reading
adc = 50; // Add this line
adc = (adc > 249L) ? 249L : adc; // Keep the value 249 or less |
|
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Sat Jul 25, 2009 3:55 am |
|
|
Thanks the compilation work (it just missed two } in the end of your code ).
But I don't understand how the compiler make the link between graphics.c which allow to display circle, rectangle and other things, with the "mg1903a.h" library which tell to the compiler how to display something...
Do you believe if I add
Code: |
#define glcd_rs RA5 //COMMNAD/DATA SELECT
#define glcd_rw RA4 //READ/WRITE SELECT
#define glcd_e RA3 //ENABLE SIGNAL
#define glcd_psb RA2 //PARALLEL/SERIAL SELECT£¨H/L£©
#define glcd_rst RA0 //RESET SIGNAL |
will it work ?
Last question, why it doesn't work with 16F family ?
When I try to compile with a 16F877A the first error is about the line:
Code: | Dots dots[32][12]; // Diemensiones máximas del display (x,y) = (191,31). |
and it's write "data item too big". I think the problem is due to the limitation of ROM or RAM.
No problem with a 18F2550... |
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Wed Aug 05, 2009 1:37 am |
|
|
Hello,
My driver work finally well:
Code: | #include <16f876.h>
#use delay (clock = 20000000)
#define rs PIN_A5 //COMMNAD/DATA SELECT
#define rw PIN_A4 //READ/WRITE SELECT
#define e PIN_A3 //ENABLE SIGNAL
#define psb PIN_A2 //PARALLEL/SERIAL
#define rst PIN_A0 //RESET SIGNAL
/*data are send by defaut with the port b. in order to change the port of data,
please change output_x in lcd_data and lcd_instruction and don't forget to change
in func lcd_check_busy 'input(PIN_B7)'*/
void lcd_init(); //LCD init
void lcd_clear(); //clear lcd display and cursor back to home
void lcd_display(unsigned char); //affichage lcd
void lcd_instruction(unsigned char); //send instruction to lcd
void lcd_data(unsigned char); //send data to lcd
void delay(); //delay func, decide the speed of init.
void lcd_check_busy(); //check if the lcd display is busy
const unsigned char TAB[]={'A','B','C','D','E','F','g','h','i','j','k','L','M' };
void main ()
{
int i ;
while(1)
{
lcd_init();
for(i=0;i<8;i++)
{
lcd_display(TAB[i]);
delay();
}
delay_ms(1000); //pause de 1 seconde permettant de voir l'affichage
lcd_clear();
}
}
//initialisation du LCD
void lcd_init()
{
output_low(rst); //reset LCD
delay();
output_high(rst); //LCD normal work.
output_high(psb); //8 bit as parrallel.
lcd_instruction(0x30); //basic operation instruction
lcd_instruction(0x01); //off display
lcd_instruction(0x06); //set the cursor's moving direction.
lcd_instruction(0x0c); //on display,off cursor,off blink
}
void lcd_clear ()
{
lcd_instruction(0x01); //clear display and cursor back to home
lcd_instruction(0x34); //extend.
lcd_instruction(0x30); //basic operation instruction
}
void lcd_display(unsigned char data)
{
lcd_data(data);
}
void lcd_instruction (unsigned char x)
{
lcd_check_busy();
output_low(rs); //data not commnad.
output_low(rw); //write not read.
output_b(x); //data to bus.
output_high(e); //enable.
delay_us(450);
output_low(e); //disable.
}
void lcd_data (unsigned char x)
{
lcd_check_busy();
output_high(rs); //data not commnad.
output_low(rw); //write not read.
output_b(x); //data to bus.
output_high(e); //enable.
delay_us(450);
output_low(e); //disable.
}
//delay
void delay()
{
int i=0;
while(i<250)
{
i=i+1;
}
}
//check lcd busy.
void lcd_check_busy()
{
int busy;
busy=1; //set busy signal
output_low(rs); //command not data.
output_high(rw); //read not write.
while(busy)
{
output_high(e); //enable.
if(!input(PIN_B7)) busy=0; //
output_low(e); //DISABLE.
}
output_low(e); //DISABLE.
}
|
but I've one last problem, it doesn't work when I try to use 20 MHz crystal, but no problem with a 4MHz crystal.
do you have got one idea ?
thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 05, 2009 1:55 am |
|
|
Quote: |
It doesn't work when I try to use 20 MHz crystal, but no problem with a 4MHz crystal.
|
It's probably because of this routine:
Quote: |
void delay()
{
int i=0;
while(i<250)
{
i=i+1;
}
}
|
That routine does not adjust for the change in crystal speed. The CCS
delay functions automatically adjust for the crystal frequency.
The while() loop in that routine takes 8 instruction cycles per loop.
You can see this by counting instruction cycles in the .LST file.
Or, you time it with the MPLAB Stopwatch feature, as described in
this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=38351
Here is the formula:
Code: | 250 loops x 8 instructions/loop x 1 usec/instruction = 2 ms |
So to fix the delay() routine, just remove the existing code and put in
a CCS delay_ms() statement for 2 ms. Now, it will do the same delay
if the crystal is 4 MHz or 20 MHz. Example:
Code: |
void delay()
{
delay_ms(2);
}
|
|
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Wed Aug 05, 2009 3:08 am |
|
|
Ok, I've done this changement.
but it was first:
Code: |
void delay()
{
int i=0;
while(i<50)
{
i=i+1;
} |
with my 4MHz crystal. I've replaced it by delay_ms(2), you're allright it's better.
But my display still doesn't work with the 20MHz crystal :( |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 05, 2009 11:44 am |
|
|
You are probably violating the timing specifications for your LCD
controller. The LCD controller data sheet will have a section with
timing diagrams, and a table of pulse durations, setup and hold times.
You need to look closely at your code and keep in mind that one
instruction cycle is 200 ns at 20 MHz, but 1 us at 4 MHz. Look for
places in your code where you're violating the LCD's required timing.
If you have a logic analyzer, capture the waveforms. Compare them
to the timing diagram in the LCD data sheet. If you have an
oscilloscope, make a small test program that repeatedly calls the same
routine, so that you can trigger on it, and look at the waveforms on
the scope.
Also, the LCD command take a minimum amount of time to complete.
Make sure you are following the required delays in the data sheet. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Aug 05, 2009 12:00 pm |
|
|
PCM programmer wrote: | You are probably violating the timing specifications for your LCD
controller. The LCD controller data sheet will have a section with
timing diagrams, and a table of pulse durations, setup and hold times.
You need to look closely at your code and keep in mind that one
instruction cycle is 200 ns at 20 MHz, but 1 us at 4 MHz. |
Agreed.
200nS is WAY too short.
As an EXAMPLE, the hd44780 has a MINIMUM enable cycle write time of 1uS with a minimum enable pulse width of 450nS
Address setup time is 60nS min.
Address hold of 20nS and a max data delay time of 360nS.
Cheers,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
mortaurat
Joined: 23 Jul 2009 Posts: 14
|
|
Posted: Wed Aug 05, 2009 1:13 pm |
|
|
I found delay in the datasheet.
In page 11, 200nS for one instruction looks good for the lcd display.
unlike to the hd44780, the ST7920 need an enable pulse width of 140nS, so it shall be ok...
If I do
Code: | output_high(e); //enable.
output_low(e); //disable.
|
enable width will be longer than 140ns.
I really don't understand where there is a bad timing :( |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|