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

20x2 LCD driver (chinese type)

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

20x2 LCD driver (chinese type)
PostPosted: Fri Nov 20, 2015 10:47 am     Reply with quote

This driver is based on PCM_p modified driver
https://www.ccsinfo.com/forum/viewtopic.php?t=24661
and an original driver based on a 32 bit ARM controller (i say chinese because the top comment with all description is in chinese and even with google translate i didn't understand too much). The driver has separate functions for all commands (except 2), i didn't find it yet. The controller for LCD is a ST7066u with modified character page. Also the datasheet don't exist. I left the original PCM_p driver intact, without any modifications, i just put the rest of the functions on the bottom, in that you way can call _LCD_putc() and lcd_putc() in same driver, difference is on _LCD_puts()
Code:

// Flex_LCD420.c

// These pins are for my Microchip PicDem2-Plus board,
// which I used to test this driver.
// An external 20x4 LCD is connected to these pins.
// Change these pins to match your own board's connections.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Clear and home
#define LCD_CLR_DISP   0x01   // Clear screen, home cursor, unshift display
#define LCD_RETURN_HOME   0x02   // Home cursor, unshift display
// commands
// Display on/off, cursor on/off, blinking char at cursor position
#define LCD_DISP_OFF 0x08 // Display off
#define LCD_DISP_ON 0x0C // Display on, cursor off
#define LCD_DISP_ON_BLINK 0x0D // Display on, cursor off, blink char
#define LCD_DISP_ON_CURSOR 0x0E // Display on, cursor on
#define LCD_DISP_ON_CURSOR_BLINK 0x0F // Display on, cursor on, blink char
// Move cursor/shift display
#define LCD_MOVE_CURSOR_LEFT 0x10 // Move cursor left (decrement)
#define LCD_MOVE_CURSOR_RIGHT 0x14 // Move cursor right (increment)
#define LCD_MOVE_DISP_LEFT 0x18 // Shift display left
#define LCD_MOVE_DISP_RIGHT 0x1C // Shift display right

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_D5
#define LCD_DB6   PIN_D6
#define LCD_DB7   PIN_D7

#define LCD_RS    PIN_D1
#define LCD_RW    PIN_D2
#define LCD_E     PIN_D3   

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define USE_RW_PIN   1     


// 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
 


//========================================
/* Local variables */
static unsigned int _lcd_ptr;

/* 8 user defined characters to be loaded into CGRAM (used for bar graph) */
static const unsigned char UserFont[8][8] = {
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 },
  { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 },
  { 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C },
  { 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E },
  { 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
};
//========================================

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

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) // lcd_rd_stat()
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();
delay_us(26); //************** 
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_us(3);  //*********

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

output_low(LCD_E);

lcd_send_nibble(n >> 4);
////delay_us(60);  //*****
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(50);         

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5); //   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);    //   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_scroll_right(void)
{
lcd_send_byte(0, 0x1E);
}
//-------------------------

void lcd_scroll_left(void)
{
lcd_send_byte(0, 0x18);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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;
   
    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#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
//// continue CORTEX curiozitate

/*--------------------------- lcd_wr_cmd ------------------------------------*/

static void _lcd_wr_cmd (unsigned int c) {
   /* Write command to LCD controller. */
output_low(LCD_RS);

#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60); 
#endif 
   output_low(LCD_RS);     
delay_us(3);  //*********

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

output_low(LCD_E);

lcd_send_nibble(c >> 4);
////delay_us(60);  //*****
lcd_send_nibble(c & 0xf);
}
/*--------------------------- lcd_wr_data -----------------------------------*/

static void _lcd_wr_data (unsigned int d) {
   /* Write data to LCD controller. */
output_low(LCD_RS);

#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60); 
#endif 
   output_high(LCD_RS);     
delay_us(3);  //*********

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

output_low(LCD_E);

lcd_send_nibble(d >> 4);
////delay_us(60);  //*****
lcd_send_nibble(d & 0xf);
}
/*--------------------------- LCD_load --------------------------------------*/

void _LCD_load (unsigned char *fp, unsigned int cnt) {
   /* Load user-specific characters into CGRAM */
   unsigned int8 i;

   _lcd_wr_cmd (0x40);                   /* Set CGRAM address counter to 0    */
   for (i = 0; i < cnt; i++, fp++)  {
      _lcd_wr_data (*fp);
   }
}
/*--------------------------- LCD_gotoxy ------------------------------------*/

void _LCD_gotoxy (unsigned int x, unsigned int y) {
   /* Set cursor position on LCD display. Left corner: 1,1, right: 20,2 */
   unsigned int c;

   c = --x;
   if (--y) {
      c |= 0x40;
   }
   _lcd_wr_cmd (c | 0x80);
   _lcd_ptr = y*16 + x;
}
/*--------------------------- LCD_cls ---------------------------------------*/

void _LCD_cls (void) {
   /* Clear LCD display, move cursor to home position. */
   _lcd_wr_cmd (0x01);
   _LCD_gotoxy (1,1);
}
/*--------------------------- LCD_cursor_off------------------------------------*/

void _LCD_cur_off (void) {
   /* Switch off LCD cursor. */
   _lcd_wr_cmd (0x0c);
}
/*--------------------------- LCD_cursor_on------------------------------------*/

void _LCD_cur_on (void) {
   /* Switch on LCD cursor. */
   _lcd_wr_cmd (LCD_DISP_ON_CURSOR);
}
/*--------------------------- LCD_on ------ ---------------------------------*/

void _LCD_on (void) {
   /* Switch on LCD and enable cursor. */
   _lcd_wr_cmd (0x0e);
}
/*--------------------------- LCD_putc --------------------------------------*/

void _LCD_putc (unsigned char c) {
   /* Print a character to LCD at current cursor position. */

   if (_lcd_ptr == 20) {
      _lcd_wr_cmd (0xc0);
   }
   _lcd_wr_data (c);
   _lcd_ptr++;
}
/*--------------------------- LCD_puts --------------------------------------*/

void _LCD_puts (unsigned char *sp) {
   /* Print a string to LCD display. */

   while (*sp) {
      _LCD_putc (*sp++);
   }
}
/*--------------------------- LCD_bargraph ----------------------------------*/

void _LCD_bargraph (unsigned int8 val, unsigned int8 size) {
   /* Print a bargraph to LCD display.  */
   /* - val:  value 0..100 %            */
   /* - size: size of bargraph 1..16    */
   unsigned int i;

   val = val * size / 20;               /* Display matrix 5 x 8 pixels       */
   for (i = 0; i < size; i++) {
      if (val > 5) {
         _LCD_putc (5);
         val -= 5;
      }
      else {
         _LCD_putc (val);
         break;
      }
   }
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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