Let me know if you'd like to see an assembly language driver?
Does that design require filling the shift register six times to send a single byte to the LCD? How long would that take, 4-5 milliseconds?
You misunderstood but I looked at your shift-1 software and it clearly shows that you send four bytes to the 74HC595 in order to get one byte to the LCD... (1) send upper nibble with E high, (2) send upper nibble with E low, (3) send lower nibble with E high, and (4) send lower nibble with E low.No, you only have to send the 7 data bits followed by the final "latch" bit, to send 1 byte.Mike said:Does that design require filling the shift register six times to send a single byte to the LCD? How long would that take, 4-5 milliseconds?
//=============================================================================
// SH1_LCD_BYTE sends a command or char byte to LCD
//=============================================================================
void SH1_Lcd_Byte(unsigned char SH1_byte, unsigned char SH1_cmd)
{
//-----------------------------------------------------
// this sends 2 4bit nibbles to the LCD, and each
// nibble is clocked by a \ edge of the LCD E pin.
// the 6 LCD pins are controlled by a 74HC595 shift
// register using RomanBlack's Shift1 timed protocol.
//-----------------------------------------------------
// send top nibble first
SH1_trashdata = (SH1_byte & 0xF0); // get top 4 bits
SH1_trashdata.F3 = 1; // set E pin hi
if(SH1_cmd) SH1_trashdata.F2 = 1; // set RS (command=0/char=1)
SH1_Send_Byte(SH1_trashdata); // send data and E hi
SH1_trashdata.F3 = 0; // set E pin lo
SH1_Send_Byte(SH1_trashdata); // send data and E \ clock pulse
// now send bottom nibble
SH1_trashdata = (SH1_byte << 4); // get bottom 4 bits
SH1_trashdata.F3 = 1;
if(SH1_cmd) Sh1_trashdata.F2 = 1; // set RS (command=0/char=1)
SH1_Send_Byte(SH1_trashdata);
SH1_trashdata.F3 = 0;
SH1_Send_Byte(SH1_trashdata);
}
Ok, so multiply that 815uS by four to get a complete command or data byte to the LCD and it can take several thousand microseconds worst case. As long as you know about that ahead of time, you should be able to work around it for all but the most demanding applications.But you made a good point it is not that fast, for worst case with the RC values I used in the kit it takes 45uS*7 for 7 zero bits, followed by 500uS for the latch bit. Total time 815uS to send the byte. Fast enough to update the LCD multiple times a second.
Please. I've been writing but not succeeding. Comparing mine to one that's working, should show me where I'm wrong.Mike said:Let me know if you'd like to see an assembly language driver?
#define dat LATA,0 ; 595 'ser' pin
#define clk LATA,1 ; 595 'sck' and 'rck' pins
#define ena LATA,2 ; lcd 'e' pin
;******************************************************************
; K8LH 74HC595 "LCD 8-bit Interface Mode" Low Level Driver *
;******************************************************************
putDat
bsf STATUS,C ; flag rs = 1 (data)
btfss STATUS,C ; skip unconditionally
putCmd
bcf STATUS,C ; flag rs = 0 (command)
movwf work ; save byte in 'work' var
movlw 8 ; use wreg as bit counter
bitlp
bcf dat ; dat = 0
btfsc work,7 ; is it '0'? yes, skip, else
bsf dat ; dat = 1
bsf clk ; clk = 1, clock out a bit
bcf clk ; clk = 0
rlncf work,F ; shift 'work' byte
decfsz WREG,F ; all 8 bits? yes, skip, else
bra bitlp ; branch (send another bit)
bcf dat ; dat = 0
btfsc STATUS,C ; rs = 0? yes, skip, else
bsf dat ; dat = 1
bsf clk ; clk = 1, clock out 'RS' bit
bcf clk ; clk = 0 (leave dat = RS)
bsf ena ; ena = 1, strobe LCD 'E' pin
bcf ena ; ena = 0
return ;
I let you no today some time I don't feel to hot right now. going back to bed.
;******************************************************************
; *
; Filename: 18F14K22 595 8 Bit LCD Test.asm *
; Author: Mike McLaren, K8LH *
; (C)2012: Micro Application Consultants *
; : All Rights Reserved *
; Date: 11-Jan-2013 *
; *
; 18F14K22 + 74HC595 - K8LH LCD 8-Bit Interface Adapter Test *
; *
; *
; *
; MPLab: 8.84 (tabs=8) *
; MPAsm: 5.44 *
; *
;******************************************************************
#include <P18F14K22.inc>
list st=off ; no symbol table in LST file
radix dec
;
; setup configuration fuses
;
CONFIG FOSC = IRC ; Internal RC oscillator
CONFIG PLLEN = OFF ; PLL is under software control
CONFIG PCLKEN = ON ; Primary clock enabled
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor disabled
CONFIG IESO = OFF ; Oscillator Switchover mode disabled
CONFIG PWRTEN = ON ; PWRT enabled
CONFIG BOREN = SBORDIS ; Brown-out Reset enabled in hardware
; only (SBOREN is disabled)
CONFIG BORV = 22 ; VBOR set to 2.2 V nominal
CONFIG WDTEN = OFF ; WDT control via WDTCON SWDTEN bit
CONFIG WDTPS = 256 ; 1:256
CONFIG HFOFST = OFF ; clock held until HFINTOSC stable
CONFIG MCLRE = ON ; MCLR enabled, RA3 I/O unavailable
CONFIG STVREN = ON ; reset on Stack full or underflow
CONFIG LVP = OFF ; Single-Supply ICSP disabled
CONFIG XINST = OFF ; extended instruction set disabled
CONFIG DEBUG = OFF ; debugger off, RA0 + RA1 available
;--< variables >---------------------------------------------------
temp equ 0x000 ; lcd subroutines
delayhi equ 0x001 ; DelayCy() subsystem var
count equ 0x002 ;
work equ 0x003 ; lcd driver work var
;--< constants >---------------------------------------------------
#define MASK(X) (1<<(X))
brgval equ (16000000/19200/4)-1 ; 19200, BRGH=1, BRG16=1
#define line1 128+0 ; lcd line 1 address
#define line2 128+64 ; lcd line 2 address
;--< defines >-----------------------------------------------------
#define dat LATA,0 ; RA0 -> 595 'ser' pin
#define clk LATA,1 ; RA1 -> 595 'sck' and 'rck' pins
#define ena LATA,2 ; RA2 -> lcd 'e' pin
;
; assembly language helpers
;
#define clrc bcf STATUS,C
#define setc bsf STATUS,C
#define skpc btfss STATUS,C
#define skpnc btfsc STATUS,C
;==================================================================
; K8LH DelayCy() subsystem macro generates four instructions =
;==================================================================
radix dec
clock equ 16 ; 4, 8, 12, 16, 20 (MHz), etc.
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ clock/4*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf delayhi
movlw low ((delay-11)/5)
call uDelay-(((delay-11)%5)*2)
endm
;******************************************************************
; reset vector *
;******************************************************************
org 0x0000
vreset
goto init ; |
;******************************************************************
; interrupt vector hi *
;******************************************************************
org 0x0008
vinthi
;******************************************************************
; interrupt vector lo *
;******************************************************************
org 0x0018
vintlo
;******************************************************************
; main init *
;******************************************************************
init
clrf ANSEL ; |
clrf ANSELH ; |
clrf TRISA ; |
clrf TRISB ; |
clrf TRISC ; |
clrf PORTA ; |
clrf PORTB ; |
clrf PORTC ; |
;
; setup INTOSC for 16 MHz
;
; movlw 1<<PLLEN ; 4xPLL 'on' for 64 MHz |
; movwf OSCTUNE ; |
movlw b'01110010' ; 16 MHz |
movwf OSCCON ; |
;
; configure EUSART for 19200 baud operation (16 MHz clock)
;
movlw low(brgval) ; |
movwf SPBRG ; |
movlw high(brgval) ; |
movwf SPBRGH ; |
movlw 1<<BRG16 ; |
movwf BAUDCON ; BRG16=1 |
movlw 1<<TXEN|1<<BRGH ; |
movwf TXSTA ; TXEN=1, BRGH=1, SYNC=0 |
movlw 1<<SPEN|1<<CREN ; |
movwf RCSTA ; SPEN=1, CREN=1 |
;
; initialize LCD (8-bit interface mode). please note this is
; not the Hitachi "initialize by instruction" procedure.
;
DelayCy(50*msecs) ; lcd 50 msec 'power up' reset |
movlw 0x38 ; 8-bit, 2-lines, 5x7 font |
call PutCmd ; send "function set" command |
movlw 0x01 ; clear display (1.53-msecs) |
call PutCmd ; send "entry mode set" command |
DelayCy(1530*usecs) ; 1.53 msec delay for "clear" |
movlw 0x06 ; cursor inc, shift off |
call PutCmd ; send "entry mode set" command |
movlw 0x0C ; display on, cursor & blink off |
call PutCmd ; send "display on/off" command |
;
; display "hello" starting at fifth column on line 2
;
movlw line2+4 ; line 2, tab 4 |
call PutCmd ; move lcd cursor to x,y = 4,1 |
movlw 'h' ; |
call PutDat ; |
movlw 'e' ; |
call PutDat ; |
movlw 'l' ; |
call PutDat ; |
movlw 'l' ; |
call PutDat ; |
movlw 'o' ; |
call PutDat ; |
;******************************************************************
; main loop *
;******************************************************************
loop
bra loop ; loop forever |
;******************************************************************
; K8LH "74HC595 LCD 8-bit Interface Mode" Low Level Driver *
;******************************************************************
PutDat
setc ; flag rs = 1 (data) |
skpc ; skip unconditionally |
PutCmd
clrc ; flag rs = 0 (command) |
movwf work ; save byte in 'work' var |
movlw 8 ; use wreg as bit counter |
bitlp
bcf dat ; dat = 0 |
btfsc work,7 ; is it '0'? yes, skip, else |
bsf dat ; dat = 1 |
bsf clk ; clk = 1, clock out a bit |
bcf clk ; clk = 0 |
rlncf work,F ; shift 'work' byte |
decfsz WREG,F ; all 8 bits? yes, skip, else |
bra bitlp ; branch (send another bit) |
bcf dat ; dat = 0 |
skpnc ; rs = 0? yes, skip, else |
bsf dat ; dat = 1 |
bsf clk ; clk = 1, clock out 'RS' bit |
bcf clk ; clk = 0 (leave dat = RS) |
bsf ena ; ena = 1, strobe LCD 'E' pin |
bcf ena ; ena = 0 |
DelayCy(50*usecs) ; required lcd inter-write delay |
return ; |
;******************************************************************
; serial subroutines *
;******************************************************************
put232
btfss PIR1,TXIF ; Tx buff empty? yes, skip, else |
bra put232 ; loop |
movwf TXREG ; |
return ; |
get232
btfss PIR1,RCIF ; Rx char avail? yes, skip, else |
bra get232 ; loop |
movf RCREG,W ; |
return ; |
;******************************************************************
; K8LH DelayCy() 16-bit uDelay (11..327690 cycle) subroutine *
;******************************************************************
nop ; entry for (delay-11)%5 == 4 |
nop ; entry for (delay-11)%5 == 3 |
nop ; entry for (delay-11)%5 == 2 |
nop ; entry for (delay-11)%5 == 1 |
uDelay addlw -1 ; subtract 5 cycle loop time |
skpc ; borrow? no, skip, else |
decfsz delayhi,F ; done? yes, skip, else |
bra uDelay ; do another loop |
return ; return with C = Z = 0 |
;******************************************************************
end
movlw low(brgval) ; |
movwf SPBRG ; |
movlw high(brgval) ; |
movwf SPBRGH ; |
movlw 1<<BRG16 ; |
movwf BAUDCTL ; BRG16=1 |
movlw 1<<TXEN|1<<BRGH ; |
movwf TXSTA ; TXEN=1, BRGH=1, SYNC=0 |
movlw 1<<SPEN|1<<CREN ; |
movwf RCSTA ; SPEN=1, CREN=1 |
;
;******************************************************************
; *
; Filename: 18F14K22 595 8 Bit LCD Test.asm *
; Author: Mike McLaren, K8LH *
; (C)2012: Micro Application Consultants *
; : All Rights Reserved *
; Date: 11-Jan-2013 *
; *
; 18F14K22 + 74HC595 - K8LH LCD 8-Bit Interface Adapter Test *
; *
; *
; *
; MPLab: 8.84 (tabs=8) *
; MPAsm: 5.44 *
; *
;******************************************************************
#include <P18F1220.inc>
list st=off ; no symbol table in LST file
radix dec
;
; setup configuration fuses
;
CONFIG OSC = HS ; Internal RC oscillator
CONFIG FSCM = OFF
CONFIG IESO = OFF
CONFIG PWRT = OFF
CONFIG BOR = OFF
CONFIG BORV = 27
CONFIG WDT = OFF
CONFIG MCLRE = ON
CONFIG STVR = OFF
CONFIG LVP = OFF
CONFIG DEBUG = OFF
CONFIG CP0 = OFF
CONFIG CP1 = OFF
CONFIG CPB = OFF
CONFIG CPD = OFF
CONFIG WRT0 = OFF
CONFIG WRT1 = OFF
CONFIG WRTC = OFF
CONFIG WRTB = OFF
CONFIG WRTD = OFF
CONFIG EBTR0 = OFF
CONFIG EBTR1 = OFF
CONFIG EBTRB = OFF
;--< variables >---------------------------------------------------
temp equ 0x000 ; lcd subroutines
delayhi equ 0x001 ; DelayCy() subsystem var
count equ 0x002 ;
work equ 0x003 ; lcd driver work var
;--< constants >---------------------------------------------------
#define MASK(X) (1<<(X))
brgval equ (16000000/19200/4)-1 ; 19200, BRGH=1, BRG16=1
#define line1 128+0 ; lcd line 1 address
#define line2 128+64 ; lcd line 2 address
;--< defines >-----------------------------------------------------
#define dat LATA,0 ; RA0 -> 595 'ser' pin
#define clk LATA,1 ; RA1 -> 595 'sck' and 'rck' pins
#define ena LATA,2 ; RA2 -> lcd 'e' pin
;
; assembly language helpers
;
#define clrc bcf STATUS,C
#define setc bsf STATUS,C
#define skpc btfss STATUS,C
#define skpnc btfsc STATUS,C
;==================================================================
; K8LH DelayCy() subsystem macro generates four instructions =
;==================================================================
radix dec
clock equ 16 ; 4, 8, 12, 16, 20 (MHz), etc.
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ clock/4*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf delayhi
movlw low ((delay-11)/5)
call uDelay-(((delay-11)%5)*2)
endm
;******************************************************************
; reset vector *
;******************************************************************
org 0x0000
vreset
goto init ; |
;******************************************************************
; interrupt vector hi *
;******************************************************************
org 0x0008
vinthi
;******************************************************************
; interrupt vector lo *
;******************************************************************
org 0x0018
vintlo
;******************************************************************
; main init *
;******************************************************************
init
movlw 0xFF ; Configure A/D
movwf ADCON1 ; for digital inputs
clrf TRISA ; |
clrf TRISB ; |
clrf PORTA ; |
clrf PORTB ; |
;
; setup INTOSC for 16 MHz
;
; movlw 1<<PLLEN ; 4xPLL 'on' for 64 MHz |
; movwf OSCTUNE ; |
; movlw 0x73 ; 8 MHz |
; movwf OSCCON ; |
;
; configure EUSART for 19200 baud operation (16 MHz clock)
;
movlw low(brgval) ; |
movwf SPBRG ; |
movlw high(brgval) ; |
movwf SPBRGH ; |
movlw 1<<BRG16 ; |
movwf BAUDCTL ; BRG16=1 |
movlw 1<<TXEN|1<<BRGH ; |
movwf TXSTA ; TXEN=1, BRGH=1, SYNC=0 |
movlw 1<<SPEN|1<<CREN ; |
movwf RCSTA ; SPEN=1, CREN=1 |
;
; initialize LCD (8-bit interface mode). please note this is
; not the Hitachi "initialize by instruction" procedure.
;
DelayCy(50*msecs) ; lcd 50 msec 'power up' reset |
movlw 0x38 ; 8-bit, 2-lines, 5x7 font |
call PutCmd ; send "function set" command |
movlw 0x01 ; clear display (1.53-msecs) |
call PutCmd ; send "entry mode set" command |
DelayCy(1530*usecs) ; 1.53 msec delay for "clear" |
movlw 0x06 ; cursor inc, shift off |
call PutCmd ; send "entry mode set" command |
movlw 0x0C ; display on, cursor & blink off |
call PutCmd ; send "display on/off" command |
;
; display "hello" starting at fifth column on line 2
;
movlw line2+4 ; line 2, tab 4 |
call PutCmd ; move lcd cursor to x,y = 4,1 |
movlw 'h' ; |
call PutDat ; |
movlw 'e' ; |
call PutDat ; |
movlw 'l' ; |
call PutDat ; |
movlw 'l' ; |
call PutDat ; |
movlw 'o' ; |
call PutDat ; |
;******************************************************************
; main loop *
;******************************************************************
loop
bra loop ; loop forever |
;******************************************************************
; K8LH "74HC595 LCD 8-bit Interface Mode" Low Level Driver *
;******************************************************************
PutDat
setc ; flag rs = 1 (data) |
skpc ; skip unconditionally |
PutCmd
clrc ; flag rs = 0 (command) |
movwf work ; save byte in 'work' var |
movlw 8 ; use wreg as bit counter |
bitlp
bcf dat ; dat = 0 |
btfsc work,7 ; is it '0'? yes, skip, else |
bsf dat ; dat = 1 |
bsf clk ; clk = 1, clock out a bit |
bcf clk ; clk = 0 |
rlncf work,F ; shift 'work' byte |
decfsz WREG,F ; all 8 bits? yes, skip, else |
bra bitlp ; branch (send another bit) |
bcf dat ; dat = 0 |
skpnc ; rs = 0? yes, skip, else |
bsf dat ; dat = 1 |
bsf clk ; clk = 1, clock out 'RS' bit |
bcf clk ; clk = 0 (leave dat = RS) |
bsf ena ; ena = 1, strobe LCD 'E' pin |
bcf ena ; ena = 0 |
DelayCy(50*usecs) ; required lcd inter-write delay |
return ; |
;******************************************************************
; serial subroutines *
;******************************************************************
put232
btfss PIR1,TXIF ; Tx buff empty? yes, skip, else |
bra put232 ; loop |
movwf TXREG ; |
return ; |
get232
btfss PIR1,RCIF ; Rx char avail? yes, skip, else |
bra get232 ; loop |
movf RCREG,W ; |
return ; |
;******************************************************************
; K8LH DelayCy() 16-bit uDelay (11..327690 cycle) subroutine *
;******************************************************************
nop ; entry for (delay-11)%5 == 4 |
nop ; entry for (delay-11)%5 == 3 |
nop ; entry for (delay-11)%5 == 2 |
nop ; entry for (delay-11)%5 == 1 |
uDelay addlw -1 ; subtract 5 cycle loop time |
skpc ; borrow? no, skip, else |
decfsz delayhi,F ; done? yes, skip, else |
bra uDelay ; do another loop |
return ; return with C = Z = 0 |
;******************************************************************
end
In post 25 I'm using that SCH
Yes, LAT = RCLK = ST_CP and CLK = SRCLK = SCK = SH_CP, etc. Modified drawing below...Mike the RCLK SRCLK pins are what you have as LAT CLK right ?
You misunderstood but I looked at your shift-1 software and it clearly shows that you send four bytes to the 74HC595 in order to get one byte to the LCD... (1) send upper nibble with E high, (2) send upper nibble with E low, (3) send lower nibble with E high, and (4) send lower nibble with E low.
...
Well I I have code for 3 chips now here a 18f2550
View attachment 69749
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?