Did anyone try to run LCD using 2 wires?

Status
Not open for further replies.

Mindaugasu

New Member
The idea is to convert serial data coming to LCD using shift register 74HC164.
My routine tryout:
Code:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <avr/iom8.h>
#define freq 8000000
#define datapin     0 // define datapin from atmega8 to 74HC164
#define clockpin    1 // define clock pin from atmega8 to 74HC164
#define register r16  
/*
LCD pins connected to 74hc164:
Q0 ->LCD_D4
Q1 ->LCD_D5
Q2 ->LCD_D6
Q3 ->LCD_D7
Q4 ->NC
Q5 ->NC
Q6 ->LCD_RS
Q7 ->LCD_E 

*/

void atmega8init(void)
{
DDRC=(1<<DDC0)|(1<<DDC1);
}
void sendByteToLCD(uint8_t LCDdata)
{
uint8_t i;

PORTC &= ~(1<<0);			// sets datapin to output a LOW
for (i=0;i<=8;i++) 				//clear shift 74HC164 register
	{
		PORTC |= (1<<1);		// sets clockpin to output a HIGH
		

		PORTC &= ~(1<<1);	// sets clockpin to output a LOW
		

	}
for (i=0;i<=7;i++)			//write 8bit LCDdata to 74HC164 register
	{
		if (LCDdata&&0x01)
			{
				
				PORTC |= (1<<0);		// sets datapin to output a HIGH
			
				PORTC |= (1<<1);		// sets clockpin to output a HIGH
			
				_delay_us(100);
				PORTC &= ~(1<<1);	// sets clockpin to output a LOW
				
				PORTC &= ~(1<<0);	// sets datapin to output a LOW
				
			}
		else
			{
				PORTC &= ~(1<<0);	// sets datapin to output a LOW
				
				PORTC |= (1<<1);		// sets clockpin to output a HIGH
			
				_delay_us(100);
				PORTC &= ~(1<<1);	// sets clockpin to output a LOW
			
				
			}
		LCDdata=LCDdata>>1;	
		if (i==7) 
		{
		PORTC &= ~(1<<1);
		PORTC |= (1<<0);
		PORTC |= (1<<0);
		}

	}
	
}
void sendChar(uint8_t topack) //forms data ready to send to 74HC164
{
uint8_t packed;
/*first 4 bits of byte contains LCD D4-D7 bits
4 and 5 bits are not used
bit 6 is for LCD RS
bit 7 is for LCD E
*/
packed=(topack&0xF0)|0x03;
sendByteToLCD(packed);
_delay_us(100);
packed=(topack<<4)|0x03;
sendByteToLCD(packed);
_delay_us(100); 
}
void sendCommand(uint8_t topack) //forms data ready to send to 74HC164
{
uint8_t packed;
/*first 4 bits of byte contains LCD D4-D7 bits
4 and 5 bits are not used
bit 6 is for LCD RS
bit 7 is for LCD E
*/
packed=(topack&0xF0)|0x01;
sendByteToLCD(packed);
_delay_us(100);
packed=(topack<<4)|0x01;
sendByteToLCD(packed);
_delay_us(100); 
}
void LCDinit(void)
{
_delay_ms(30); //wait for poverup
sendByteToLCD(0x31);//1
_delay_ms(10);
sendByteToLCD(0x31);//2
_delay_ms(10);
sendByteToLCD(0x31);//3
_delay_ms(20);
sendByteToLCD(0x21);//sends 00100001 to enable 4 bit mode
_delay_ms(15);
sendByteToLCD(0x21);
_delay_ms(5);
sendByteToLCD(0x01);
_delay_ms(5);
sendByteToLCD(0x11);//clear display
_delay_ms(5);
sendByteToLCD(0x01);
_delay_ms(5);


}

