# interfacing 74595 with 2x16 LCD in 8 bit mode

Status
Not open for further replies.

#### tony64

##### New Member
I have made some code for this but nothing can be seen on lcd.
my hardware is ok.can any one suggest a soluotion to this please.

#### tony64

##### New Member
The schematic I can not draw here but I can say that I used porta for control of lcd and the shift register.my micro is atmega32a. at 8 mhz .Hope you can help.
This is my code:

C:
#include <io.h>
#include <delay.h>
#include <mega32a.h>
/***************************************

Configure Connections

****************************************/

#define HC595_PORT   PORTA
#define HC595_DDR    DDRA

#define HC595_DS_POS PORTA.4      //Data pin (DS) pin location

#define HC595_SH_CP_POS PORTA.5      //Shift Clock (SH_CP) pin location
#define HC595_ST_CP_POS PORTA.6      //Store Clock (ST_CP) pin location

//#define LCD_DATA PORTA.4 // LCD data port
#define en PORTA.2 // enable signal
#define rw PORTA.1 // read/write signal
#define rs PORTA.0 // register select signal

/***************************************
Configure Connections ***ENDS***
****************************************/

//Initialize HC595 System

void HC595Init()
{
//Make the Data(DS), Shift clock (SH_CP), Store Clock (ST_CP) lines output
HC595_DDR|=((1<<HC595_SH_CP_POS)|(1<<HC595_ST_CP_POS)|(1<<HC595_DS_POS));
}

//Low level macros to change data (DS)lines
#define HC595DataHigh() (HC595_PORT|=(1<<HC595_DS_POS))

#define HC595DataLow() (HC595_PORT&=(~(1<<HC595_DS_POS)))

//Sends a clock pulse on SH_CP line
void HC595Pulse()
{
//Pulse the Shift Clock

HC595_PORT|=(1<<HC595_SH_CP_POS);//HIGH
delay_ms(20);
HC595_PORT&=(~(1<<HC595_SH_CP_POS));//LOW

}

//Sends a clock pulse on ST_CP line
void HC595Latch()
{
//Pulse the Store Clock

HC595_PORT|=(1<<HC595_ST_CP_POS);//HIGH
delay_ms(10);

HC595_PORT&=(~(1<<HC595_ST_CP_POS));//LOW
delay_ms(10);
}

/*

Main High level function to write a single byte to
Output shift register 74HC595.

Arguments:
single byte to write to the 74HC595 IC

Returns:
NONE

Description:
The byte is serially transfered to 74HC595
and then latched. The byte is then available on
output line Q0 to Q7 of the HC595 IC.

*/
//unsigned int data ;
void HC595Write(unsigned int data)
{
//Send each 8 bits serially
int i=0;
//Order is MSB first
for(i=0;i<8;i++)
{
//Output the data on DS line according to the
//Value of MSB
if(data & 0b10000000)
{
//MSB is 1 so output high

HC595DataHigh();
}
else
{
//MSB is 0 so output high
HC595DataLow();
}

HC595Pulse();  //Pulse the Clock line
delay_ms(10);
data=data<<1;  //Now bring next bit at MSB position

}

//Now all 8 bits have been transferred to shift register
//Move them to output latch at one
HC595Latch();

}

/*

Simple Delay function approx 0.5 seconds

*/

