Programming 4x20 lcd display with pic16f877a

Thread Starter

AlucardSensei

Joined Aug 7, 2012
20
First of all, hey everyone! I'm kinda new to this business (although I have a couple of years worth of experience with programming in general), and I just found out about this forum, because I've encountered a problem with my microcontroller programming. I have a bit of experience with microcontrollers from one of college courses, but only in Assembly and this is a bit more complex than what I've learned there. I have a project where I need to program the microcontroller to write some text to the LCD, and for starters I just it to write a simple "Hello world", but I've ran headfirst into a wall right off the bat. I've gotten a header file online for working with the LCD, and I've managed to pick up what's it doing for the most part, but I can't seem to get the LCD to display any text at all, all it does is start up, I get a blinking cursor which I can move around by setting the ENABLE bit to 1 through my developing board (not sure if that's the correct term, English is not my native language) and that's it (even though it shouldn't be blinking or even be there at all based on the code). I'm using MPLAB with Hi-Tech C Compiler. Something seemed wrong with the interface length setup with the code being 0x28, because the datasheet clearly states that the 5th bit should be 1, so I've tried changing that, but to no avail. Here's the code and the datasheet for the LCD; any help would be greatly appreciated. Thanks in advance!

#delay.h
Rich (BB code):
#define	MHZ	*1000L			/* number of kHz in a MHz */
#define	KHZ	*1			/* number of kHz in a kHz */

#if	XTAL_FREQ == 20MHZ

	#define	DelayUs(x)	{ unsigned int _dcnt; \
		_dcnt = (x)/3; \
		while(--_dcnt != 0) \
	continue; }

#elif XTAL_FREQ == 16MHZ

	#define	DelayUs(x)	{ unsigned int _dcnt; \
		_dcnt = (x)/3.75; \
		while(--_dcnt != 0) \
	continue; }

#elif XTAL_FREQ == 8MHZ

	#define	DelayUs(x)	{ unsigned int _dcnt; \
		_dcnt = (x)/7.5; \
		while(--_dcnt != 0) \
	continue; }

#elif XTAL_FREQ == 4MHZ

	#define	DelayUs(x)	{ unsigned int _dcnt; \
		_dcnt = (x)/15; \
		while(--_dcnt != 0) \
	continue; }

#else
	#error Please define XTAL_FREQ - 20MHZ/16MHZ/8MHZ/4MHZ
#endif

void DelayMs(unsigned int cnt){
	do {
		DelayUs(1000);
	} while(--cnt);
}
#lcd.h
Rich (BB code):
/*
 *	LCD interface example
 *	Uses routines from delay.c
 *	
 *	RD3 is connected to the LCD RS input (register select)
 *  RD2 is connected to the LCD RW bit (read/write)
 *	RD1 is connected to the LCD EN bit (enable)
 *	RD4-RD7 are connected to the LCD data bits 4-7 (high nibble)
 *	
 *	To use these routines, set up the port I/O (TRISD) then
 *	call lcd_init(), then other routines as required.
 *	
 */

#ifndef _XTAL_FREQ
 // Unless specified elsewhere, 4MHz system frequency is assumed
 #define _XTAL_FREQ 4000000
#endif


#include	<htc.h>
#include "delay.h"

#define	LCD_RS RD3
#define	LCD_RW RD2
#define LCD_EN RD1
#define LCD_DATA	PORTD

#define	LCD_STROBE()	((LCD_EN = 1),(LCD_EN=0))

unsigned char lcd_line;

/* write a byte to the LCD in 4 bit mode */

void lcd_write(unsigned char rs_bit, unsigned char c)
{
	LCD_RS = rs_bit;
	DelayUs(50);
	LCD_DATA = (c & 0xF0);// | (LCD_DATA & 0x0F);
	LCD_STROBE();
	LCD_DATA = ( ( c << 4 ) & 0xF0 );// | (LCD_DATA & 0x0F);
	LCD_STROBE();
	DelayUs(50);
}

/*
 * Go to the specified position
 */

void lcd_goto(unsigned char pos_x,unsigned char pos_y)
{
	pos_y--;
	lcd_line = pos_x;
	lcd_write(0, 0b00000010);	//1.1: CURSOR RETURN
	DelayMs(2);
	if(pos_x == 1)
	{
		lcd_write(0, 0x80+pos_y);
	}
	else if(pos_x == 2)
	{
		lcd_write(0, 0xC0+pos_y);
	}
	else if(pos_x == 3)
	{
		lcd_write(0, 0x94+pos_y);
	}
	else if(pos_x == 4)
	{
		lcd_write(0, 0xD4+pos_y);
	}
}

/*
 * 	Clear and home the LCD
 */

void lcd_clear(void)
{
	lcd_line=1;
	lcd_write(0,0x1);
	DelayMs(2);
}

/* write a string of chars to the LCD */

void lcd_puts(const char * s)
{
	LCD_EN = 0;
	int i = 0;

	while(*s)
	{
		switch (*s) 
		{
			case '\b':  lcd_write(0,0x10);  break; //backspace
	     	case '\f': 	lcd_write(0,0x1); //clear display
					   	DelayMs(2);
	                   	break;
	     	case '\n': 	lcd_goto(lcd_line++,1);  break; //newline
	     	default  : 	lcd_write(1,s);     // write characters
						break;
	   	}
		i++;
	}
	LCD_EN = 1;
}

/* write one character to the LCD */

void lcd_putch(unsigned char c)
{
	lcd_write(1, c); // write characters
}

//Backspace
void lcd_back(void)
{
	lcd_write(0,0x10);
}
	
/* initialise the LCD - put into 4 bit mode */
void lcd_init()
{
	LCD_RS = 0;
	LCD_EN = 0;
	LCD_RW = 0;
	
	DelayMs(15);	// wait 15mSec after power applied,
	LCD_DATA = (LCD_DATA & 0x0F) | ( ( 0x3 << 4 ) & 0xF0 );	//Reset
	LCD_STROBE();
	DelayMs(5);
	LCD_STROBE();
	DelayUs(200);
	LCD_STROBE();
	DelayUs(200);	
	LCD_DATA = (LCD_DATA & 0x0F) | ( ( 0x2 << 4 ) & 0xF0 );	// Four bit mode
	LCD_STROBE();

	lcd_write(0, 0b00101000); // Set interface length
	lcd_write(0, 0b00001100);  // Display On, Cursor Off, Cursor Blink Off
	lcd_clear();	 	// Clear screen
	lcd_write(0, 0x6);  // Set entry Mode
}


#main.c
Rich (BB code):
#define	XTAL_FREQ 4MHZ
#include <htc.h>
#include "lcd.h"

void
main(void)
{
	TRISD = 0b00000000;
	lcd_init();
	lcd_goto(2, 5);
	lcd_puts("Hello world!");

	while (1);
}
 

Attachments

Top