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

How to make custom LCD characters ?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ratgod



Joined: 27 Jan 2006
Posts: 69
Location: Manchester, England

View user's profile Send private message

PostPosted: Sat Sep 22, 2007 8:06 am     Reply with quote

How do you make and send the custom characters to the screen?
many thanks.

I'm using a 4x20 LCD with a PIC18F252
libor



Joined: 14 Dec 2004
Posts: 288
Location: Hungary

View user's profile Send private message

PostPosted: Sat Sep 22, 2007 9:17 am     Reply with quote

If you have a HD44780 controller in your LCD module,
then you can use this very useful utility 'LCD character creator' to design your characters: download from here
You can have up to 8 custom characters (but you can reprogram them on fly, while displayed also) You send instruction 0x40 before filling the character RAM.
Mark Weir



Joined: 11 Sep 2003
Posts: 51
Location: New Zealand

View user's profile Send private message

Custom Characters
PostPosted: Sun Sep 23, 2007 2:44 pm     Reply with quote

Hi There,

Try this site, it has everything you need.

Take note, you need both int() statements to make it work.

http://www.loginway.com/custom_char.htm

Cheers

Mark
_________________
Life is too short to avoid asking questions
ratgod



Joined: 27 Jan 2006
Posts: 69
Location: Manchester, England

View user's profile Send private message

PostPosted: Fri Oct 05, 2007 11:40 pm     Reply with quote

Many thanks,
I will try them all out as soon as I get a chance
ratgod



Joined: 27 Jan 2006
Posts: 69
Location: Manchester, England

View user's profile Send private message

PostPosted: Tue Oct 09, 2007 7:44 am     Reply with quote

I have had mixed success using the code from www.loginway.com

The LCD driver didn't seem to work for me too well, probably because its for a 2 line display, I kept getting garble even though I was printing normal characters.

I tried to add it to the 20x4 driver I am using now but I lose the top line when I initialize the custom characters. works fine with normal characters if I don't initialize the custom ones.

here is the modified driver

Code:
////////////////////////////////////////////////////////////////////////////
////                             LCD_4b.C                               ////
////            Driver for common 4x20 LCD modules                      ////
////                                                                    ////
////  lcd_init()   Must be called before any other function.            ////
////                                                                    ////
////  lcd_putc(c)  Will display c on the next position of the LCD.      ////
////                     The following have special meaning:            ////
////                      \f  Clear display                             ////
////                      \n  Go to start of second line                ////
////                      \b  Move back one position                    ////
////                                                                    ////
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)     ////
////                                                                    ////
////  lcd_getc(x,y)   Returns character at position x,y on LCD          ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////
// lcd4.c

  #define LCD_DB7   PIN_B5
  #define LCD_DB6   PIN_B4
  #define LCD_DB5   PIN_B3
  #define LCD_DB4   PIN_B2


  #define LCD_RS    PIN_B0
//  #define LCD_RW    PIN_A0 // testing
  #define LCD_E     PIN_B1

// These are the line addresses for most 4x20 LCDs.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/


//========================================

#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)

//#define LCD_CGRAM_ADDR 0x40           // Set the CGRAM address
//#define LCD_DDRAM_ADDR 0x80           // Set the DDRAM address
#define LCD_CGRAM_ADDR 0x40           // Set the CGRAM address
#define LCD_DDRAM_ADDR 0x80           // Set the DDRAM address


#define LCD_CHAR_1 0x01
#define LCD_CHAR_2 0x02
#define LCD_CHAR_3 0x03
#define LCD_CHAR_4 0x04
#define LCD_CHAR_5 0x05
#define LCD_CHAR_6 0x06
#define LCD_CHAR_7 0x07
#define LCD_CHAR_8 0x08

BYTE const LCD_CUSTOM_CHARS[64] =
{0x0A,0x15,0x11,0x0A,0x11,0x15,0x0A,0x00,
0x15,0x14,0x1D,0x15,0x15,0x10,0x1F,0x0F,
0x12,0x12,0x12,0x12,0x09,0x00,0x1F,0x1F,
0x06,0x08,0x04,0x02,0x0C,0x00,0x1F,0x1F,
0x04,0x0E,0x04,0x04,0x04,0x00,0x1F,0x1F,
0x0E,0x0A,0x0A,0x0A,0x0E,0x00,0x1F,0x1F,
0x0C,0x0A,0x0A,0x0A,0x0A,0x00,0x1F,0x1F,
0x0E,0x08,0x0C,0x08,0x0E,0x00,0x1F,0x1F};

int8 lcd_line;

int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
 0xc,                     // Display on
 1,                       // Clear display
 6                        // Increment cursor
 };


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));   
 output_bit(LCD_DB7, !!(nibble & 8));   

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_RW_PIN
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;
   
output_high(LCD_E);
delay_us(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
 
output_low(LCD_E);
delay_us(1);
   
return(retval);   
}   
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_RW_PIN
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);
     
 delay_cycles(1);

#ifdef USE_RW_PIN
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------

void lcd_init(void)
{
int8 i;

lcd_line = 1;

output_low(LCD_RS);

#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif

output_low(LCD_E);

// Some LCDs require 15 ms minimum delay after
// power-up.  Others require 30 ms.  I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);         

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);
   
    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 50 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_RW_PIN
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;


switch(y)
  {
   case 1:
     address = LCD_LINE_1_ADDRESS;
     break;

   case 2:
     address = LCD_LINE_2_ADDRESS;
     break;

   case 3:
     address = LCD_LINE_3_ADDRESS;
     break;

   case 4:
     address = LCD_LINE_4_ADDRESS;
     break;

   default:
     address = LCD_LINE_1_ADDRESS;
     break;
     
  }

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      lcd_line = 1;
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1, ++lcd_line);
       break;
   
    case '\b':
       lcd_send_byte(0,0x10);
       break;

   case '\1' : lcd_send_byte(1,LCD_CHAR_1); break; //custom
   case '\2' : lcd_send_byte(1,LCD_CHAR_2); break; //characters
   case '\3' : lcd_send_byte(1,LCD_CHAR_3); break;
   case '\4' : lcd_send_byte(1,LCD_CHAR_4); break;
   case '\5' : lcd_send_byte(1,LCD_CHAR_5); break;
   case '\6' : lcd_send_byte(1,LCD_CHAR_6); break;
   case '\7' : lcd_send_byte(1,LCD_CHAR_7); break;
   case '\8' : lcd_send_byte(1,LCD_CHAR_8); break;

    default:
       lcd_send_byte(1,c);
       break;
   }
   if (lcd_line>4)
     {
       lcd_line=1;
     }
}

//------------------------------
#ifdef USE_RW_PIN
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(LCD_RS);

return(value);
}
#endif


 void lcd_init_custom_chars()
{
BYTE i;

lcd_send_byte(0,LCD_CGRAM_ADDR);
for(i=0;i<=63;i++)
{
lcd_send_byte(1,LCD_CUSTOM_CHARS[i]);
delay_ms(2);
}
}


And here is the test code I was using:
Code:
#include <18F252.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOOSCSEN                 //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES PUT                      //Enable Power Up Timer
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOCPD                    //No EE protection
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads

#use delay(clock=10000000)
#include "lcd_4b.c"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define button_1 pin_a3
#define button_2 pin_a4
#define button_3 pin_a5
#define button_4 pin_a0
#define button_5 pin_a1
#define button_6 pin_a2

void main()
{
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_OFF);
  setup_spi(FALSE);
  setup_wdt(WDT_OFF);
  setup_timer_0(RTCC_INTERNAL);
  setup_timer_1(T1_DISABLED);
  setup_timer_2(T2_DISABLED,0,1);
  lcd_init();
  lcd_init_custom_chars();
  printf(lcd_putc,"\1\2\3\4\5\6\7\n");
  printf(lcd_putc,"\1\2\3\4\5\6\7\n");
  printf(lcd_putc,"\1\2\3\4\5\6\7\n");
  printf(lcd_putc,"\1\2\3\4\5\6\7");
 while(true)
  {
  }
}


I feel its do with the CG and DD ram address, but the current values seem to be the best so far.
anyone have an idea what the problem could be?
thanks[/quote]
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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