Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Interfacing LCD 16x2 with PIC16F648A on 4-bits

Status
Not open for further replies.

storage

Junior Member level 1
Joined
Feb 21, 2011
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,373
Can someone correct my coding if I did it right? I hope I didn't assigned the pins incorrectly, if so, please help revise it for me. Thanks.

This is the LCD which I am using and the PIC.


k9as7s[1].jpg

/*

* PORTB bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
* PORTA bit 2 is connected to the LCD RS input (register select)
* PORTA bit 3 is connected to the LCD EN bit (enable)
*
* To use these routines, set up the port I/O (TRISA, TRISB) then
* call lcd_init(), then other routines as required.
*
*/

//Define compiler error message.
#ifndef __CPU_16F877__
#error "This program is tailored for PIC16F648A controller"
#endif

//Include required header files here.
#include "io16f877.h" //the hardware register definition file.
//-----------------------------------------------------------------delay---------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
void DelayUs(int count)
{
int i;
int j;
for(i=0;i<count;i++)
{
for(j=0;j<5;j++);
//This for loop has 5 NOPs & wastes 1 uS for our PIC clock frequency of 20MHz.
}
}

void DelayMs(int count)
{
int i;
for(i=0;i<count;i++)
{DelayUs(4000);}
}
//---------------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------

#define LCD_RS RA2 // Register select
#define LCD_EN RA3 // Enable

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


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

void
lcd_write(unsigned char c)
{
PORTB = (PORTB & 0xF0) | (c >> 4);
LCD_STROBE;
PORTB = (PORTB & 0xF0) | (c & 0x0F);
LCD_STROBE;
DelayUs(40);
}

/*
* Clear and home the LCD
*/

void
lcd_clear(void)
{
LCD_RS = 0;
lcd_write(0x1);
DelayMs(2);
}

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

void
lcd_puts(const char * s)
{
LCD_RS = 1; // write characters
while(*s)
lcd_write(*s++);
}

/* write one character to the LCD */

void
lcd_putch(char c)
{
LCD_RS = 1; // write characters
PORTB = (PORTB & 0xF0) | (c >> 4);
LCD_STROBE;
PORTB = (PORTB & 0xF0) | (c & 0x0F);
LCD_STROBE;
DelayUs(40);
}


/*
* Go to the specified position
*/

void
lcd_goto(unsigned char pos)
{
LCD_RS = 0;
lcd_write(0x80+pos);
}

/* initialise the LCD - put into 4 bit mode */

void
lcd_init(void)
{
LCD_RS = 0; // write control bytes
DelayMs(15); // power on delay
PORTB = 0x2; // attention! or 0x2
LCD_STROBE; // Step 1
DelayMs(5);
LCD_STROBE; // Step 2
DelayUs(100);
LCD_STROBE; // Step 3
DelayMs(5);
PORTB = 0x2; // set 4 bit mode
LCD_STROBE; // Step 4
DelayUs(40);
lcd_write(0x28 ); // 4 bit mode, 1/16 duty, 5x8 font
lcd_write(0x08 ); // display off
lcd_write(0x0F); // display on, blink curson on
lcd_write(0x06); // entry mode
}
void IniPort()
{
ADCON1=0x06;
TRISA=0x00;
TRISB=0x00;
PORTA=0x00;
PORTB=0x00;


}

char text[]="len di\n";
int count=0;
void main(void)
{
IniPort();
lcd_init();
while (text[count]!='\n')
{
lcd_putch(text[count]);
count++;
}
DelayUs(100);
while(1){}
}
 

I do fully understand C but it looks like there might be an issue with the timing in your write commands. It looks like there is no delay between the upper and lower nibbles sent to the display.

Check out this link **broken link removed** it may help
 

I do fully understand C but it looks like there might be an issue with the timing in your write commands. It looks like there is no delay between the upper and lower nibbles sent to the display.

Check out this link **broken link removed** it may help

If that's the case, can you try helping me to edit what may have been right in the program? I can't seem to compile and get it working.
 


Hi,

What extend does your code work ?
what is the error you receive ?
 

subscribing, i am also gonna build the same project, using 16f873, and i hope that flowcode can help me out of it...
 

Hi,

What extend does your code work ?
what is the error you receive ?

it allows data to transmit to the lcd with the possibility of pc interface. i just dont know if i wrote the correct addresses corresponding to the pins/ports
 

Hi,

What error you receive when you compile the project ?
Also tell what language you use and version of it to check compatibility of libraries you use.
 

Hi,

What error you receive when you compile the project ?
Also tell what language you use and version of it to check compatibility of libraries you use.

im using visual studio 2008 and im having problems with incorrect pins assignment
 

@sir storage, have you tried different compiler? or gui based programming? like flowcode..
 

I think the connection mistake, and try the mikroC compiler> help> LCD topic. may help you
 

Your writes to the Port wont work?

Try something like this

Code:
/*--- Write data to display ---*/

void write_data(char data)        
  {
  set_hi_nibble(data);
  Strobe_E();
  data_delay();  /* Your delay routine */

  set_lo_nibble(data);
  Strobe_E();
  data_delay();
  } 

/*--- Output hi nibble data on port lines ---*/

void set_hi_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0x0f;
  temp |= (data & 0xf0); 
  LATB = temp;
  }

/*--- Output lo nibble data on port lines ---*/

void set_lo_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0x0f;
  temp |= ((data << 4) & 0xf0); 
  LATB = temp;
  }
 
Last edited:

Your writes to the Port wont work?

Try something like this

Code:
/*--- Write data to display ---*/

void write_data(char data)        
  {
  set_hi_nibble(data);
  Strobe_E();
  data_delay();  /* Your delay routine */

  set_lo_nibble(data);
  Strobe_E();
  data_delay();
  } 

/*--- Output hi nibble data on port lines ---*/

void set_hi_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0x0f;
  temp |= (data & 0xf0); 
  LATB = temp;
  }

/*--- Output lo nibble data on port lines ---*/

void set_lo_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0x0f;
  temp |= ((data << 4) & 0xf0); 
  LATB = temp;
  }

that sort of worked. but i need it to work with my pic16f648a
 

Should work with any pic16 ?

Try slowing up your strobe pulse.
Code:
/*--- Strobe E ---*/

void Strobe_E(void)
  {
  E = 1;	
  NOP();
  NOP();
  NOP();
  NOP();
  E = 0;       
  }

You also need a longer delay when writing a command than you do when writing a char.
Read the data sheet of your display for the timings.


My mistake, I have just noticed that you are using the low nibble of port b for your data.
I thought you were using the hi nibble,
So, try this.

Code:
/*--- Write data to display ---*/

void write_data(char data)        
  {
  set_hi_nibble(data);
  Strobe_E();
  data_delay();  /* Your delay routine */

  set_lo_nibble(data);
  Strobe_E();
  data_delay();
  } 

/*--- Output hi nibble data on port lines ---*/

void set_hi_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0xf0;
  temp |= (data >> 4); 
  LATB = temp;
  }

/*--- Output lo nibble data on port lines ---*/

void set_lo_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0xf0;
  temp |= (data & 0x0f); 
  LATB = temp;
  }
 
Last edited:

Should work with any pic16 ?

Try slowing up your strobe pulse.
Code:
/*--- Strobe E ---*/

void Strobe_E(void)
  {
  E = 1;	
  NOP();
  NOP();
  NOP();
  NOP();
  E = 0;       
  }

You also need a longer delay when writing a command than you do when writing a char.
Read the data sheet of your display for the timings.


My mistake, I have just noticed that you are using the low nibble of port b for your data.
I thought you were using the hi nibble,
So, try this.

Code:
/*--- Write data to display ---*/

void write_data(char data)        
  {
  set_hi_nibble(data);
  Strobe_E();
  data_delay();  /* Your delay routine */

  set_lo_nibble(data);
  Strobe_E();
  data_delay();
  } 

/*--- Output hi nibble data on port lines ---*/

void set_hi_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0xf0;
  temp |= (data >> 4); 
  LATB = temp;
  }

/*--- Output lo nibble data on port lines ---*/

void set_lo_nibble(char data)
  {
  unsigned char temp = PORTB;

  temp &= 0xf0;
  temp |= (data & 0x0f); 
  LATB = temp;
  }


wow thanks master....

gonna try this one...
 

Here is the hello world program for MikroC. Its very simple compared to other compilers

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

char txt1[] = "Embedded";
char txt2[] = "Projects";
char txt3[] = "Lcd 4 bit";
char txt4[] = "Example";

char i; // Loop variable

void Move_Delay() { // Function used for text moving
Delay_ms(500); // You can change the moving speed here
}

void main(){


Lcd_Init(); // Initialize LCD

Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,6,txt3); // Write text in first row

Lcd_Out(2,6,txt4); // Write text in second row
Delay_ms(2000);
Lcd_Cmd(_LCD_CLEAR); // Clear display

Lcd_Out(1,1,txt1); // Write text in first row
Lcd_Out(2,5,txt2); // Write text in second row

Delay_ms(2000);

// Moving text
for(i=0; i<4; i++) { // Move text to the right 4 times
Lcd_Cmd(_LCD_SHIFT_RIGHT);
Move_Delay();
}

while(1) { // Endless loop
for(i=0; i<8; i++) { // Move text to the left 7 times
Lcd_Cmd(_LCD_SHIFT_LEFT);
Move_Delay();
}

for(i=0; i<8; i++) { // Move text to the right 7 times
Lcd_Cmd(_LCD_SHIFT_RIGHT);
Move_Delay();
}
}
}

- - - Updated - - -
 
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top