📄 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 + -