📄 10000clock.asm
字号:
MOV P0,A ;写入毫秒十位
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P0,#0C6H ;写入显示起始地址(第2行第7个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV DPTR,#NUM_TAB
MOV A,S_SEC1
MOVC A,@A+DPTR
MOV P0,A ;写入秒十位
LCALL WR_DATA ;调用LCD数据写入子程序
MOV DPTR,#NUM_TAB
MOV A,S_SEC0
MOVC A,@A+DPTR
MOV P0,A ;写入秒个位
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P0,#0C3H ;写入显示起始地址(第2行第4个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV DPTR,#NUM_TAB
MOV A,S_MIN1
MOVC A,@A+DPTR
MOV P0,A ;写入分十位
LCALL WR_DATA ;调用LCD数据写入子程序
MOV DPTR,#NUM_TAB
MOV A,S_MIN0
MOVC A,@A+DPTR
MOV P0,A ;写入分个位
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P0,#0C0H ;写入显示起始地址(第2行第1个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV DPTR,#NUM_TAB
MOV A,S_HOU1
MOVC A,@A+DPTR
MOV P0,A ;写入时十位
LCALL WR_DATA ;调用LCD数据写入子程序
MOV DPTR,#NUM_TAB
MOV A,S_HOU0
MOVC A,@A+DPTR
MOV P0,A ;写入时个位
LCALL WR_DATA ;调用LCD数据写入子程序
RET
PATTERN:
MOV A,P_COUNT
E_PATTERN:
CJNE A,#0,E_PATTERN1
MOV P0,#0CCH ;写入显示起始地址(第2行第13个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV P0,#11111111B ;写入图案
LCALL WR_DATA ;调用LCD数据写入子程序
INC P_COUNT
LJMP P_EXIT
E_PATTERN1:
CJNE A,#1,E_PATTERN2
MOV P0,#0CDH ;写入显示起始地址(第2行第14个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV P0,#11111111B ;写入图案
LCALL WR_DATA ;调用LCD数据写入子程序
INC P_COUNT
LJMP P_EXIT
E_PATTERN2:
CJNE A,#2,E_PATTERN3
MOV P0,#0CEH ;写入显示起始地址(第2行第15个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV P0,#11111111B ;写入图案
LCALL WR_DATA ;调用LCD数据写入子程序
INC P_COUNT
LJMP P_EXIT
E_PATTERN3:
CJNE A,#3,E_PATTERN4
MOV P0,#0CFH ;写入显示起始地址(第2行第16个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV P0,#11111111B ;写入图案
LCALL WR_DATA ;调用LCD数据写入子程序
INC P_COUNT
SJMP P_EXIT
E_PATTERN4:
MOV P0,#0CCH ;写入显示起始地址(第2行第13个位置)
LCALL ENABLE_LCD ;调用写入命令子程序
MOV P0,#00100000B ;写入空值
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P0,#00100000B ;写入空值
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P0,#00100000B ;写入空值
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P0,#00100000B ;写入空值
LCALL WR_DATA ;调用LCD数据写入子程序
MOV P_COUNT,#0
P_EXIT:
RET
;日历初始化
LOAD8563:
MOV R0, #XmtDat ;发送缓冲区首地址送R0
MOV @R0, #00H ;秒初值
INC R0
MOV @R0, #59H ;分初值
INC R0
MOV @R0, #23H ;时初值
INC R0
MOV @R0, #28H ;日初值
INC R0
MOV @R0, #01H ;星期初值
INC R0
MOV @R0, #02H ;世纪及月初值(21世纪)
INC R0
MOV @R0, #08H ;年初值
MOV ByteCnt, #07H ;传送7字节
MOV SlvAdr, #0A2H ;PCF8563日历时钟器件地址为A2H
MOV SubAdr, #02H ;从日历时钟的02H单元开始
LCALL SendData ;调用写EEPROM多字节写入过程,将发送缓冲区内的信息写入
;PCF8563日历芯片内日历时间单元
RET
;闹钟初始化(闹钟无效)
LOADCLOCK:
MOV R0,#XmtDat ;发送缓冲区首地址送R0
MOV @R0,#80H ;闹钟分初值
INC R0
MOV @R0,#80H ;闹钟时初值
INC R0
MOV @R0,#80H ;闹钟时初值
INC R0
MOV @R0,#80H ;闹钟星期初值
INC R0
MOV ByteCnt,#04H ;传送4字节
MOV SlvAdr,#0A2H ;PCF8563日历时钟器件地址为A2H
MOV SubAdr,#09H ;从日历时钟的09H单元开始
LCALL SendData ;调用写EEPROM多字节写入过程,将发送缓冲区内的信息写入
;PCF8563日历芯片内日历时间单元
MOV R0,#XmtDat ;发送缓冲区首地址送R0
MOV @R0,#00000000B ;初始化状态控制寄存器2
MOV ByteCnt,#01H ;传送1字节
MOV SlvAdr,#0A2H ;PCF8563日历时钟器件地址为A2H
MOV SubAdr,#01H ;从日历时钟的09H单元开始
LCALL SendData ;调用写EEPROM多字节写入过程,将发送缓冲区内的信息写入
;PCF8563日历芯片内日历时间单元
RET
;压缩式BCD转非压缩式BCD,且把接收缓冲区的内容放入显示缓冲区
LCDBUF:
MOV A,RcvDat
ANL A,#7FH ;屏蔽数据无关位
ANL A,#0FH
MOV SEC0,A ;秒低四位送显示缓冲区
MOV A,Rcvdat
ANL A,#7FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV SEC1,A ;秒高四位送显示缓冲区
MOV A,RcvDat+1
ANL A,#7FH ;屏蔽数据无关位
ANL A,#0FH
MOV MIN0,A ;分低四位送显示缓冲区
MOV A,Rcvdat+1
ANL A,#7FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV MIN1,A ;分高四位送显示缓冲区
MOV A,RcvDat+2
ANL A,#3FH ;屏蔽数据无关位
ANL A,#0FH
MOV HOU0,A ;时低四位送显示缓冲区
MOV A,Rcvdat+2
ANL A,#3FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV HOU1,A ;时高四位送显示缓冲区
MOV A,RcvDat+3
ANL A,#3FH ;屏蔽数据无关位
ANL A,#0FH
MOV DAY0,A ;日低四位送显示缓冲区
MOV A,Rcvdat+3
ANL A,#3FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV DAY1,A ;日高四位送显示缓冲区
MOV A,RcvDat+4
ANL A,#07H ;屏蔽数据无关位
MOV WEK,A ;星期送显示缓冲区
MOV A,RcvDat+5
ANL A,#1FH ;屏蔽数据无关位
ANL A,#0FH
MOV MON0,A ;月低四位送显示缓冲区
MOV A,Rcvdat+5
ANL A,#1FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV MON1,A ;月高四位送显示缓冲区
MOV A,RcvDat+6
ANL A,#0FH
MOV YER0,A ;年低四位送显示缓冲区
MOV A,Rcvdat+6
SWAP A
ANL A,#0FH
MOV YER1,A ;年高四位送显示缓冲区
RET
;把时钟的压缩式BCD转非压缩式BCD,且把接收缓冲区的内容放入闹钟显示缓冲区
C_LCDBUF:
MOV A,RcvDat
ANL A,#7FH ;屏蔽数据无关位
ANL A,#0FH
MOV C_MIN0,A ;分低四位送显示缓冲区
MOV A,Rcvdat
ANL A,#7FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV C_MIN1,A ;分高四位送显示缓冲区
MOV A,RcvDat+1
ANL A,#3FH ;屏蔽数据无关位
ANL A,#0FH
MOV C_HOU0,A ;时低四位送显示缓冲区
MOV A,Rcvdat+1
ANL A,#3FH ;屏蔽数据无关位
SWAP A
ANL A,#0FH
MOV C_HOU1,A ;时高四位送显示缓冲区
MOV A,RcvDat+3
ANL A,#07H ;屏蔽数据无关位
MOV C_WEK,A ;星期送显示缓冲区
RET
;LCD写入控制命令的子程序
ENABLE_LCD:
CLR RS
CLR RW
CLR E ;执行指令
LCALL DELAY_LCD
SETB E
RET
;LCD写数据子程序
WR_DATA:
SETB RS
CLR RW
CLR E
LCALL DELAY_LCD
SETB E
RET
;判断液晶显示器是否忙的子程序
DELAY_LCD:
MOV P0,#0FFH
CLR RS
SETB RW
CLR E ;执行指令
NOP
SETB E
JB P0.7,DELAY_LCD ;如果P0.7为高电平表示忙就循环等待
RET
;------------------------串行EEPROM、日历时钟读写子程序------------
; 发送数据子程序
;名称:SendData
;描述:发送ByteCnt 个字节给从器件,如I2C总线串行EEPROM
;从器件地址在SlvAdr 中,存储单元地址在SubAdr 中
;所发送数据的字节数在ByteCnt中,发送的数据在XmtDat 缓冲区中
;成功发送数据,FHbit标志为0; 当FHbit为1时表示从器件无应答或损坏
;*************************************************************************************************
PROC SendData
SendData:
PUSH PSW
PUSH ACC
CLR RS0 ;使用2区(10)
SETB RS1
LCALL START ;启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
LCALL SentByte ;发送从器件总线地址
JB FHBIT,SenReturn ;从器件不应答返回
;--------对于存储器单元地址为16位的EEPROM存储器
; MOV R0, #SubAdr+1
; MOV A, @R0 ;存储单元地址高8位送累加器Acc,即先发送高8位地址A15~A8
; LCALL SentByte ;发存储单元地址
; JB FHbit,SenReturn ;从器件不应答返回
;--------对于存储单元地址为8位时,仅保留如下内容即可
MOV R0, #SubAdr
MOV A, @R0 ;存储单元地址低8位送累加器Acc,再发送低8位地址A7~A0
LCALL SentByte ;发存储单元地址
JB FHbit,SenReturn ;从器件不应答返回
MOV R0,#XmtDat ;取发送数据缓冲区首址
SentNext:
MOV A,@R0
LCALL SentByte ;发送一次数据
JB FHbit,SenReturn ;出错返回
INC R0 ;取下一个数据
DJNZ ByteCnt,SentNext ;重复操作直到发送完最后一个数据
LCALL STOP ;停止IC总线操作
;********查询方式检测内部写入周期是否已完成**********
LOOP:
NOP ;两次操作之间的延迟
NOP
NOP
NOP
LCALL START ;启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
LCALL SentByte ;发送从器件总线地址
JB FHBIT,LOOP ;从器件不应答返回
LCALL STOP ;停止IC总线操作
;***********************************************************
SenReturn:
POP ACC
POP PSW
RET
END
;************************************************************************************************
; 接收数据子程序
;名称:ReceData
;描述:自从器件(如I2C总线串行EEPROM)读出ByteCnt个字节数据信息
;从器件地址在SlvAdr 中,待读出的存储单元地址在SubAdr 中
;所发送数据的字节数在ByteCnt中,接收的数据放在RevDat 缓冲区中
;成功接收数据,FHbit标志为0; 当FHbit为1时表示从器件无应答或损坏
;*************************************************************************************************
PROC ReceData
ReceData:
PUSH PSW
PUSH ACC
CLR RS0 ;使用2区(10)
SETB RS1
LCALL START ;启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
LCALL SentByte ;发送从器件总线地址
JB FHBIT,RevReturn ;从器件不应答返回
;-----------对于存储器单元地址为16位的EEPROM存储器
; MOV R0, #SubAdr+1
; MOV A, @R0 ;存储单元地址高8位送累加器Acc,即先发送高8位地址A15~A8
; LCALL SentByte ;发存储单元地址
; JB FHbit,RevReturn ;从器件不应答返回
;-----------对于存储单元地址为8位时,仅保留如下内容即可
MOV R0, #SubAdr
MOV A, @R0 ;存储单元地址低8位送累加器Acc,再发送低8位地址A7~A0
LCALL SentByte ;发存储单元地址(只完成存储单元定位功能
;既不给数据,也没有给停止信号,因为停止总线后写操作
;才被执行,故称为“哑写”
JB FHbit,RevReturn ;从器件不应答返回
;*****完成“哑写”过程,将从器件地址计数器定位到将要读出的存储单元****
LCALL START ;重新启动IC总线
MOV A ,SlvAdr ;将从器件地址放累加器A中
SETB ACC.0 ;将从器件地址改为读状态
LCALL SentByte ;发送从器件总线地址
JB FHBIT,RevReturn ;从器件不应答返回
;****准备接收数据*****************************************
CLR NOACK ;清除非应答标志
MOV R0,#Rcvdat ;取接收数据缓冲区首地址
DJNZ ByteCnt,Next ;继续接受下一字节
SJMP ReceLast ;减1为0,说明仅接收一个字节数据(也是最后一个字节)。
Next:
LCALL ReceByte ;接收一个字节数据
MOV @R0,A ;把接收到的数据放入接收缓冲区内。
INC R0 ;将指针移到缓冲区下一存储单元
DJNZ ByteCnt,Next ;重复进行直到最后一个字节
ReceLast:
SETB NOACK ;已接收了最后一个字节,主器件无需应答
LCALL ReceByte ;接收一个字节数据
MOV @R0,A ;把接收到的数据放入接收缓冲区内
LCALL STOP ;停止总线操作
RevReturn:
POP ACC
POP PSW
RET
END
;字节发送(写入)子程序
;用于将从器件地址字节或数据字节发送到从器件(串行EEPROM)中
;入口参数:发送字节信息存放在寄存器A中
;出口参数:返回标志存放在Fhbit(位地址)中
;0—成功;1—失败(从器件不应答,发送失败)
PROC SentByte
SentByte:
CLR FHbit ;清除失败标志。
MOV R7,#08H ;初始化发送数据位长度R7
SentLOOP:
CLR SCL ;主器件输出时,在SCL下降沿后立即输出数据,以便接收
;方(从器件)接收
RLC A ;将Acc.7位移到进位标志C中,即先写高位。
MOV SDA, C ;将数据位发送到SDA引脚。由于写入时用SCL上升沿同
;步,因此要先送数据后将SCL置高电平。
NOP ;SCL同步时钟低电平时间大于4.7uS
NOP ;根据CPU时钟频率可以插入0~6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -