/****************************************************************************
** **
** Hitachi Character-Type LCD Display **
** **
****************************************************************************/
//
// NOTE: This is set up for 4 MHz oscillator
//
#define LCD_C // "I am LCD.C"
#ifndef CLRWDT
#include <pic.h>
#endif
#include "defs.h"
#include "lcd.h"
#include "delay.h" // Contains delay routines & macros
const byte const LCD_ROW_ADDRESS[] = // Row/Column information for lcd_gotoxy()
{
#if LCD_MODE_1x8
0x00
#endif
#if LCD_MODE_1x16_A
0x00
#endif
#if LCD_MODE_1x16_B
0x00,
0x40
#endif
#if LCD_MODE_1x40
0x00,
#endif
#if LCD_MODE_2x8
0x00,
0x40
#endif
#if LCD_MODE_2x12
0x00,
0x40
#endif
#if LCD_MODE_2x16
0x00,
0x40
#endif
#if LCD_MODE_2x20
0x00,
0x40
#endif
#if LCD_MODE_2x24
0x00,
0x40
#endif
#if LCD_MODE_2x40
0x00,
0x40
#endif
#if LCD_MODE_4x16
0x00,
0x40,
0x10,
0x50
#endif
#if LCD_MODE_4x20
0x00,
0x40,
0x14,
0x54
#endif
#if LCD_MODE_4x24
0x00,
0x40,
0x80,
0xc0
#endif
};
const byte const LCD_INIT_STRING [] = // LCD Init String on powerup
{
0b00000001, // Clear display
0b00000010, // Home cursor
0b00000100 // Entry Mode
#if LCD_CURSOR_INCREMENT
| 0b00000010 // Increment cursor
#endif
#if LCD_CURSOR_SHIFT
| 0b00000001 // Shift on cursor
#endif
, // end
0b00001000 // Display Control
#if LCD_DISPLAY_ON
| 0b00000100 // Display on
#endif
#if LCD_CURSOR_ON
| 0b00000010 // Cursor on
#endif
#if LCD_CURSOR_BLINK
| 0b00000001 // Blink on
#endif
, // end
0b00100000 // Function Set
#if LCD_8_BIT_MODE
| 0b00010000 // 8-bit data bus
#endif
#if LCD_MULTI_LINE
| 0b00001000 // 2-line refreshing
#endif
#if LCD_DISPLAY_5x10
| 0b00000100 // 5x10 matrix
#endif
};
#if LCD_4_BIT_MODE
void lcd_putnybble (byte c) // Write nybble to port in current RS mode
{
c = c << LCD_D4_BIT; // Shift over to correct bit column
c &= LCD_TRIS_DATAMASK; // Remove any extraneous bits
LCD_DATA_PORT = (LCD_DATA_PORT & ~LCD_TRIS_DATAMASK) | c; // Write data bits to port
delay_uS (1);
LCD_E = 1; // Start to write it
delay_uS (2);
LCD_E = 0; // Finish write cycle
}
#endif
byte lcd_getbyte (void) // Read byte at cursor (RS=1) or ready status (RS=0)
{
byte retval;
#if LCD_4_BIT_MODE
byte highbits;
LCD_TRIS_PORT |= LCD_TRIS_DATAMASK; // Set port to read mode for data pins
LCD_RW = 1; // Tell LCD we want to read
delay_uS (1);
LCD_E = 1;
highbits = (((LCD_DATA_PORT & LCD_TRIS_DATAMASK) >> LCD_D4_BIT) << 4);// Grab high bits and shift to right place
LCD_E = 0;
delay_uS (1);
LCD_E = 1;
delay_uS (1);
retval = ((LCD_DATA_PORT & LCD_TRIS_DATAMASK) >> LCD_D4_BIT); // Grab low bits
LCD_E = 0;
retval |= highbits;
LCD_TRIS_PORT &= ~LCD_TRIS_DATAMASK; // Set port back to output mode
#else
LCD_TRIS_PORT = 0xFF; // Set port to all input
LCD_RW = 1; // Tell LCD we want to read
delay_uS (1);
LCD_E = 1; // Do the read
delay_uS (1);
retval = LCD_DATA_PORT;
LCD_E = 0;
LCD_TRIS_PORT = 0x00; // Set port back to outputs
#endif
return (retval); // Give answer to caller
}
void lcd_putbyte (byte c) // Write byte to port in current RS mode
{
byte RS_Status;
RS_Status = LCD_RS; // Get old pin state
LCD_RS = 0; // Force into command mode to read state
while (lcd_getbyte () & 0x80); // Wait for read state
if (RS_Status)
LCD_RS = 1; // Restore RS to old state
delay_uS (1);
LCD_RW = 0; // Set to write mode
delay_uS (1);
#if LCD_4_BIT_MODE
lcd_putnybble (c >> 4); // Send the character out
lcd_putnybble (c);
#else
LCD_DATA_PORT = c; // Send the character out
#endif
LCD_E = 1;
delay_uS (1);
LCD_E = 0;
}
void lcd_command (byte c) // Send command to LCD port
{
LCD_RS = 0;
lcd_putbyte (c);
}
#if LCD_ALLOW_USER_CHARS
void lcd_define_char (byte c, const byte *bitmap) // Define user-defined chars
{
byte i;
lcd_command ((0b01000000) | (c << 3)); // Select char to define
LCD_RS = 1;
for (i = 0; i < 8; i++)
lcd_putbyte (*bitmap++); // Put in each byte of memory
}
#endif
byte lcd_lineof (byte CursorAddress) // Calculate cursor row from it's address
{
CursorAddress &= 0x50; // Strips out uniquely the address bits
switch (CursorAddress)
{
case 0x00: // Note - this handles all cases except for some
CursorAddress = 1; // of those unsupported displays listed in
case 0x40: // lcd.h file.
#if LCD_MODE_1x16_B
CursorAddress = 1; // Only 1 row this type of display
#else
CursorAddress = 2;
#endif
case 0x10:
CursorAddress = 3;
case 0x50:
CursorAddress = 4;
default:
CursorAddress = 1;
}
return (CursorAddress);
}
byte lcd_cursorpos (void) // Return address of cursor position
{
LCD_RS = 0;
return (lcd_getbyte ()); // Get cursor position
}
void lcd_putc (byte c) // Write character to LCD
{
#if !LCD_ALLOW_USER_CHARS
byte CursAddr;
#endif
#if LCD_ALLOW_USER_CHARS // Allow user-defined characters - no terminal mode
LCD_RS = 1;
lcd_putbyte (c);
#else
switch (c)
{
case '\b': // Backspace?
lcd_command (LCD_COMMAND_BACKSPACE); // back cursor up
#if LCD_DESTRUCTIVE_BS
LCD_RS = 1; // set display mode
lcd_putbyte (' '); // erase previous character
lcd_command (LCD_COMMAND_BACKSPACE); // move cursor back again
#endif
break;
case '\n': // Newline?
RS = 0;
CursAddr = lcd_getbyte (); // Get cursor position
CursAddr = lcd_lineof (CursAddr);
#if LCD_ENABLE_SCROLL
if (CursAddr >= LCD_MAXROWS) // Bottom line?
lcd_scroll (); // Yes, force scroll
else // No, just go to start of next line
lcd_gotoxy (CursAddr+1,1);
#else
lcd_gotoxy (CursAddr+1, 1); // Position cursor to start of line
#endif
break;
case '\f': // Form Feed (clear screen)?
lcd_command (LCD_COMMAND_CLEAR); // Erase screen
lcd_gotoxy (1,1); // Position cursor to top of screen
break;
default: // Printable?
LCD_RS = 1; // Set to display mode
lcd_putbyte (c); // Send character out
}
#endif
}
#if LCD_ENABLE_GETC
byte lcd_getc (void) // Read character at cursor
{
byte retval;
LCD_RS = 1;
retval = lcd_getbyte ();
LCD_RS = 0;
return (retval);
}
#endif
#if LCD_ENABLE_GOTOXY
void lcd_gotoxy (byte row, byte col) // Position cursor
{
#if LCD_MODE_1x16_B
if (col > 7) // 1x16 is treated the same as 2x8 for addressing
{
row++;
col -= 8;
}
if (col > 8)
col = 8;
if (row > 2)
row = 2;
#else
if (row > LCD_MAXROWS) // Range limit
row = LCD_MAXROWS;
if (col > LCD_MAXCOLS)
col = LCD_MAXCOLS;
#endif
row = LCD_ROW_ADDRESS[row-1]; // Get address of first byte on desired row
row += col - 1;
lcd_command (0x80 | row); // Write new cursor address
}
void lcd_getxy (byte *row, byte *col) // Return row and column of cursor position
{
byte rr,
cc;
cc = lcd_cursorpos ();
rr = lcd_lineof (cc); // Get row of the cursor
cc = (cc & 0x7f) - LCD_ROW_ADDRESS[rr-1]; // Find the column
*row = rr; // Convert to lcd_gotoxy() units
*col = cc;
}
#endif
#if LCD_ENABLE_PRINTF
void lcd_printf (const char* message) // Write message to LCD (C string type)
{
while (*message) // Look for end of string
lcd_putc (*message++); // Show and bump
}
#endif
#if LCD_ENABLE_SCROLL
void lcd_scroll (void) // Scroll up one line
{
byte CursorPos, // Hold position of cursor
Character, // Hold character being moved
SrcAddr, // Source Address
DestAddr, // Destination Address
EndAddr; // Ending copy address (last address of Source)
LCD_RS = 0;
CursorPos = lcd_getbyte () | 0x80; // Get cursor position
lcd_gotoxy (2,1);
LCD_RS = 0;
SrcAddr = lcd_getbyte () | 0x80; // Find address of copy start
lcd_gotoxy (1,1);
LCD_RS = 0;
DestAddr = lcd_getbyte () | 0x80; // Find address of copy destination
lcd_gotoxy (LCD_MAXROWS, LCD_MAXCOLS);
LCD_RS = 0;
EndAddr = lcd_getbyte () | 0x80; // Find address of last byte to copy over
do
{
LCD_RS = 0; // Position to source of copy char
lcd_putbyte (SrcAddr);
LCD_RS = 1;
Character = lcd_getbyte (); // Read the character there
LCD_RS = 0;
lcd_putbyte (DestAddr); // Move to the destination
LCD_RS = 1;
lcd_putbyte (Character); // Write it the char there
SrcAddr++;
DestAddr++;
}
while (SrcAddr <= EndAddr); // Loop through all memory
for (Character = 1; Character <= LCD_MAXCOLS; Character++)
{
lcd_gotoxy (LCD_MAXROWS, Character); // Position on last line
lcd_putc (' '); // Blank out the char
}
lcd_gotoxy (lcd_lineof (CursorPos) + 1,1); // Home cursor next line
}
#endif
#if LCD_ENABLE_UNSCROLL
void lcd_unscroll (void) // Roll scroll backwards one line
{
byte CursorPos, // Hold position of cursor
Character, // Hold character being moved
SrcAddr, // Source Address
DestAddr; // Destination Address
LCD_RS = 0;
CursorPos = lcd_getbyte () | 0x80; // Get cursor position
lcd_gotoxy (LCD_MAXROWS-1,LCD_MAXCOLS);
LCD_RS = 0;
SrcAddr = lcd_getbyte () | 0x80; // Find address of copy start
lcd_gotoxy (LCD_MAXROWS,LCD_MAXCOLS);
LCD_RS = 0;
DestAddr = lcd_getbyte () | 0x80; // Find address of copy destination
do
{
LCD_RS = 0; // Position to source of copy char
lcd_putbyte (SrcAddr);
LCD_RS = 1;
Character = lcd_getbyte (); // Read the character there
LCD_RS = 0;
lcd_putbyte (DestAddr); // Move to the destination
LCD_RS = 1;
lcd_putbyte (Character); // Write it the char there
SrcAddr--;
DestAddr--;
}
while (SrcAddr != 0x80); // Loop through all memory
for (Character = 0; Character < LCD_MAXCOLS; Character++)
{
lcd_gotoxy (1, Character); // Position on top row
lcd_putc (' '); // Blank out the char
}
lcd_gotoxy (lcd_lineof (CursorPos),1); // Home cursor same line as before
}
#endif
#if LCD_ENABLE_CLEAR
void lcd_clear (void) // Clear LCD screen
{
lcd_command (LCD_COMMAND_CLEAR);
}
#endif
void lcd_init (void) // Reset display from software
{
byte i;
LCD_E = 0; // Set up control pin I/O
LCD_TRIS_E = 0;
LCD_RW = 0; // Write mode
LCD_TRIS_RW = 0;
LCD_RS = 0; // Command mode
LCD_TRIS_RS = 0;
LCD_TRIS_PORT &= ~LCD_TRIS_DATAMASK; // Set data bus to output
LCD_E = 0; // Start talking to LCD
delay_mS (15); // Wait a little while
#if LCD_4_BIT_MODE // Set LCD into 4-bit mode
lcd_putnybble (0b0011); // Select 8-bit mode
delay_mS (5); // Spec calls for 4.1 mS
lcd_putnybble (0b0011); // Do it again
delay_uS (100);
lcd_putnybble (0b0011);
lcd_putnybble (0b0010); // Off and running...
#else
lcd_putbyte (0b00110000); // Select 8-bit mode
delay_mS (5); // Spec calls for 4.1 mS
lcd_putbyte (0b00110000); // Do it again
delay_uS (100);
lcd_putbyte (0b00110000);
lcd_putbyte (0b00110000); // Off and running...
#endif
for (i = 0; i < sizeof(LCD_INIT_STRING); i++) // Send other LCD initialization stuff
lcd_command (LCD_INIT_STRING[i]);
}
Questions:
| file: /Techref/microchip/language/c/io/lcd/hitachilcd-ak/lcd_c.htm, 52KB, , updated: 2006/6/13 10:00, local time: 2025/10/24 18:01,
216.73.216.188,10-3-157-36:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.ecomorder.com/Techref/microchip/language/c/io/lcd/hitachilcd-ak/lcd_c.htm"> Hitachi Character-Type LCD Display</A> |
| Did you find what you needed? |
Welcome to ecomorder.com! |
Welcome to massmind.ecomorder.com! |
.