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

📄 hwframe.asm

📁 本程序为集中抄表系统中低压电力线载波数据采集器程序源代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
                MOV     @R0,A                             ;转换后重存回接收缓冲
                MOV	A,#REPEATER_ADDR                  ;得出当前采集器的中继器的地址
		MOV	DPL,A
                MOV	DPH,#C04_ADDR_H                   
                MOV     A,@R0
                ADD     A,#50H                            ;得出中继器低位字节
		MOV	B,A                               ;存当前表的采集器的中继器的低位地址
		LCALL	WR_C04_1BYTE
                INC     DPL                               ;高位地址
                MOV	DPH,#C04_ADDR_H
                MOV     B,#0C3H                           ;高位字节
                LCALL	WR_C04_1BYTE
                RET                 
;------------------------------------------------------
;写继电器状态字
HW_WR_JDQ_BYTE:
                PUSH    07H                                    ;保存当前表号
                MOV     R0,#HW_REC_DATA_ITEM
                MOV     A,@R0
                LCALL   BCD_HEX_1BYTE
                POP     07H
                MOV     @R0,A                             ;转换后重存回接收缓冲
                CJNE    A,#00H,HW_JUDGE_JDQ01
                AJMP    HW_WRITE_JDQSTATE
HW_JUDGE_JDQ01:
                CJNE    A,#01H,HW_WR_FRM_OVER
HW_WRITE_JDQSTATE:
                LCALL   JUDGE_JDQ_STATE_BYTE              ;判断当前表对应继电器下发状态
		MOV	A,R7
		DEC	A
		ADD	A,#C04_RELAY_STATE_0              ;得出当前表的继电器状态字的地址
		MOV	DPL,A
                MOV	DPH,#C04_ADDR_H                   ;状态合法,存储当前状态字
                MOV     R0,#HW_REC_DATA_ITEM
		MOV	B,@R0                             ;存当前表的继电器状态字
		LCALL	WR_C04_1BYTE
HW_WR_FRM_OVER:
                RET
;-------------------------------
;判断接收的地址号是否为本采集器号
JUDGE_REC_TERMINAL_ID:
                    MOV   R0,#HW_REC_ADDR+5                  ;接收到的地址第六字节(AA)
                    CJNE  @R0,#0AAH,ADDR_IS_ERR              ;;取出接收到的地址高位第一字,不是AA,错误地址
                    DEC   R0                                 ;下一字节
                    CJNE  @R0,#0AAH,ADDR_IS_ERR              ;接收到的地址第五字节(AA),不是AA,错误地址
                    DEC   R0                                 ;下一字节
                    CJNE  @R0,#0AAH,ADDR_IS_ERR              ;接收到的地址第四字节(AA),不是AA,错误地址
                    DEC   R0                                 ;下一字节
                    MOV   A,@R0                              ;接收到的地址第五字节(AA)
                    ANL   A,#0FH                             ;分离出采集器地址高位字节
                    MOV   R4,A                               ;暂存到R4
                    DEC   R0                                 ;下一字节
                    MOV   A,@R0                              ;采集器地址第二字节
                    MOV   R5,A                               ;暂存到R5
                    DEC   R0                                 ;下一字节
                    MOV   A,@R0                              ;接收到的地址第三字节
                    MOV   R6,A                               ;暂存到R6
                    LCALL BCD_HEX_3BYTES                     ;将地址由BCD码转换为16进制
                    LJMP  IS_RIGHT_ID                        ;地址正确转
;------------------------------------------
;接收到的地址非法或非本采集器地址号
ADDR_IS_ERR:
                    CLR     HW_FRM_PROCESS                   ;不是本采集器地址,清帧处理标志位
;------------------------------------------
;接收地址为本采集器地址或为广播地址等合法地址
IS_RIGHT_ID:
                    RET
;------------------------------------------------------------------------------------------------
;数据域数据减33H处理子程序
DATA_SUBB_33H:
                MOV     R0,#HW_REC_DATA_FEILD_LEN           ;数据域长度
                CJNE    @R0,#00H,ABLE_SUBB_33H              ;数据域长度不为0才能进行减33H处理
                SJMP    UNABLE_SUBB_33H                     ;不进行减33H处理
ABLE_SUBB_33H:
                MOV     B,@R0                               ;放到B寄存器
                MOV     R0,#HW_REC_DATA_FEILD               ;数据域首地址
SUBB_33H_LOOP:  CLR     C
                MOV     A,@R0                               ;读出数据域数据
                SUBB    A,#33H                              ;数据减33H
                MOV     @R0,A                               ;减后数据重写到原地址
                INC     R0                                  ;下一字节
                DJNZ    B,SUBB_33H_LOOP                     ;数据域数据减33H完成否?
UNABLE_SUBB_33H:
                RET
;----------------------------------------------------------------------------------------------
;形成读/写帧正常回应帧
;R5:正常应答控制码;R6:数据域长度
FORM_SEND_READ_FRAMES:
                    LCALL       CJQ_ACK_AND_FRAMES_HEAD_ADDR;形成发送帧头地址
                    MOV         A,R5                        ;正常应答控制码
                    LCALL       PRODUCE_CTRL_CODE           ;发送帧的控制码暂存发送缓冲区
                    MOV         A,R6                        ;数据域长度
                    LCALL       PRODUCE_DATA_FEILD_LEN      ;发送帧的数据长度
                    LCALL       MAKE_AND_SEND_ACK_FRAMES    ;产生数据标/校验和/帧结束符并发送回应帧
                    RET
;------------------------------------------------------------------------------------------
;从站读异常应答帧
READ_FRAMES_ERR_ACK:
                    RET                                     ;数据标识错误不回应

                    MOV     A,#02H                          ;数据标识错
                    ADD     A,#33H                          ;加33H
                    MOV     R0,#HW_SEND_DATA_ID1            ;发送缓冲区中要放错误信息字地址
                    MOV     @R0,A                           ;错误信息字送发送缓冲区
                    LCALL   CJQ_ACK_AND_FRAMES_HEAD_ADDR    ;形成发送帧头地址
                    MOV     A,#0C1H                         ;读异常回应标识
                    LCALL   PRODUCE_CTRL_CODE               ;发送帧的控制码暂存发送缓冲区
                    MOV     A,#01H                          ;数据域长度
                    LCALL   PRODUCE_DATA_FEILD_LEN          ;发送帧的数据长度
                    LCALL   PRODUCE_SUM_TAIL                ;形成校验和与帧结束符#16H
                    LCALL   SEND_ONE_FRAMES_ACK             ;发送读回应帧
                    RET
;------------------------------------------------------------------------------------------
;从站写异常应答帧
WRITE_FRAMES_ERR_ACK:
                    RET                                     ;数据标识错误不回应
                     
                    MOV     A,#02H                          ;数据标识错
                    ADD     A,#33H                          ;加33H
                    MOV     R0,#HW_SEND_DATA_ID1            ;发送缓冲区中要放错误信息字地址
                    MOV     @R0,A                           ;错误信息字送发送缓冲区
                    LCALL   CJQ_ACK_AND_FRAMES_HEAD_ADDR    ;形成发送帧头地址
                    MOV     A,#0C4H                         ;写异常回应标识
                    LCALL   PRODUCE_CTRL_CODE               ;发送帧的控制码暂存发送缓冲区
                    MOV     A,#01H                          ;数据域长度
                    LCALL   PRODUCE_DATA_FEILD_LEN          ;发送帧的数据长度
                    LCALL   PRODUCE_SUM_TAIL                ;形成校验和与帧结束符#16H
                    LCALL   SEND_ONE_FRAMES_ACK             ;发送写回应帧
                    RET
;---------------------------------------
;发送帧的控制码暂存发送缓冲区
;入口:A 控制码
PRODUCE_CTRL_CODE:
                MOV     R0,#HW_SEND_CTRL_CODE               ;控制码在接收缓冲区的地址
                MOV     @R0,A                               ;控制码暂存到接收缓冲区中
                RET
;---------------------------------------
;发送帧的数据长度域暂存发送缓冲区
;入口:A 数据域长度
PRODUCE_DATA_FEILD_LEN:
                MOV     R0,#HW_SEND_DATA_FEILD_LEN          ;数据长度域在接收缓冲区的地址
                MOV     @R0,A                               ;数据长度域暂存到接收缓冲区中
                RET
;--------------------------------------
;发送帧的数据标识1暂存发送缓冲区
;入口:A 数据标识DI0
;-------------------------------------
PRODUCE_DATA_ID1:
                MOV     R0,#HW_SEND_DATA_ID1                  ;数据标识1在接收缓冲区的地址
                ADD     A,#33H                                ;数据域数据加33H处理
                MOV     @R0,A                                 ;数据标识1暂存到接收缓冲区中
                RET
;--------------------------------------
;发送帧的数据标识2暂存发送缓冲区
;入口:A 数据标识DI1
;-------------------------------------
PRODUCE_DATA_ID2:
                MOV     R0,#HW_SEND_DATA_ID2                  ;数据标识2在接收缓冲区的地址
                ADD     A,#33H                                ;数据域数据加33H处理
                MOV     @R0,A                                 ;数据标识2暂存到接收缓冲区中
                RET
;---------------------------------------
;形成发送帧头和地址域
CJQ_ACK_AND_FRAMES_HEAD_ADDR:
                    MOV         R0,#HW_SEND_BUF              ;发送缓冲区首地址
                    MOV         @R0,#68H                     ;第一个帧起始符68H
                    INC         R0                           ;下一字节,地址域首址
                    MOV         R1,#HW_REC_ADDR              ;接收到的设备(采集器/表)地址
SAVE_RECE_ADDR_TO_SBUF:
                    MOV         A,@R1
                    MOV         @R0,A                       ;设备地址第一字节送发送缓冲区
                    INC         R0                          ;下一字节
                    INC         R1                          ;下一地址
                    CJNE        R1,#HW_REC_HEAD2,SAVE_RECE_ADDR_TO_SBUF ;6字节没存完继续
                    MOV         @R0,#68H                                ;第二个帧起始符68H
                    RET
;----------------------------------------------------------------------------------------------
;读写正常应答产生数据标识(读回应)和校验和及帧结束符并发送回应帧
MAKE_AND_SEND_ACK_FRAMES:
                    CJNE        R5,#81H,MAKE_WRITE_RRIGHT_ACK ;判断是读回应帧还是写回应帧
                    MOV         R0,#HW_REC_DATA_ID1
                    MOV         A,@R0                         ;数据标识一
                    LCALL       PRODUCE_DATA_ID1              ;形成发送数据标识一
                    MOV         R0,#HW_REC_DATA_ID2           ;数据标识二
                    MOV         A,@R0
                    LCALL       PRODUCE_DATA_ID2              ;形成发送数据标识二
MAKE_WRITE_RRIGHT_ACK:
                    LCALL       PRODUCE_SUM_TAIL              ;形成校验和与帧结束符#16H
                    LCALL       SEND_ONE_FRAMES_ACK           ;发送读回应帧
                    RET
;-------------------------------------------------------------------------------------------
;产生发送帧的和校验和帧尾
;B:需累加字节总数,R0:发送缓冲区地址,R1:当前累加器值暂存
;-------------------------------------------------------------------------------------------
PRODUCE_SUM_TAIL:
                MOV     R0,#HW_SEND_DATA_FEILD_LEN          ;发送数据域字节长度地址
                MOV     A,@R0                               ;读出数据域字节长度
                ADD     A,#0AH                              ;计算出需累加字节总数
                MOV     B,A                                 ;送B寄存器
                MOV     R0,#HW_SEND_BUF                     ;发送缓冲区首地址
                MOV     A,@R0                               ;读出帧起始符68H
                MOV     R1,A                                ;暂存到R1
                MOV     A,#00H                              ;累加器清0
PRODUCE_SUM_TAIL_LOOP:
                ADD     A,R1                                ;需累加字节相加
                MOV     R1,A                                ;低位保存高位溢出
                INC     R0                                  ;下一字节
                MOV     A,@R0
                DJNZ    B,PRODUCE_SUM_TAIL_LOOP
                MOV     A,R1                                ;加完后R1中为和校验值
                MOV     @R0,A                               ;存和校验
                INC     R0
                MOV     @R0,#16H                            ;存帧尾16H
                RET
;------------------------------------------
;发送一完整回应帧
;------------------------------------------
SEND_ONE_FRAMES_ACK:
                CLR     R_LEDR                              ;红外发送灯亮
                CLR     ES                                  ;禁止串行中断
                SETB    HW_CONTRA                           ;置红外发送状态
                MOV     SCON,#0C0H                          ;设置串行控制寄存器为发送状态
                CLR     TB8                                 ;清数据第9位(偶校验位)
                CLR     REN                                 ;禁止接收
                CPL     WATCH_DOG
                LCALL   SEND_FRAM_HEAD_BYTE                 ;发送3个前导字#0FEH以唤醒从机
                SETB    S_LEDR                              ;红外接收灯灭
;-----------------------------------------------------
;发送数据帧
                MOV     R0,#HW_SEND_DATA_FEILD_LEN          ;发送帧数据域长度
                MOV     A,@R0
                ADD     A,#0CH                              ;待发送帧的总长度=数据域长度+12个固定字节长度
                MOV     B,A
                MOV     R0,#HW_SEND_BUF                     ;发送缓冲区首地址
HW_SEND_FRM1:
                MOV     A,@R0
                LCALL   HW_SEND_ONE_BYTE                    ;发送单字节
                INC     R0
                DJNZ    B,HW_SEND_FRM1
                MOV     SCON,#0D0H                          ;允许接收状态
                SETB    ES                                  ;开串行中断
                CLR     HW_CONTRA                           ;置红外为接收状态
                SETB    R_LEDR                              ;红外发送灯灭
                RET
;-----------------------------------------------------------------
;发送3个前导字#0FEH
;-----------------------------------------------------------------
SEND_FRAM_HEAD_BYTE:
                MOV     A,#0FEH                             ;发送帧唤醒字FEH
                LCALL   HW_SEND_ONE_BYTE                    ;调发送一字节子程序
                MOV     A,#0FEH
                LCALL   HW_SEND_ONE_BYTE
                MOV     A,#0FEH
                LCALL   HW_SEND_ONE_BYTE
                RET
;-----------------------------------------------------------------
;发送单个字节
;入口:A为要发送字节
;-----------------------------------------------------------------
HW_SEND_ONE_BYTE:
                CPL     WATCH_DOG
                MOV     C,P                                 ;奇偶标志位赋予C(A中1的位数为奇数时P=1,反之为0)
                MOV     TB8,C                               ;送到第9位,使整个数据1的个数为偶数,形成偶校验
                MOV     SBUF,A                              ;要发送字节送发送缓冲区
HW_SEND_WAIT:
                JBC     TI,HW_SEND_BYTE_OK                  ;TI=1当前字节发送完毕,清TI位允许发送下一字节
                SJMP    HW_SEND_WAIT                        ;TI=0该字节没发完继续等待
HW_SEND_BYTE_OK:
                RET

⌨️ 快捷键说明

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