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

📄 spl10a_driver.asm

📁 适用于凌阳单片机的SPL10A液晶驱动程序
💻 ASM
字号:
		.include hardware.inc

		.external _TimeCounter

		.define SETCOMMAND		0x00
		.define WRITECOMMAND	0x01

		.define STB				0x20
		.define ACK				0x40
		.define BITDATA			0x80
		.define TRUE			0x00
		.define FALSE			0x01

		.ram
		.public _Result,_KeyValue,_DisplayBuffer
		.var _Result,_KeyValue	//_Result=1表示对SPL10A操作失败,_KeyValue保存1-8键值(0表示无键)
		.var Page
_DisplayBuffer:	.dw 11 dup(0)	//显示缓冲区。第0-7单元为自左至右共8个数据。第8单元为增量条形标识。
								//第9单元为文字(含小数点)标识。第10单元为电池、阀门标识。
LCDBuffer:		.dw 10 dup(0)	//段显示缓冲区,将显示缓冲区内的内容转变为段码后存入段显示缓冲区
		
		.data
//SPL10A的总命令表
CommandTbl:				
		.dw 0x8100		//00:Tone off
		.dw 0x8200		//01:Tone on
		.dw 0x8400		//02:Set Tone 1K
		.dw 0x8500		//03:Set Tone 2K
		.dw 0x8600		//04:Set Tone 4K
		.dw 0x8700		//05:Battery Level Detect
		.dw 0x8300		//06:LCD 1/4duty 1/3bias
		.dw 0x9000		//07:Key Mode0(5*4)    no shift
		.dw 0x9100		//08:Key Mode1(4*4)    shift1
		.dw 0x9200		//09:Key Mode2(3*4)    shift1,2
		.dw 0x9300		//0A:Key Mode3(3*4)    rolling F/B
		.dw 0x9800		//0B:Key continue refresh mode
		.dw 0x9900		//0C:Key hold until read out
		.dw 0xE000		//0D:Sleep mode

//数据长度表
//在Set Command操作中数据长度8位,在Write Command操作中数据长度为16位
SizeTbl:
		.dw 8,16

//数字显示段码
SegTbl:
		.dw 0x003F,0x0006,0x005B,0x004F,0x0066				//0,1,2,3,4
		.dw 0x006D,0x007D,0x0007,0x007F,0x006F				//5,6,7,8,9
		.dw 0x0000											//全灭

//增量条形标识段码
StickTbl:
		.dw 0x00,0x01,0x03,0x07,0x0F

		.code
		.public InitIO
//初始化IO口,其中A7接DATA(输出),A5接STB(输出),A6接ACK(输入)
//入口:无
//出口:无
InitIO:	.proc
		R1=0x00A0
		[P_IOA_Dir]=R1		//A7(DATA)、A5(STB)输出,A6(ACK)输入
		[P_IOA_Attrib]=R1
		R1=0x00E0
		[P_IOA_Data]=R1
		RETF
			.endp
			
		.public _InitSPL10A
//SPL10A初始化,包括初始化IO口、向SPL10A写初始化命令
//入口:无
//出口:无
_InitSPL10A:	.proc
		CALL InitIO			//初始化IO口
		BP=_DisplayBuffer	//显示缓冲区初始化
		R1=0x0A				//前8个单元写入0x0A则不显示
		R2=8				
CL1:	[BP++]=R1
		R2-=1
		JNZ CL1
		R1=0				//后3个单元写入0则不显示
		R2=3
CL2:	[BP++]=R1
		R2-=1
		JNZ CL2
		R1=0x0B
		CALL SetCommand		//送Key初始化命令:Key continue refresh mode
		RETF
			.endp
		
		.public SetCommand
//向SPL10A送命令
//入口:R1。R1内容不是真正的控制命令,而是实际命令在命令表中的存储偏移量,通过查表得出实际命令
//出口:无
SetCommand:	.proc
		BP=CommandTbl		//BP指向命令表首地址
		BP+=R1
		R1=[BP]				//取出实际命令
		R2=SETCOMMAND		//当前操作为Set Command
		CALL SendData		//送出
		CALL Delay			//让STB、DATA信号保持一段时间的高电平
		RETF
			.endp
		
		.public SendData
//数据传送,完成061A向SPL10A的送数据过程。传送过程遵循Set Command、Write Command通讯时序
//入口:R1--数据,R2--操作模式(Set Command、Write Command)
//出口:无
SendData:	.proc
		BP=SizeTbl			//确定不同操作模式下数据长度
		BP+=R2
		R2=[BP]
		R3=[P_IOA_Data]		//STB、DATA信号置高,准备发送同步信号
		R3|=STB+BITDATA
		[P_IOA_Data]=R3
		R3=[P_IOA_Data]		//DATA置低,送同步信号
		R3^=BITDATA
		[P_IOA_Data]=R3
		R3=100				//启动100ms定时
		[_TimeCounter]=R3
Wait1:
		R3=[_TimeCounter]
		JNZ OK1
		GOTO Error			//100ms内未收到ACK信号则传送失败
