⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 50451

📁 Small RTOS51是为51系列单片机而编写的。它是完全免费的、源代码公开的多任务实时操作系统。它可在无任何外部数据存储器的单片80C51系统上运行
💻
字号:
	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 + -