📄 50451
字号:
cs bit P2.4 ;
si bit P2.2 ;
sck bit P2.3 ;
so bit P2.0 ;
wp bit p2.1 ;
BYTE_ADDR EQU 00H
WREN_INST equ 06H ; 写允许命令字(WREN)
WRDI_INST equ 04H ; 写禁止命令字(WRDI)
WRSR_INST equ 01H ; 写状态寄存器命令字(WRSR)
RDSR_INST equ 05H ; 读状态寄存器命令字(RDSR)
WRITE_INST equ 02H ; 写存储器命令字 (WRITE)
READ_INST equ 03H ; 读存储器命令字 (READ)
PAGE_ADDR equ 1F0H ; 演示页写的存储器启即地址
PAGE_DATA1 equ 22H ; 演示页写的第一个数据
PAGE_DATA2 equ 33H ; 演示页写的第二个数据
PAGE_DATA3 equ 44H ; 演示页写的第三个数据
STATUS_REG equ 00H ; 演示写入的状态寄存器的内容
MAX_POLL equ 99H ; 测试的最大次数
INIT_STATE equ 11H ; 控制端的初始值
BYTE_DATA equ 55H ; 演示单字节写的数据
;***************************************************************************************
KMark bit 00h ;有键被按着
KFirst bit 01h ;第一次
KFunc bit 02h ;代表两种功能
KEnter bit 03h ;代表执行S4键的操作
KS12 bit 04h ;S1 S2两个键被按下
KFunc1 bit 05h
Kcount EQU 21h ;统计次数
Count EQU 22H
COUNTER EQU 23H ;用于显示的计数器
DataAddr EQU 24H ;待读或写的EEPROM单元地址
DataNum Equ 25H ;数值寄存器,放入的是待写的数据
FIRST EQU P2.7 ;第一位数码管的位控制
SECOND EQU P2.6 ;第二位数码管的位控制
DISPBUF EQU 5EH ;5E,5FH是显示缓冲区
TMRVAR EQU 60110 ;65536-5000*12/11.0592 定时器初值5毫秒
ORG 0
JMP START
ORG 0BH
JMP INT_T0
ORG 30H
START: MOV SP,#5FH
call INIT_T0
mov P2,#INIT_STATE ;初始化控制线 (/CS & SO =1, SCK & SI =0)
MOV 20H,#0 ;复位所有标志
CLR A
MOV COUNT,A
MOV KCOUNT,A
MOV COUNTER,A
mov p1,#11111110b ;点亮“读”控制灯
mov a,count
call calc
MOV P2,#INIT_STATE
setb ea
LOOP: jb KS12,main_0
jmp main_1
main_0: mov a,count
call calc
main_1: jb KFunc,main_2 ;如果是第二功能(写)转
mov P1,#11111110B ;否则点亮LED1
mov DataAddr,Count ;将计数值送到地址寄存器中
jmp main_3
main_2: mov p1,#11111101b ;点亮LED2
mov DataNum,Count ;将计数值送入数值寄存器中
main_3:
jb KEnter,main_4 ;如果有回车键,转
jmp loop ;否则回去继续循环
main_4: jb KFunc,main_5 ;如果是第二功能,转
call byte_read ;否则读数据
MOV DataNum,A ;将数据送数值寄存器
mov Count,A ;送到计数器中
call calc ;调用计算显示程序
clr KEnter ;清回车标记
jmp loop ;继续循环
main_5: setb wp ;
lcall wren_cmd ;写允许
call byte_write ;写入
clr KEnter
clr wp
jmp loop
;主程序到此结束
calc:
mov b,#16
div ab
mov dispbuf,a
mov dispbuf+1,b
ret
INIT_T0: ;初始化T0为5毫秒的定时器
MOV TMOD,#01H
MOV TH0,#HIGH(TMRVAR)
MOV TL0,#LOW(TMRVAR)
SETB ET0 ;开T0中断
SETB TR0 ;定时器0开始运行
RET ;返回
;以下是中断程序,实现秒计数和显示及键盘处理
INT_T0: ;定时器T0的中断响应程序
PUSH ACC ;ACC入栈
PUSH PSW ;PSW入栈
MOV TH0,#HIGH(TMRVAR);
MOV TL0,#LOW(TMRVAR)
SETB FIRST
SETB SECOND ;关显示
MOV A,#DISPBUF ;显示缓冲区首地址
ADD A,Counter
MOV R0,A
MOV A,@R0 ;根据计数器的值取相应的显示缓冲区的值
MOV DPTR,#DISPTAB ;字形表首地址
MOVC A,@A+DPTR ;取字形码
MOV P0,A ;将字形码送P0位(段口)
MOV A,Counter ;取计数器的值
JZ DISPFIRST ;如果是0则显示第一位
CLR SECOND ;否则显示第二位
AJMP DISPNEXT
DISPFIRST:
CLR FIRST ;显示第一位
DISPNEXT:
INC Counter ;计数器加1
MOV A,Counter
DEC A ;如果计数器计到2,则让它回0
DEC A
JZ RSTCOUNT
AJMP Key
RSTCOUNT:
MOV Counter,#0 ;计数器的值只能是0或1
Key: ORL P3,#00111100B
mov A,P3
ORL A,#11000011B
CPL A
JZ No_key ;无键按下,返回
JNB KMark,key_1 ;键按下标志有效吗(无效转)?
dec KCount ;键值计数器减1
mov a,KCount
jnz int_exit ;如果是0,退出中断
JNB P3.2,Key_S1 ;S1键按下
JNB P3.3,Key_S2 ;S2键按下
JNB P3.4,Key_S3 ;S3键按下
JNB P3.5,Key_S4 ;S4键搂下
jmp No_Key ;无键按下
Key_1:
mov KCount,#4
SETB KMark
jmp int_exit
Key_S1: inc Count
SETB KS12
jmp key_2
Key_S2: dec Count
SETB KS12
jmp key_2
Key_S3: JB KFunc1,Key_S31
CPL KFunc ;如果KFunc=0,代表第一种功能,KFunc=1,第二种功能
SETB KFunc1
Key_S31:
CLR KS12
jmp Key_2
Key_S4: SETB KEnter ;如果该位是1,则根据KFunc分别执行读或写的操作
CLR KS12
Key_2: JNB KFirst,key_3 ;如果无效,转
mov Kcount,#20
jmp int_exit
Key_3: mov Kcount,#200
setb KFirst
jmp int_exit
No_key: clr KMark
clr KFirst
clr KFunc1
mov KCount,#0
int_exit:
pop PSW
POP ACC
RETI
DISPTAB: DB 28H,7EH,0a4H,64H,72H,61H,21H,7CH,20H,60H,30H,23H,0A9H,26H,0A1H,0B1H,0FFH
;*******************************************************************************************
;名称:WREN_CMD
;描述:写允许
;功能:这段程序发送命令允许写存储器单元和状态寄存器
;调用子程序: outbyt
;输入:没有
;输出:没有
;寄存器使用:A
;*******************************************************************************************
wren_cmd:
clr sck ; 将SCK拉低
clr cs ; 将 /CS 拉低
mov A, #WREN_INST
lcall outbyt ;送出WREN_INST指令
clr sck ; 将SCK拉低
setb cs ; 将 /CS 升高
ret
;*******************************************************************************************
;名称:WRDI_CMD
;描述:写禁止
;功能:这段程序发送命令禁止对存储单元和状态寄存器写
;调用子程序:outbyt
;输入:无
;输出:无
;寄存器使用:A
;*******************************************************************************************
wrdi_cmd:
clr sck ; 将SCK拉低
clr cs ; 将/CS拉低
mov A, #WRDI_INST
lcall outbyt ;送出WRDI指令
clr sck ; 将SCK拉低
setb cs ;升高/CS
ret
;*******************************************************************************************
;名称;WRSR_CMD
;描述:写状态寄存器
;功能:将WD0、WD1、BP0、BP1的状态写入状态寄存器
;调用子程序:outbyt, wip_poll
;输入:无
;输出:无
;寄存器使用:A
;*******************************************************************************************
wrsr_cmd:
clr sck ; 将SCK拉低
clr cs ; 将/CS拉低
mov A, #WRSR_INST
lcall outbyt ; 送出 WRSR 指令
mov A, #STATUS_REG
lcall outbyt ; 送出状态寄存器的状态
clr sck ; 将SCK拉低
setb cs ;升高/CS
lcall wip_poll ;测试是否已器件内部是否写完
ret
;*******************************************************************************************
;名称:RDSR_CMD
;描述:读状态寄存器
;功能:本程序发送命令用以读状态寄存器
;调用子程序:outbyt, inbyt
;输入:无
;输出:A= 状态寄存器
;寄存器使用:A
;*******************************************************************************************
rdsr_cmd:
clr sck ; 将SCK拉低
clr cs ; 将/CS拉低
mov A, #RDSR_INST
lcall outbyt ; 发送 RDSR 指令
lcall inbyt ; 读状态寄存器
clr sck ; 将SCK拉低
setb cs ;升高/CS
ret
;*******************************************************************************************
;名称:BYTE_WRITE
;描述:单字节写
;功能:本程序用于单字节写入EEPROM
;调用子程序:outbyt, wip_poll
;输入:无
;输出:无
;寄存器使用:A, B
;*******************************************************************************************
byte_write:
mov dph,#0
mov dpl,DataAddr
clr sck ; 将SCK拉低
clr cs ; 将/CS拉低
mov A, #WRITE_INST
mov B, DPH
mov C, B.0
mov ACC.3, C
lcall outbyt ; 送出含有地址最高位的写指令
mov A, DPL
lcall outbyt ; 送出地址的低8位
mov A, DataNum
lcall outbyt ; 送出数据
clr sck ; 将SCK拉低
setb cs ;升高/CS
lcall wip_poll ;测试是否已器件内部是否写完
ret
;*******************************************************************************************
;名称:BYTE_READ
;描述:单字节读
;功能:本程序从EEPROM中读出一个字节
;调用: outbyt, inbyt
;输入:无
;输出: A = 读到的内容
;寄存器使用:A, B
;*******************************************************************************************
byte_read:
mov DPH,#0; 设置读的地址
MOV DPL,DATAADDR
clr sck ; 将SCK拉低
clr cs ; 将/CS拉低
mov A, #READ_INST
mov B, DPH
mov C, B.0
mov ACC.3, C
lcall outbyt ; 送出含有地址最高位的读指令
mov A, DPL
lcall outbyt ;送出低8位地址
lcall inbyt ; 读数据
clr sck ; 将SCK拉低
setb cs ;升高/CS
ret
;*******************************************************************************************
;名称:rst_wdog
;描述:复位看门狗定时器
;功能:这段程序用来复位看门狗定时器,不发送命令
;调用子程序:无
;输入:无
;输出:无
;寄存器使用:无
;*******************************************************************************************
rst_wdog:
clr cs ; 将 /CS 拉低
setb cs ; 将 /CS 升高
ret
;*******************************************************************************************
;名称: WIP_POLL
;描述: 器件内部编程检查
;功能:本程序通过检查WIP位来确定X5045内部编程是否结束
;子程序调用: rdsr_cmd
;输入:无
;输出:无
;寄存器使用: R1, A
;*******************************************************************************************
wip_poll:
mov R1, #MAX_POLL ; 设置用于偿使的最大次数Set maximum number of polls
wip_poll1:
lcall rdsr_cmd ; 读状态寄存器
jnb ACC.0, wip_poll2 ; 如果WIP 位是 '0' 说明内部的写周期完成了
djnz R1, wip_poll1 ; 如果WIP 位是 '1'说明内部写周期还没有完成
wip_poll2:
ret
;*******************************************************************************************
;名称: OUTBYT
;描述:将一个字节送到EEPROM
;功能:本段程序移位送出一个字节,从最高位开始送PROM
;调用子程序:无
;输入:A = 待送的字节
;输出:无
;寄存器使用: R0, A
;*******************************************************************************************
outbyt:
mov R0, #08 ; 设置位计数(共8位)
outbyt1:
clr sck ; 将SCK拉低
rlc A ;带进位位的左移位
mov si, C ; 送出进位位
setb sck ; 将 SCK 升高
djnz R0, outbyt1 ; 循环8次
clr si ; 将SI置于已知的状态
ret
;*******************************************************************************************
;名称: INBYT
;描述:从EEPROM中接收数据
;功能:这段程序从EEPROM中接收数据,高位在先
;调用子程序:无
;输入:无
;输出:A = 接收到的数据
;寄存器使用:R0, A
;*******************************************************************************************
inbyt:
mov R0, #08 ; 设置计数(共8位)
inbyt1:
setb sck ; 将 SCK 升高
clr sck ; 将SCK拉低
mov C, so ; 将输出线的状态读到进位位
rlc A ; 带进位位的循环左移
djnz R0, inbyt1 ; 循环8次
ret
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -