PDA

View Full Version : Driving a 2x16 LCD with only One Pin and 74HC595



struppi81
- 25th January 2014, 14:26
Hello,

with the idea from this WebSide http://www.romanblack.com/shift1.htm, using the Darrel Taylor LCD_AnyPin.pbp + HighJack as a template and the willing to drive the LCD with only one Pin and to use the LCDOUT Command with all features, i wrote a routine for the 74HC595 controlling.

7206

and here is the Code:




@ DEVICE pic16F628A, intOSC_osc_noclkout, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_OFF

define osc 8

INTCON = 0
PortA = 0
PortB = 0
TRISA = 0 ' CATODES TO PORTA
TRISB = 0 ' ANODES TO PORTB
CMCON = 7

Serial_Pin var PortA.3

B0 var byte
B1 VAR Byte
B2 VAR Byte
B3 VAR Byte
B4 var Byte
B5 VAR Byte
B6 VAR Byte
B7 VAR Byte

B0 = 0
B1 = 255


;----[ Change these to match your LCD ]---------------------------------------
INCLUDE "One_Wire_74HC595.pbp" ; *** Include MUST be AFTER LCD Pin assignments *

;----[ Your Main program starts here ]----------------------------------------
LCDOUT $FE, 1
LCDOUT $FE, 1, IHex 255
Pause 2000
Start:
Repeat
B0 = B0 + 1
B1 = B1 - 1
B2 = B0 DIG 2
B3 = B0 DIG 1
B4 = B0 Dig 0
B5 = B1 DIG 2
B6 = B1 DIG 1
B7 = B1 Dig 0
LCDOUT $FE,$80,"Counter = ",#B2,#B3,#B4
LCDOUT $FE,$C0,"Counter = ",#B5,#B6,#B7
Pause 1000
Until B0 > 254 OR B1 < 1
SWAP B0, B1
goto Start
END






A var byte
B var byte
C var byte
D var bit
E VAR byte


INCLUDE "VirtualPort.bas"

LCD_DATAUS CON 2000
LCD_COMMANDUS CON 50
'PAUSE 100 : LCDOUT $FE,1 : PAUSE 100 ; Initialize LCD

Goto Over_One_Wire_74HC595

;===============( DO NOT Change anything below this line )====================

ASM ; Make sure HighJack has been installed in PBP's .LIB file
ifndef LCDOUT_HIGHJACKED
error "HighJacked-LCDOUT Not found in PBPPIC??.LIB"
endif
ENDASM
DEFINE HJ_LCDOUT _LCDsend ; Redirect PBP's LCDOUT to LCDsend: Subroutine

;----[Send a byte to the Virtual LCD PORT]------------(DO NOT Change)---------
TempChar var byte
Char VAR Byte
LCD_Initialized VAR FLAGS.1
RSS VAR FLAGS.0 ; LCD RS State

;----[ This routine is called once for every character sent by LCDOUT ]-------
LCDsend:
@ MOVE?AB _TempChar ; Get char sent by LCDOUT, in WREG
if !LCD_Initialized then LCD_Init ; Make sure LCD was Initialized
LCDAfterInit:
if TempChar = $FE then RSS=0 : goto LCDsendDone ; next char is Command
Char = TempChar
LCDsendCOM:
Gosub Toggle_Nibble
IF RSS = 0 then ; Is a Command
IF Char = 1 then CommandDelay ; Long delay for Clear Screen
IF Char = 2 then CommandDelay ; Long delay for Home
@ DelayUS _LCD_DATAUS ; Short delay for everything else
goto DelayDone
else
@ DelayUS _LCD_DATAUS ; Short delay for Data
goto DelayDone
endif
CommandDelay:
@ DelayUS _LCD_COMMANDUS
DelayDone:
if LCD_Initialized then RSS = 1 ; Set RS to Data next time
LCDsendDone:
return

;----[Initialize the LCD]-------------------(DO NOT Change)-------------------
LCD_Init:
A = 2
Char = $33 : gosub LCDsendCOM : @ DelayUS 5000
gosub LCDsendCOM : @ DelayUS 100
gosub LCDsendCOM : @ DelayUS 100
Char = $22 : gosub LCDsendCOM ; Start 4-bit mode
A = 5
Char = $28 : gosub LCDsendCOM ; Function Set, 4-bit, 2-line, 5x7
Char = $0C : gosub LCDsendCOM ; Display ON

Char = $06 : gosub LCDsendCOM ; Entry Mode
LCD_Initialized = 1 ; LCD has been Initialized
goto LCDAfterInit

Toggle_Nibble:
For C = 0 to A
SELECT CASE c
CASE 0
B = Char & %11110000 ' Upper 4 Bits
If RSS = 1 Then
B = B | %00000100 ' Set RS Bit
Endif
CASE 1, 4
B = B | %00001000 ' Set Enable Bit
CASE 2, 5
B = B ^ %00001000 ' Enable Toggel
Case 3
B = Char * 16 ' Lower 4 Bits Shift
If RSS = 1 Then
B = B | %00000100 ' Set RS Bit
Endif
END SELECT
'******************************Shift_74HC595****** *****************************
E = 7
Repeat
D = B >> E
E = E - 1
SELECT CASE D
CASE 1
Serial_Pin = 0
@ nop ' min 1 µs for 1
Serial_Pin = 1
Pauseus 15 ' min 15 µs
Case 0
Serial_Pin = 0
Pauseus 15 ' min 15 µs for 0
Serial_Pin = 1
Pauseus 30 ' min 30 µs danach
END SELECT
Until E = 0

'Latch
Serial_Pin = 0
Pauseus 200 ' min 200 µs for Latch
Serial_Pin = 1
Pauseus 300 ' min 300 µs
Next
Return

Over_One_Wire_74HC595:




As long as Strings will be send, all runs pretty good
Example:
LCDOUT $FE, 1, "Hello"

But I can do what I want, everytime I want to use the HEX, BIN, DEC, REP or STR commands i get Errors in displaying the correct Data.

Example:
LCDOUT, $FE, 1 IHex 255

I get F0 as answer and not $FF
Without I the answer is $220

What I also found out is, when I wrote a simple loop that show me the Hex Characters from 1 to 20....
Till 16 all is Displayed correct. After 16 till 20, 10 is displaying.


I hope somebody can help me.

Thanks

P.S. Sorry for my Bad English

Darrel Taylor
- 25th January 2014, 17:35
Change all of your PAUSEUS's to @ DelayUS xxx

PAUSEUS will change PBP's system variables that are already in use creating ASCII characters from a value using DEC, BIN, HEX etc.
@ DelayUS does not use the system vars.

struppi81
- 25th January 2014, 17:58
Hi Darrel,

First, Thanks for your Help.

I replace all, but the situation is the same.

Darrel Taylor
- 25th January 2014, 19:31
Ok, you also have a multiplication in your code, which has the same problem of using System variables.

Change it to this ...


; B = Char * 16 ' Lower 4 Bits Shift
B = Char << 1
B = B << 1
B = B << 1
B = B << 1


Added:

7208

The 16F628A only has a 4Mhz internal oscillator, yours was running at 8Mhz, and your circuit wouldn't work at 4Mhz.
I had to increase the capacitors to 4.7nF


@ DEVICE pic16F628A, intOSC_osc_noclkout, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_OFF
DEFINE OSC 4

Serial_Pin var PortA.3

B0 var byte
B1 VAR Byte

OUTPUT Serial_Pin
CMCON = 7
B0 = 0
B1 = 255

INCLUDE "One_Wire_74HC595.pbp" ; *** Include MUST be AFTER LCD Pin assignments *

;----[ Your Main program starts here ]----------------------------------------
LCDOUT $FE, 1
LCDOUT $FE, 1, IHex 255
Pause 2000

Main:
LCDOUT $FE,$80,"B0 = ",DEC B0," "
LCDOUT $FE,$C0,"B1 = ",DEC B1," "
B0 = B0 + 1
B1 = B1 - 1
PAUSE 1000
GOTO Main

struppi81
- 25th January 2014, 20:43
Awesome, Darrel

Yes, that's it!!

Can I also write:

B = Char
B = B << 4

I tested it once more with the Pauseus...it also runs.:confused:
Would you still recommend to use the DelayUS Command in whole code?

Thanks in advance!

Darrel Taylor
- 25th January 2014, 22:44
Most definitely, you must not use PAUSEUS.

And no, you cant use B = B << 4
The CPU can only shift one bit at a time. So it requires a loop and a variable to count the number of shifts.
That uses a SYSTEM variable.

And there are two more issues that cause instability.

1) The reason I had to change the capacitors is the @ NOP which changes timing with different oscillator frequencies.

It should be replaced with ...
@ DelayUS 1
And the capacitors should be left at 4.7nF
That way it will work with all PBP OSC frequencies.
.

2) And this statement also affects System variables, for the same reason as B =B << 4 ...

D = B >> E
It could be replaced with ...
F var byte
G var byte

;D = B >> E
F = E
G = B
ShiftLoop
G = G >> 1
F = F - 1
IF F != 0 THEN ShiftLoop
D = G.0

Although I have a feeling it can be reduced somehow.
.

I think that should give a stable include file.
At least it works well here.

But I'll add that you are using common variable names in the include like ...A, B, C etc.
That means that when someone uses your include, they cannot use those variable names.
It's better to make unique variable names that are unlikely to be used by the person using your code.
Descriptive names are the best. Try to use a name that describes what the variable is used for.

struppi81
- 26th January 2014, 00:42
Ok, with the variable name you are right!

About Point 2:

Could be this a better Solution:



'******************************Shift_74HC595****** *****************************
F = B
E = 7
Repeat
;D = B >> E
ASM
rlf _F, F
BTFSS STATUS, C
BCF _D
BTFSC STATUS, C
BSF _D
ENDASM
E = E - 1
SELECT CASE D
CASE 1
Serial_Pin = 0
@ DelayUS 1 ' min 1 µs for 1
Serial_Pin = 1
@ DelayUS 15 ' min 15 µs
Case 0
Serial_Pin = 0
@ DelayUS 15 ' min 15 µs for 0
Serial_Pin = 1
@ DelayUS 30 ' min 30 µs
END SELECT
Until E = 0

'Latch
Serial_Pin = 0
@ DelayUS 200 ' min 200 µs for Latch
Serial_Pin = 1
@ DelayUS 300 ' min 300 µs
Next
Return


Thanks in advance!

struppi81
- 26th January 2014, 15:32
Here I'm again.

Again to my last post:
I think over it again and C Flag is also an System Variable.
Also too unsuitable.

What have I done:

I rewrite the code once again.
I change the Variable Name's an insert your code from Statement 2.
Could it be, that there is an small mistake.


F var byte
G var byte

;D = B >> E
F = E
G = B
ShiftLoop
;G = G >> 1
G = G << 1
F = F - 1
IF F != 0 THEN ShiftLoop
;D = G.0
D = G.7


Once Again here is the code



Char_Temp var byte
ShiftOut_Steps var byte
Count_ShiftOut_Steps var byte
ShiftLoop_Steps Var byte
Bit_Shift Var byte
Readout_Bit var bit

INCLUDE "VirtualPort.bas"

LCD_DATAUS CON 2000
LCD_COMMANDUS CON 50

Goto Over_One_Wire_74HC595

;===============( DO NOT Change anything below this line )====================

ASM ; Make sure HighJack has been installed in PBP's .LIB file
ifndef LCDOUT_HIGHJACKED
error "HighJacked-LCDOUT Not found in PBPPIC??.LIB"
endif
ENDASM
DEFINE HJ_LCDOUT _LCDsend ; Redirect PBP's LCDOUT to LCDsend: Subroutine

;----[Send a byte to the Virtual LCD PORT]------------(DO NOT Change)---------
TempChar var byte
Char VAR Byte
LCD_Initialized VAR FLAGS.1
RSS VAR FLAGS.0 ; LCD RS State

;----[ This routine is called once for every character sent by LCDOUT ]-------
LCDsend:
@ MOVE?AB _TempChar ; Get char sent by LCDOUT, in WREG
if !LCD_Initialized then LCD_Init ; Make sure LCD was Initialized
LCDAfterInit:
if TempChar = $FE then RSS=0 : goto LCDsendDone ; next char is Command
Char = TempChar
LCDsendCOM:
Goto ShiftLoop_Char
After_ShiftLoop_Char:
IF RSS = 0 then ; Is a Command
IF Char = 1 then CommandDelay ; Long delay for Clear Screen
IF Char = 2 then CommandDelay ; Long delay for Home
@ DelayUS _LCD_DATAUS ; Short delay for everything else
goto DelayDone
else
@ DelayUS _LCD_DATAUS ; Short delay for Data
goto DelayDone
endif
CommandDelay:
@ DelayUS _LCD_COMMANDUS
DelayDone:
if LCD_Initialized then RSS = 1 ; Set RS to Data next time
LCDsendDone:
return

;----[Initialize the LCD]-------------------(DO NOT Change)-------------------
LCD_Init:
ShiftOut_Steps = 2
Char = $33 : gosub LCDsendCOM : @ DelayUS 5000
gosub LCDsendCOM : @ DelayUS 100
gosub LCDsendCOM : @ DelayUS 100
Char = $22 : gosub LCDsendCOM ; Start 4-bit mode

ShiftOut_Steps = 5
Char = $28 : gosub LCDsendCOM ; Function Set, 4-bit, 2-line, 5x7
Char = $0C : gosub LCDsendCOM ; Display ON

Char = $06 : gosub LCDsendCOM ; Entry Mode
LCD_Initialized = 1 ; LCD has been Initialized
goto LCDAfterInit

;----[Send it to 74HC595]-------------------(DO NOT Change)-------------------

ShiftLoop_Char:
For Count_ShiftOut_Steps = 0 to ShiftOut_Steps ' For To Loop
SELECT CASE Count_ShiftOut_Steps
CASE 0
Char_Temp = Char & %11110000 ; Isolate Upper 4 Bits
If RSS = 1 Then : Char_Temp = Char_Temp | %00000100 ; Set RS Bit
CASE 1, 4
Char_Temp = Char_Temp | %00001000 ; Set Enable Bit
CASE 2, 5
Char_Temp = Char_Temp ^ %00001000 ; Toggel Enable
Case 3
Char_Temp = Char << 1 ; Shift Up Lower 4 Bits
Char_Temp = Char_Temp << 1
Char_Temp = Char_Temp << 1
Char_Temp = Char_Temp << 1
If RSS = 1 Then : Char_Temp = Char_Temp | %00000100 ; Set RS Bit
END SELECT
Bit_Shift = Char_Temp

;----[Shift_Routine_74HC595 ]---------------(DO NOT Change)-------------------
ShiftLoop_Steps = 7

ShiftLoop:

Readout_Bit = Bit_Shift.7
SELECT CASE Readout_Bit
CASE 1
Serial_Pin = 0 : @ DelayUS 1 ; min 1 µs for 1
Serial_Pin = 1 : @ DelayUS 15 ; min 15 µs
Case 0
Serial_Pin = 0 : @ DelayUS 15 ; min 15 µs for 0
Serial_Pin = 1 : @ DelayUS 30 ; min 30 µs
END SELECT

Bit_Shift = Bit_Shift << 1
ShiftLoop_Steps = ShiftLoop_Steps - 1
IF ShiftLoop_Steps != 0 THEN : Goto ShiftLoop

;Latch
Serial_Pin = 0 : @ DelayUS 200 ; min 200 µs for Latch
Serial_Pin = 1 : @ DelayUS 300 ; min 300 µs

'Count_ShiftOut_Steps = Count_ShiftOut_Steps + 1 ' for If Then Request
'IF Count_ShiftOut_Steps != ShiftOut_Steps Then : goto ShiftLoop_Char ' for If Then Request
Next ' For To Loop
Goto After_ShiftLoop_Char

Over_One_Wire_74HC595:


I also wanted to replace the For To Loop with an normal If - Then request, because of the Usage of System Variables; or is there neither.
It also works well but when I simulate it, it takes too much CPU Usage and Runs very slow.
Using an Repeat Until Loop also.
With an For To Loop the simulation is better.

But which Loop is the best, when one think only about the Usage in an Microcontroller?
What did you say. Is it OK or is there something which one can also improve.

Thanks in advance!

Darrel Taylor
- 26th January 2014, 17:59
STATUS,C is not a PBP system variable. You can use it.

FOR loops, REPEAT/UNTIL, WHILE/WHEN, DO/LOOP all do not use the system vars (as long as the test condition is = or !=).
They will use system vars if the test condition is <, <=, >, >= etc.

Speed differences between any of the loop types will not be significant on a real chip.
The major slow down with this interface is the timing required to activate inputs on the 595 using the capacitors.
All those delays in the code make writing to the LCD very slow.

Darrel Taylor
- 27th January 2014, 17:38
Your include looks better with the new variable names.
I ran it this morning, and it seems to be working.

Have you looked at the signals going to the 595 on a scope? :eek:
Scary stuff to be putting in a digital chip.

Yellow is the serial data.
Blue is after the 1.5K resistor.
Magenta is after the 33K resistor.

7209

And you can see that it takes 910 uS per nibble (1.82 mS per byte).

It would be interesting to see how it works on real hardware.

struppi81
- 27th January 2014, 22:16
Hello Darrel,

yes your are right, very scary!

And yes I use the scope, because of controlling the puls length (µs).


What I have done again:

I reduce the code a little bit and I change/simplified some parts.



I replace this:

Char_Temp = Char << 1 ; Shift Up Lower 4 Bits
Char_Temp = Char_Temp << 1
Char_Temp = Char_Temp << 1
Char_Temp = Char_Temp << 1

with this:

Char_Temp = Char & %00001111 ; Shift Up Lower4 Bits
@ swapf _Char_Temp ,F



Also I reduce the Upper an Lower Nibbel Part from 6 to only 4 Steps.



SELECT CASE Count_ShiftOut_Steps
CASE 0
Char_Temp = Char & %11110000 ; Isolate Upper 4 Bits
If RSS = 1 Then : Char_Temp = Char_Temp | %00000100 ; Set RS Bit
CASE 1, 3
Char_Temp = Char_Temp | %00001000 ; Set Enable Bit
Case 2
Char_Temp = Char & %00001111 ; Shift Up Lower4 Bits
@ swapf _Char_Temp ,F
If RSS = 1 Then : Char_Temp = Char_Temp | %00000100 ; Set RS Bit
END SELECT


Because Toggle the Enable Bit again is not necessary.


Further, I change (Post 6, Point 2...."Although I have a feeling it can be reduced somehow")



This:

;----[Shift_Routine_74HC595 ]---------------(DO NOT Change)-------------------
ShiftLoop_Steps = 7

ShiftLoop:
Readout_Bit = Bit_Shift.7
SELECT CASE Readout_Bit
CASE 1
Serial_Pin = 0 : @ DelayUS 1 ; min 1 µs for 1
Serial_Pin = 1 : @ DelayUS 15 ; min 15 µs
Case 0
Serial_Pin = 0 : @ DelayUS 15 ; min 15 µs for 0
Serial_Pin = 1 : @ DelayUS 30 ; min 30 µs
END SELECT

Bit_Shift = Bit_Shift << 1
ShiftLoop_Steps = ShiftLoop_Steps - 1
IF ShiftLoop_Steps != 0 THEN : Goto ShiftLoop

;Latch
Serial_Pin = 0 : @ DelayUS 200 ; min 200 µs for Latch
Serial_Pin = 1 : @ DelayUS 300 ; min 300 µs
Next

To This:

;----[Shift_Routine_74HC595 ]---------------(DO NOT Change)-------------------
ShiftLoop:
For ShiftLoop_Steps = 0 to 6
@ rlf _Bit_Shift, F ; Shift 1.Pos left
If STATUS.0 = 1 Then ; Carry Flag
Serial_Pin = 0 : @ DelayUS 1 ; min 1 µs for 1
Serial_Pin = 1 : @ DelayUS 15 ; min 15 µs
else
Serial_Pin = 0 : @ DelayUS 15 ; min 15 µs for 0
Serial_Pin = 1 : @ DelayUS 30 ; min 30 µs
endif
next

;Latch
Serial_Pin = 0 : @ DelayUS 200 ; min 200 µs for Latch
Serial_Pin = 1 : @ DelayUS 300 ; min 300 µs
Next


Up to now, the code runs very good. (I Think a little bit better then before.)
But sometimes when I simulate it on the PC, after some time, the LCD shows only cryptic characters.
Then I have to restart the simulation again an all works fine.

What du you think, is there something one can improve?

Thanks in advance!

Charlie
- 28th January 2014, 02:27
Note also there will be a wide variation of timings across components, a wide variation of chip sensitivity, and a sensitivity to clock speed, temperature, power supply voltage, data rates, etc. etc. This approach is "O.K." for a hobby project, but it would be a very bad idea to try to use it in a commercial project, especially anything that might see volume.

Not to rain on your parade, but given you can get PIC devices with fewer pins and at lower cost than a 74HC595, you would be further ahead to create a dedicated display driver PIC that you can send data to by 1 pin serial. Fewer components too, and rock solid communications.

struppi81
- 9th February 2014, 19:20
Hello,

Yesterday I tested it with an 12F675 at 4 Mhz intOSC and till now it runs stable and fast.:smile:
When I less busy, I will test it out with other frequencies.

But i have yet again an comprehension question to this code:



LCDsend:
@ MOVE?AB _TempChar ; Get char sent by LCDOUT, in WREG
if !LCD_Initialized then LCD_Init ; Make sure LCD was Initialized
LCDAfterInit:
if TempChar = $FE then RSS=0 : goto LCDsendDone goto DONE ; next char is Command
Char = TempChar
LCDsendCOM:
Goto ShiftLoop_Char
After_ShiftLoop_Char:
IF RSS = 0 then ; Is a Command
IF Char = 1 then CommandDelay ; Long delay for Clear Screen
IF Char = 2 then CommandDelay ; Long delay for Home
@ DelayUS _LCD_DATAUS ; Short delay for everything else
goto DelayDone
else
@ DelayUS _LCD_DATAUS ; Short delay for Data
goto DelayDone
endif
CommandDelay:
@ DelayUS _LCD_COMMANDUS
DelayDone:
if LCD_Initialized then RSS = 1 ; Set RS to Data next time
LCDsendDone:
bsf STATUS, C ; Set no timeout for Serout2mod
return


When i compare these steps with them in pbppic14.lib, than i note that in the upper code some parts (Red marked) not exist, like in the library code.

@ Darrel:
Are these Commands not necessary or why didn't you include them?


Further I would shrink this code to this:



LCDsend:
@ MOVE?AB _TempChar ; Get char sent by LCDOUT, in WREG
if !LCD_Initialized then LCD_Init ; Make sure LCD was Initialized
LCDAfterInit:
if TempChar = $FE then RSS=0 : goto LCDsendDone ; next char is Command
Char = TempChar
LCDsendCOM:
Goto ShiftLoop_Char
After_ShiftLoop_Char:
if LCD_Initialized then RSS = 1 ; Set RS to Data next time
LCDsendDone:
return


Because of the fact, that the shifting time of 1 byte needs about 2 - 4ms, it is not nessesary to include extra Delays for Data or Commands.

Can I do it in this way?



Thanks in advance!

Darrel Taylor
- 9th February 2014, 21:43
If you use GOTO DONE, it limits the use of your include to 14-bit devices.
In the 18F library, it's called DUNN.

There's no need to use DONE, since the FSR hasn't been changed, and RETURN resets the BANK to 0 anyhow.

The bsf STATUS, C is only required if the end user is using the SEROUT2 command with a Flow Control Pin.
My observations have concluded that nobody uses that function. Or if they understand how to use Flow Control, they probably aren't using LCD_AnyPin. :)

However, to cover ALL the bases ... you are correct! bsf STATUS, C should be there. But it needs an @ sign.

As for removing the delays ... I don't think that's a good idea.
The measurement I took previously was 1.8 mS per byte.
Most good LCD's take 1.6 mS for a Clear Screen, so it would be fine (with a good LCD).
But there are LCD's that take longer, 2.4 mS is not uncommon.

You could remove the LCD_DATAUS part since it will always be under 1.8 mS.

But I think the ability to add delays for LCD_COMMANDUS should remain in the program.
You can easily set LCD_COMMANDUS to 0 in the main program for normal displays.
For slower LCD's, just set it to the difference of say 2.4 mS - 1.8 ms = 0.6 mS or 600 uS.

struppi81
- 10th February 2014, 17:07
Thanks Darrel,

now I'm wiser, again thanks.

With the delays......

To shift out one byte (Data or Command) after LCDInit it needs 4 Steps.
One Step require a time nearly 910µs - 1ms.
That makes nearly 4ms. => No extra Delay necessary. Right?

The First 4 commands in the LCD_Init part needs only 2 Steps, because only the 4 upper bits shifted out.
There, I'm agree with you that the delay should be longer.

Could I place them here: ?



LCD_Init:
ShiftOut_Steps = 1
Char = $33 : gosub LCDsendCOM : @ DelayUS 5000
gosub LCDsendCOM : @ DelayUS 600
gosub LCDsendCOM : @ DelayUS 600
Char = $22 : gosub LCDsendCOM : @ DelayUS 600 ; Start 4-bit mode
.........
.........
.........



Further I tested again with other frequencies.
I use 8 Mhz and a 20 Mhz quarz.
Also there are, no problems. It runs stable.

What I find out is that it is absolute necessary, to add an capacitor between +V and GND of the 74HC595.
I use an 100nF.
Otherwise you get sometimes error in displaying the right things.:smile:

The capacitor for the Latch Pulse, I would change back to 2.2nF. And the capacitor for the 1 or 0 Pulse should be left at 4.7nF.

Here are some picture make with my mini DSO.:rolleyes:

Clock Pulse
7226

Pulse 1 or 0 with 2.2nF
7228 7232

Pulse 1 or 0 with 4.7nF
7229 7233

Latch 2.2nF & Latch 4.7nF
7231 7230

Darrel Taylor
- 10th February 2014, 17:36
To shift out one byte (Data or Command) after LCDInit it needs 4 Steps.
One Step require a time nearly 910µs - 1ms.
That makes nearly 4ms. => No extra Delay necessary. Right?
No, each byte whether it's a command or data requires two nibbles at 910 uS or 1.82 mS total.

You need the delays!

And I would leave the initialization timing the same.
It only happens once per power-on, so you're not saving any time during normal operations.

struppi81
- 10th February 2014, 19:05
Now im confused:confused:

LCD_Init _Only the First 4 Commands (2 Steps):

Step1: shiftout 1 byte.
Enable_High + Data high nibble + Latch => nearly 910µs (Delay at the next Command)

Step2: shiftout 1 byte
Enable_Low + Data high nibble + Latch => nearly 910µs (Delay at the next Command till Latch)

=> 1,8 µs => extra delay necessary.

Next Command....

The 3 others Commands 4 Steps ; (see after LCD Init)


After LCD Init (4 Steps): (Commands without RS)

Step1: shiftout 1 byte.
RS + Enable_High + Data high nibble + Latch => nearly 910µs (Delay at the next Command or Data)

Step2: shiftout 1 byte
RS + Enable_Low + Data high nibble + Latch => nearly 910µs (Delay at the next Command or Data)

Step3: shiftout 1 byte
RS + Enable_High + Data low nibble + Latch => nearly 910µs (Delay at the next Command or Data)

Step4: shiftout 1 byte
RS + Enable_Low + Data low nibble + Latch => nearly 910µs (Delay at the next Command or Data till Latch)

=> 3,6µs

Next Command or Data....

:confused:

Darrel Taylor
- 10th February 2014, 20:02
Or I'm confused, not sure.
I see how it takes 4 "steps" just to toggle the E line.

But, the LCD will not accept any data or commands while it is busy.
Even though it takes 4 steps ... you are clocking in the first nibble after the first 2 steps 1.82 mS.

The HD44780 datasheet timing diagrams show that the first nibble can't be clocked in until after the last command is complete (not busy).
There is no text that confirms it, but that's what the timing diagrams show.

struppi81
- 12th February 2014, 11:37
OK,

now I post my Final, good working code.

I implement the ability to add delays for LCD_COMMANDUS in the main programm and the part, if somebody want to use SEROUT2 with a Flow Control Pin. (I don't have test it yet)

With my LCD's, I could set the LCD_COMMANDUS Value to 0.

It would be very interesting if somebody could test it out with an slower LCD and post which value he have to set or general experiences.

A big thanks to Darrel Taylor.

Zip File implements:
One_Wire_74HC595_Main.pbp
One_Wire_74HC595.bas
VirtualPort.bas

mimie64
- 12th February 2014, 17:08
Hello,:)
I desperately looking for a simple code
use an LCD via a 74HC595 or 3 wire.
why is it so difficult to make a code with
LCDOUT the order?
mimie64:confused:

WMakoto
- 27th April 2015, 02:02
Hello.

In the simulation proteus, sometimes appear strange characters, is this normal?