1. 0 基于 Modbus 主机接口的 OS 方案
用户可通过 22.BIN 字库文件 0x1C000~0x1FFFF 的 16KB 空间大小来定义 Modbus 数;也可通过 T5 OS 直接访问 0xE000~0xFFFF 的 8KW 变量空间来定义 Modbus ;
定义如下表:
Modbus Master 指令操作对应表(注意,Modbus 的位(线圈)变量是按照 LSB 定义的,T5 平台是按照 MSB 定义)
备注:
1. 0xE000-0xE007 的参数为主从机通用,Modbus 通信不启用时,0xE000-0xFFFF 空间以及 UART4 可任意使用;启用 Modbus 通信时,必须按表中格式配置相关参数;
2. 串口波特率设置参数(0xE002)若被写入 0x0000 时,将恢复 UART4 默认波特率(115200bps);波特率具体可设置范围请参考 T5OS 开发指南;
3. 读/写指令等待时间设置范围为 1~9999mS,默认为 60mS;(若写入 0,则自动恢复为默认值);
4. 采用 02 模式发送 Modbus 指令时,程序检测到指定 VP 地址的变量为 0x5A 时立即发送,发送完成清零 VP 变量内容,同时令指令等待时间计时器重新开始计时;
5.单次最多可读写 90 个字,若设定读写数据长度大于上限,则会自动跳过该条无效
指令;
6.禁止将读写数据在 VP 空间的起始地址以及起始地址+数据长度大于 0xDFFF,否则将视为无效指令;
2.0 基于 Modbus 从机接口的 OS 方案
Modbus Slave 指令操作表如下:(设备地址默认为 0x5A,若设定值为 0,则自动恢复默认 ID)
备注:
1. 主机可读写数据变量范围为 0x0000-0xDFFF,若超出此范围,程序会将功能码最高位置 1 并返回给主机,表明通信错误;
2. 主机可读写数据长度上限为 90 个字,超出范围则通信失败。
3.0 22 号文件初始化说明
(1)首先请确保 T5 屏幕系统配置值为“上电加载 22 号文件初始化”(具体配置方法请参考,屏幕出厂默认已经配置好,用户一般无需重新配置);
(2)此版程序基本功能与 DGUS 屏的 MDOBUS 主从机基本一致,但 22 号文件的参数配置地址改为了 0x1C000~0x1FFFF,对映 T5 变量空间中的最后 8KW 地址 0xE000~0xFFFF;
(3)指令等待时间参数的设置范围与波特率以及 MODBUS 指令长度有关,默认 115200bps下,建议最小设置为 20mS;(若不设置此参数,则程序以默认值 60mS 运行)
(4)如下图所示,图 1 为 Modbus 主机模式下的 22 号文件配置参考,0x1c000 开始的 16 字节内容为接口参数;指令配置范围 0x1c010~0x1ffff,最多 1023 条指令,两条指令之间可以连续也可以间隔若干条指令地址;图 2 为 Modbus 从机模式下的 22 号文件配置参考,仅配置 0x1c000 开始的 16 个字节即可;(主从机模式的 22 号参考文件请见附件)
图 1 主机参数配置
图 2 从机参数配置参数
4.0 参考样例
- ;DWIN OS
- ;T5 MODBUS V5 20181130 08:56 ;
- ;R10寄存器以被Modbus程序占用,用户禁止使用
- ORG 1000H
- GOTO SYS_Init ;代码的第一条指令必须是GOTO指令跳转到初始化或者主程序
- GOTO T0INT ;中断定时器0服务程序入口,必须用GOTO跳转
- NOP ;中断定时器1服务程序入口,NOP指令表示未使用
- NOP ;中断定时器2服务程序入口
-
- ORG 1080H
- SYS_Init:
- ; CALL MODBUS_SET ;MODBUS参数配置,用于测试(也可用于从OS配置MODBUS)
- CALL UART_Init ;串口初始化
- CALL Constant_Init ;常量初始化(应用程序版本号)
- CALL tiMER0_Init ;中断定时器0初始化
- CALL TIMER0_Enable ;使能中断定时器0
- CALL EA_Enable ;开定时器总中断
- CONFIG 1,2,30 ;T2定时器,基准30MS
-
- GOTO MAIN
- ;中断定时器0服务程序
- T0INT:
- ;保护现场
- LDBR R10,7,1 ;此为第0页的R10寄存器
- MOVRD R10,0,1
- ;第7页寄存器作为Modbus状态变量空间,其他地方禁用
- IJNE R19,1,T0INT_NEXT ;MODBUS_RW_STA=1,表示指令已发送
- INC R20,1,1 ;MODBUS_Cnt,单位mS
- ;超时检测
- IJNE R34,0,2
- IJNE R35,0,1
- LDWR R34,60
- JS R20,R34,T0INT_NEXT ;当前指令等待时间,最大值为9999mS
- ;清零相关参数,进入下一条指令
- LDBR R18,0,4
- LDBR R30,0,16
- T0INT_NEXT:
- ;恢复现场
- LDBR R10,0,1 ;此为第7页的R10寄存器
- MOVRD R10,0,1
- RETI ;中断返回,必须用RETI指令
- ;主函数
- MAIN:
- CALL Modbus_Master ;主机Modbus程序
- ;CALL Modbus_Slave ;从机Modbus程序
- CALL 基准定时ms
- CALL FUZHI ;上电附初值
- CALL SYS_STU
-
- GOTO MAIN
- ;*****************应用程序
-
-
-
- 基准定时ms: ;每30ms增1
- LDBR R20,0,50
- MOVDR 37,R60,2
- LDWR R62,1 ;
- JS R60,R62,MS_RET
- LDWR R0,4000H
- MOVXR R20,1,1
- INC R20,1,1
- MOVXR R20,0,1
- LDWR R60,0
- MOVRD R60,37,2
- RET
- MS_RET:
- RET
-
-
-
-
- FUZHI:
- LDWR R0,4000H
- MOVXR R20,1,1
- LDWR R22,10
- JS R20,R22,FUZHI_RUN
- LDWR R0,4000H
- LDWR R20,100
- MOVXR R20,0,1
- LDWR R0,4001H
- LDWR R20,1
- MOVXR R20,0,1
- RET
-
- FUZHI_RUN:
-
- LDWR R0,2000H
- LDWR R2,3000H
- MOVXX 14
- RET
-
-
- SYS_STU:
- LDWR R0,0X4001
- MOVXR R20,1,1
- IJNE R21,1,1
- CALL BILI_STU
-
- RET
-
- BILI_STU:
- LDWR R0,3000H
- MOVXR R20,1,14
- LDWR R0,2000H
- MOVXR R80,1,14
- TESTS R20,R80,28
- IJNE R0,0,1
- RET
- LDWR R0,0X1700
- LDWR R150,0X005A
- MOVXR R150,0,1
- RET
-
-
-
- ;******************************
- MODBUS_SET:
- LDWR R0,Modbus_EN ;MODBUS启用标记
- LDWR R60,5AA5H ;0x5AA5=启用,其他=不启用
- LDWR R62,0 ;主从机标记,0=主机,1=从机
- LDWR R64,1152 ;串口波特率,115200bps
- LDWR R66,0 ;串口模式,8N1
- LDWR R68,5AH ;从机设备地址
- MOVXR R60,0,5
- ;
- LDADR MODBUS_CMD1_TAB ;第一条指令表
- MOVC R60,16
- LDWR R0,Modbus_CMD1
- MOVXR R60,0,8
- ;
- LDADR MODBUS_CMD2_TAB
- MOVC R60,16
- LDWR R0,Modbus_CMD1
- INC R0,1,8
- MOVXR R60,0,8
- ;
- LDADR MODBUS_CMD3_TAB
- MOVC R60,16
- LDWR R0,Modbus_CMD1
- INC R0,1,16
- MOVXR R60,0,8
- RET
-
- UART_Init:
- ;UART4配置,详见<基于T5CPU的DWIN OS程序开发指南>
- LDWR R0,Modbus_EN ;Modbus启用标记
- MOVXR R60,1,1
- LDWR R62,5AA5H
- TESTS R60,R62,2
- IJNE R0,0,UART_Init_RET
- ;Modbus_EN=0x5AA5,启用Modbus,从0xE002读取串口配置信息
- LDBR R20,40H,1 ;串口4
- LDWR R0,Modbus_UART ;0xE002-E003为串口配置参数
- MOVXR R60,1,2
- LDWR R70,4
- JU R62,R70,1 ;R63为串口模式设置参数,设置范围0-3
- LDWR R62,0
- OR R20,R63,1
- LDWR R64,0
- TESTS R60,R64,2
- IJNE R0,0,1
- LDWR R60,1152 ;若波特率设定值为0,则恢复默认波特率
- LDBR R70,0,8
- MOV R60,R70,2 ;波特率设置值,单位*100bps
- LDWR R72,100
- SMAC R70,R72,R74
- LDBR R70,0,4
- LDBR R80,0,8
- LDWR R84,EFH
- LDWR R86,1000H ;0xEF1000=15667200
- DIV R80,R70,0
- MOV R86,R21,2
- COMSET R20,0
- UART_Init_RET:
- RET
-
- TIMER0_Init:
- ;定时参数设置
- LDBR R20,100,1 ;100*10uS=1mS
- MOVRD R20,46,1 ;DR46=Timer INT0 Set
- RET
-
-
- TIMER0_Enable:
- ;开定时器0中断
- MOVDR 45,R20,1 ;DR45=Int_Reg
- LDBR R21,40H,1 ;Int_Reg.6=Timer INT0 Enable
- OR R20,R21,1
- MOVRD R20,45,1
- RET
-
- TIMER0_Disable:
- ;关定时器0中断
- MOVDR 45,R20,1
- LDBR R21,BFH,1
- AND R20,R21,1
- MOVRD R20,45,1
- RET
-
- EA_Enable:
- ;开定时器总中断
- MOVDR 45,R20,1
- LDBR R21,80H,1 ;Int_Reg.7=EA
- OR R20,R21,1
- MOVRD R20,45,1
- RET
-
- EA_Disable:
- ;关定时器总中断
- MOVDR 45,R20,1
- LDBR R21,7FH,1
- AND R20,R21,1
- MOVRD R20,45,1
- RET
- Constant_Init:
- ;将版本号保存在变量空间,方便从串口读取
- LDADR Version_TAB
- MOVC R20,2
- LDWR R0,Mdobus_Ver
- MOVXR R20,0,1
- RET
-
- Modbus_Master:
- LDWR R0,Modbus_EN ;Modbus启用标记,5AA5H表示启用Modbus_Master
- MOVXR R60,1,1
- IJNE R60,5AH,Modbus_Master_RET
- IJNE R61,A5H,Modbus_Master_RET
- LDWR R0,Modbus_Mode ;Modbus主从机模式
- MOVXR R60,1,1
- IJNE R61,0,Modbus_Master_RET
- ;Modbus主机
- RDXLEN 4,R18 ;读串口4接收缓冲区字节长度
- IJNE R18,0,Modbus_Master_Rx
- ;0x00表示接收缓冲区没有数据,可以发送
- GOTO Modbus_Master_Tx
- Modbus_Master_Rx:
- MOVDR 17,R19,1 ;DR17表示串口4接收帧超时定时器状态
- IJNE R19,0,Modbus_Master_RET
- ;DR17=0x00表示一帧数据接收完成
- RDXDAT 4,R20,R18 ;读取串口缓冲区数据到R20开始的寄存器
- DEC R18,0,2
- CRCA R20,R16,R18 ;计算CRC16校验值,结果存放在R16:R17
- MOV R16,R254,2
- LDBR R238,0,8 ;R238-253,16个寄存器
- LDWR R240,20 ;数据帧起始位置
- MOV R18,R245,1 ;帧长度-校验位
- ADD R238,R242,R246
- MOV R253,R2,1 ;数据帧中CRC校验值存放位置
- LDBR R3,18,1
- LDBR R9,2,1
- MOVA
- CJNE R254,R18,MODBUS_MasterRx_ERR
- CJNE R255,R19,MODBUS_MasterRx_ERR
- ;校验正确,数据帧存放的寄存器空间为R20-R199,最长180字节
- LDWR R0,MODBUS_CMD_Buff ;当前16字节指令缓存区
- LDWR R2,240
- LDBR R9,16,1
- MOVA 1
- CJNE R241,R20,MODBUS_MasterRx_ERR
- ;站号匹配
- IJNE R21,1,2
- ;从机响应0x01指令
- CALL MODBUS_MasterRx_CMD01
- GOTO MODBUS_MasterRx_END
- IJNE R21,2,2
- ;从机响应0x02指令
- CALL MODBUS_MasterRx_CMD01 ;0x02指令响应内容与0x01类似,数据存储格式为LSB
- GOTO MODBUS_MasterRx_END
- IJNE R21,3,2
- ;从机响应0x03指令
- CALL MODBUS_MasterRx_CMD03 ;0x03指令响应,数据存储格式为MSB
- GOTO MODBUS_MasterRx_END
- IJNE R21,4,2
- ;从机响应0x04指令
- CALL MODBUS_MasterRx_CMD03 ;0x04指令响应内容与0x03类似
- GOTO MODBUS_MasterRx_END
- IJNE R21,7,2
- ;从机响应0x07指令
- CALL MODBUS_MasterRx_CMD07
- GOTO MODBUS_MasterRx_END
- IJNE R21,5,1
- GOTO MODBUS_MasterRx_END
- IJNE R21,6,1
- GOTO MODBUS_MasterRx_END
- IJNE R21,0FH,1
- GOTO MODBUS_MasterRx_END
- IJNE R21,10H,MODBUS_MasterRx_ERR
- MODBUS_MasterRx_END:
- ;当前指令已完成收发,下一条指令不再延时,准备直接发送
- MOV R244,R60,2
- LDWR R0,60
- LDWR R2,MODBUS_Cnt
- LDBR R9,2,1
- MOVA 1
- LDWR R100,FFH ;通信成功
- CALL MODBUS_STA_FeedBack
- GOTO Modbus_Master_RET
- MODBUS_MasterRx_ERR:
- LDWR R100,0 ;通信失败
- CALL MODBUS_STA_FeedBack
- GOTO Modbus_Master_RET
-
- Modbus_Master_Tx:
- CALL TIMER0_Disable ;停止定时器0中断
- LDWR R0,MODBUS_STA ;MODBUS指令状态,0表示可以进入下一条指令,1表示正在计时
- LDWR R2,60
- LDBR R9,1,1
- MOVA 1
- IJNE R60,0,Modbus_MasterTx_NEXT
- CALL Modbus_Master_CMDCheck ;检测并依次读取有效指令
- IJNE R50,0,1
- GOTO Modbus_Master_END
- ;当前指令有效
- LDBR R60,1,1 ;MODBUS指令状态标记置1
- LDBR R61,0,1 ;MODBUS_RW_STA
- LDWR R0,60
- LDWR R2,MODBUS_STA
- LDBR R9,2,1
- MOVA 1
- Modbus_MasterTx_NEXT:
- LDWR R0,MODBUS_CMD_Buff ;当前16字节发送指令缓存区
- LDWR R2,20
- LDBR R9,16,1
- MOVA 1
- IJNE R27,2,Modbus_MasterTx_NEXT1
- ;0x02模式,直接发送
- MOV R28,R0,2
- LDWR R60,0 ;发送完成后将VP变量内容清零
- MOVXR R60,0,1
- LDBR R60,0,16
- LDWR R0,60
- LDWR R2,MODBUS_CMD_Buff ;将指令缓存区清零,防止重复发送本条指令
- LDBR R9,16,1
- MOVA 1
- CALL Modbus_Master_TXD
- GOTO Modbus_Master_END
- Modbus_MasterTx_NEXT1:
- ;MODBUS_RW_STA=0表示可以发送指令,1表示已发送或正在延时
- LDWR R0,MODBUS_RW_STA
- LDWR R2,60
- LDBR R9,1,1
- MOVA 1
- IJNE R60,0,1
- CALL Modbus_Master_TXD ;执行当前指
- Modbus_Master_END:
- CALL TIMER0_Enable
- Modbus_Master_RET:
- RET
- MODBUS_MasterRx_CMD01:
- LDBR R200,0,16
- MOV R22,R207,1 ;字节数,存在单数
- LDWR R214,2
- DIV R200,R208,0
- IJNE R215,0,1
- GOTO MODBUS_MasterRx_CMD01_NEXT
- ;单数字节,末位字节填0
- LDBR R216,0,16
- LDWR R218,23 ;首地址
- MOV R206,R222,2 ;除数
- ADD R216,R220,R224
- MOV R214,R226,2 ;余数
- ADD R224,R228,R216 ;首地址R23+除数+余数=需要填0的末位字节地址
- LDWR R216,0
- LDWR R0,216
- MOV R222,R2,2
- LDBR R9,1,1
- MOVA
- INC R207,0,1
- MODBUS_MasterRx_CMD01_NEXT:
- MOV R207,R9,1 ;字数
- MOV R250,R0,2 ;变量存储空间首地址
- MOVXR R23,0,0
- RET
- MODBUS_MasterRx_CMD03:
- LDBR R200,0,16
- MOV R22,R207,1 ;字节数
- LDWR R214,2
- DIV R200,R208,0
- MOV R207,R9,1 ;字数
- MOV R250,R0,2 ;变量存储空间首地址
- MOVXR R23,0,0
- RET
-
- MODBUS_MasterRx_CMD07:
- ;从机响应内容:站号 功能码 异常状态高位 异常状态低位 CRCL CRCH
- MOV R250,R0,2 ;变量存储地址
- MOVXR R22,0,1
- RET
- MODBUS_STA_FeedBack:
- ;总线通信状态反馈,用户读取通信状态反馈字后应清零
- LDBR R60,0,16
- LDWR R0,MODBUS_SP
- LDWR R2,62
- LDBR R9,2,1
- MOVA 1
- JU R60,R62,2
- ;R62:R63=0,上一刻发送的是第1022条指令(最后一条)
- LDWR R62,1022
- GOTO MODBUS_FeedBack_NEXT
- DEC R62,1,1 ;上一刻发送的是第N条指令,N=0~1021
- MODBUS_FeedBack_NEXT:
- LDWR R60,8 ;一条指令占8个字
- SMAC R60,R62,R64
- LDBR R60,0,4
- LDWR R62,Modbus_CMD1
- ADD R60,R64,R68 ;SP(Modbus_CMD1)+N*8=当前指令首地址
- LDBR R60,0,12
- LDWR R70,7
- ADD R68,R72,R60 ;当前指令首地址+0x07=总线通信状态反馈地址
- MOV R66,R0,2
- MOVXR R100,0,1
- RET
-
- Modbus_Master_CMDCheck:
- ;R50=0表示无有效指令,1表示有待发送指令
- ;R20-35为当前待发送指令
- LDBR R50,0,1 ;清空R50寄存器
- LDBR R60,0,8
- LDWR R0,MODBUS_SP ;当前指令指针,表示第N条指令,0<=N<=1022
- LDWR R2,60 ;目标寄存器地址
- LDBR R9,2,1 ;交换的字节长度
- MOVA 1 ;寄存器数据交换(跨寄存器页)
- LDWR R62,8 ;每条指令占8个字
- SMAC R60,R62,R64 ;SP*8为指令偏移字数
- LDBR R70,0,12
- LDWR R72,Modbus_CMD1 ;第一条指令的起始地址
- ADD R70,R64,R74
- MOV R80,R0,2 ;第N条指令的起始地址
- MOVXR R20,1,8
- INC R60,1,1 ;指令指针N+1
- LDWR R100,1023
- JU R60,R100,MM_CMDCheck_NEXT
- ;第1022条指令检测完毕
- LDWR R60,0
- MM_CMDCheck_NEXT:
- LDWR R0,60
- LDWR R2,MODBUS_SP ;保存下一条指令指针N
- LDBR R9,2,1
- MOVA 1
- IJNE R20,5AH,MM_CMDCheck_RET ;若当前指令无效,则退出,等待下一周再检测下一条指令
- IJNE R23,0,1
- ;读写数据长度=0,本条指令无效
- GOTO MM_CMDCheck_RET
- IJNE R27,1,MM_CMDCheck_NEXT1
- ;0x01模式,在指定页面下执行
- LDWR R0,PIC_Now ;当前页面ID
- MOVXR R200,1,1
- TESTS R200,R28,2
- IJNE R0,0,MM_CMDCheck_RET
- GOTO MM_CMDCheck_NEXT2
- MM_CMDCheck_NEXT1:
- IJNE R27,2,MM_CMDCheck_NEXT2
- ;0x02模式,仅在指向的变量低字节为0x5A时才执行
- MOV R28,R0,2
- MOVXR R200,1,1
- IJNE R201,5AH,MM_CMDCheck_RET
- MM_CMDCheck_NEXT2:
- LDWR R200,0
- LDWR R202,180 ;数据长度上限,180字节=90字
- MOV R23,R201,1 ;读写数据长度
- JU R202,R200,MM_CMDCheck_RET
- LDBR R200,0,16
- MOV R30,R202,2 ;读写数据在VP空间的起始地址
- MOV R23,R207,1 ;读写数据长度
- ADD R200,R204,R208
- LDWR R208,DFFFH ;VP空间可读写上限
- JU R208,R214,MM_CMDCheck_RET
- ;本条指令有效
- LDWR R0,20
- LDWR R2,MODBUS_CMD_Buff ;将待发送的指令内容写入到发送缓冲区
- LDBR R9,16,1
- MOVA 1
- LDBR R50,1,1
- MM_CMDCheck_RET:
- RET
-
- Modbus_Master_TXD:
- ;发送状态置1,表明已经发送
- LDBR R60,1,1
- LDWR R0,60
- LDWR R2,MODBUS_RW_STA
- LDBR R9,1,1
- MOVA 1
- ;执行指令
- MOV R21,R60,2 ;ID+功能码
- IJNE R22,1,2
- ;0x01,读取输入线圈状态
- CALL Modbus_Master_CMD01
- GOTO Modbus_MasterTXD_RET ;发送指令后,等待从机回复再进入下一条指令
- IJNE R22,2,2
- ;0x02,读取输入位变量状态
- CALL Modbus_Master_CMD01 ;0x02指令除了功能码以外,其余和0x01指令内容一样
- GOTO Modbus_MasterTXD_RET
- IJNE R22,3,2
- ;0x03,读取保持寄存器数据
- CALL Modbus_Master_CMD03
- GOTO Modbus_MasterTXD_RET
- IJNE R22,4,2
- ;0x04,读取输入寄存器数据
- CALL Modbus_Master_CMD03 ;0x04指令除功能码外和0x03指令相同
- GOTO Modbus_MasterTXD_RET
- IJNE R22,7,2
- ;0x07,读取异常状态
- CALL Modbus_Master_CMD07
- GOTO Modbus_MasterTXD_RET
- IJNE R22,5,2
- ;0x05,强置单个线圈
- CALL Modbus_Master_CMD05
- GOTO Modbus_MasterTXD_RET
- IJNE R22,6,2
- ;0x06,预置单个寄存器
- CALL Modbus_Master_CMD05 ;0x06指令除功能码外和0x05指令相同
- GOTO Modbus_MasterTXD_RET
- IJNE R22,0FH,2
- ;0x0F,强置多个线圈
- CALL Modbus_Master_CMD0F
- GOTO Modbus_MasterTXD_RET
- IJNE R22,10H,Modbus_MasterTXD_RET
- ;0x10,预置多个寄存器
- CALL Modbus_Master_CMD10
- Modbus_MasterTXD_RET:
- RET
-
- Modbus_Master_CMD01:
- ;站号ID 功能码 起始地址高位 起始地址低位 总位数高位 总位数低位 CRCL CRCH
- MOV R32,R62,2 ;起始地址
- LDBR R40,0,8
- MOV R23,R41,1 ;待读取数据长度=线圈个数/8
- LDWR R42,8
- SMAC R40,R42,R44 ;总位数(线圈个数)=待读取数据长度*8
- MOV R46,R64,2 ;总位数
- LDBR R40,6,1
- CRCA R60,R66,R40 ;LSB
- INC R40,0,2
- COMTXD 4,R60,R40
- RET
-
- Modbus_Master_CMD03:
- ;站号ID 功能码 起始地址高位 起始地址低位 总寄存器数高位 总寄存器数低位 CRCL CRCH
- MOV R32,R62,2 ;起始地址
- LDBR R40,0,16
- MOV R23,R47,1 ;待读取数据长度=寄存器数*2
- LDWR R54,2
- DIV R40,R48,0 ;总寄存器数=待读取数据长度/2
- MOV R46,R64,2 ;总寄存器数
- LDBR R40,6,1
- CRCA R60,R66,R40 ;LSB
- INC R40,0,2
- COMTXD 4,R60,R40
- RET
-
- Modbus_Master_CMD05:
- ;站号ID 功能码 线圈地址高位 线圈地址低位 强制状态高位 强制状态低位 CRCL CRCH
- MOV R32,R62,2 ;线圈地址
- MOV R30,R0,2 ;存放线圈状态的变量地址
- MOVXR R64,1,1
- LDBR R40,6,1
- CRCA R60,R66,R40 ;LSB
- INC R40,0,2
- COMTXD 4,R60,R40
- RET
- Modbus_Master_CMD07:
- ;站号ID 功能码 CRCL CRCH
- LDBR R40,2,1
- CRCA R60,R62,R40
- INC R40,0,2
- COMTXD 4,R60,R40
- RET
-
- Modbus_Master_CMD0F:
- ;站号ID 功能码 线圈地址高位 线圈地址低位 线圈数量高位 线圈数量低位 字节数 n*(线圈状态高位 线圈状态低位) CRCL CRCH
- MOV R32,R62,2 ;线圈地址
- LDBR R64,0,1
- MOV R23,R65,1 ;线圈数量
- LDBR R40,0,16
- MOV R23,R47,1
- LDWR R54,16 ;1字节=16个线圈
- DIV R40,R48,0
- IJNE R55,0,1
- ;余数为0,则字节数正确
- GOTO Modbus_MasterCMD0F_NEXT
- ;余数不为0,则字节数+1
- INC R47,0,1
- Modbus_MasterCMD0F_NEXT:
- MOV R47,R66,1 ;字节数
- MOV R47,R9,1
- MOV R30,R0,2 ;线圈状态存放的变量地址
- MOVXR R67,1,0
- INC R47,0,7
- CRCA R60,R58,R47 ;CRC校验值结果存放在R58:59
- LDBR R40,0,16
- LDWR R42,60 ;目标寄存器起始地址
- MOV R67,R47,1
- INC R47,0,7 ;数据长度
- ADD R40,R44,R48
- LDBR R2,58,1
- MOV R55,R3,1 ;CRC校验在数据帧中的位置=起始地址+数据长度
- LDBR R9,2,1
- MOVA
- INC R47,0,2 ;数据长度+2字节校验值=数据帧长度
- COMTXD 4,R60,R47
- RET
-
- Modbus_Master_CMD10:
- ;站号ID 功能码 起始地址高位 起始地址低位 寄存器总数高位 寄存器总数低位 寄存器总字节数 n*(寄存器值高位 寄存器值低位) CRCL CRCH
- MOV R32,R62,2 ;起始地址
- LDBR R40,0,8
- MOV R23,R47,1 ;字节数
- LDBR R50,0,8
- LDWR R56,2
- DIV R40,R50,0
- MOV R46,R64,2 ;寄存器总数
- MOV R23,R66,1 ;寄存器总字节数
- MOV R30,R0,2 ;待写入变量起始地址
- MOV R65,R9,1 ;数据字长度(1-94)
- MOVXR R67,1,0
- INC R23,0,7
- CRCA R60,R58,R23 ;CRC校验值结果存放在R58:59
- LDBR R40,0,16
- LDWR R42,60 ;目标寄存器起始地址
- MOV R23,R47,1 ;数据长度
- ADD R40,R44,R48
- LDBR R2,58,1
- MOV R55,R3,1 ;CRC校验在数据帧中的位置=起始地址+数据长度
- LDBR R9,2,1
- MOVA
- INC R47,0,2 ;数据长度+2字节校验值=数据帧长度
- COMTXD 4,R60,R47
- RET
-
- Modbus_Slave:
- LDWR R0,Modbus_EN ;Modbus启用标记
- MOVXR R60,1,1
- LDWR R62,5AA5H
- TESTS R60,R62,2
- IJNE R0,0,Modbus_Slave_RET
- LDWR R0,Modbus_Mode ;Modbus主从机模式
- MOVXR R60,1,1
- IJNE R61,0,1
- GOTO Modbus_Slave_RET
- ;Modbus从机
- CALL ModbusSlave_ID_Check ;设备ID检测
- RDXLEN 4,R18 ;读串口4接收缓冲区字节长度
- IJNE R18,0,Modbus_Slave_Rx
- ;0x00表示没有数据
- GOTO Modbus_Slave_RET
- Modbus_Slave_Rx:
- MOVDR 17,R19,1 ;DR17表示串口4接收帧超时定时器状态
- IJNE R19,0,Modbus_Slave_RET
- ;DR17=0x00表示一帧数据接收完成
- RDXDAT 4,R20,R18 ;读取串口缓冲区数据到R20-199的寄存器空间
- MOV R18,R237,1
- DEC R237,0,2
- CRCA R20,R16,R237 ;计算CRC16校验值,结果存放在R16:R17
- MOV R16,R254,2
- LDBR R238,0,8 ;R238-253,16个寄存器
- LDWR R240,20 ;数据帧起始位置
- MOV R237,R245,1 ;帧长度-校验位
- ADD R238,R242,R246
- MOV R253,R2,1 ;数据帧中CRC校验值存放位置
- LDBR R3,238,1
- LDBR R9,2,1
- MOVA
- CJNE R254,R238,Modbus_SlaveRx_ERR
- CJNE R255,R239,Modbus_SlaveRx_ERR
- ;校验正确
- LDWR R0,Modbus_SlaveID
- MOVXR R250,1,1
- CJNE R20,R251,Modbus_SlaveRx_ERR
- ;站号匹配
- IJNE R21,03H,Modbus_SlaveRx_CMD06
- ;0x03指令,读取VP变量空间
- LDWR R250,90 ;单次最多读写90个字
- JU R250,R24,Modbus_SlaveRx_ERR ;R24:25存放的是寄存器总数,即字数
- LDBR R240,0,16
- MOV R22,R242,2 ;VP变量起始地址
- MOV R24,R246,2 ;变量字数
- ADD R240,R244,R248
- LDWR R250,DFFFH ;变量可读写范围:0x0000~0xDFFF
- JU R250,R254,Modbus_SlaveRx_ERR
- MOV R22,R0,2 ;起始地址
- MOV R25,R9,1 ;读取字数
- MOVXR R23,1,0
- LDWR R244,2
- LDBR R240,0,4
- SMAC R244,R246,R240
- MOV R243,R22,1 ;待返回的寄存器字节数
- MOV R22,R255,1
- INC R255,0,3
- CRCA R20,R250,R255 ;校验值存放在R250:251
- LDBR R230,0,16
- LDWR R232,20
- MOV R255,R237,1
- ADD R230,R234,R238 ;CRC校验应存放的位置=数据帧首地址+帧数据长度
- LDBR R2,250,1
- MOV R245,R3,1
- LDBR R9,2,1
- MOVA
- INC R255,0,2 ;待发送数据帧总长度
- COMTXD 4,R20,R255
- GOTO Modbus_Slave_RET
- Modbus_SlaveRx_CMD06:
- IJNE R21,06H,Modbus_SlaveRx_CMD10
- ;0x06指令,写单个VP变量
- LDWR R240,DFFFH
- JU R240,R22,Modbus_SlaveRx_ERR
- MOV R22,R0,2 ;目标变量
- MOVXR R24,0,1
- COMTXD 4,R20,R18 ;原指令返回
- GOTO Modbus_Slave_RET
- Modbus_SlaveRx_CMD10:
- IJNE R21,10H,Modbus_SlaveRx_ERR
- ;0x10指令,写VP变量空间
- LDWR R250,90 ;单次最多读写90个字
- JU R250,R24,Modbus_SlaveRx_ERR ;R24:25存放的是寄存器总数,即字数
- LDBR R240,0,16
- MOV R22,R242,2 ;VP变量起始地址
- MOV R24,R246,2 ;变量字数
- ADD R240,R244,R248
- LDWR R250,DFFFH ;变量可读写范围:0x0000~0xDFFF
- JU R250,R254,Modbus_SlaveRx_ERR
- MOV R22,R0,2 ;目标变量起始地址
- MOV R25,R9,1 ;写入变量字数
- MOVXR R27,0,0
- LDBR R255,6,1
- CRCA R20,R250,R255
- MOV R250,R26,2
- LDBR R18,8,1
- COMTXD 4,R20,R18
- GOTO Modbus_Slave_RET
- Modbus_SlaveRx_ERR:
- LDBR R250,0x80,1
- OR R21,R250,1 ;将功能码最高位置1,并返回给主机,表示错误信息
- MOV R18,R255,1
- DEC R255,0,2
- CRCA R20,R250,R255
- LDBR R230,0,16
- LDWR R232,20
- MOV R255,R237,1
- ADD R230,R234,R238 ;计算校验值存放位置
- LDBR R2,250,1
- MOV R245,R3,1
- LDBR R9,2,1
- MOVA
- COMTXD 4,R20,R18
- Modbus_Slave_RET:
- RET
- ModbusSlave_ID_Check:
- ;若设备ID被错误地设置为0,则恢复默认值
- LDWR R0,Modbus_SlaveID
- MOVXR R60,1,1
- LDWR R62,0
- CJNE R60,R62,MSID_Check_RET
- CJNE R61,R63,MSID_Check_RET
- LDWR R60,5AH
- MOVXR R60,0,1
- MSID_Check_RET:
- RET
-
- Version_TAB:
- DW 0405H
- MODBUS_CMD1_TAB:
- DB 5AH ;0x5A=本条指令有效,其他表示无效
- DB 04H ;读写的MODBUS设备地址
- DB 03H ;读写的MODBUS指令
- DB 20 ;读写数据长度,0x00表示本条指令无效
- DW 50 ;指令等待时间,单位mS
- DB 0 ;未定义
- DB 0 ;指令操作模式,0x01=指定页面下执行,0x02=指定变量低字节内容为0x5A才执行(执行完自动清零),其他表示总是执行
- DW 0 ;Page_ID或VP地址
- DW 1400H ;数据变量存储地址(VP)
- DW 00H ;MODBUS设备寄存器地址
- DW 0 ;总线通信状态反馈
- MODBUS_CMD2_TAB:
- DB 5AH, 01H, 03H, 20, 0, 50, 0, 0, 0, 0, 15H, 00H, 0, 00H, 0, 0
-
- MODBUS_CMD3_TAB:
- DB 5AH, 03H, 03H, 20, 0, 50, 0, 0, 0, 0, 16H, 00H, 0, 00H, 0, 0
-
-
-
- ;*****滚动显示
- TEMTAB1: ;温度测量错误
- DB CEH,C2H,B6H,C8H,B2H,E2H,C1H,BFH,B4H,EDH,CEH,F3H,20H,20H,20H,20H,20H,20H,20H,20H,
- TEMTAB2: ;温度过低或传感器短路
- DB CEH,C2H,B6H,C8H,B9H,FDH,B5H,CDH,BBH,F2H,B4H,ABH,B8H,D0H,C6H,F7H,B6H,CCH,C2H,B7H
- TEMTAB3: ;温度过低或传感器短路
- DB CEH,C2H,B6H,C8H,B9H,FDH,B8H,DFH,BBH,F2H,B4H,ABH,B8H,D0H,C6H,F7H,B6H,CCH,C2H,B7H
- TEMTAB4: ;超温
- DB B3H,ACH,CEH,C2H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H
- TEMTAB5: ;正在自整定
- DB D5H,FDH,D4H,DAH,D7H,D4H,D5H,FBH,B6H,A8H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H
- TEMTAB6: ;缺水
- DB C8H,B1H,CBH,AEH,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H
- TEMTAB7: ;缺水
- DB D4H,CBH,D0H,D0H,BDH,E1H,CAH,F8H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H
- TEMTAB8: ;空
- DB 20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H
-
复制代码
|