CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

QL200 development board LCD display –128*64 lattice
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mortaurat



Joined: 23 Jul 2009
Posts: 14

View user's profile Send private message

QL200 development board LCD display –128*64 lattice
PostPosted: Thu Jul 23, 2009 2:06 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jul 23, 2009 3:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jul 23, 2009 4:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jul 24, 2009 3:26 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jul 24, 2009 12:44 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jul 24, 2009 2:26 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Jul 25, 2009 1:20 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Jul 25, 2009 2:00 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Jul 25, 2009 3:55 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 1:37 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 1:55 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 3:08 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 11:44 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 12:00 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 1:13 pm     Reply with quote

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 :(
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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