1602液晶初始化程序汇编.docx
《1602液晶初始化程序汇编.docx》由会员分享,可在线阅读,更多相关《1602液晶初始化程序汇编.docx(22页珍藏版)》请在冰点文库上搜索。
1602液晶初始化程序汇编
〔原创〕1602液晶初始化程序(2007-12-2218:
10:
40)
标签:
1602液晶 it/科技 汇编语言
液晶初始化,显示数字,按秒计数
RS EQU P2.0
RW EQU P2.1
E EQU P2.2
IN_0EQUP0
SECLEQU 40H ;秒低位
SECHEQU 41H ;秒高位
MH1 EQU42H ;冒号
MINLEQU 43H ;分低位
MINHEQU 44H ;分高位
MH2 EQU45H ;冒号
HOURLEQU46H ;时低位
HOURHEQU47H ;时高位
;*********************************
ORG0000H
AJMPSTART
ORG000BH
AJMPINTT_0
START:
MOVSP,#70H
MOVR2,#20
ACALLINIT_LCD ;初始化液晶
MOVR5,#00H
MOV IN_0,#84H ;写入显示起始地址(第一行第五个位置
ACALLENABLE
MOVTH0,#3fH ;50MS
MOVTL0,#0b0H
MOVTMOD,#01H
ACALLSJCZ
START1:
SETBEA
SETBET0
SETBTR0
LCALLWDATA
AJMPSTART1
;*****时间初值*******
SJCZ:
MOV40H,#8 ;显示初值是 08:
08:
08
MOV41H,#0
MOV42H,#10
MOV43H,#8
MOV44H,#0
MOV45H,#10
MOV46H,#8
MOV47H,#0
RET
;****T0定时器中断****
INTT_0:
PUSHACC
MOV TL0,#0b0H ;送定时初值
MOV TH0,#3fH
DJNZR2,TT
MOVR2,#20
INC SECL ;秒记数,到60S就清0
MOV A,SECL
CJNE A,#0AH,TT
INC SECH
MOV SECL,#0
MOV A,SECH
CJNE A,#06H,TT
MOVSECH,#0
INC MINL ;分记数,到60分请0
MOVA,MINL
CJNEA,#0AH,TT
MOVMINL,#0
INCMINH
MOVA,MINH
CJNEA,#06H,TT
MOVMINH,#0
INCHOURL ;时记数,到24时清0
MOVA,HOURL
CJNEA,#04H,TT2
MOVA,HOURH
CJNEA,#02H,TT1
MOVHOURL,#0
MOVHOURH,#0
AJMPTT
TT2:
CJNEA,#0AH,TT
MOVHOURL,#0
INCHOURH
AJMPTT
TT1:
MOVA,HOURL
CJNEA,#0AH,TT
MOVHOURL,#0
INCHOURH
AJMPTT
TT:
POPACC
RETI
;*******液晶初始化*****
INIT_LCD:
CALLDELAYL ;延时20ms,等待LCD完成电源的启动
MOV IN_0,#01H ;清屏并光标复位
ACALLENABLE
MOV IN_0,#38H ;设置显示模式:
8位2行5x7点阵
ACALLENABLE
MOV IN_0,#0FH ;显示器开、光标开、光标允许闪烁
ACALLENABLE
MOV IN_0,#06H ;文字不动,光标自动右移
ACALLENABLE
MOV IN_0,#0C0H ;写入显示起始地址(第二行第一个位置)
ACALLENABLE
RET
;******写数据程序***
WDATA:
MOV IN_0,#84H ;写入显示起始地址(第一行第五个位置
ACALLENABLE
MOVR1,#8
MOVR0,#47H
WDATA1:
MOVA,@R0
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOV IN_0,A ;写入数据
SETBRS
CLR RW
CLR E
ACALLCHECKBUSY
SETBE ;忙检测
DECR0
DJNZR1,WDATA1
MOVR1,#8
RET
;*******显示字母表********
TABLE:
DB30H,31H,32H,33H,34H,35H ;012345
DB36H,37H,38H,39H,3AH,80H,2EH ;6789:
空格.
;*********写指令*****
ENABLE:
CLR RS ;写入控制命令的子程序
CLR RW
CLR E
ACALLCHECKBUSY
SETBE
RET
;*******程序忙检测***
CHECKBUSY:
MOV IN_0,#0FFH ;判断液晶显示器是否忙的子程序
CLR RS
SETBRW
CLR E
NOP
SETBE
JB P0.7,CHECKBUSY ;如果P1.7为高电平表示忙就循环等待
RET
;******延时程序****
DELAY:
MOVR6,#50
DEL:
MOVR7,#48
DJNZR7,$
DJNZR6,DEL
RET
DELAYL:
MOV R7,#100 ;长延时20ms
D1:
MOV R6,#98
DJNZR6,$
DJNZR7,D1
RET
END
51单片机的1602没做过,只做过其他的控制。
做过PIC,不过写51的也不难,熟悉一下指令集就行了,思路都是一样的,大体上,单片机的任务就是把AD结果读出来放到一个寄存器中,然后向1602中送数,时序是这样:
写地址使能开——送地址数——写地址使能关——写数据使能开——送AD结果()也就是数据)——写数据使能关,破折号处需要加3-5毫秒的延时。
具体1602的寄存器地址和硬件的接线形式在它的PDF上有,这个你得自己去查查,因为1602有好几种,地址有所差异。
需要的话我看改天给你调个程序上来。
补充:
查表可以,用间接寻址还是很方便的。
以前的思路也许可以给你参考一下,我当时的做法是把转换结果按权值做除法,也就是比如254,先除以100得到2,余数送临时寄存器,再用余数除以10,得到5,还有余数4,然后将这三个数分别送进1602就行了。
毕竟1602只是个字符屏,我觉得这种做法可取。
这种做法做过12864显示的三相表,用于显示各种电力参数。
不过遗憾的是PIC的中档单片机没有乘法器,所以连乘除法指令都没有,用累加的办法非常慢,我用倍加的办法写了函数。
好在它内置AD,就当时的应用来讲,精度还是可以满足设计要求的。
顺便请教你的电压基准一般用什么芯片?
我一直没找到合适的,好的都太贵也没必要。
补充:
用除法没问题,我就这么做的,当时用的是PIC16F877A,它没有除法,要是用51就方便了,一个DIV就解决了而且还快。
补充:
好的。
稍等一会。
我写写。
补充:
;P1口为数据
;P2.0为RS
;P2.1为RW
;P2.2为E
;P0为AD转换结果输入
;P3.1为AD使能位,假设高电平有效
;P3.2为AD等待,假设低电平为等待结束
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
res100equ0x20;百位结果
res10equ0x21;十位结果
res1equ0x22;个位结果
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org0x00
nop
nop
ajmpmain
;;;;;;;;;;;;;;主程序;;;;;;;;;;;;;;;;
main:
lcallinitial
mainloop:
lcallADconvert
movB,#0x64
divAB
lcalldata_convert
movres100,A;得到百位
movA,B
movB,#0x0a
divAB
lcalldata_convert
movres10,A;得到十位
movA,B
lcalldata_convert
movres1,A;得到个位
lcalldata_w;写电压数值
lcalldelay1s
ajmpmainloop
;;;;;;;;;;;;;数据转换;;;;;;;;;;;;;;;
data_convert:
addA,#0x30
ret
;;;;;;;;;;;;;;写数据;;;;;;;;;;;;;;;;
data_w:
movP1,#0x8a
lcallenable_w
movA,res100
movP1,A
lcallenable_data;写百位数
movP1,#0x8b
lcallenable_w
movA,res10
movP1,A
lcallenable_data;写十位数
movP1,#0x8c
lcallenable_w
movA,res1
movP1,A
lcallenable_data;写个位数
ret
;;;;;;;;;;;;;;AD转换;;;;;;;;;;;;;;;;
ADconvert:
setbP3.1
wait:
movA,P3;使能AD转换
anlA,#00000100b;等待AD转换结束
jnzwait;否则继续等待
movA,P0;存放转换结果
ret
;;;;;;;;;;;;;;初始化;;;;;;;;;;;;;;;;
initial:
movP0,#00000000b
nop
movP1,#00000000b
nop
movP2,#00000000b
nop
movP3,#00000000b
nop
lcallinitial_lcd
ret
;;;;;;;;;;;;液晶初始化;;;;;;;;;;;;;;
;第一行显示Voltage:
V
;第二行显示Current:
A
initial_lcd:
lcalldelay15ms
movP1,#0x38
lcalldelay5ms
movP1,#0x38
lcalldelay5ms
movP1,#0x38
lcalldelay15ms
movP1,#0x38;显示模式设置为16字*2行
lcallenable_w
movP1,#0x0c;不显示光标
lcallenable_w
movP1,#0x06;显示方向正向且屏不移动
lcallenable_w
movP1,#0x01;清屏
lcallenable_w
movP1,#0x82;第一行第三字
lcallenable_w
movP1,#0x56
lcallenable_data;V
movP1,#0x83
lcallenable_w
movP1,#0x6f
lcallenable_data;o
movP1,#0x84
lcallenable_w
movP1,#0x6c
lcallenable_data;l
movP1,#0x85
lcallenable_w
movP1,#0x74
lcallenable_data;t
movP1,#0x86
lcallenable_w
movP1,#0x61
lcallenable_data;a
movP1,#0x87
lcallenable_w
movP1,#0x67
lcallenable_data;g
movP1,#0x88
lcallenable_w
movP1,#0x65
lcallenable_data;e
movP1,#0x89
lcallenable_w
movP1,#0x3a
lcallenable_data;:
movP1,#0x8d
lcallenable_w
movP1,#0x56
lcallenable_data;V
movP1,#0xc2;第二行第三字
lcallenable_w
movP1,#0x43
lcallenable_data;C
movP1,#0xc3
lcallenable_w
movP1,#0x75
lcallenable_data;u
movP1,#0xc4
lcallenable_w
movP1,#0x72
lcallenable_data;r
movP1,#0xc5
lcallenable_w
movP1,#0x72
lcallenable_data;r
movP1,#0xc6
lcallenable_w
movP1,#0x65
lcallenable_data;e
movP1,#0xc7
lcallenable_w
movP1,#0x6e
lcallenable_data;n
movP1,#0xc8
lcallenable_w
movP1,#0x74
lcallenable_data;t
movP1,#0xc9
lcallenable_w
movP1,#0x3a
lcallenable_data;:
movP1,#0xcd
lcallenable_w
movP1,#0x41
lcallenable_data;A
ret
;;;;;;;;;;;;写地址使能;;;;;;;;;;;;;;
enable_w:
movP2,#00000000b
lcalljudgement
setbP2.2
ret
;;;;;;;;;;;;写数据使能;;;;;;;;;;;;;;
enable_data:
setbP2.0
clrP2.1
clrP2.2
lcalljudgement
setbP2.2
ret
;;;;;;;;;;;;;;;判忙;;;;;;;;;;;;;;;;;
judgement:
movP1,#0xff
clrP2.0
setbP2.1
clrP2.2
nop
nop
nop
setbP2.2
jbP1.7,judgement
ret
;;;;;;;;;;;;;延时5毫秒;;;;;;;;;;;;;;
delay5ms:
movR6,#0x32
delaymark:
movR7,#0x28
djnzR7,$
djnzR6,delaymark
ret
;;;;;;;;;;;;;延时15毫秒;;;;;;;;;;;;;
delay15ms:
movR7,#0x64
delaylongmark:
movR6,#0x3c
djnzR6,$
djnzR7,delaylongmark
ret
;;;;;;;;;;;;;;延时1秒;;;;;;;;;;;;;;;
delay1s:
movR7,#0x64
delaylongmark2:
movR6,#0x3c
djnzR6,$
djnzR7,delaylongmark2
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end
这个程序我编译过了没有问题,不过硬件电路我还没来得及试,现学现卖哈,上班还是有点忙的,让你久等啦。
程序实现的是:
第一行:
Voltage:
V,Voltage前和V后面有两个空格,也就是居中,第二行是:
Current:
A,格式也一样也是居中,不过电流的我没有给你写,因为写起来也一样,送数操作都是一样的无非地址不一样。
另外我没用过ADC0809,所以启动AD转换的思路上我是参照PIC的内部AD转换来的,大体上是这样:
使能AD转换,判断并等待AD转换结束,取转换结果并读入保存。
如果0809只是一路AD,那么你可以再添加一片做双路,这样就可以同时检测电流了。
除法的个十百位结果我做了一下处理,直接在真值上加了30H,这样就可以直接当作数据送入液晶,不必查表,其实那个小小的子程序只有一行,直接写进主循环会更快,毕竟lcall需要两个机器周期。
不过这样看起来层次性好点。
请指教,希望多多交流。
补充:
汗……最后这个延时1S子程序里面的值我忘记改了,当时直接复制的延时15毫秒的,你改改吧,否则理论上刷新会很快。
事实上我估计得再加两层延时才能到秒级。
不好意思哈
单片机的ADC0832数字LCD1602电压表程序
SET_LCD:
CLRLCD_EN
CALLINIT_LCD;初始化LCD
CALLDELAY1
MOVDPTR,#INFO1;指针指到显示信息1
MOVA,#1;显示在第一行
CALLLCD_SHOW
MOVDPTR,#INFO2;指针指到显示信息2
MOVA,#2;显示在第二行
CALLLCD_SHOW
RET
;-----------------------------------------------------
INFO1:
DB"DIGITALVOLTMETER",0;LCD第一行显示信息
INFO2:
DB"VOLTAGE:
V",0;LCD第二行显示信息
;-----------------------------------------------------
;-----------------------------------------------------
;LCD接口初始化
;-----------------------------------------------------
INIT_LCD:
MOVA,#38H;双列显示,字形5*7点阵
CALLWCOM
CALLDELAY1
MOVA,#38H;双列显示,字形5*7点阵
CALLWCOM
CALLDELAY1
MOVA,#38H;双列显示,字形5*7点阵
CALLWCOM
CALLDELAY1
MOVA,#0CH;开显示,关光标,
CALLWCOM
CALLDELAY1
MOVA,#01H;清除LCD显示屏
CALLWCOM
CALLDELAY1
RET
;-------------------------------------------------
DELAY1:
;延时5MS
MOVR6,#25
DEL1:
MOVR7,#100
DJNZR7,$
DJNZR6,DEL1
RET
;==================================================
;在LCD的第一行或第二行显示信息字符
;==================================================
LCD_SHOW:
CJNEA,#1,LINE2;判断是否为第一行
LINE1:
MOVA,#80H;设置LCD的第一行地址
CALLWCOM;写入命令
CALLCLR_LINE;清除该行字符数据
MOVA,#80H;设置LCD的第一行地址
CALLWCOM;写入命令
JMPFILL
LINE2:
MOVA,#0C0H;设置LCD的第二行地址
CALLWCOM;写入命令
CALLCLR_LINE;清除该行字符数据
MOVA,#0C0H;设置LCD的第二行地址
CALLWCOM
FILL: