E

CCS C 4x20 Flexible driver

Başlatan Erata, 06 Kasım 2012, 05:08:08

Erata

CCS c

4x20  LCD  flexible  driver


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

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

#define LCD_RS    PIN_E0
#define LCD_RW    PIN_E1
#define LCD_E     PIN_E2

/*
// To prove that the driver can be used with random
// pins, I also tested it with these pins:
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_B1
#define LCD_DB6   PIN_C5
#define LCD_DB7   PIN_B5

#define LCD_RS    PIN_E2
#define LCD_RW    PIN_B2
#define LCD_E     PIN_D6
*/

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.  Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD.  It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit.  Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.
#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
*/


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

#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)
{
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;
   
    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





test program :



#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)

#include <Flex_LCD420.c>   

//===================================
void main()
{
int8 i;
int8 b1, b2, b3, b4;

// The lcd_init() function should always be called once,
// near the start of your program.
lcd_init();

// Clear the LCD.
printf(lcd_putc, "\f");
delay_ms(500);


while(1)
  {
   // Test the clear screen and newline commands.
   // Also test that we can write to all 4 lines.
   printf(lcd_putc, "\fThis is the 1st line");
   printf(lcd_putc, "\nNext is the 2nd line");
   printf(lcd_putc, "\nThis is the 3rd line");
   printf(lcd_putc, "\nFinally the 4th line");
   delay_ms(3000);

   // Test some additional characters.
   printf(lcd_putc, "\fABCDEFGHIJKLMNOPQRST");
   printf(lcd_putc, "\nabcdefghijklmnopqrst");
   printf(lcd_putc, "\n12345678901234567890");
   printf(lcd_putc, "\n!@#$^&*(){}[]:;<>?/=");
   delay_ms(3000);

   // Clear the LCD.
   printf(lcd_putc, "\f");
   delay_ms(500);

   // Test that lcd_gotoxy() works.  Go to each of
   // the four corners and put a number in each one,
   // in a clockwise direction, starting with the upper
   // left corner.
   lcd_gotoxy(4, 2);       
   printf(lcd_putc, "Put a number in");   
   lcd_gotoxy(4, 3);       
   printf(lcd_putc, "each corner.");   
   lcd_gotoxy(1, 1);       
   printf(lcd_putc, "1");   
   lcd_gotoxy(20, 1);       
   printf(lcd_putc, "2");   
   lcd_gotoxy(20, 4);       
   printf(lcd_putc, "3");   
   lcd_gotoxy(1, 4);       
   printf(lcd_putc, "4");   
   delay_ms(3000);

// Read the character that was written in each corner
// of the LCD and display it.   This tests the lcd_getc()
// function.   
// The following test can only be done if we can read
// from the LCD.  If the RW pin is not used, then the
// LCD is in write-only mode, and we can't do this test.
// The #ifdef statement will prevent the code from
// being compiled, in that case.

#ifdef USE_RW_PIN   
   // Test if lcd_getc() can read
   // a byte from each corner.
   b1 = lcd_getc(1,1);   
   b2 = lcd_getc(20,1);   
   b3 = lcd_getc(20,4);   
   b4 = lcd_getc(1,4);   
   lcd_gotoxy(1, 1);       
   printf(lcd_putc, "\fRead these bytes\n");
   printf(lcd_putc, "from the 4 corners:\n\n");
   printf(lcd_putc, "     %c %c %c %c", b1, b2, b3, b4);       
   delay_ms(3000);
#endif

   // Type some characters and backspace over them.
   printf(lcd_putc, "\fType characters and\n");
   printf(lcd_putc,   "backspace over them.");
   delay_ms(2000);

   // Go to end of 2nd line.
   lcd_gotoxy(20, 2);       

   // Backspace over 2nd line.
   for(i = 0; i < 20; i++)
      {
       printf(lcd_putc," \b\b");
       delay_ms(150);
      }

   // Go to end of first line.               
   lcd_gotoxy(20, 1);       

   // Backspace over first line.
   for(i = 0; i < 20; i++)
      {
       printf(lcd_putc," \b\b");
       delay_ms(150);
      }         

  }   

}







alıntıdır


Powered by EzPortal