OK1:	R3=[P_IOA_Data]		//等待ACK信号为低
		R3&=ACK
		JNZ Wait1
		R3=[P_IOA_Data]		//DATA置高
		R3|=BITDATA
		[P_IOA_Data]=R3
		R3=100				//启动100ms定时
		[_TimeCounter]=R3
Wait2:
		R3=[_TimeCounter]
		JNZ OK2
		GOTO Error
OK2:	R3=[P_IOA_Data]		//等待ACK信号为高
		R3&=ACK
		JZ Wait2			//只有ACK信号随DATA信号从高变低,又从低变高,则同步成功
		R4=0x8000			//数据从最高位开始传送
Next:	R3=R1
		R3&=R4				//判断传送位为高还是低
		JZ ResBit
		R3=[P_IOA_Data]		//传送位为高
		R3|=BITDATA
		JMP Send
ResBit:	R3=[P_IOA_Data]		//传送位为低
		R3|=BITDATA
		R3^=BITDATA
Send:	[P_IOA_Data]=R3
		NOP
		NOP
		NOP
		NOP
		R3=[P_IOA_Data]		//STB信号置低
		R3|=STB
		R3^=STB
		[P_IOA_Data]=R3
		R3=100				//启动100ms定时
		[_TimeCounter]=R3
Wait3:
		R3=[_TimeCounter]
		JZ Error
		R3=[P_IOA_Data]		//等待ACK信号置低
		R3&=ACK
		JNZ Wait3
		R3=[P_IOA_Data]		//STB信号置高
		R3|=STB
		[P_IOA_Data]=R3
		R3=100				//启动100ms定时
		[_TimeCounter]=R3
Wait4:
		R3=[_TimeCounter]
		JZ Error
		R3=[P_IOA_Data]		//等待ACK信号置高
		R3&=ACK
		JZ Wait4
		R3=0x01				//清狗
		[P_Watchdog_Clear]=R3
		R4=R4 LSR 1			//R4右移一位,以便判断下一位数据
		R2-=1
		JNZ Next			//继续,直至所有的数据位传送完毕
		R3=TRUE
		JMP Stop
Error:	R3=FALSE
Stop:	[_Result]=R3
		R3=[P_IOA_Data]		//传送完毕后STB、DATA信号置高
		R3|=STB+BITDATA
		[P_IOA_Data]=R3
		RETF
			.endp

		.public Delay
Delay:	.proc
		R3=0x8000			
Wait:	R1=0x01				//清狗
		[P_Watchdog_Clear]=R1
		R3-=1
		JNZ Wait
		RETF
		.endp

		.public _CheckKeypad
//键盘读取程序。过程遵循Read Command时序。
//入口:无
//出口:_KeyValue。0表示无键按下,1-8对应8个按键
_CheckKeypad:	.proc
		R1=0xC000			//取出实际命令
		R2=SETCOMMAND		//当前操作为Set Command
		CALL SendData		//送出
		R1=[_Result]
		JZ ComeOn
		R1=0
		[_KeyValue]=R1
		RETF
ComeOn:	R1=0x0020			//变化端口方向
		[P_IOA_Dir]=R1		//A7(DATA)输入、A5(STB)输出,A6(ACK)输入
		[P_IOA_Attrib]=R1
		R1=0x00E0
		[P_IOA_Data]=R1
		R1=8				//读入的数据是8位
		R2=0				//读入的数据暂存处
		R4=0x0080
RdNext:	R3=100				//启动100ms定时
		[_TimeCounter]=R3
Wait5:	R3=[_TimeCounter]
		JZ RdFail
		R3=[P_IOA_Data]		//等待ACK置高,表示SPL准备放置数据
		R3&=ACK
		JZ Wait5
		R3=[P_IOA_Data]		//STB置低表示SPCE准备接收数据
		R3|=STB
		R3^=STB
		[P_IOA_Data]=R3
		R3=100				//启动100ms定时
		[_TimeCounter]=R3
Wait6:	R3=[_TimeCounter]
		JZ RdFail
		R3=[P_IOA_Data]		//等待ACK置低,表示SPL数据就绪
		R3&=ACK
		JNZ Wait6
		R3=[P_IOA_Data]		//读入位数据
		R3&=BITDATA
		JNZ SetBit
		R2|=R4
		R2^=R4				//读入的位为低
		JMP Con
SetBit:	R2|=R4				//读入的位为高
Con:	R4=R4 LSR 1
		R3=[P_IOA_Data]		//STB置高,表示SPCE已完成读取
		R3|=STB
		[P_IOA_Data]=R3
		R1-=1
		JNZ RdNext
		R1=TRUE
		[_Result]=R1
		JMP RdSuc
RdFail:	R1=FALSE
		[_Result]=R1
		R2=0	
RdSuc:	[_KeyValue]=R2
		CALL InitIO			//恢复IO口原方向
		R3=[P_IOA_Data]		//读完毕后STB、DATA信号置高
		R3|=STB+BITDATA
		[P_IOA_Data]=R3
		CALL Delay
		R1=[_KeyValue]		//返回值
		RETF
			.endp

		.public Convert
//显示缓冲区内容到段显示缓冲区内容的转变,完成将显示缓冲区内的所有显示内容转换为要
//实际显示的段码送入段显示缓冲区功能
//入口:_DisplayBuffer
//出口:LCDBuffer
Convert:	.proc
		BP=LCDBuffer		//首先清除段显示缓冲区
		R1=0
		R2=10				//段显示缓冲区有10个单元
Clr:	[BP++]=R1
		R2-=1
		JNZ Clr
		R1=9
		[Page]=R1			//先从第9页到第0页写数据
		R1=_DisplayBuffer	//R1指向显示缓冲区
		R2=8				//先处理8个数字
Lp1:	BP=SegTbl			//BP指向段码表
		R3=[R1++]			//取显示缓冲区内容
		BP+=R3
		R3=[BP]				//取段码
		PUSH R3 TO [SP]		//段码的高4位与低4位要分开处理
		R3&=0x0F
		BP=LCDBuffer		//BP指向段显示缓冲区
		R4=[Page]
		BP+=R4
		R4=[BP]
		R4|=R3
		[BP]=R4				//存入低4位段码
		POP R3 FROM [SP]
		R3&=0xF0
		BP=LCDBuffer
		R4=[Page]
		R4-=1
		BP+=R4
		R4=[BP]
		R4|=R3
		[BP]=R4				//存入高4位段码
		R3=[Page]
		R3-=1
		[Page]=R3
		R2-=1
		JNZ Lp1				//8个数字未转换完毕
		R3=[R1++]			//增量条形标识显示数据范围1-10
		PUSH R3 TO [SP]
		CMP R3,5
		JNAE Stick1
		R3=4
Stick1:	BP=StickTbl			//BP指向条形标识段码
		BP+=R3
		R3=[BP]
		R4=1				//第1页
		BP=LCDBuffer
		BP+=R4
		R4=[BP]
		R4|=R3
		[BP]=R4
		POP R3 FROM [SP]
		PUSH R3 TO [SP]
		CMP R3,5
		JAE C10
		POP R3 FROM [SP]
		JMP Word
C10:	CMP R3,8
		JNAE C1
		JMP C2
C1:		R3-=4
		JMP Stick2
C2:		R3=3
Stick2:	BP=StickTbl
		BP+=R3
		R3=[BP]
		R3=R3 LSL 4
		BP=LCDBuffer		//第0页
		R4=[BP]
		R4|=R3
		[BP]=R4
		POP R3 FROM [SP]
		CMP R3,8
		JNAE Word
		CMP R3,11
		JNAE C3
		JMP C4
C3:		R3-=7
		JMP Stick3
C4:		R3=3
Stick3:	BP=StickTbl
		BP+=R3
		R3=[BP]
		BP=LCDBuffer		//第0页
		R4=[BP]
		R4|=R3
		[BP]=R4
Word:	R2=1
		R3=1
		[Page]=R3
C6:		R4=[R1]			//取出文字标识显示内容
		R4&=R3
		JZ C5
		BP=LCDBuffer
		BP+=R2
		R4=[BP]
		R4|=0x80
		[BP]=R4
C5:		R3=R3 LSL 1
		R2+=1
		CMP R2,9
		JNE C6
		R1+=1
		R2=[R1]
		BP=LCDBuffer
		R3=[BP]
		PUSH R2 TO [SP]
		R2&=0x01
		JNZ C7
		JMP C8
C7:		R3|=0x08
C8:		POP R2 FROM [SP]
		R2&=0x02
		JNZ C9
		JMP C11
C9:		R3|=0x80
C11:	[BP]=R3
		RETF

			.endp
		
		.public _RefreshLCD
//LCD刷新程序。主程序修改显示缓冲区后调用,完成LCD显示。
//入口:_DisplayBuffer
//出口:无
_RefreshLCD:	.proc
		CALL Convert		//调转换程序,将显示缓冲区内容转换为段显示缓冲区内容
		R1=0
		[Page]=R1
		R4=10				//共有10页的数据要传送
		BP=LCDBuffer		//BP指向段显示缓冲区
Lop:	R1=0xA000			//LCD写命令
		R2=[Page]			//将页码移至D8-D11
		R2=R2 LSL 4
		R2=R2 LSL 4
		R1|=R2
		R2=[BP++]			//取出段显示内容
		R1|=R2				//这时完整包含LCD写命令、页码、段显示内容
		R2=WRITECOMMAND		//Write Command操作标识
		PUSH BP TO [SP]
		PUSH R4 TO [SP]
		CALL SendData		//向SPL10A送数据
		POP R4 FROM [SP]
		POP BP FROM [SP]
		R2=[Page]			//准备传送下一页数据
		R2+=1
		[Page]=R2
		R4-=1
		JNE Lop
		RETF
			.endp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -