hi,
i'm starting with lcd programming, but i can only display a black squares row...
i'm using a PIC 16F877A and a 16X2 LCD display (MDLS 16265K, 44780 compatible) with a OLIMEX P40 board (20Mhz frequency)
here the connections:
LCD PIC
RS RB1
RW RB2
EN RB0
D4 RB4
D5 RB5
D6 RB6
D7 RB7
it seems to be all ok but i'm working from 1 week and i'm not understanding where the problem is.
this is the test code:
and this is lcd.c
can anyone help me???
many thanks
i'm starting with lcd programming, but i can only display a black squares row...
i'm using a PIC 16F877A and a 16X2 LCD display (MDLS 16265K, 44780 compatible) with a OLIMEX P40 board (20Mhz frequency)
here the connections:
LCD PIC
RS RB1
RW RB2
EN RB0
D4 RB4
D5 RB5
D6 RB6
D7 RB7
it seems to be all ok but i'm working from 1 week and i'm not understanding where the problem is.
this is the test code:
Code:
#include <pic.h>
#include "defs.h"
#include "lcd.h"
#include "delay.h"
void main (void)
{
UINT i;
byte j;
const byte const UpArrow[] = {0x04, 0x0e, 0x15, 0x04, 0x04, 0x04, 0x04, 0x04};
const byte const DownArrow[] = {0x04, 0x04, 0x04, 0x04, 0x04, 0x15, 0x0e, 0x04};
TRISB = 0;
PORTB = 0;
TRISA=0;
lcd_init ();
lcd_clear ();
lcd_command (LCD_COMMAND_HOME); // Home cursor
lcd_define_char (0, UpArrow); // Define user-defined char
lcd_define_char (1, DownArrow); // Define user-defined char
lcd_gotoxy (1,1);
lcd_putc (0);
lcd_gotoxy (2,1);
lcd_putc (1); // Display special character
lcd_gotoxy (1,8);
for (j = 0; j < 43; j++)
{
lcd_putc ('.');
for (i = 0; i < 1000; i++)
delay_mS (1);
}
NOP ();
asm ("goto $-1");*/
}
and this is lcd.c
Code:
/****************************************************************************
** **
** 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
Lamp(10);
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]);
}
void Lamp(unsigned int n)
{
for (int i=0;i<n;i++)
{
RA0=1;
delay_mS(1);
RA0=0;
delay_mS(1);
}
}
can anyone help me???
many thanks