?? h40.asm
字號:
;擴展試驗四 紅外遙控試驗
;ASM for MCS51
OUTBIT equ 0FE02h ; 位控制口
CLK164 equ 0FE04h ; 段控制口(接164時鐘位)
DAT164 equ 0FE06h ; 段控制口(接164數據位)
IN equ 0FE00h ; 鍵盤讀入口
RCV_PORT equ 08004h ; 紅外接收端口
SND_PORT equ 08002h ; 紅外發送端口
RCV_PORT_ equ p1.0 ; 紅外接收端口
SND_PORT_ equ p1.1 ; 紅外發送端口
; 脈沖寬度下限
ldhmin equ 0d9h
ldlmin equ 0d9h
p0hmin equ 0f9h
p0lmin equ 0f9h
p1hmin equ 0eah
; 脈沖寬度上限
ldhmax equ 0dfh
ldlmax equ 0dfh
p0hmax equ 0fbh
p0lmax equ 0fbh
p1hmax equ 0ech
; 發送信號時載波信號寬度
send5 equ 192
send1 equ 38
send3 equ 115
LEDBuf equ 60h ; 顯示緩沖
status equ 70h
rcvdat equ 71h
snddat equ 72h
vldmin equ 73h
vldmax equ 74h
hasdat equ 75h
ljmp Start
LEDMAP: ; 八段管顯示碼
db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h
db 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h
Delay: ; 延時子程序
mov r7, #10h
DelayLoop:
call ir_receive
djnz r7, DelayLoop
djnz r6, DelayLoop
ret
DisplayLED:
mov r0, #LEDBuf
mov r1, #6 ; 共6個八段管
mov r2, #00100000b ; 從左邊開始顯示
Loop:
mov dptr, #OUTBIT
mov a, #0
movx @dptr, a ; 關所有八段管
mov a, @r0
mov B, #8 ; 送164
DLP:
rlc a
mov r3, a
mov acc.0, c
mov dptr, #DAT164
movx @dptr, a
mov dptr, #CLK164
setb acc.0
movx @dptr, a
clr acc.0
movx @dptr, a
mov a, r3
djnz B, DLP
mov dptr, #OUTBIT
mov a, r2
movx @dptr, a ; 顯示一位八段管
mov r6, #1
call Delay
mov a, r2 ; 顯示下一位
rr a
mov r2, a
inc r0
djnz r1, Loop
ret
TestKey:
mov dptr, #OUTBIT
mov a, #0
movx @dptr, a ; 輸出線置為0
mov dptr, #IN
movx a, @dptr ; 讀入鍵狀態
cpl a
anl a, #0fh ; 高四位不用
ret
KeyTable: ; 鍵碼定義
db 16h, 15h, 14h, 0ffh
db 13h, 12h, 11h, 10h
db 0dh, 0ch, 0bh, 0ah
db 0eh, 03h, 06h, 09h
db 0fh, 02h, 05h, 08h
db 00h, 01h, 04h, 07h
GetKey:
mov dptr, #OUTBIT
mov P2, dph
mov r0, #Low(IN)
mov r1, #00100000b
mov r2, #6
KLoop:
mov a, r1 ; 找出鍵所在列
cpl a
movx @dptr, a
cpl a
rr a
mov r1, a ; 下一列
movx a, @r0
cpl a
anl a, #0fh
jnz Goon1 ; 該列有鍵入
djnz r2, KLoop
mov r2, #0ffh ; 沒有鍵按下, 返回 0ffh
sjmp Exit
Goon1:
mov r1, a ; 鍵值 = 列 X 4 + 行
mov a, r2
dec a
rl a
rl a
mov r2, a ; r2 = (r2-1)*4
mov a, r1 ; r1中為讀入的行值
mov r1, #4
LoopC:
rrc a ; 移位找出所在行
jc Exit
inc r2 ; r2 = r2+ 行值
djnz r1, LoopC
Exit:
mov a, r2 ; 取出鍵碼
mov dptr, #KeyTable
movc a, @a+dptr
mov r2, a
WaitRelease:
mov dptr, #OUTBIT ; 等鍵釋放
clr a
movx @dptr, a
mov r6, #10
call Delay
call TestKey
jnz WaitRelease
mov a, r2
ret
TestLow: ; 檢測低電平寬度
mov r7,#0
waithigh0:
mov r6,#0bh
waithigh:
movx a,@dptr
jb acc.1, lowwidth
djnz r6,waithigh
djnz r7,waithigh0
mov r7,#0 ; 出錯
lowwidth:
mov a,r7
ret
TestHigh: ; 檢測高電平寬度
mov r7,#0
waitlow0:
mov r6,#0bh
waitlow1:
movx a, @dptr
jnb acc.1, highwidth
djnz r6, waitlow1
djnz r7, waitlow0
mov r7,#0 ; 出錯
highwidth:
mov a,r7
ret
TestValid: ; 脈沖是否在有效范圍內
cjne a,vldmin,vt01
jmp valid ; A = #min
vt01:
jnc vt02 ; A > #min
jmp invalid ; A < #min
vt02:
cjne a,vldmax,vt03
jmp valid ; A = #max
vt03:
jnc invalid ; A > #max
jmp valid ; A < #max
invalid:
setb c
ret
valid:
clr c
ret
ir_receive: ; 紅外接收
push psw
setb rs0
mov dptr,#RCV_PORT
movx a, @dptr
jnb acc.1, lead_l ; 是否有紅外信號?
pop psw ; 無,則退出
ret
lead_l:
call TestLow ; 引導碼低電平
mov vldmin,#ldlmin
mov vldmax,#ldlmax
call TestValid
jnc lead_h
jmp error
lead_h:
call TestHigh ; 引導碼高電平
mov vldmin,#ldhmin
mov vldmax,#ldhmax
call TestValid
jnc pulse_l
jmp error
pulse_l:
mov status,#1 ; 開始接收數據碼
pulse_t:
call TestLow ; 數據碼低電平
mov vldmin,#p0lmin
mov vldmax,#p0lmax
call TestValid
jnc Its0L
jmp error
Its0L:
call TestHigh ; 數據碼高電平
mov vldmin,#p0hmin
mov vldmax,#p0hmax
call TestValid ; '0'數據位的高電平?
jnc Its0H
jmp next5
Its0H:
mov a,rcvdat ; 數據碼移位到緩沖
rrc a
mov rcvdat,a
inc status
mov a,status
cjne a,#9, pulse_t ; 是否已收到8位數據
jmp process
next5:
mov vldmin,#p1hmin
mov vldmax,#p1hmax
call TestValid ; '1'數據位的高電平?
jnc Its1H
jmp error
Its1H:
setb c
jmp Its0H
process: ; 對收到的數據進行校驗
push b
mov a,rcvdat
mov b,a
anl b,#0fh
anl a,#0f0h
swap a
xrl a,b
pop b
cjne a,#0fh,error
mov a,rcvdat
anl a,#0fh
mov hasdat,#1
pop psw
ret
error: ; 出錯退出
pop psw
ret
carrier: ; 發送載波信號
xrl a,b
movx @dptr,a
nop
xrl a,b
movx @dptr,a
ret
ir_send:
mov dptr,#SND_PORT
mov a, #0h
mov b, #02
mov r0,#send5 ; 引導碼低電平
leaderh:
call carrier ; 發載波信號
djnz r0,leaderh
mov a,#0
mov b,a
mov r0,#send5 ; 引導碼高電平
leaderl:
call carrier ; 無載波信號
djnz r0,leaderl
mov status,#0 ; 準備發數據位
sendp:
mov a, #0
mov b, #02
mov r0, #send1 ; 數據碼低電平
sp0: call carrier ; 發載波信號
djnz r0, sp0
mov a, snddat
mov r0, #send1 ; '0'數據位高電平
rrc a
mov snddat,a
jnc sp1
mov r0, #send3 ; '1'數據位高電平
sp1: mov a, #0
mov b,a
sp2: call carrier ; 無載波信號
djnz r0, sp2
inc status
mov a, status
cjne a,#8, sendp ; 8 位數據已發完
mov a, #0 ; 發停止位
mov b, #02
mov r0, #send1
sp3: call carrier
djnz r0, sp3
mov a, #0
mov b, a
mov r0,#0 ; 數據間的間隔
mov r1,#3
sp4: call carrier
djnz r0, sp4
djnz r1, sp4
ret
Start:
mov sp, #40h
mov LEDBuf, #0ffh ; 顯示 8.8.8.8.
mov LEDBuf+1, #0ffh
mov LEDBuf+2, #0ffh
mov LEDBuf+3, #0ffh
mov LEDBuf+4, #0
mov LEDBuf+5, #0
mov hasdat, #0
MLoop:
mov a,hasdat
jnz show_dat
call DisplayLED ; 顯示
call TestKey ; 有鍵入?
jz MLoop ; 無鍵入, 繼續顯示
call GetKey ; 讀入鍵碼
anl a, #0fh ; 顯示鍵碼
mov b, a ; 將鍵碼編碼
cpl a
anl a,#0fh
swap a
orl a,b
mov snddat,a
call ir_send ; 紅外發送
ljmp MLoop
show_dat:
mov hasdat,#0
mov LEDBuf+4,#0
mov a, rcvdat
anl a,#0fh
mov dptr, #LEDMap
movc a, @a+dptr
mov LEDBuf+5, a
ljmp MLoop
end
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -