Does anyone have a working driver for CFAG14432B?

cbarberis

New member
Hi,

I recently purchased one of these 144X32 graphics/char modules (CFAG14432B) I have followed both the data sheets from Crystal Fontz as well as the data sheets for the Sitronix ST7920 and I am still having no luck making this thing work, I have contacted CF tech support, but so far, no luck. I am trying to use this module in the parallel 8 bit mode for graphics, If anyone has suceeded with such a feat and would not mind sharing some info on this driver, it would be greatly appreciated.:confused::confused:
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.
 
If you can't find any driver code samples, then you could post your own code (and your cpu/hookup details) and we could try to troubleshoot it.
 

cbarberis

New member
SO FAR I HAVE TRIED EVERYTHING, FOLLOWED THE DATA SHEET AND LOOKED OVER THE CRYSTALFONTZ C++ TEST APP.....NO LUCK!! I AM SURE IT'S SOMETHING STUPID THAT I AM MISSING IN MY DRIVER.

THE FOLLOWING IS MY DRIVER WRITTEN FOR A PIC18 uCONTROLLER USING THE CCS C COMPILER:
/////////////////////////////////////////////////////////////////////////
//// ////
//// ////
//// This file contains drivers for using a CrystalFontz CFAG14432B ////
//// that uses a ST7920 display controller. The CFAG14432B is 144 by ////
//// 32 pixels. ////
//// The driver treats the upper left pixel as (0,0). ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// LCD Pin connections: ////
//// * 1: VSS is connected to GND ////
//// * 2: VDD is connected to +5V ////
//// * 3: V0 - LCD operating voltage (Constrast adjustment) ////
//// * 4: R/S - Data or Instruction is connected to C7 ////
//// * 5: R/W - Read or Write is connected to C6 ////
//// * 6: Enable is connected to C5 ////
//// * 7-14: Data Bus 0 to 7 is connected to port B ////
//// * 15: Positive voltage for LED backlight is connected to +5V ////
//// * 16: Negavtive voltage for LED backlight is connected to GND ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// glcd_init () ////
//// * Must be called before any other function. ////
//// ////
//// glcd_pixel (x,y,color) ////
//// * Sets the pixel to the given color. ////
//// - color can be ON or OFF ////
//// ////
//// glcd_fillScreen (color) ////
//// * Fills the entire LCD with the given color. ////
//// - color can be ON or OFF ////
//// ////
/////////////////////////////////////////////////////////////////////////

#define GLCD_RS RC7 // Display Data / Control Data.
#define GLCD_RW RC6 // Read / Write
#define GLCD_E RC5 // Enable Signal.

#define GLCD_WIDTH 144

#define RS_FUNCTION 0
#define RS_DATA 1
#define RW_WRITE 0
#define RW_READ 1
#define TRIS_READ 0xFF
#define TRIS_WRITE 0x00


// Color Values
#define ON 1
#define OFF 0

typedef union
{
int16 word;
int8 byte[2];
} Dots;

typedef struct
{
int1 refresh;
Dots pix[32][12]; // Max dimensions for display (x,y) = (144,31)
} GDRAM; // (0,0) corresponds to upper lefthand corner.

GDRAM gdram;


/*----------------------------------------------------------------------------------------------
* glcd_readByte
*
* Reads a byte of data from the LCD.
*
* In/Out:
*
* Return: A byte of data read from the LCD.
*
*--------------------------------------------------------------------------------------------*/

unsigned int8 glcd_readByte (unsigned int8 address)
{
unsigned int8 data; // Stores the data read from the LCD

set_tris_b (TRIS_READ); // Set PORTB to input
delay_us(15);
GLCD_RS = address;
GLCD_RW = RW_READ; // Set for reading
delay_us(50);
GLCD_E = 1; // Pulse the enable pin
delay_us(50);
data = PORTB; // Get the data from the display's output register
GLCD_E = 0;
delay_us(15);
GLCD_RS = 1;
return (data);
}

/*----------------------------------------------------------------------------------------------
* Function Name: CheckBusyFlag()
*
* Function: Reads the status of bit 7 to test busy flag
*
* In/Out:
*
* Return: Flagdata
*
*
*
*--------------------------------------------------------------------------------------------*/

unsigned int8 CheckBusyFlag ()
{
unsigned int8 Flagdata; // flag data value

set_tris_b (TRIS_READ); // Set PORTB to input
delay_us(15);
GLCD_RS = 0;
GLCD_RW = RW_READ; // Set for reading
delay_us(5);
GLCD_E = 1; // Pulse the enable pin
delay_us(15);
Flagdata = (PORTB & 0x40); // mask bit 7 to test busy flag data from the display's output register
delay_us(15);
GLCD_E = 0;
delay_us(15);
GLCD_RS = 1;
return (Flagdata);
}


/*----------------------------------------------------------------------------------------------
* glcd_writeByte
*
* Write a byte of data to the LCD.
*
* - data (in): the byte of data to write.
*
*
*--------------------------------------------------------------------------------------------*/

void glcd_writeByte (unsigned int8 address, unsigned int8 data)
{
GLCD_RS = RS_FUNCTION;
//while ( CheckBusyFlag () ) ; // Whait Busy Flag = FALSE!
set_tris_b (TRIS_WRITE); // Set PORTB to output
delay_us(1000);
GLCD_RS = address;
GLCD_RW = RW_WRITE; // Set for writing

GLCD_E = 0;
delay_us(1000);
PORTB = data; // Put the data on the port
//GLCD_E = 1;
delay_us(1000);
GLCD_E = 1;
// PORTB = data; // Put the data on the port
delay_us(1000);
GLCD_E = 0; // Pulse the enable pin
GLCD_RW = 1;

}


/*----------------------------------------------------------------------------------------------
glcd_fillScreen
*
* Fill the LCD screen with the passed in color.
*
* - color (in):
* ON - turn all the pixels on.
* OFF - turn all the pixels off.
*
*--------------------------------------------------------------------------------------------*/

void glcd_fillScreen (unsigned int1 color)
{
int8 v, h;
int16 d;

d = (color == ON ? 0xFFFFL : 0x0000L);

for (v=0; v<32; v++)
{
for (h=0; h<12; h++)
{
gdram.pix[v][h].word = d;
}
}
gdram.refresh = TRUE;
}


/*----------------------------------------------------------------------------------------------
* glcd_update
*
* Update the LCD with data from the display cache.
*
*--------------------------------------------------------------------------------------------*/

void glcd_update ()
{
int8 v, h;

if (gdram.refresh)
{
for (v=0; v<32; v++)
{
glcd_writeByte (RS_FUNCTION, 0x80 | v); // Set Vertical Address.
glcd_writeByte (RS_FUNCTION, 0x80 | 0); // Set Horizontal Address.

for (h=0; h<12; h++)
{
glcd_writeByte (RS_DATA, gdram.pix[v][h].byte[1]); // Write High Byte.
glcd_writeByte (RS_DATA, gdram.pix[v][h].byte[0]); // Write Low Byte.
}
}
gdram.refresh = FALSE;
}
}


/*----------------------------------------------------------------------------------------------
* glcd_init
*
* Initialize LCD.
*
* - mode (in): OFF/ON - Turns the LCD off/on.
*
* Call before using any other LCD function.
*
*--------------------------------------------------------------------------------------------*/

void glcd_init ()
{
set_tris_b (TRIS_WRITE); // PORTB as output.
GLCD_RS = RS_FUNCTION;
GLCD_RW = RW_WRITE;
GLCD_E = 0;
delay_ms (40);

glcd_writeByte (RS_FUNCTION, 0x30); // Specify 8 bit interface and basic instruction set.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x30); // Specify 8 bit interface and basic instruction set.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x0C); // Specify Display on, Cursor off and Blink off.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x01); // Display clear.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x06); // AC Increase (cursor move right), don't shift the display.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x34); // Select extended instruction set.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x36); // Graphic display ON.
delay_ms (10);

glcd_fillScreen (1);
glcd_update ();
}


/*----------------------------------------------------------------------------------------------
* Turn a pixel on a graphic LCD on or off.
*
*
* - x (in): the x coordinate of the pixel.
* - y (in): y - the y coordinate of the pixel.
* - color (in): ON or OFF.
*--------------------------------------------------------------------------------------------*/

void glcd_pixel(int8 x, int8 y, int1 color)
{
int8 v, h, b;

v = y;
h = x/16;
b = 15 - (x%16);

// Modify the actual word.
if (color == ON) bit_set (gdram.pix[v][h].word, b);
else bit_clear (gdram.pix[v][h].word, b);

gdram.refresh = TRUE;
}
 
First, I will say that I have no direct experience using this display, or any other that uses this controller chip, so my advice is "theoretical".

Next, contrast concerns. Are you able to see anything at all on the screen? What is the voltage at Vo? Are you able to vary Vo and see the entire screen turn dark (or light, depending on your model, which you don't specify)?

Then, do you have a way to check whether your control & data signals are "good" at the display inputs? Like using a scope to check the waveform for correct voltage level and not noise or garbage. Or you could write test loops to toggle each signal, one at a time, at a slow rate (1 sec on, 1 sec off) and measure with a meter to see that the signal is reaching the correct input, and no other inputs are changing. If this is not correct, nothing will work properly.

Codewise, your CheckBusyFlag () function won't work because you are masking the wrong bit. Bit 7 requires a mask of 0x80:
Flagdata = PORTB & 0x80; // mask bit 7 to test busy flag

Also, there is no need to change RW or RS after the E strobe is complete, since it is set explicitely prior to the next E strobe.

Otherwise, your code looks like it should work, i.e. no obvious errors at a casual examination.

Have you tried staying in basic mode (0x30), and send characters to be displayed from the internal CGROM (i.e. treat it like a character display)?

P.S. it looks like your CAPSLOCK is stuck on.
 

cbarberis

New member
Thank you COSMICVOID!

YES my caps lock were on and there was a typo on the mask should have been 0x80 not 0x40, nevertheless that was not the problem as I was not testing the busy flag bit, I am sure if I did, I would have spent an eternity or overiden the busy codition in that routine. I am truly embarrased to admit as to the real problem which I spent nearly two full days!!!! The problem was that I had selected the data to be placed on portB of my Picmicro, unfortunately portB bits 6 and 7 are used for the ICD debugger, which I was using and therefore any data that i would send to the LCD display would never have the values for these two bits..duh!

Once I swapped the data byte to another port everything worked just fine!!!!

It goes to show how true the old adage "can’t see the forest for the trees"
:eek::eek::eek::eek::eek::eek:
 
Top