📄 lcddrv.c
字号:
#define Byte unsigned char
unsigned char sysCounter;
void PrintOffset (char* Msg, char Offset) {
Byte index;
LCDClear ();
LCDCtrl (0x80);
for (index = 0; index < 16; index++) {
if (index == 8) LCDCtrl (0xC0);
if (Msg[index] == 0) break;
LCDData (Msg[(index + Offset) & 0x0F]);
}
}
void PrintMsg (char* Msg) {
Byte index;
LCDClear ();
LCDCtrl (0x80);
for (index = 0; index < 16; index++) {
if (index == 8) LCDCtrl (0xC0);
if (Msg[index] == 0) break;
LCDData (Msg[index]);
}
}
void putch (char c) {
}
#asm
xref.b _sysCounter
xdef _LCDInit, _LCD8Ctrl, _LCDCtrl
xdef _LCDClear, _LCDHome, _LCDData, _msDelay
BUSFREQ: EQU 2
USCOUNT: EQU $0E
USDELAY: EQU BUSFREQ*USCOUNT
PORTB: EQU $01
DDRB: EQU $05
RS: EQU 1
RW: EQU 2
E_LCD: EQU 3
; -------------------------------------------------------------------
; LCD INITIALIZATION
; Called on startup to initialize the LCD into 4-bit mode
; Don't use the LCDControl subroutine at first, because initially
; the LCD is in 8-bit interface mode.
; -------------------------------------------------------------------
_LCDInit:
;-----------------------------
;Port B setup for LCD module
;-----------------------------
BCLR RS,PORTB ;Preset control line output levels
BCLR RW,PORTB
BCLR E_LCD,PORTB
MOV #$FE,DDRB ;Setup PB1-PB7 as outputs for LCD
BCLR RS,PORTB ;Preset control line output levels
BCLR RW,PORTB
BCLR E_LCD,PORTB
;------------------------------------------
;8-bit interface at first
;------------------------------------------
LDA #$0F ;Wait 15ms
JSR _msDelay
LDA #$30 ;Function set
JSR _LCD8Ctrl
LDA #5 ;Wait 5ms
JSR _msDelay
LDA #$30 ;Function set
JSR _LCD8Ctrl
LDA #1 ;Wait 1ms
JSR _msDelay
LDA #$30 ;Function set
JSR _LCD8Ctrl
LDA #$20 ;Function set first set up 4-bit
JSR _LCD8Ctrl
;------------------------------------------
;4-bit operation
;------------------------------------------
LDA #$28 ;Second 4-bit function set
JSR _LCDCtrl ;Also 2-line setup
LDA #$06 ;Increment, no shift
JSR _LCDCtrl
LDA #$01 ;Clear display, cursor home
JSR _LCDCtrl
LDA #$0C ;Display on, cursor off, blink off
JSR _LCDCtrl
RTS
; -------------------------------------------------------------------
; If the LCD is in 8-bit mode, just send the upper data bits through
; the lower port C bits
; Acc contains control byte
; -------------------------------------------------------------------
_LCD8Ctrl:
AND #$F0 ;Mask out lower data bits
PSHA ;Store value to send temporarily
LDA PORTB ;Don't change other PORTB pins
AND #$0F ;Mask out UPPER nibble
ADD 1,SP ;Add value to send
STA PORTB ;Store to PORTB
BSET E_LCD,PORTB ;Toggle enable line
BCLR E_LCD,PORTB
JSR _40usDelay ;40us setup time
PULA ;Deallocate stack data
RTS
; -------------------------------------------------------------------
; Write LCD control byte in 4-bit mode
; For 4-bit mode, need to send the nibbles one at a time, high nibble first
; Acc contains control byte to send
; This routine is also used for Address writes to LCD, when MSbit of
; data byte is set. (i.e. $80 for address 00)
; -------------------------------------------------------------------
_LCDCtrl:
;------------------------------------------
;Upper nibble
;------------------------------------------
PSHA ;Store data on stack
AND #$F0 ;Mask out lower nibble
PSHA ;Store upper nibble on stack
LDA PORTB ;Load PORTB contents
AND #$0F ;Mask out UPPER nibble
ADD 1,SP ;Add the data nibble
STA PORTB ;Present upper nibble to LCD
BSET E_LCD,PORTB ;Toggle Enable line
BCLR E_LCD,PORTB
JSR _40usDelay ;40us setup time
;------------------------------------------
;Lower nibble
;------------------------------------------
PULA ;Deallocate last temp storage
PULA ;Get original data byte
AND #$0F ;Mask out upper nibble
NSA ;Put LOWER nibble in UPPER nibble
PSHA ;Store onto stack
LDA PORTB ;Get existing PORTB data
AND #$0F ;Mask out lower nibble
ADD 1,SP ;Add lower nibble of data byte
STA PORTB ;Store to PORTB
BSET E_LCD,PORTB ;Toggle Enable line
BCLR E_LCD,PORTB
PULA ;Deallocate temp storage
CMP #$10 ;Longer delay for commands 1 or 2
BEQ LCLonger
CMP #$20
BEQ LCLonger
JSR _40usDelay ;40us for any other command
RTS ;Return
LCLonger:
LDA #2
JSR _msDelay
RTS
; -------------------------------------------------------------------
; Write data byte to LCD, using 4-bit mode
; Acc contains data byte to send
; -------------------------------------------------------------------
_LCDData:
;------------------------------------------
;First nibble
;------------------------------------------
PSHA ;Store data on stack temporarily
AND #$F0 ;Mask out lower nibble
PSHA ;Store upper nibble on stack
LDA PORTB ;Load PORTB contents
AND #$0F ;Mask out UPPER nibble
ADD 1,SP ;Add the data nibble
STA PORTB ;Store to PORTB
BSET RS,PORTB ;Set RS for control
BSET E_LCD,PORTB ;Toggle Enable line
BCLR E_LCD,PORTB
;------------------------------------------
;Second nibble
;------------------------------------------
PULA ;Deallocate temp storage
PULA ;Get original data
AND #$0F ;Mask out upper nibble
NSA ;Put LOWER nibble in UPPER port pins
PSHA ;Store onto stack
LDA PORTB
AND #$0F
ADD 1,SP
STA PORTB
BSET E_LCD,PORTB ;Toggle enable line
BCLR E_LCD,PORTB
JSR _40usDelay ;40us setup time
JSR _40usDelay ;40us setup time
BCLR RS,PORTB ;Clear RS for data
JSR _40usDelay ;40us setup time
JSR _40usDelay ;40us setup time
PULA ;Deallocate temp storage
RTS
; -------------------------------------------------------------------
; Clear the LCD display by sending the appropriate command byte
; -------------------------------------------------------------------
_LCDClear:
LDA #$01 ;Clear display AND home cursor
JSR _LCDCtrl
RTS
_LCDHome: LDA #$02
JSR _LCDCtrl
RTS
; -------------------------------------------------------------------
; DELAY ROUTINES
; -------------------------------------------------------------------
; 1ms delay loop, causes _roughly_ 1.3ms delay @ fop = 8MHz
; uses constant for loop control
; cycles = 4 + X(6+7+1275) + 3 + 6
; cycles = 13 + X(1288)
; where X is value loaded into Acc
; Causes 1.3ms delay for BUSFREQ values of (1-8 integer values)
; -------------------------------------------------------------------
_1msDelay:
PSHA ;2 cycles
LDA #BUSFREQ ;2
DLLoop: DBNZA DLSub ;3
BRA DLDone ;3
DLSub:
MOV #$FF,_sysCounter ;4
Here:
DBNZ _sysCounter,Here ;5
BRA DLLoop ;3
DLDone: PULA ;2
RTS ;4
; -------------------------------------------------------------------
; Variable ms delay loop
; Calls DelayLoop Acc number of times
; -------------------------------------------------------------------
_msDelay:
JSR _1msDelay
DBNZA _msDelay
RTS
; -------------------------------------------------------------------
; 40usec delay routine. Important for LCD module, which requires 40us
; delay for many of its commands, including the "data setup time"
; 6+X(3)
; Where X = BUSFREQ*USCOUNT = USDELAY
; Provides _roughly_ 40us delay
; -------------------------------------------------------------------
_40usDelay:
LDA #BUSFREQ*USCOUNT ;2
DBNZA * ;3
RTS ;4
#endasm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -