📄 bfar.asm
字号:
; “验证式? 红外线遥控实验
OUTBIT equ 0e101h ; 位控制口
CLK164 equ 0e102h ; 段控制口(接164时钟位)
DAT164 equ 0e102h ; 段控制口(接164数据位)
IN equ 0e103h ; 键盘读入口
; 脉冲宽度下限
ldhmin equ 0cbh
ldlmin equ 0cbh
p0hmin equ 0f3h
p0lmin equ 0f3h
p1hmin equ 0deh
; 脉冲宽度上限
ldhmax equ 0d0h
ldlmax equ 0d0h
p0hmax equ 0f9h
p0lmax equ 0f9h
p1hmax equ 0e3h
; 发送信号时载波信号宽度
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
anl a,#0fdh
movx @dptr, a
mov dptr, #CLK164
orl a,#02h
movx @dptr, a
anl a,#0fdh
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 00h, 01h, 04h, 07h
db 0fh, 02h, 05h, 08h
db 0eh, 03h, 06h, 09h
db 0dh, 0ch, 0bh, 0ah
db 10H,10H,10H,10H,10H
db 10H,10H,10H,10H,10H
GetKey:
mov dptr, #OUTBIT
mov P2, dph
mov r0, #03H
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:
jb p1.6, 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 p1.6, 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
jnb p1.6, 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
carrier0:
setb p1.5 ;发送载波信号 ,p1.5 = 发送脚
nop
nop
nop
nop
nop
clr p1.5
ret
carrier1:
clr p1.5 ;发送载波信号 ,p1.5 = 发送脚
nop
nop
nop
nop
nop
clr p1.5
ret
ir_send:
mov r0,#send5 ; 引导码低电平
leaderh:
call carrier0 ; 发载波信号
djnz r0,leaderh
mov r0,#send5 ; 引导码高电平
leaderl:
call carrier1 ; 无载波信号
djnz r0,leaderl
mov status,#0 ; 准备发数据位
sendp:
mov r0, #send1 ; 数据码低电平
sp0:
call carrier0 ; 发载波信号
djnz r0, sp0
mov a, snddat
mov r0, #send1 ; '0'数据位高电平
rrc a
mov snddat,a
jnc sp2
mov r0, #send3 ; '1'数据位高电平
sp2:
call carrier1 ; 无载波信号
djnz r0, sp2
inc status
mov a, status
cjne a,#8, sendp ; 8 位数据已发完
mov r0, #send1 ; 发停止位
sp3:
call carrier0
djnz r0, sp3
mov r0,#0 ; 数据间的间隔
mov r1,#3
sp4:
call carrier1
djnz r0, sp4
djnz r1, sp4
ret
Start:
mov sp, #40h
mov dptr,#0e100h
mov a,#03h
movx @dptr,a
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 + -