📄 library.asm
字号:
;点亮LCD屏LAMP(灯)标志
;********************************
LCDLAMP_ON:
MOV LCDCMD,#0BFH ;1011 1XXX 其中XXX=111,即第7页
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#7CH ;01XX XXXX 其中XX XXXX=11 1100,即第60列
;注:每执行一次数据读或写,列计数器均要递增
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL LCDPRR2 ;LCD右半屏数据读
LCALL LCDPRR2 ;再读一次,即必须有一次空读操作
MOV A,LCDDAT
SETB ACC.7 ;置高电平,点亮LCD屏上的LAMP(灯)标志
MOV LCDDAT,A
LCALL LCDPRR1 ;LCD右半屏数据写
RET
;********************************
;点亮LCD屏DELTA(三角符)标志
;********************************
LCDDELTA_ON:
MOV LCDCMD,#0BFH ;1011 1XXX 其中XXX=111,即第7页
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#7DH ;01XX XXXX 其中XX XXXX=11 1101,即第61列
;注:每执行一次数据读或写,列计数器均要递增
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL LCDPRR2 ;LCD右半屏数据读
LCALL LCDPRR2 ;再读一次,即必须有一次空读操作
MOV A,LCDDAT
SETB ACC.7 ;置高电平,点亮LCD屏上的DLETA(三角符)标志
MOV LCDDAT,A
LCALL LCDPRR1 ;LCD右半屏数据写
RET
;********************************
;关闭LCD屏BATT(电池)标志
;********************************
LCDBATT_OFF:
MOV LCDCMD,#0BFH ;1011 1XXX 其中XXX=111,即第7页
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#7AH ;01XX XXXX 其中XX XXXX=11 1010,即第58列
;注:每执行一次数据读或写,列计数器均要递增
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL LCDPRR2 ;LCD右半屏数据读
LCALL LCDPRR2 ;再读一次,即必须有一次空读操作
MOV A,LCDDAT
CLR ACC.7 ;置低电平,关闭LCD屏上的BATT(电池)标志
MOV LCDDAT,A
LCALL LCDPRR1 ;LCD右半屏数据写
RET
;********************************
;关闭LCD屏ARROW(箭头)标志
;********************************
LCDARROW_OFF:
MOV LCDCMD,#0BFH ;1011 1XXX 其中XXX=111,即第7页
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#7BH ;01XX XXXX 其中XX XXXX=11 1011,即第59列
;注:每执行一次数据读或写,列计数器均要递增
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL LCDPRR2 ;LCD右半屏数据读
LCALL LCDPRR2 ;再读一次,即必须有一次空读操作
MOV A,LCDDAT
CLR ACC.7 ;置低电平,关闭LCD屏上的ARROW(箭头)标志
MOV LCDDAT,A
LCALL LCDPRR1 ;LCD右半屏数据写
RET
;********************************
;关闭LCD屏LAMP(灯)标志
;********************************
LCDLAMP_OFF:
MOV LCDCMD,#0BFH ;1011 1XXX 其中XXX=111,即第7页
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#7CH ;01XX XXXX 其中XX XXXX=11 1100,即第60列
;注:每执行一次数据读或写,列计数器均要递增
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL LCDPRR2 ;LCD右半屏数据读
LCALL LCDPRR2 ;再读一次,即必须有一次空读操作
MOV A,LCDDAT
CLR ACC.7 ;置低电平,关闭LCD屏上的LAMP(灯)标志
MOV LCDDAT,A
LCALL LCDPRR1 ;LCD右半屏数据写
RET
;********************************
;关闭LCD屏DELTA(三角符)标志
;********************************
LCDDELTA_OFF:
MOV LCDCMD,#0BFH ;1011 1XXX 其中XXX=111,即第7页
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#7DH ;01XX XXXX 其中XX XXXX=11 1101,即第61列
;注:每执行一次数据读或写,列计数器均要递增
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL LCDPRR2 ;LCD右半屏数据读
LCALL LCDPRR2 ;再读一次,即必须有一次空读操作
MOV A,LCDDAT
CLR ACC.7 ;置低电平,关闭LCD屏上的DLETA(三角符)标志
MOV LCDDAT,A
LCALL LCDPRR1 ;LCD右半屏数据写
RET
;********************************
;LCD清屏(清LCD显示RAM)子程序
;********************************
LCDCLEAR:
MOV R2,#00H ;从XPAGE=0页开始LCD清屏操作
LCDCLEAR1:
MOV A,R2
ORL A,#10111000B ;计算新页面地址: 1011 1XXX (XPAGE页面地址)
MOV LCDCMD,A ;页面地址设置
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#01000000B ;清屏时,每页列起始地址为0: 01XX XXXX (列地址)
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
MOV R3,#64 ;LCD每页左、右半屏各有64列(COLUMN)
LCDCLEAR2:
MOV LCDDAT,#00H ;显示数据为"0",即关闭显示
LCALL LCDPRL1 ;LCD左半屏数据写
LCALL LCDPRR1 ;LCD右半屏数据写
DJNZ R3,LCDCLEAR2
INC R2
CJNE R2,#08H,LCDCLEAR1 ;LCD显示屏共有8页,循环清零,直至结束
MOV LCDCMD,#3FH ;开显示设置, 3F-开显示, 3E-关显示
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
MOV LCDCMD,#11000000B;设显示起始行为LCD屏上的第一行
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
RET
;********************************
;LCD屏上滚程序
;********************************
LCDSCRN_UP:
MOV R2,#0C0H ;置LCD屏显示起始行为0
LCDSCRN_UP1:
MOV LCDCMD,R2
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL DELAY ;延时
INC R2
CJNE R2,#0FFH,LCDSCRN_UP1
SJMP LCDSCRN_UP
;********************************
;LCD屏下滚程序
;********************************
LCDSCRN_DOWN:
MOV R2,#03FH ;置LCD屏显示起始行为3FH
LCDSCRN_DOWN1:
MOV A,#0C0H
ORL A,R2
MOV LCDCMD,A
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
LCALL DELAY ;延时
DJNZ R2,LCDSCRN_DOWN1
SJMP LCDSCRN_DOWN
;===================================================
; LCD显示驱动子程序(扩展)
; 2001/12/16
;===================================================
;********************************
;英文ASCII字符写入子程序
;********************************
LCDASCIIWR:
MOV DPTR,#ASCBMAP ;确定字符字模块首地址
MOV A,LCDCHR ;取代码
MOV B,#8 ;字模块宽度为8个字节
MUL AB ;代码×8
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码×8
MOV A,B
ADDC A,DPH
MOV DPH,A
MOV LCDCHR,#0 ;借用为间址寄存器
MOV LCDCNT,#8 ;8×8点阵,字符占用8个字节
MOV A,LCDXPG ;读页地址值寄存器
ANL A,#07H ;计算页地址
ORL A,#0B8H ;计算LCD页地址指令代码
MOV LCDCMD,A
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
MOV A,LCDCOL ;取列地址
CLR C
SUBB A,#40H ;列地址减64,判断是LCD哪个区域
JC LCDASCIIWR_1 ;<64, 为LCD左半屏
MOV LCDCOL,A ;否则,为LCD右半屏
MOV A,LCDXPG
SETB ACC.7 ;设置区域标志位
MOV LCDXPG,A ;0为左半屏,1为右半屏
LCDASCIIWR_1:
MOV LCDCMD,LCDCOL ;取列地址值
ORL LCDCMD,#40H ;计算LCD列地址指令
MOV A,LCDXPG ;判断应设置哪个控制器
JNB ACC.7,LCDASCIIWR_2
LCALL LCDPRR0 ;标志为1,LCD右半屏指令写
SJMP LCDASCIIWR_3
LCDASCIIWR_2:
LCALL LCDPRL0 ;标志为0,LCD左半屏指令写
LCDASCIIWR_3:
MOV A,LCDCHR ;取间址寄存器值
MOVC A,@A+DPTR ;取字符字模数据
MOV LCDDAT,A ;写数据
MOV A,LCDXPG ;判区域标志
JNB ACC.7,LCDASCIIWR_4 ;判区域标志以确定对哪个控制器数据写
LCALL LCDPRR1 ;标志为1,LCD右半屏数据写
LJMP LCDASCIIWR_5
LCDASCIIWR_4:
LCALL LCDPRL1 ;标志为0,LCD左半屏数据写
LCDASCIIWR_5:
INC LCDCHR ;间址加1
INC LCDCOL ;列地址加1
MOV A,LCDCOL ;判列地址是否超出区域范围
CJNE A,#40H,LCDASCIIWR_6 ;未超出64列,继续循环
MOV A,LCDXPG ;超出64列,判断在LCD哪个区域
JB ACC.7,LCDASCIIWR_6 ;在LCD右半屏,退出
SETB ACC.7 ;在LCD左半屏,设将转为右半屏
MOV LCDXPG,A
MOV LCDCOL,#00H
MOV LCDCMD,#40H ;设置LCD右半屏启始列地址为0
LCALL LCDPRR0 ;LCD右半屏指令写
LCDASCIIWR_6:
DJNZ LCDCNT,LCDASCIIWR_3
RET
;********************************
;中文ASC字符写入子程序
;8X16
;********************************
LCDCHNASCWR:
MOV A,LCDCHR ;取代码
MOV B,#16 ;!!!字模块宽度为32个字节
MUL AB ;代码×16
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码×16
MOV A,B
ADDC A,DPH
MOV DPH,A
PUSH LCDCOL ;由于显示一个汉字要跨越两页,必须两次调用LCDCHNWR_1,
PUSH LCDCOL ;因此用PUSH/POP方法保存列地址LCDCOL的值
MOV LCDCHR,#00H ;代码寄存器借用为间址寄存器
LCDCHNASCWR_1:
MOV LCDCNT,#8 ;!!!计数器设置为8
MOV A,LCDXPG ;读页地址寄存器
ANL A,#07H
ORL A,#0B8H ;计算页地址
MOV LCDCMD,A ;设置页地址
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
POP LCDCOL ;取列地址值,与前面的两个连续的PUSH相对应
MOV A,LCDCOL ;读列地址
CLR C
SUBB A,#40H ;列地址减64
JC LCDCHNASCWR_2 ;<64, 为LCD左半屏显示
MOV LCDCOL,A ;否则,为LCD右半屏显示
MOV A,LCDXPG
SETB ACC.7 ;设置区域标志位, 0为左半屏, 1为右半屏
MOV LCDXPG,A
LCDCHNASCWR_2:
MOV LCDCMD,LCDCOL ;取列地址值
ORL LCDCMD,#40H ;计算列地址
MOV A,LCDXPG
JNB ACC.7,LCDCHNASCWR_3 ;判断区域标志
LCALL LCDPRR0 ;为1,LCD右半屏指令写
LJMP LCDCHNASCWR_4
LCDCHNASCWR_3:
LCALL LCDPRL0 ;为0,LCD左半屏指令写
LCDCHNASCWR_4:
MOV A,LCDCHR ;取间址寄存器值
MOVC A,@A+DPTR ;取字符字模数据
MOV LCDDAT,A ;写数据
MOV A,LCDXPG
JNB ACC.7,LCDCHNASCWR_5 ;判断区域标志
LCALL LCDPRR1 ;为1,LCD右半屏数据写
LJMP LCDCHNASCWR_6
LCDCHNASCWR_5:
LCALL LCDPRL1 ;为0,LCD左半屏数据写
LCDCHNASCWR_6:
INC LCDCHR ;间址加1
INC LCDCOL ;列地址加1
MOV A,LCDCOL
CJNE A,#40H,LCDCHNASCWR_7 ;判断列地址是否超出64列
MOV LCDCOL,#00H ;超出64列,LCDCOL清零
MOV A,LCDXPG
JB ACC.7,LCDCHNASCWR_7 ;判断是否为右半屏,是,则继续下一页显示
SETB ACC.7 ;为左半屏,则设将转为右半屏显示
MOV LCDXPG,A
MOV LCDCMD,#40H ;设置右半屏列地址为0
LCALL LCDPRR0 ;LCD右半屏指令写
LCDCHNASCWR_7:
DJNZ LCDCNT,LCDCHNASCWR_4 ;继续本页显示循环
MOV A,LCDXPG ;读页地址寄存器
JB ACC.6,LCDCHNASCWR_8 ;判断一个汉字写完标志,D6=1完成退出
INC A ;否则,页地址加1
SETB ACC.6 ;设置完成位D6=1
CLR ACC.7 ;清区域标志
MOV LCDXPG,A
MOV LCDCHR,#8 ;!!!间址寄存器设置为8
LJMP LCDCHNASCWR_1 ;大循环
LCDCHNASCWR_8:
RET
;********************************
;中文字符写入子程序
;16X16
;********************************
LCDCHNWR:
MOV DPTR,#CHINESEBMAP;确定字符字模块首地址
LCDCHNWR0:
MOV A,LCDCHR ;取代码
MOV B,#32 ;字模块宽度为32个字节
MUL AB ;代码×32
ADD A,DPL ;字符字模块首地址
MOV DPL,A ;=字模库首地址+代码×32
MOV A,B
ADDC A,DPH
MOV DPH,A
PUSH LCDCOL ;由于显示一个汉字要跨越两页,必须两次调用LCDCHNWR_1,
PUSH LCDCOL ;因此用PUSH/POP方法保存列地址LCDCOL的值
MOV LCDCHR,#00H ;代码寄存器借用为间址寄存器
LCDCHNWR_1:
MOV LCDCNT,#10H ;计数器设置为16
MOV A,LCDXPG ;读页地址寄存器
ANL A,#07H
ORL A,#0B8H ;计算页地址
MOV LCDCMD,A ;设置页地址
LCALL LCDPRL0 ;LCD左半屏指令写
LCALL LCDPRR0 ;LCD右半屏指令写
POP LCDCOL ;取列地址值,与前面的两个连续的PUSH相对应
MOV A,LCDCOL ;读列地址
CLR C
SUBB A,#40H ;列地址减64
JC LCDCHNWR_2 ;<64, 为LCD左半屏显示
MOV LCDCOL,A ;否则,为LCD右半屏显示
MOV A,LCDXPG
SETB ACC.7 ;设置区域标志位, 0为左半屏, 1为右半屏
MOV LCDXPG,A
LCDCHNWR_2:
MOV LCDCMD,LCDCOL ;取列地址值
ORL LCDCMD,#40H ;计算列地址
MOV A,LCDXPG
JNB ACC.7,LCDCHNWR_3 ;判断区域标志
LCALL LCDPRR0 ;为1,LCD右半屏指令写
LJMP LCDCHNWR_4
LCDCHNWR_3:
LCALL LCDPRL0 ;为0,LCD左半屏指令写
LCDCHNWR_4:
MOV A,LCDCHR ;取间址寄存器值
MOVC A,@A+DPTR ;取字符字模数据
MOV LCDDAT,A ;写数据
MOV A,LCDXPG
JNB ACC.7,LCDCHNWR_5 ;判断区域标志
LCALL LCDPRR1 ;为1,LCD右半屏数据写
LJMP LCDCHNWR_6
LCDCHNWR_5:
LCALL LCDPRL1 ;为0,LCD左半屏数据写
LCDCHNWR_6:
INC LCDCHR ;间址加1
INC LCDCOL ;列地址加1
MOV A,LCDCOL
CJNE A,#40H,LCDCHNWR_7 ;判断列地址是否超出64列
MOV LCDCOL,#00H ;超出64列,LCDCOL清零
MOV A,LCDXPG
JB ACC.7,LCDCHNWR_7 ;判断是否为右半屏,是,则继续下一页显示
SETB ACC.7 ;为左半屏,则设将转为右半屏显示
MOV LCDXPG,A
MOV LCDCMD,#40H ;设置右半屏列地址为0
LCALL LCDPRR0 ;LCD右半屏指令写
LCDCHNWR_7:
DJNZ LCDCNT,LCDCHNWR_4 ;继续本页显示循环
MOV A,LCDXPG ;读页地址寄存器
JB ACC.6,LCDCHNWR_8 ;判断一个汉字写完标志,D6=1完成退出
INC A ;否则,页地址加1
SETB ACC.6 ;设置完成位D6=1
CLR ACC.7 ;清区域标志
MOV LCDXPG,A
MOV LCDCHR,#10H ;间址寄存器设置为16
LJMP LCDCHNWR_1 ;大循环
LCDCHNWR_8:
RET
;===================================================
; LCD屏幕显示子程序
; 2001/12/16
;===================================================
;********************************
; 英文ASCII字符表显示程序
;********************************
LCDASCIIDISP:
MOV R2,#0 ;从字符编码0开始,显示英文ASCII字符表
MOV LCDXPG,#0 ;8×8点阵字体,从第0页开始
LCDASCIIDISP0:
MOV R3,#10H ;每列16个英文ASCII字符
MOV LCDCOL,#0 ;列地址为0
LCDASCIIDISP1:
MOV LCDCHR,R2 ;字符代码
LCALL LCDASCIIWR ;英文ASCII字符写入LCD显示器
INC R2 ;下一个字符
DJNZ R3,LCDASCIIDISP1 ;一行是否显示完毕
MOV A,LCDXPG ;下一页
ANL A,#0FH
INC A
MOV LCDXPG,A
CJNE A,#6,LCDASCIIDISP0 ;6行英文ASCII字符是否显示完毕
RET ;返回
;********************************
; 中文ASC字符演示程序
;
; 注:中文字符建议在偶数页上显示
;********************************
LCDCHNASCDEMO:
MOV R2,#0 ;字符编码
MOV LCDCOL,#0 ;第0列
LCDCHNASCDEMO_1:
MOV DPTR,#ASCFIXEDBMAP ;确定字符字模块首地址
MOV LCDXPG,#0 ;第0页
MOV LCDCHR,R2 ;汉字代码:0
LCALL LCDCHNASCWR ;调用LCD中文ASC写程序
INC R2
MOV A,R2
RL A
RL A
RL A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -