?? spl10a_driver.asm
字號:
.include hardware.inc
.external _TimeCounter
.define SETCOMMAND 0x00
.define WRITECOMMAND 0x01
.define STB 0x2000
.define ACK 0x4000
.define BITDATA 0x8000
.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=BITDATA+STB
[P_IOA_Dir]=R1 //A7(DATA)、A5(STB)輸出,A6(ACK)輸入
[P_IOA_Attrib]=R1
R1=BITDATA+STB+ACK
[P_IOA_Data]=R1
RETF
.endp
.public _InitSPL10A
//SPL10A初始化,包括初始化IO口、向SPL10A寫初始化命令
//入口:無
//出口:無
_InitSPL10A: .proc
CALL InitIO //初始化IO口
BP=_DisplayBuffer
R1=0x0A
R2=8
CL1: [BP++]=R1
R2-=1
JNZ CL1
R1=0
R2=3
CL2: [BP++]=R1
R2-=1
JNZ CL2
R1=0x07
CALL SetCommand //送Key初始化命令:KeyMode(5*4)
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的送數據過程
//入口:R1--數據,R2--操作模式(Set Command、Write Command、Transform Data)
//出口:無
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
jmp Wait3
Next2:
jmp Next //?????好像這條代碼沒有存在的必要
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 Next2 //繼續,直至所有的數據位傳送完畢
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
//鍵盤讀取程序
//入口:無
//出口:_KeyValue。0表示無鍵按下,1-8對應8個按鍵
_CheckKeypad: .proc
push R2,R5 to [sp]
R1=0xC000 //取出實際命令
R2=SETCOMMAND //當前操作為Set Command
CALL SendData //送出
R1=[_Result]
JZ ComeOn
R1=0
[_KeyValue]=R1
POP R2,R5 FROM [SP]
RETF
ComeOn: R1=STB //變化端口方向
[P_IOA_Dir]=R1 //A7(DATA)輸入、A5(STB)輸出,A6(ACK)輸入
[P_IOA_Attrib]=R1
R1=STB+ACK+BITDATA
[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] //返回值
pop R2,R5 from [sp]
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]
CMP R2,1
JNE C7
R3|=0x08
JMP C8
C7: CMP R2,2
JNE C9
R3|=0x80
JMP C8
C9: R3|=0x88
C8: [BP]=R3
RETF
.endp
.public _RefreshLCD
_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
R2=WRITECOMMAND
PUSH BP TO [SP]
PUSH R4 TO [SP]
CALL SendData
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 + -