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

📄 h40.asm

📁 单片机程序集合
💻 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 + -