void Wait()
{
int i=0;
for(i=0;i<30;i++)
{
delay_ms(10);
}
}
int i=0;
// uint_t data;     //Initialize HC595 system
void main()
{
DDRB=0xff;
PORTB=0xff;
DDRA=0xff;
PORTA=0xff;

for(i=0;i<=3;i++) //Startup Led
{
PORTB.4=~PORTB.4;
delay_ms(200);
}
PORTB.4=1;
// PORTA.7=0;
PORTA.1=0;
HC595Init();
HC595Write(0x38);   //Write the data to HC595
Wait();                 //Wait

rs=0;rw=0;en=1; // RS and RW as LOW and EN as HIGH
delay_ms(10);
rs=0;rw=0;en=0;
delay_ms(20);

while(1)
{
PORTA.7=1;  // back light on/off
delay_ms(1000);
rs=1;rw=0;en=1; // RS and RW as LOW and EN as HIGH
delay_ms(10);
HC595Write(0x0f) ; //Write the data to HC595
Wait();                 //Wait

rs=1;rw=0;en=0;
delay_ms(20);
//     rs=1;rw=0;en=1; // RS and RW as LOW and EN as HIGH
//    delay_ms(1000);
//         HC595Write(0x14) ;   //Write the data to HC595
//         Wait();                 //Wait
//
//   rs=1;rw=0;en=0;
//   delay_ms(20);
//    rs=1;rw=0;en=1; // RS and RW as LOW and EN as HIGH
//    delay_ms(10);
//         HC595Write(0xff) ;   //Write the data to HC595
//         Wait();                 //Wait
//
//   rs=1;rw=0;en=0;
//   delay_ms(20);
PORTA.7=0;
delay_ms(1000);

}

}

Last edited by a moderator:

Forum Supporter

#### tony64

##### New Member
Hi Sir,I repeated the command 3 times but still no effect.
This is my schematic (sorry a bit messy).

#### Attachments

• 1.3 MB Views: 86

#### polprog

##### New Member
Are you sure you've set the contrast properly on that LCD? I don't see the setting parts on that schematic (given the pin labels I'm assuming it's the regular Hitachi HD44780).

Also, why do you connect together 595's pin 13 with R/W on the LCD and pin 39 on the AVR? This may casue problems since there are no resistors there, and if 595's pin happens to be logic 0 and AVR's pin happens to be logic 1 it's gonna be a short-circuit.

Last edited:

#### tony64

##### New Member
Yes contrast is ok and its HD44780.
The reason why pin 13 &39 is connected together is obvious in 13 is the enable of 595 which must be zero to be selected .pin 39 is also zero in this case all the time.
So to my opinion if even pin 39 goes high , no problem !is it?

#### polprog

##### New Member
I get it, but I think that if a pin (an input pin ofc) is suposed to be always zero it should be tied to ground - it would be more readable and less error-prone.

Please post your current code, what exactly do you want to diplsay as a test and what data, byte by byte are you sending. I suppose you checked that 595 handling code by attaching some test leads or LEDs to the 595 output?

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
HC595Write(0x0f) ; //Write the data to HC595
This is displaying the 16th user defined graphic... But you haven't defined a graphic..

Try HC595Write('A') ; and see if something happens..

#### tony64

##### New Member
I get it, but I think that if a pin (an input pin ofc) is suposed to be always zero it should be tied to ground - it would be more readable and less error-prone.

Please post your current code, what exactly do you want to diplsay as a test and what data, byte by byte are you sending. I suppose you checked that 595 handling code by attaching some test leads or LEDs to the 595 output?
Well thak you for your time.this is a part of a larger pcb hardware which some time we have to disable the 595 and also some time need to Read data instead of writing to lcd.
So that why we have not tied them to Grnd.
Now the problem is a bit confusing to me much more to you and others.You see I have set up a circuit on table by soldering pieces together ie 595 ,lcd,and atmega32 and run them on 8bit mode with good result ,but when I turn to actual framework it just dos,nt work.no character or any thing at all is seen.why ?I don.t know!

#### tony64

##### New Member
This is displaying the 16th user defined graphic... But you haven't defined a graphic..

Try HC595Write('A') ; and see if something happens..
As I said it works ok on the set up but not on the other side.

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
As I said it works ok on the set up but not on the other side.
Explain!! Do you mean the commands work but not the data?... If so how do you know??

The code you posted will not show anything even if the LCD somehow boots to 8 bit...

There is another command in the set up that turns the display on/off , writing 0xC0 will turn it on..

#### polprog

##### New Member
Can you post some photos of the setup or something else that could let us get the whole picture?

#### tony64

##### New Member
Explain!! Do you mean the commands work but not the data?... If so how do you know??

The code you posted will not show anything even if the LCD somehow boots to 8 bit...

There is another command in the set up that turns the display on/off , writing 0xC0 will turn it on..
Both command and data work.The only (or so far only) bug is that it would not go to the second line (0xC0) and there are one unwanted space between the characters.
See this film!(sorry film didn,t upload)
and this is the code:

void main()
{
DDRA=0xff; // making LCD_DATA port as output port
DDRB=0xff; // making signal as out put
DDRC=0xff;

PORTB=0xff;
PORTB.4=0; //buzer
delay_ms(200);
PORTB.4=1;
PORTB.0=0; //v0 lcd
PORTA.1=0;//w
PORTA.7=0;//enable 595
HC595Init();
delay_ms(10);

init_LCD(); // initialization of LCD

delay_ms(100); // delay of 50 milli seconds

while(1)
{

lcd_gotoxy(2,0);//this dose not work
LCD_write('A');
LCD_write('B');
LCD_write('C');
LCD_write('D');
LCD_write('E');
// LCD_cmd(0x18);
LCD_write('F');
LCD_write('G');
LCD_write('H');
LCD_write('I');
LCD_write('J');
LCD_write('K');
LCD_write('L');
LCD_write('M');
// LCD_cmd(0x18);
LCD_write('N');
delay_ms(2000);
LCD_cmd(0x01);
LCD_cmd(0xc0);//this dose not work
LCD_write('O');
LCD_write('P');
LCD_write('Q');
LCD_write('R');
LCD_write('S');
LCD_write('T');
LCD_write('U');
// LCD_cmd(0x18);
LCD_write('V');
LCD_write('W');
LCD_write('X');
LCD_write('Y');
LCD_write('Z');
LCD_write(' ');
delay_ms(2000);
LCD_cmd(0x01); //clear the screen
delay_ms(1000);

}
}
void init_LCD(void)
{

LCD_cmd(0x38); // initialization of 16X2 LCD in 8bit mode
delay_ms(1);

LCD_cmd(0x01); // clear LCD
delay_ms(1);

LCD_cmd(0x0E); // cursor ON
delay_ms(1);

//LCD_cmd(0x80); // ---8 go to first line and --0 is for 0th position
//delay_ms(10);
return;
}

void LCD_cmd(unsigned char cmd)
{

LCD_DATA=cmd;
HC595Write(cmd);
rs=0;rw=0;en=1;//ctrl =(0<<rs)|(0<<rw)|(1<<en); // RS and RW as LOW and EN as HIGH
delay_ms(1);
rs=0;rw=0;en=0;//ctrl =(0<<rs)|(0<<rw)|(0<<en); // RS, RW , LOW and EN as LOW
delay_ms(5);
return;
}

void LCD_write(unsigned char data)
{
LCD_DATA= data;
HC595Write(data);
rs=1;rw=0;en=1;//ctrl = (1<<rs)|(0<<rw)|(1<<en); // RW as LOW and RS, EN as HIGH
delay_ms(1);
rs=1;rw=0;en=0;//ctrl = (1<<rs)|(0<<rw)|(0<<en); // EN and RW as LOW and RS HIGH
delay_ms(5); // delay to get things executed
return ;
}

#### polprog

##### New Member
the only (or so far only) bug is that it would not go to the second line (0xC0)
Ok, a bit of theory (please correct me if im wrong here), the command 0xC0 does not clear the display.
The proper byte is 0x0C which tells the display to do theese things: turn on the LCD, cursor off, cursor blink off. To send it, the following pins must have the following states:
Code:
RS=0
RW=0
D[7-0]=0x0C
You are using the method called lcd_gotoxy(x,y) which we don't know the code for. I suppose it's sending proper bits. It doesn't work because the topmost line of the LCD is line 0 not 1!
For that space between the characters, i can't understand the LCD_write method.
This part (and some other parts):
Code:
rs=1;rw=0;en=1;//ctrl = (1<<rs)|(0<<rw)|(1<<en); // RW as LOW and RS, EN as HIGH
would probably not compile because it sets some variables called rs, rw and en whch are not defined, and the proper AVR pin setting code is after the first "//"

And, for the future, please put the code inside [CODE] the program goes here [/CODE] blocks - it's easier to read!

#### tony64

##### New Member
Thanks ,you are right 0xC0 dose not clean the lcd .So I used 0x0C ,you won,t believe it! it corrected the space between the characters.
I did not send the complete code ,rs,rd,en have been defined on top.
now the problem is going to the second line and printing the numbers,which now it won,t do.

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Ok, a bit of theory (please correct me if im wrong here), the command 0xC0 does not clear the display.
The proper byte is 0x0C which tells the display to do theese things: turn on the LCD, cursor off, cursor blink off. To send it, the following pins must have the following states:
The command is correct... In his LCDinit we have LCD_cmd(0x0E); which includes the display on...

The code isn't complete and it appears that the first code posted and the second bear no resemblance whatsoever!!

I have reproduced the code on a pic..... I hate the bit shift defines nearly always don't work.

This works fine..

C:
#include<xc.h>

#define _XTAL_FREQ 4000000

#pragma config FOSC = INTRCIO
#pragma config MCLRE = OFF
#pragma config WDTE = OFF

#define HC595_PORT   GPIO
#define HC595_DDR    TRISIO

#define HC595_DS_POS GPIO2      //Data pin (DS) pin location

#define HC595_SH_CP_POS GPIO1     //Shift Clock (SH_CP) pin location
#define HC595_ST_CP_POS GPIO0      //Store Clock (ST_CP) pin location

//#define LCD_DATA PORTA.4 // LCD data port
#define E GPIO4 // enable signal
#define RW GPIO3 // read/write signal
#define RS GPIO5 // register select signal

#define HC595DataHigh() HC595_DS_POS = 1
#define HC595DataLow() HC595_DS_POS  =0

void HC595Init()
{
//Make the Data(DS), Shift clock (SH_CP), Store Clock (ST_CP) lines output
HC595_DDR|=0;
}

void HC595Pulse()
{
//Pulse the Shift Clock

HC595_SH_CP_POS=1;//HIGH
__delay_us(20);
HC595_SH_CP_POS=0; //
}

void HC595Latch()
{
//Pulse the Store Clock

HC595_ST_CP_POS = 1;//HIGH
__delay_us(10);
HC595_ST_CP_POS = 0;//LOW
__delay_us(10);
}

void HC595Write(unsigned int data)
{
//Send each 8 bits serially
int i=0;
//Order is MSB first
for(i=0;i<8;i++)
{
//Output the data on DS line according to the
//Value of MSB
if(data & 0b10000000)
{
//MSB is 1 so output high

HC595DataHigh();
}
else
{
//MSB is 0 so output high
HC595DataLow();
}
HC595Pulse();  //Pulse the Clock line
__delay_us(10);
data=data<<1;  //Now bring next bit at MSB position
}
//Now all 8 bits have been transferred to shift register
//Move them to output latch at one
HC595Latch();
}

void LCDcmd(unsigned char cmd)
{
RS = 0;
HC595Write(cmd);
E = 1;
__delay_us(100);
E = 0;
}

void LCDdata(unsigned char data)
{
RS = 1;
HC595Write(data);
E=1;
__delay_us(100);
E =0;
}

void LCDinit(void)
{
TRISIO = 0;
__delay_ms(15);
HC595Write(0x33);
RS = 0;
E = 1;
__delay_ms(5);
E = 0;
__delay_ms(5);
E = 1;
__delay_ms(5);
E = 0;
LCDcmd(0x38);
__delay_ms(5);
LCDcmd(0x38);
LCDcmd(0xC);
LCDcmd(0x6);
LCDcmd(0x1);
}

void LCDprint(const char* str)
{
while(*str != 0)
LCDdata(*str++);
}

void LCDgoto(char x, char y)
{
}

void main(void)
{
ANSEL = 0;
LCDinit();
__delay_ms(10);
LCDprint("Hello World");
LCDgoto(0,2);
LCDprint("Serial LCD driver");

while(1);
}

#### tony64

##### New Member
You are great Rogers,
Thank you very much ,it works fine.I did a few changes in your code and omitted xc.h .and it works fine.Thanks again

Status
Not open for further replies.