📄 hy12864b.a51
字号:
;
;rebuild on 2004/03/08
;hy12864b and no character mold lcd compatible provided
;pin4:RS(CS) connect to A1
;pin5:RW connect to A0
;
;!!the follow is important ,please vary the address 0x4000 accord to your hardware!!
;for example,if your A_LCD address is 0x2000,modify it to 'A_LCD_WC_L EQU 2004H',as follows
;
;pin6:EN=(!A_LCD)&(!(WRn&RDn) ;HARDWARE connect:WRn and RDn is 8031 P3.6,P3.7 respectively;
; A_LCD is 74138 output Y2n,also as 8031 address of 0x4000
; 74138 input A connect to 8031 P2.7(A15),B to P2.6(A14),C to P2.5(A13)
;
;pin7:DB0 connect to D0
;... ...
;pin14:DB7 connect to D7
;pin15:CS1 connect to A2
;pin16:CS2 connect to A3
;pin17:RESETn not used
;
;D0-D7 is the data bus,and A0-A15 is the address bus(so you must use a 74373)
;
;****address define*******
;you can only modify this part accord to your hardware
A_LCD_WC_L EQU 4004H ;写指令代码地址(右)
A_LCD_RC_L EQU 4005H ;读状态字地址(右)
A_LCD_WD_L EQU 4006H ;写显示数据地址(右)
A_LCD_RD_L EQU 4007H ;读显示数据地址(右)
A_LCD_WC_R EQU 4008H ;写指令代码地址(左)
A_LCD_RC_R EQU 4009H ;读状态字地址(左),BUSY(D7),ON/OFF(D5),RESET(D4)
;ON BUSY OR RESET STATE,ONLY READ STATE INSTRUCTION VALID
A_LCD_WD_R EQU 400aH ;写显示数据地址(左)
A_LCD_RD_R EQU 400bH ;读显示数据地址(左)
;// ***************命令字定义 *************** //
LCD_SET_SHOW_OFF EQU 3EH ;//开关显示
LCD_SET_SHOW_ON EQU 3FH ;开显示
LCD_SET_START_LINE EQU 0C0H ;//设置起始行(0-63)
LCD_SET_PAGE_NUMBER EQU 0B8H ;//设置页号(0-7)
LCD_SET_Y_ADDR EQU 40H ;//设置列地址(0-63)
TOTAL_X_PIXELS EQU 80H
TOTAL_Y_PIXELS EQU 40H
TOTAL_PAGES EQU 8H
BLOCK_WIDTH EQU 40H
BIGGEST_CHAR_HEIGHT EQU 4H ;最大的字符占四行,PAGE_COUNT:32(0),24(1),16(2),8(3)
PAGE_COUNT32 EQU 0 ;32*32
PAGE_COUNT24 EQU 1 ;24*24 OR 16*24
PAGE_COUNT16 EQU 2 ;16*16 OR 8*16
PAGE_COUNT8 EQU 3 ;8*8
;***************************************************
;COM DATA 20H ;指令寄存器
;DAT DATA 21H ;数据寄存器
;COUNT DATA 33H ;计数器
;PAGE_COUNT DATA 35H
;LR BIT 20H ;0:L ,1:R
NAME HY12864B
;?PR?RESET?HY12864B SEGMENT CODE
?PR?INITIAL?HY12864B SEGMENT CODE
?PR?_CLEARPAGE?HY12864B SEGMENT CODE
;?DT?_CLEARPAGE?HY12864B SEGMENT DATA OVERLAYABLE
?PR?_ROLL?HY12864B SEGMENT CODE
;?DT?_ROLL?HY12864B SEGMENT DATA OVERLAYABLE
?PR?_CHAR_PR?HY12864B SEGMENT CODE
?DT?_CHAR_PR?HY12864B SEGMENT DATA OVERLAYABLE
?BI?_CHAR_PR?HY12864B SEGMENT BIT OVERLAYABLE
?DT?HY12864B SEGMENT DATA OVERLAYABLE
?C0?CHARLIB?HY12864B SEGMENT CODE
; PUBLIC RESET
PUBLIC INITIAL
PUBLIC _CLEARPAGE
PUBLIC _ROLL
PUBLIC _CHAR_PR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RSEG ?DT?_ROLL?HY12864B
;?_ROLL?HY12864B?BYTE:
; START_LINE: DS 1
RSEG ?DT?_CHAR_PR?HY12864B
?_CHAR_PR?HY12864B?BYTE:
COLUMN: DS 1
PAGE0: DS 1
CODE0: DS 1
RSEG ?BI?_CHAR_PR?HY12864B
?BI?_CHAR_PR?HY12864B?BIT:
LR: DBIT 1
RSEG ?DT?HY12864B
?DT?HY12864B?BYTE:
COM: DS 1
DAT: DS 1
COUNT: DS 1
PAGE_COUNT:DS 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RSEG ?PR?RESET?HY12864B
;0,复位子程序
;RESET: MOV DPTR,#2000H ;RESET
; MOV A,#7FH
; MOVX @DPTR,A
; NOP
; NOP
; MOV R7,#010H
;RESET1: MOV R6,#0FFH
; DJNZ R6,$
; DJNZ R7,RESET1
; NOP
; NOP
; MOV A,#0FFH
; MOVX @DPTR,A
; RET
RSEG ?PR?INITIAL?HY12864B
;1、 初始化子程序
INITIAL: MOV COM,#LCD_SET_START_LINE ;设置显示起始行为第一行
LCALL LcdWriteCmdL
LCALL LcdWriteCmdR
MOV COM,#LCD_SET_SHOW_ON ;开显示设置
LCALL LcdWriteCmdL
LCALL LcdWriteCmdR
RET
RSEG ?PR?_CLEARPAGE?HY12864B
;2、清显示RAM区(清屏)子程序
_CLEARPAGE:MOV A,R7 ;每次清一行,参数由R7传递
ORL A,#LCD_SET_PAGE_NUMBER ;"或"页面地址设置代码,1011 1000B
MOV COM,A ;页面地址设置
LCALL LcdWriteCmdL
LCALL LcdWriteCmdR
MOV COM,#LCD_SET_Y_ADDR ;列地址设置为"0"
LCALL LcdWriteCmdL
LCALL LcdWriteCmdR
MOV R3,#40H ;一页清64个字节
CLEAR2: MOV DAT,#00H ;显示数据为"0"
LCALL LcdWriteDataL
LCALL LcdWriteDataR
DJNZ R3,CLEAR2 ;页内字节清零循环
RET
RSEG ?PR?_ROLL?HY12864B
;3,翻页卷动
_ROLL: MOV A,R7 ;传递参数为行起始地址START_LINE,参数由R7传递
ORL A,#LCD_SET_START_LINE
MOV COM,A
LCALL LcdWriteCmdL
LCALL LcdWriteCmdR
RET
RSEG ?PR?_CHAR_PR?HY12864B
_CHAR_PR:MOV CODE0,R3 ;传递参数
MOV COLUMN,R7
MOV PAGE0,R5
MOV A,CODE0 ;取字符代码
CLR C
SUBB A,#80H
JC ENGLISH
MOV CODE0,A
CLR C
SUBB A,#70H
JNC SMALLCH
MOV A,CODE0
MOV DPTR,#CCTAB ;确定字符字模块首地址
MOV B,#20H ;字模块宽度为32个字节;;;;;;;;;;;;;;
MUL AB ;代码X32
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码X32
MOV A,B
ADDC A,DPH
MOV DPH,A
MOV COUNT,#10H ;16*16点阵,汉字分两行显示;;
PUSH COLUMN
PUSH COUNT
JMP CW_2
SMALLCH:MOV DPTR,#LIU ;确定字符字模块首地址
MOV B,#18H ;字模块宽度为24个字节;;;;;;;;;;;;;;
MUL AB ;代码X24
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码X24
MOV A,B
ADDC A,DPH
MOV DPH,A
MOV COUNT,#0CH ;12*16点阵,汉字分两行显示;;;;;;;;;;;;;
PUSH COLUMN
PUSH COUNT
JMP CW_2
ENGLISH: MOV A,CODE0 ;取字符代码
CLR C
SUBB A,#40H
JNC SMALL
MOV DPTR,#CTAB ;确定字符字模块首地址
MOV B,#10H ;字模块宽度为16个字节
MOV A,CODE0 ;取字符代码
MUL AB ;代码X16
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码X16
MOV A,B
ADDC A,DPH
MOV DPH,A
MOV COUNT,#08H ;8X16点阵;;;;;;;;;;;;;;;;;;;;;;
PUSH COLUMN
PUSH COUNT
JMP CW_2
SMALL: MOV DPTR,#STAB ;确定字符字模块首地址
MOV B,#08H
MUL AB
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码X8
MOV A,B
ADDC A,DPH
MOV DPH,A
MOV COUNT,#08H ;8X8点阵;;;;;;;;;;;;;;;;;;;;;;
MOV PAGE_COUNT,#PAGE_COUNT8
JMP CW_3
CW_2: MOV PAGE_COUNT,#PAGE_COUNT16 ;字符的行,0 OR 1
CW_3: MOV CODE0,#00H ;借用为间址寄存器,指向单个字符的第几列
RTN: MOV A,PAGE0 ;取页地址值,确定从第几行开始显示,分两行显示
ORL A,#LCD_SET_PAGE_NUMBER ;"或"页地址指令代码????????????
MOV COM,A ;写页地址指针
LCALL LcdWriteCmdL
LCALL LcdWriteCmdR
CLR LR ;!!!!!!!!!!!!!!
MOV A,COLUMN ;读列地址寄存器,确定从第几列(单位为像素)开始显示
CLR C
SUBB A,#BLOCK_WIDTH ;列地址-64
JC CW_L ;<0为左屏显示区域
SETB LR ;;;;;;;;;;;;;;;;;;
MOV COM,A ;;;;;;;;;;;;;;;
ORL COM,#LCD_SET_Y_ADDR ;"或"列地址指令标志位?????????????
LCALL LcdWriteCmdR
JMP CW_4
CW_L: MOV COM,COLUMN ;设置列地址值
ORL COM,#LCD_SET_Y_ADDR ;"或"列地址指令标志位?????????????
LCALL LcdWriteCmdL ;"00"为左区
CW_4: MOV A,CODE0 ;取间址寄存器值
MOVC A,@A+DPTR ;取字符字模数据
MOV DAT,A ;;;;;;;;;;写数据;;;;;;;;;;;;
JNB LR,CW_R3
LCALL LcdWriteDataR
LJMP CW_5
CW_R3: LCALL LcdWriteDataL ;"00"为左区
CW_5: INC CODE0 ;间址加1
INC COLUMN ;列地址加1
MOV A,COLUMN ;判列地址是否超出区域范围
CJNE A,#BLOCK_WIDTH,CW_91 ;未超出则继续;;;;;;;;;;;;;;;;;;?????????
MOV COLUMN,#00H
SETB LR
MOV COM,#LCD_SET_Y_ADDR ;设置右区列地址为"0"
LCALL LcdWriteCmdR ;;;;;;;;;;;;;;;;;;;;;
JMP CW_9
CW_91: CJNE A,#TOTAL_X_PIXELS,CW_9
MOV COUNT,#1 ;右屏超出部分不显示
CW_9: DJNZ COUNT,CW_4 ;循环
INC PAGE_COUNT
MOV A,PAGE_COUNT
CJNE A,#BIGGEST_CHAR_HEIGHT,L1
LJMP FINISH
L1: INC PAGE0
POP COUNT
POP COLUMN
MOV R1,PAGE0
CJNE R1,#TOTAL_PAGES,GOON
JMP FINISH ;下屏超出部分不显示
GOON: MOV CODE0,COUNT
LJMP RTN
FINISH: RET
SUBFUNCTION SEGMENT CODE
RSEG SUBFUNCTION
;1 写指令代码子程序(左)
LcdWriteCmdL: PUSH DPL ;片选设置为"00"
PUSH DPH
MOV DPTR,#A_LCD_RC_L ;设置读状态字地址
WriteCmdL1: MOVX A,@DPTR ;读状态字
JB ACC.7,WriteCmdL1 ;判"忙"标志为"0"否,否在读
MOV DPTR,#A_LCD_WC_L ;设置写指令代码地址
MOV A,COM ;取指令代码
MOVX @DPTR,A ;写指令代码
POP DPH
POP DPL
RET
;2 写显示数据子程序(左)
LcdWriteDataL: PUSH DPL ;片选设置为"00"
PUSH DPH
MOV DPTR,#A_LCD_RC_L ;设置读状态字地址
WriteDataL1: MOVX A,@DPTR ;读状态字
JB ACC.7,WriteDataL1 ;判"忙"标志为"0"否,否在读
MOV DPTR,#A_LCD_WD_L ;设置写显示数据地址
MOV A,DAT ;取数据
MOVX @DPTR,A ;写数据
POP DPH
POP DPL
RET
;3 读显示数据子程序(左)
LcdReadDataL: PUSH DPL ;片选设置为"00"
PUSH DPH
MOV DPTR,#A_LCD_RC_L ;设置读状态字地址
ReadDataL1: MOVX A,@DPTR ;读状态字
JB ACC.7,ReadDataL1 ;判"忙"标志为"0"否,否在读
MOV DPTR,#A_LCD_RD_L ;设置读显示数据地址
MOVX A,@DPTR ;读数据
MOV DAT,A ;存数据
POP DPH
POP DPL
RET
;7 写指令代码子程序(右)
LcdWriteCmdR: PUSH DPL ;片选设置为"10"
PUSH DPH
MOV DPTR,#A_LCD_RC_R ;设置读状态字地址
WriteCmdR1: MOVX A,@DPTR ;读状态字
JB ACC.7,WriteCmdR1 ;判"忙"标志为"0"否,否在读
MOV DPTR,#A_LCD_WC_R ;设置写指令代码地址
MOV A,COM ;取指令代码
MOVX @DPTR,A ;写指令代码
POP DPH
POP DPL
RET
;8 写显示数据子程序(右)
LcdWriteDataR: PUSH DPL ;片选设置为"10"
PUSH DPH
MOV DPTR,#A_LCD_RC_R ;设置读状态字地址
WriteDataR1: MOVX A,@DPTR ;读状态字
JB ACC.7,WriteDataR1 ;判"忙"标志为"0"否,否在读
MOV DPTR,#A_LCD_WD_R ;设置写显示数据地址
MOV A,DAT ;取数据
MOVX @DPTR,A ;写数据
POP DPH
POP DPL
RET
;9 读显示数据子程序(右)
LcdReadDataR: PUSH DPL ;片选设置为"10"
PUSH DPH
MOV DPTR,#A_LCD_RC_R ;设置读状态字地址
ReadDataR1: MOVX A,@DPTR ;读状态字
JB ACC.7,ReadDataR1 ;判"忙"标志为"0"否,否在读
MOV DPTR,#A_LCD_RD_R ;设置读显示数据地址
MOVX A,@DPTR ;读数据
MOV DAT,A ;存数据
POP DPH
POP DPL
RET
RSEG ?C0?CHARLIB?HY12864B
CTAB: ;(8*16,FROM 000H)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -