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

📄 p2p.asm

📁 基于51单片机,利用RS232接口进行两个单片机间的点对点传输
💻 ASM
字号:

;功能:5*4键盘扫描程序

KEYNAME DATA 28H  ;b4~b0位记录按键值
                  ;b7-作为按键值有效标志,b7为0时,表示b4-b0位中的按键值无效。
                  ;b7为1时,表示b4-b0位记录的按键值有效,且未尚未处理,不能
                  ;接受新按键。
		  ;b6-保留。
;外部程序执行了按键功能后,将按键有效标志清0,允许接收新按键
KEYSTU  DATA 2AH  ;键盘按键状态寄存器,其中b2、b1、b0分别记录最近
                  ;三次定时中断的按键状态。

DISPBUF DATA 30H  ;显示缓冲区首地址(30H-33H)

PORTDR  DATA 34H  ;U105(八上升沿D型触发器74HC273)地址内存中的影射地址
                  ;设置影射地址目的是为了在执行键盘扫描过程中不影响
                  ;该输出口高3位(b5~b3)位内容
DISPCB  DATA 35H  ;显示数码
TIMEBELL DATA 36H ;蜂鸣器鸣响时间

RXDBUF	DATA 38H  ;接收缓冲区(38H-3BH)
RXDB    BIT  01H  ;串行接收有效标志

BTIME   DATA 40H  ;10ms计数单元
DISPB   BIT  00H  ;50ms定时时间到标志

SDI     BIT  P1.2 ;串行数据输入
SCLK    BIT  P3.4 ;串行数据移位脉冲
PCLK    BIT  P3.5 ;并行锁存脉冲

PORTA   EQU 9000H ;8255A口地址
PORTB   EQU 9100H ;8255B口地址
PORTC   EQU 9200H ;8255C口地址
PORTS   EQU 9300H ;8255控制/状态口地址
PORTD   EQU 8800H ;U105(八上升沿D型触发器74HC273)地址


ORG 0000H
LJMP MAIN

ORG 0023H
LJMP UART        ;跳串行口中断服务程序入口地址

ORG 002BH
LJMP CTC2       ;定时/计数器T2中断服务程序入口地址

ORG 0050H
;-----主程序开始-----
PROC MAIN
MAIN:
     MOV SP, #0DFH     ;对于具有256字节内部RAM芯片来说,
                       ;将0E0H-0FFH,共计32字节作为堆栈区
     MOV DPTR, #8000H  ;关闭蜂鸣器
     MOV A, #0FFH
     MOVX @DPTR, A

     ;---复位后,将08H-0FF内部RAM单元清0。
     MOV R7, #248
     MOV R0, #08H
LOOP1:
     MOV @R0, #0
     INC R0
     DJNZ R7, LOOP1


     ;初始化U107(8255)可编程并行I/O接口芯片的工作方式
     MOV DPTR, #PORTS       ;8255控制/状态口地址
     MOV A, #10011011B      ;A口工作在方式0,输入;B口工作在方式0,输入;
                            ;C口高、低半部暂时定义为输入
     MOVX @DPTR, A          ;送控制字寄存器
     ;将PD4~PD0置为高电平,使U105(74HC273)输出级截止,降低功耗。
     MOV DPTR, #PORTD       ;U105口地址送DPTR
     MOV A, PORTDR          ;读U105口在内存中的映象地址
     ORL  A, #1FH
     MOVX @DPTR, A          ;数据送U105输出口

     ;初始化定时器T1(作串行通信波特率发生器输入信号)
;     MOV TL1, #244          ;4800波特率对应定时器初值(6时钟)
;     MOV TH1, #244

     MOV TL1, #250          ;4800波特率对应定时器初值(12时钟)
     MOV TH1, #250
     ANL TMOD, #0F0H
     ORL TMOD, #00100000B   ;定时器T1工作在方式2(8位自动重装初值)
     SETB TR1               ;启动定时器T1
     CLR ET1                ;禁止T1中断

     ;初始化串行口
     MOV SCON, #11010000B   ;串行口工作在方式3,SM2=0,以便使用
                            ;TB8位作奇偶校验位。
     ;SETB REN              ;允许接收


     ;----初始化定时器T2
;     MOV TH2, #0B8H
;     MOV TL2, #00H          ;初值0BC00送定时器T2(6时钟模式)
;     MOV RCAP2H, #0B8H
;     MOV RCAP2L, #00H       ;初始化重装初值

     MOV TH2, #0DCH
     MOV TL2, #00H          ;初值0DC00送定时器T2(12时钟模式)
     MOV RCAP2H, #0DCH
     MOV RCAP2L, #00H       ;初始化重装初值
     MOV T2CON, #00000100B   ;初始化T2工作方式(自动重装初值、定时)
                            ;并启动了T2

     ;-----初始化中断控制器
     ORL IE, #10110000B
     ;SETB ET2              ;允许定时器T2中断
     ;SETB ES               ;允许串行口中断
     ;SETB EA               ;开中断

     MOV BTIME, #5           ;初值为5(即每50ms检测一次)
     MOV KEYSTU, #07H 	   ;按键状态初始化为111
     MOV KEYNAME, #1FH	   ;将键盘按键置为1FH(无效)

     ;检查串行接收是否有效,如果有效,则把接收码送显示缓冲区
LOOP2:
     JNB RXDB, NEXT1
     ;串行接收有效
     CLR RXDB
     MOV DISPCB, RXDBUF      ;接收数码送SIDPCB
     SJMP DISP1              ;送LED显示
NEXT1:
     ;检查是否有按键输入
     JNB DISPB, LOOP2        ;50ms定时时间未到
     ;50ms延迟时间到!
     CLR DISPB
     LCALL KEYCHK            ;每50ms读键盘状态
     ;检查键盘有无输入
     MOV A, KEYNAME
     JNB ACC.7, LOOP2        ;键盘按键无效,就循环等待

     MOV A, KEYNAME          ;读按键值
     ANL A, #1FH             ;保留
     MOV KEYNAME, A          ;清除按键处理标志

     ;----初始化串行发送一字节----
     MOV C, P                ;奇偶标志P送C
     MOV TB8, C              ;奇偶标志P送TB8,即b8位
     MOV SBUF, A             ;写串行口缓冲寄存器即可将一字节信息
                             ;按设定的波特率发送到串行口上。
     ;--------------------------
     MOV DISPCB, A           ;显示数码送DISP
DISP1:
     ;数据送串行显示缓冲
     ;先将显示缓冲区笔段码左移一个字节
     MOV R0, #DISPBUF        ;显示缓冲区首地址送R0
     MOV R1, #DISPBUF+1      ;显示缓冲区地址送R1
     MOV R7, #3
LOOP3:
     MOV A, @R1
     MOV @R0, A
     INC R0
     INC R1
     DJNZ R7, LOOP3

     MOV A, DISPCB
     CJNE A, #10H, NEXT2
NEXT2:
     JC NEXT3
     ;按下了功能键,键值>=10H,用两位LED来显示
     ANL A, #0F0H
     SWAP A
     MOV DPTR, #LEDTAB       ;0-F字模表首地址送DPTR
     MOVC A, @A+DPTR         ;查表取模
     MOV R1, #DISPBUF+2      ;显示缓冲区地址送R1
     MOV @R1, A              ;字模送显示缓冲区
NEXT3:
     MOV A, DISPCB           ;读按键值
     ANL A, #0FH             ;保留低4位
     MOV DPTR, #LEDTAB       ;0-F字模表首地址送DPTR
     MOVC A, @A+DPTR         ;查表取模
     MOV R1, #DISPBUF+3      ;显示缓冲区地址送R1
     MOV @R1, A              ;字模送显示缓冲区
     LCALL S_DISP            ;串行显示
     LJMP LOOP2              ;循环等待
END


PROC S_DISP             ;串行输出子程序
S_DISP:
    MOV R0, #DISPBUF    ;显示缓冲区首地址送R0
    MOV R7, #4
LOOP2:
    MOV A, @R0
    MOV R6, #8
LOOP1:
    CLR SCLK
    RLC A
    MOV SDI, C         ;串行数据送SDI引脚
    NOP
    SETB SCLK          ;锁存串行输入数据
    DJNZ R6, LOOP1
    ;取下一显示码
    INC R0
    DJNZ R7, LOOP2
    ;4位笔段码已全部移到串入并出芯片中
    CLR PCLK
    NOP                  ;延迟一个机器周期
    SETB PCLK
    RET
END

;定时/计数器T2中断服务程序
PROC CTC2
CTC2:
     PUSH PSW
     PUSH ACC
     PUSH DPH
     PUSH DPL

     ;检查是否需要关闭蜂鸣器
     MOV A, TIMEBELL
     JZ BLEXIT
     DJNZ TIMEBELL, BLEXIT
     ;延迟时间到,关闭
     MOV DPTR, #8000H  ;关闭蜂鸣器
     MOV A, #0FFH
     MOVX @DPTR, A
BLEXIT:

     DJNZ  BTIME, EXIT ;溢出次数减1,不为0跳转
     ;溢出次数已经回到0,重新初始化溢出次数
     MOV BTIME, #5
     SETB DISPB         ;置位50ms时间到标志
EXIT:

     CLR TF2             ;清除定时器T2溢出标志

     POP DPL
     POP DPH
     POP ACC
     POP PSW
     RETI
END

PROC KEYCHK            ;键盘检测
KEYCHK:
;---键盘检测-----------
    MOV DPTR, #PORTD         ;U105口地址送DPTR
    MOV A, PORTDR            ;读U105口在内存中的映象地址
    ANL A, #0E0H             ;输出全为低电平的扫描信号
    MOVX @DPTR, A            ;数据送U105输出口,将PD4~PD0置为低电平

    MOV DPTR, #PORTB         ;8255(U107)B口地址送DPTR
    MOVX A, @DPTR            ;读出B口
    ANL A, #0FH              ;屏蔽高4位
    CJNE A, #0FH, NEXT1
    ;等于0F,说明没有按键被按下
    SETB C                   ;将C标志置1
    SJMP NEXT2
NEXT1:
    CLR C                    ;C标志清0
NEXT2:
    MOV A, KEYSTU
    RLC A                    ;左移一位,记录最新的按键状态
    ANL A, #07H              ;保留按键状态
    MOV KEYSTU, A            ;保存按键状态

    ;判别按键状态,决定是否执行按键扫描
    CJNE A, #0, SNEXT1
    ;处于000态,按键未释放,退出(假设一次按键仅视为一次输入)
    SJMP KEXIT
SNEXT1:
    CJNE A, #1, SNEXT2
    ;处于001态, 按键可能刚被释放,不处理
    SJMP KEXIT
SNEXT2:
    CJNE A, #2, SNEXT3
    ;处于010态,干扰,作000态处理
    ANL KEYSTU, #00H
    SJMP KEXIT
SNEXT3:
    CJNE A, #3, SNEXT4
    ;处于011态,按键处于释放状态,退出
    SJMP KEXIT
SNEXT4:
    CJNE A, #4, SNEXT5
    ;处于100态,按键已经稳定闭合,进行按键扫描
    LCALL KEYSCAN               ;执行键盘扫描,确定哪一按键被按下
    SJMP KEXIT
SNEXT5:
    CJNE A, #5, SNEXT6
    ;处于101态, 干扰,作111态处理
    ORL KEYSTU, #07H       ;b2~b0位置1
    SJMP KEXIT
SNEXT6:
    CJNE A, #6, SNEXT7
    ;处于110态,按键刚被按下,未稳定,暂不处理
;    LJMP EXIT
SNEXT7:
    ;处于111态
KEXIT:
    ;将PD4~PD0置为高电平,使74HC273输出级截止,降低功耗。
    MOV DPTR, #PORTD       ;U105口地址送DPTR
    MOV A, PORTDR          ;读U105口在内存中的映象地址
    ORL  A, #1FH
    MOVX @DPTR, A          ;数据送U105输出口
;---键盘检测结束-----------
    RET
END

PROC KEYSCAN                 ;键盘扫描程序
KEYSCAN:
    MOV R7, #5               ;定义扫描次数
    MOV R1, #0               ;初始化列地址
    MOV R3, #01111111B       ;扫描码初值

LOOP1:
    ;生成扫描码
    MOV A, R3
    RL A                     ;左移一位(从PD0开始扫描)
    MOV R3, A                ;保存扫描码
    ANL A, #00011111B        ;保留扫描
    MOV B, A                 ;暂时保存在B寄存器中

    MOV DPTR, #PORTD         ;U105口地址送DPTR
    MOV A, PORTDR            ;读U105口在内存中的映象地址
    ANL A, #0E0H             ;保留与键盘扫描无关的b7~b5位。
    ORL A, B                 ;与扫描或
    MOVX @DPTR, A            ;数据送U105输出口,将PD4~PD0置为低电平
    NOP                      ;延迟一个机器周期等待输出口状态稳定

    MOV DPTR, #PORTB         ;B口地址送DPTR
    MOVX A, @DPTR            ;读B口
    ANL A, #0FH              ;屏蔽高4位
    JB ACC.0, NEXT1
    ;ACC.0位为0,说明0行有按键被按下
    MOV R2, #0               ;行地址为0
    SJMP NEXT5
NEXT1:
    JB ACC.1, NEXT2
    ;ACC.1位为0,说明1行有按键被按下
    MOV R2, #1               ;行地址为1
    SJMP NEXT5
NEXT2:
    JB ACC.2, NEXT3
    ;ACC.2位为0,说明2行有按键被按下
    MOV R2, #2               ;行地址为2
    SJMP NEXT5
NEXT3:
    JB ACC.3, NEXT4
    ;ACC.3位为0,说明3行有按键被按下
    MOV R2, #3               ;行地址为3
    SJMP NEXT5
NEXT4:
    ;说明该列上没有按键被按下
    INC R1                   ;列地址加+1,继续扫描
    DJNZ R7, LOOP1
    ;扫描所有列,均没发现按按键被按下
    SJMP EXIT

NEXT5:
    ;计算行列地址,查表或区
    MOV A, R1
    RL A
    RL A                   ;列地址乘4(每列对应4行)
    ADD A, R2              ;加行地址
    MOV DPTR, #KEYTAB
    MOVC A, @A+DPTR        ;查表获取键值
    MOV KEYNAME, A         ;按键值送键名寄存器中
    ORL KEYNAME, #80H      ;按键有效标志置1
    ;开蜂鸣器,响一短声
    MOV DPTR, #8000H  ;关闭蜂鸣器
    MOV A, #7FH
    MOVX @DPTR, A
    MOV TIMEBELL, #25     ;响25*10ms,即250Ms
EXIT:
    RET
END

PROC UART                  ;串行中断服务子程序
UART:
    PUSH ACC
    PUSH PSW
    JNB TI, NEXT1
    ;串行发送结束中断
    CLR TI                 ;清除发送结束中断
NEXT1:
    JNB RI, EXIT
    ;串行接收有效
    CLR RI                 ;清除发送结束中断
    MOV A, SBUF
    ;进行奇偶校验,P标志与RB8位应该相同,否则就算错
    MOV C, P
    ANL C, /RB8            ;计算P. /RB8
    MOV F0, C              ;暂时保存F0标志中
    MOV C, RB8
    ANL C, /P              ;计算RB8. /P
    ORL C, F0              ;完成了P与RB8的异或运算!
    JC EXIT
    ;校验正确!
    MOV RXDBUF, A          ;数据送串行接收缓冲区
    SETB RXDB              ;串行接收有效标志置1
EXIT:
    POP PSW
    POP ACC
    RETI
END

;***********按键扫描码、键值对应关系******************
KEYTAB:
DB 0FH		;扫描码为0,即PD0与PB0交叉点对应数字键"F"
DB 0EH		;扫描码为1,即PD0与PB1交叉点对应数字键"E"
DB 0DH		;扫描码为2,即PD0与PB2交叉点对应数字键"D"
DB 0CH		;扫描码为3,即PD0与PB3交叉点对应数字键"C"

DB 09H		;扫描码为4,即PD1与PB0交叉点对应数字键"9"
DB 06H		;扫描码为5,即PD1与PB1交叉点对应数字键"6"
DB 03H		;扫描码为6,即PD1与PB2交叉点对应数字键"3"
DB 0BH		;扫描码为7,即PD1与PB3交叉点对应数字键"B"

DB 08H		;扫描码为8,即PD2与PB0交叉点对应数字键"8"
DB 05H		;扫描码为9,即PD2与PB1交叉点对应数字键"5"
DB 02H		;扫描码为A,即PD2与PB2交叉点对应数字键"2"
DB 00H		;扫描码为B,即PD2与PB3交叉点对应数字键"0"

DB 07H		;扫描码为C,即PD3与PB0交叉点对应数字键"7"
DB 04H		;扫描码为D,即PD3与PB1交叉点对应数字键"4"
DB 01H		;扫描码为E,即PD3与PB2交叉点对应数字键"1"
DB 0AH		;扫描码为F,即PD3与PB3交叉点对应数字键"A"

DB 13H		;扫描码为10,即PD4与PB0交叉点对应"↑"
DB 12H		;扫描码为11,即PD4与PB1交叉点对应"Enter"
DB 11H		;扫描码为12,即PD4与PB2交叉点对应"ESC"
DB 10H		;扫描码为13,即PD4与PB3交叉点对应"↓"

LEDTAB:                 ;八段LED共阳数码管字模
;数码  0     1     2     3     4     5    6    7
DB     0C0H, 0F9H, 0A4H, 0B0H, 99H, 92H, 82H, 0F8H

;数码  8     9     A     B     C     D     E     F
DB     80H,  90H,  88H, 83H,  0C6H, 0A1H, 86H, 8EH

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -