请教例子Tip041B(Modbus RTU)的问题

已锁定

翼龙

  • 帖子

    34
  • 精华

    0
  • 被关注

    1

论坛等级:新手

注册时间:2005-03-23

普通 普通 如何晋级?

请教例子Tip041B(Modbus RTU)的问题

642

5

2005-08-21 15:58:33

西门子的程序例子Tip041B(S7-214做从站Modbus RTU)中,程序说明中VB3300-VB3359为通信缓冲区,VB3560-VB3575为MODBUS的临时存储器,VB3580-VB4095为CRC数据库。
请教:VB3300-VB3359为通信缓冲区是不是说由它们来存储主机发送来的请求和从机应答的数据?它们在程序中那儿被指定的?具体是如何分配的?VW3302为请求的功能号,VW3304为请求位或字的起始地址,VW3306为请求的位或字的个数,那么VW3300中是不是应该为请求的从机地址呢?
程序如下:
---------------------------------------------------------------------
MAIN
Network 1
LD SM0.1
CALL SBR50
Network 2
LD M31.7 // 如果有Modbus请求出现
CALL SBR51 // 则调用处理程序
R M31.7, 1 // 清除请求标志(M31.7=0)
Network 3 // 主程序结束// MEND
---------------------------------------------------------------------
SBR_50 初始化 Modbus RTU 驱动器
初始化Modbus驱动器通信口0,注意:由于要初始化CRC表,这段初始化子程序需要大约690ms,执行时间不要报警!初始化不同数据类型的存储器极限注意:存储的最大值必须比实际极限大1,例如:允许32个输出,那就设定33
Network 1

// SBR 50
Network 2
LD SM0.0 // SM0.0总为1
MOVW +65, VW3290 // 最大值IR = 64 位
MOVW +1001, VW3292 // 最大 V 字= 2000 字节(1000)字
MOVW +17, VW3294 // 最大AI字= 16 字
MOVD &VB2000, VD3296 // V存储器的AI字首址


MOVW +8, VW3574 // Load a constant value = 8 to be
// used in mathmatical operations.
MOVB 1, VB4095 // Modbus 地址= 1.
MOVB 16#49, SMB30 // 9600波特,每个符8位,偶校验
CALL SBR62 // 初始化CRC表
R M31.7, 1 // 信息到达标志复位(M31.7=0)
ENI // 允许中断
MOVB 6, SMB34 // 设定静止线定时器>5ms
ATCH INT120, 10 // 开始寻找静止线,若静止线定时器到时,
//则调用中断程序INT 120
ATCH INT121, 8 // 在寻找静止线期间,如果收到一个字符,
// 那就执行中断程序INT121
---------------------------------------------------------------------
SBR_51 处理 Modbus 请求和传送响应
该子程序在正常的梯形图扫描周期内处理Modbus请求。计算收到信息的CRC。由于收到信息中的CRC包含在计算之内,若没有接收错误,那么计算结果总是0。
Network 1 // SBR 51
Network 2
LD SM0.0 // SM0.0总为1
MOVW VW3300, AC0 // 取缓冲区长度存入AC0
MOVD &VB3302, AC1 // 取缓冲区地址存入AC1,用于CRC检查
CALL SBR63 // 计算 CRC.
Network 3
LDW= +0, AC2 // 如果(计算CRC不等于0)
NOT // 那就表示有接收错误
JMP 255 // 跳转到LBL255
Network 4
// 信息正常,决定哪个Modbus功能被请求。// 再调用返回后总是执行紧随调用之后的跳步指令。// 因为返回前子程序总设定TOS 为1
LD SM0.0 // SM0.0总是1
MOVB VB3303, AC0 // 从请求缓冲区中取功能号存入AC0
Network 5
LDB= 1, AC0 // 是功能1?
CALL SBR52 // 是,执行功能1
JMP 254 // 然后跳到结束(LBL 254)
Network 6
LDB= 2, AC0 // 是功能2?
CALL SBR52 // 是,执行
JMP 254 // 然后跳到结束

Network 7
LDB= 3, AC0 // 是功能3?
CALL SBR53 // 是,执行
JMP 254 // 然后跳到结束
Network 8
LDB= 4, AC0 // 是功能4?
CALL SBR53 // 是,执行
JMP 254 // 然后跳到结束
Network 9

LDB= 5, AC0 // 是功能5?
CALL SBR54 // 是,执行
JMP 254 // 然后跳到结束
Network 10
LDB= 6, AC0 // 是功能6?
CALL SBR55 // 是,执行
JMP 254 // 然后跳到结束
Network 11
LDB= 15, AC0 // 是功能15?
CALL SBR56 // 是,执行
JMP 254 // 然后跳到结束
Network 12
LDB= 16, AC0 // 是功能16?
CALL SBR57 // 是,执行


JMP 254 // 然后跳到结束
Network 13
LD SM0.0 // 如果上面都不成立
MOVW +3, VW3300 // 装入错误响应长度
ORW 16#80, VW3302 // 把功能MS位置1,表示出错
MOVB 1, VB3304 // 装入"功能不支持"代码(VB3304=1)
Network 14 // 功能服务,首先计算响应的CRC,然后发送响应。根请求一样,把响应
// 的长度也放在缓冲区的第一个字中。该长度不包括CRC的2个字节长度,因此在调用发送指令之前必须将长度增加2。
LBL 254 // 标签254(跳转入口)
Network 15
LD SM0.0 // SM0.0总为1
MOVW VW3300, AC0 // 取信息长度存入AC0
MOVD &VB3302, AC1 // 取缓冲区起始地址存入AC1,用于CRC检验
CALL SBR63 // 计算CRC,
MOVD &VB3302, AC3 // 取缓冲区起始地址
+I VW3300, AC3 // 指向缓冲区尾
MOVW AC2, *AC3 // 把CRC放到缓冲区
+I +2, VW3300 // 加CRC的两字节
XMT VB3301, 0 // 发送响应
ATCH INT125, 9 // 当发送完成时执行中断程序INT125
CRET // 返回
Network 16 // CRC或长度出错处理// 在下列情况下,如CRC出错,或者没有收到足够字节的处理信息,除了通信复位外,寻找下一段信息,且使主机到时。
LBL 255 // 标签255(跳转入口)
Network 17
LD SM0.0 // SM0.0总为1
ATCH INT120, 10 // 开始寻找静止线,此期间
ATCH INT121, 8 // 如果收到字符,那就执行中断程序INT121
Network 18 // 返回// RET
---------------------------------------------------------------------
SBR_51 处理 Modbus 请求和传送响应
该子程序在正常的梯形图扫描周期内处理Modbus请求。计算收到信息的CRC。由于收到信息中的CRC包含在计算之内,若没有接收错误,那么计算结果总是0。
Network 1 // SBR 51
Network 2
LD SM0.0 // SM0.0总为1
MOVW VW3300, AC0 // 取缓冲区长度存入AC0
MOVD &VB3302, AC1 // 取缓冲区地址存入AC1,用于CRC检查
CALL SBR63 // 计算 CRC.
Network 3
LDW= +0, AC2 // 如果(计算CRC不等于0)
NOT // 那就表示有接收错误
JMP 255 // 跳转到LBL255
Network 4
// 信息正常,决定哪个Modbus功能被请求。// 再调用返回后总是执行紧随调用之后的跳步指令。// 因为返回前子程序总设定TOS 为1
LD SM0.0 // SM0.0总是1
MOVB VB3303, AC0 // 从请求缓冲区中取功能号存入AC0
Network 5
LDB= 1, AC0 // 是功能1?
CALL SBR52 // 是,执行功能1
JMP 254 // 然后跳到结束(LBL 254)
Network 6
LDB= 2, AC0 // 是功能2?
CALL SBR52 // 是,执行
JMP 254 // 然后跳到结束

Network 7
LDB= 3, AC0 // 是功能3?
CALL SBR53 // 是,执行
JMP 254 // 然后跳到结束
Network 8
LDB= 4, AC0 // 是功能4?
CALL SBR53 // 是,执行
JMP 254 // 然后跳到结束
Network 9

LDB= 5, AC0 // 是功能5?
CALL SBR54 // 是,执行
JMP 254 // 然后跳到结束
Network 10
LDB= 6, AC0 // 是功能6?
CALL SBR55 // 是,执行
JMP 254 // 然后跳到结束
Network 11
LDB= 15, AC0 // 是功能15?
CALL SBR56 // 是,执行
JMP 254 // 然后跳到结束
Network 12
LDB= 16, AC0 // 是功能16?
CALL SBR57 // 是,执行


JMP 254 // 然后跳到结束
Network 13
LD SM0.0 // 如果上面都不成立
MOVW +3, VW3300 // 装入错误响应长度
ORW 16#80, VW3302 // 把功能MS位置1,表示出错
MOVB 1, VB3304 // 装入"功能不支持"代码(VB3304=1)
Network 14 // 功能服务,首先计算响应的CRC,然后发送响应。根请求一样,把响应
// 的长度也放在缓冲区的第一个字中。该长度不包括CRC的2个字节长度,因此在调用发送指令之前必须将长度增加2。
LBL 254 // 标签254(跳转入口)
Network 15
LD SM0.0 // SM0.0总为1
MOVW VW3300, AC0 // 取信息长度存入AC0
MOVD &VB3302, AC1 // 取缓冲区起始地址存入AC1,用于CRC检验
CALL SBR63 // 计算CRC,
MOVD &VB3302, AC3 // 取缓冲区起始地址
+I VW3300, AC3 // 指向缓冲区尾
MOVW AC2, *AC3 // 把CRC放到缓冲区
+I +2, VW3300 // 加CRC的两字节
XMT VB3301, 0 // 发送响应
ATCH INT125, 9 // 当发送完成时执行中断程序INT125
CRET // 返回
Network 16 // CRC或长度出错处理// 在下列情况下,如CRC出错,或者没有收到足够字节的处理信息,除了通信复位外,寻找下一段信息,且使主机到时。
LBL 255 // 标签255(跳转入口)
Network 17
LD SM0.0 // SM0.0总为1
ATCH INT120, 10 // 开始寻找静止线,此期间
ATCH INT121, 8 // 如果收到字符,那就执行中断程序INT121
Network 18 // 返回// RET
---------------------------------------------------------------------

功能3、4、5、6、15、16-------略

---------------------------------------------------------------------
SBR_61 产生错误响应2
Network 1 // SBR 61
Network 2 // 该子程序将建立响应缓冲区,并装入Modbus异常码2
LD SM0.0 //
MOVW +3, VW3300 // 装入错误响应长度
ORW 16#80, VW3302 // 把功能MS置位1,表示出错
MOVB 2, VB3304 // 装入异常码2
Network 3 // 返回

// RET
--------------------------------------------------------------------------------------------------------------
SBR_62 初始化 CRC 表
该子程序产生CRC表,用来计算信息的CRC值,多项式为:: x16 + x15 + x2 + 1
Network 1 // SBR 62
Network 2
LD SM0.0 //
MOVD &VB3580, AC3 // 装入表指针
MOVD +0, AC2 // 装入索引 index.
FOR VW3560, +1, +256 // 外循环开始
MOVW AC2, AC0 // 值 = index.
FOR VW3562, +1, +8 // 内循环开始(由于每字节8位,所以循环8次).
SRW AC0, 1 // 移出LS位
Network 3
LD SM1.1 // 如果移出位是1
XORW 16#A001, AC0 // 则执行异或
Network 4 // 内循环结束
NEXT
Network 5
LD SM0.0 //
INCW AC2 // 索引 (index) +1,
MOVW AC0, *AC3 // 储存表字
+I +2, AC3 // 表指针加2
WDR // 复位看门狗
Network 6 // 外循环结束
NEXT
Network 7 // 返回// RET
---------------------------------------------------------------------------------------------------------------
SBR_63 计算 CRC。
该子程序用快速表查找方法计算出信息的CRC值。 输入:AC0 信息长度,AC1 信息指针,输AC2 CRC 值的LS字
Network 1 // SBR 63
Network 2
LD SM0.0 //
WDR // 复位看门狗
MOVD 16#08000000, AC3 // 清除临时寄存器
MOVD 16#FFFF, AC2 // 初始化CRC值为0xFFFF.
FOR VW3560, +1, AC0 // 循环开始
MOVB *AC1, AC3 // 取信息字节
XORW AC2, AC3 // 数据与CRC异或,
ANDW 16#FF, AC3 // 只保留LS字节
SLW AC3, 1 // 把索引置换成字表
+I +3580, AC3 // 加表起始地址(VB3580)
SWAP AC2 // 交换CRC字节,
ANDW 16#FF, AC2 // 只保留LS字节
XORW *AC3, AC2 // 表值与CRC异或
INCW AC1 // 指向下一段信息字节
Network 3 // 循环结束
NEXT
Network 4
SWAP AC2 // 返回前交换CRC字节
WDR // 复位看门狗
Network 5 // 返回// RET
-------------------------------------------------------------------------------
INT_120 静止线定时器到时处理
检查是否输出数超过最大值当静止线定时器到时,该中断程序执行,起动接收请求首字符的中断程序INT122,因为下一个字符应当是我们要接收信息的开始。
Network 1 // INT 120
Network 2
LD SM0.0 //
DTCH 10 // 关断静止线定时器
ATCH INT122, 8 // 起动接收请求首字符的中断程序122
MOVW +0, VW3300 // 把接收计数器清零
MOVD &VB3302, VD3570 // 设定接收缓冲区指针
Network 3 // 返回// RETI
----------------------------------------------------------------------------------------------------------------------
INT_121 在等待静止线定时器到时期间收到字符的处理
Network 1 // INT 121
Network 2 //
LD SM0.0 // ,
ATCH INT120, 10 // 重新使能静止线定时器
Network 3 // 返回// RETI
---------------------------------------------------------------------------------------------------------------------
INT_122 接收请求的首字符
该中断程序在寻找静止线时处理串行口中断,如果在寻找静止线期间收到字符,则重新起动静止线定时器。在静止线定时器到时后,将接收信息的第一个字节。信息的第一个字节是地址。检查是否是请求的这个地址,若是,则起动中断程序INT123接收整个信息。如果不是这个地址的信息,则返回并寻找静止线时间。
注意:在执行中当加上额外代码时不支持广播地址。如果需要这个特性,该中断程序必须修改成能适应所有功能的处理器,因为广播地址不被所有功能支持。当响应已完成,发送回主机时该中断程序执行。复位中断系统,重新寻找静止线开始新的请求
Network 1 // INT 122 //中断程序INT122.
Network 2
LD SM3.0 // 若奇偶校验错,则
ATCH INT120, 10 // 开始寻找静止线,此期间
ATCH INT121, 8 // 若收到一个字符,那就执行中断程序LNT121
CRETI // 返回
Network 3 // 否则
LDB= SMB2, VB4095 // 若地址 = 我的地址
MOVB SMB2, *VD3570 // 把地址写入缓冲区
INCW VW3572 // 缓冲区指针加1
INCW VW3300 // 接收字节计数器加1
ATCH INT123, 8 // 接收其余信息
ATCH INT124, 10 // 若时间到,则结束接收
CRETI // 返回
Network 4
LD SM0.0 // 若地址不等于我的地址
ATCH INT120, 10 // 重新使能静止线定时器,此期间
ATCH INT121, 8 // 若收到一个字符,就执行中断程序INT121
Network 5 // 返回// RETI
----------------------------------------------------------------------------------------------------------------------
INT_123 接收请求的其余字符
这是主要字符中断服务程序。接收字符、校验奇偶错,接着存入通信缓冲区。每接收一个字符将字节计数增加1。若收到的字节数大于256,则接收失败。
Network 1 // INT 123 // 中断程序INT123.
Network 2

LD SM0.0 //
ATCH INT124, 10 // 下一个静止线定时器时间到信息完成
MOVB SMB2, *VD3570 // 在缓冲区里存储收到的信息
INCW VW3572 // 缓冲区指针加1
INCW VW3300 // 接收字节计数器加1
Network 3
LD SM3.0 // 若奇偶校验错,或
O V3300.0 // 缓冲区溢出
ATCH INT120, 10 // 则开始寻找静止线,此期间


ATCH INT121, 8 // 若收到一个字符,那就执行中断程序INT121
Network 4 // 返回 // RETI
--------------------------------------------------------------------------------------------------------------------
INT_124 静止线定时器到时后结束请求
当信息已收到,且我们已收到另一个静止线而意味着请求完成时,则这个中断程序执行。它关断静止线定时器,关断端口中断,且设置一个处理信息的反馈标志。
Network 1 // INT 124
Network 2
LD SM0.0 //
DTCH 10 // 关断静止线定时器
DTCH 8 // 关断端口中断
S M31.7, 1 // 设置处理信息的反馈标志(M31.7=1)
Network 3 // 返回// RETI
---------------------------------------------------------------------------------------------------------------------
INT_125 发送完后复位静止线寻找
Network 1 // INT 125
Network 2
LD SM0.0 //
ATCH INT120, 10 // 开始寻找静止线,此期间
ATCH INT121, 8 // 若收到一个字符,那就执行中断程序INT121
Network 3 // 返回// RETI
END_INTERRUPT_BLOCK

---------------------------------------------------------------------
请教例子Tip041B(Modbus RTU)的问题 已锁定
编辑推荐: 关闭

请填写推广理由:

本版热门话题

SIMATIC S7-200

共有33276条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

  • 分享

  • 只看
    楼主

top
X 图片
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。