int main (void)
{
    atmega8init();
	LCDinit();
   sendChar(0x49);

    /* loop forever, the interrupts are doing the rest */



    for (;;) /* Note [6] */


    return (0);
}
LIkely signals are OK by LCD giving me strange results few messy characters instead of one desired. I cant see where ismy mistake...
 

Attachments

  • LCD.GIF
    8.2 KB · Views: 473
I think the E pin gets strobed too many times or too early. Even though you are ANDing the data pin with output 7 (pin 13), I don't see how it would work correctly. The E pin sees the sequence of each bit of the current output byte being shifted in ANDed with each bit of the previous output byte as it is getting shifted out.

I would use a 74HC595 which has output registers that you load via a seperate strobe line. 3 pins vs 2 but complete control of the output.

Alternatively, you could move the input to the AND gate from PC0 to some other pin on the uC (PC2?). Keep it 0 until AFTER the E bit is shifted into place and then toggle it.
 
Like Philba has said, you cannot allow the LCD "E" line to pulse while you are setting up the data as strobing the "E" line would cause the LCD to accept whatever data currently on the data pins.

I would refer you to the follow webpage:

Build your own "2-Wire LCD Interface"

and use a 74HC174 instead of the 74HC164. I tried it and it works.
 

Attachments

  • 2wirelcd.jpg
    21.9 KB · Views: 417
hmmm, that's a cute circuit and code. the original circuit should work if he first outputs a 0 byte and then the actual byte to be output. The zeros being shifted in keep E low and then the zeros in the SR keep E low until the actual E bit (high) is shifted into place. since E is at the end of the SR, the data output pin needs to be set high after tha data byte has been shifted in. I'd switch it around so that the E bit is the last to be shifted in and thus it just works. I'd also just use the 1st 6 outputs of the SR so you only have to shift 6 bits, not 8. (ok, 12, not 16).

Phil
 
Instead of using 2 wires, and a 16 pin IC, why not use a single wire and a 14 pin PIC? - SM if it needs to be small. Little bit more expensive, but only uses 50% of the I/O of the shift register version, and it's easier and more versatile.
 
philba said:
I'd switch it around so that the E bit is the last to be shifted in and thus it just works. I'd also just use the 1st 6 outputs of the SR so you only have to shift 6 bits, not 8. (ok, 12, not 16). Phil

If you shift the "E" bit in last, can you explain how the LCD "E" line is kept always low while the data is being shifted into the latch?
 
Dallas has an example of running an 4/8 bit LCD without any dedicated wires, via their 1-wire bus system (I suppose it would be dedicated if the lcd were the only thing on the bus) ... kinda interesting, uses a d1w 8bit io expander... but the expander is about the same cost as a 14pin pic, makes more sense to dedicate a cheap pic to 'serialize' the display... and accept normal rs232 style signalling.
 
I am familiar wit this example. Using my schematic e signal shouldn't be strobed multiple times because there is AND element standing. I shift nibbles to register in format [ddddxxRE]
dddd - nibble;
x- not used;
R- RS;
E- enable;
I send this byte in 8 clock cycles in last cycle I get 74hc164 Q7 bit high and then I toggle controllers data-line to "1" and both with Q7 line they enable LCD E signal through AND element. After this nibble is saved, then I set microcontrollers data line to "0" (this gives "0" in AND element) and then clock register 8 times to clean it. In my opinion this schema should work. In my personal opinion there is somewhere mistake in program not in shematic...
I understand with 3 wires it would be much easier, but I want to make this with 2.
Anyway thank you guys for response.
 
You're right. The hardware should work. The AND gate would held the LCD E line low when you shift in the data.
 
At last it is working. Changed a little bit schematic - I used diode and resitor insted as AND gate. And also changed the code. I found a bug where data were shifed to register.
Code:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <avr/iom8.h>
#define datapin     0 // define datapin from atmega8 to 74HC164
#define clockpin    1 // define clock pin from atmega8 to 74HC164

/*
LCD pins connected to 74hc164:
Q0 ->NC
Q1 ->LCD_D7
Q2 ->LCD_D6
Q3 ->LCD_D5
Q4 ->LCD_D4
Q5 ->NC
Q6 ->LCD_RS
Q7 ->LCD_E 
*/

void atmega8init(void)
{
PORTC&=~((1<<datapin)|(1<<clockpin));//set pins to LOW
DDRC|=(1<<datapin)|(1<<clockpin);//Enable pins as outputs
}
void sendByteToLCD(uint8_t LCDdata)
{
uint8_t i, temp;

PORTC&=~_BV(datapin);			// sets datapin to output a LOW
for (i=0;i<=7;i++) 				//clear shift 74HC164 register
	{
		PORTC|=_BV(clockpin);		// sets clockpin to output a HIGH
		_delay_ms(1);
		PORTC&= ~_BV(clockpin);	// sets clockpin to output a LOW
		_delay_ms(1);
	}
temp=LCDdata;	
for (i=0;i<=7;i++)			//write 8bit LCDdata to 74HC164 register
	{
		PORTC |= (LCDdata&1);
		_delay_ms(1);
		PORTC |= _BV(clockpin);		// sets clockpin to output a HIGH
		_delay_ms(1);
		PORTC&= ~_BV(clockpin);	// sets clockpin to output a LOW
		_delay_ms(1);
		PORTC&=~_BV(datapin);	// sets datapin to output a LOW
		_delay_ms(1);
		LCDdata=temp>>1;
		temp=LCDdata;	
	}
	PORTC|=_BV(datapin);
	_delay_ms(10);
	PORTC&=~_BV(datapin);
}
void sendChar(uint8_t topack) //forms data ready to send to 74HC164
{
uint8_t packed, temp;
temp=topack;
/*first 4 bits of byte contains LCD D4-D7 bits
4 and 5 bits are not used
bit 6 is for LCD RS
bit 7 is for LCD E
*/
packed=((temp>>1)&0x78)|0x03;
sendByteToLCD(packed);
_delay_ms(1);
packed=(((temp<<3)|0x03)&0x7F);
sendByteToLCD(packed);
_delay_ms(1); 
}
void sendCommand(uint8_t topack) //forms data ready to send to 74HC164
{
uint8_t packed, temp;
temp=topack;
/*first 4 bits of byte contains LCD D4-D7 bits
4 and 5 bits are not used
bit 6 is for LCD RS
bit 7 is for LCD E
*/
packed=((temp>>1)&0x78)|0x01;
sendByteToLCD(packed);
_delay_ms(1);
packed=(((temp<<3)|0x01)&0x7F);
sendByteToLCD(packed);
_delay_ms(1); 
}
void LCDinit(void)
{
_delay_ms(30); //wait for poverup
sendByteToLCD(0x19);//1
_delay_ms(5);
sendByteToLCD(0x19);//2
_delay_us(150);
sendByteToLCD(0x19);//3
_delay_ms(10);
sendByteToLCD(0x11);//sends 00100001 to enable 4 bit mode
_delay_ms(5);
sendCommand(0x28);
sendCommand(0x2C);
sendCommand(0x0F);
sendCommand(0x01);
}

int main (void)
{
    atmega8init();
	LCDinit();
   sendChar('T');
   sendChar('E');
   sendChar('S');
   sendChar('T');
   sendChar('!');
    /* loop forever, the interrupts are doing the rest */

    for (;;) /* Note [6] */

    return (0);
}
Thank you all Guys
 

Attachments

  • 2WLCD.BMP
    87.6 KB · Views: 240
Mindaugasu,

I am also trying to do the same thing, however, I am using a PIC microcontroller and have a program that is written in assembly. I have run into the exact same problem that you described with what is displayed on the LCD display.

What was the error in the code that you noticed. I cannot follow the C code; I've never used the C programming language. I would like to get this to work.

Thanks!
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…