您的位置:控制工程论坛网论坛 » PLC与PAC » 请教例子Tip041B(Modbus RTU)的问题

tony_k

tony_k   |   当前状态:离线

总积分:917  2024年可用积分:0

注册时间: 2008-09-27

最后登录时间: 2008-11-28

空间 发短消息加为好友

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

tony_k  发表于 2008/10/8 15:46:18      1030 查看 4 回复  [上一主题]  [下一主题]

手机阅读

西门子的程序例子Tip041B(S7-214做从站Modbus RTU)中,程序说明中VB3300-VB3359为通信缓冲区,VB3560-VB3575为MODBUS的临时存储器,VB3580-VB4095为CRC数据库。请教:VB3300-VB3359为通信缓冲区是不是说由它们来存储主机发送来的请求和从机应答的数据?它们在程序中那儿被指定的?具体是如何分配的? VW3302为请求的功能号,VW3304为请求位或字的起始地址,VW3306为请求的位或字的个数,那么VW3300中是不是应该为请求的从机地址呢?程序如下:---------------------------------------------------------------------MAINNetwork 1LD SM0.1CALL SBR50Network 2LD 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个输出,那就设定33Network 1// SBR 50Network 2LD SM0.0 // SM0.0总为1MOVW +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 // 设定静止线定时器>5msATCH INT120, 10 // 开始寻找静止线,若静止线定时器到时,//则调用中断程序INT 120ATCH INT121, 8 // 在寻找静止线期间,如果收到一个字符,// 那就执行中断程序INT121---------------------------------------------------------------------SBR_51 处理 Modbus 请求和传送响应该子程序在正常的梯形图扫描周期内处理Modbus请求。计算收到信息的CRC。由于收到信息中的CRC包含在计算之内,若没有接收错误,那么计算结果总是0。Network 1 // SBR 51Network 2LD SM0.0 // SM0.0总为1MOVW VW3300, AC0 // 取缓冲区长度存入AC0MOVD &VB3302, AC1 // 取缓冲区地址存入AC1,用于CRC检查CALL SBR63 // 计算 CRC.Network 3LDW= +0, AC2 // 如果(计算CRC不等于0)NOT // 那就表示有接收错误JMP 255 // 跳转到LBL255Network 4// 信息正常,决定哪个Modbus功能被请求。// 再调用返回后总是执行紧随调用之后的跳步指令。// 因为返回前子程序总设定TOS 为1LD SM0.0 // SM0.0总是1MOVB VB3303, AC0 // 从请求缓冲区中取功能号存入AC0Network 5LDB= 1, AC0 // 是功能1?CALL SBR52 // 是,执行功能1JMP 254 // 然后跳到结束(LBL 254)Network 6LDB= 2, AC0 // 是功能2?CALL SBR52 // 是,执行JMP 254 // 然后跳到结束Network 7LDB= 3, AC0 // 是功能3?CALL SBR53 // 是,执行JMP 254 // 然后跳到结束Network 8LDB= 4, AC0 // 是功能4?CALL SBR53 // 是,执行JMP 254 // 然后跳到结束Network 9LDB= 5, AC0 // 是功能5?CALL SBR54 // 是,执行JMP 254 // 然后跳到结束Network 10LDB= 6, AC0 // 是功能6?CALL SBR55 // 是,执行JMP 254 // 然后跳到结束Network 11LDB= 15, AC0 // 是功能15?CALL SBR56 // 是,执行JMP 254 // 然后跳到结束Network 12LDB= 16, AC0 // 是功能16?CALL SBR57 // 是,执行JMP 254 // 然后跳到结束Network 13LD 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 15LD SM0.0 // SM0.0总为1MOVW VW3300, AC0 // 取信息长度存入AC0MOVD &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 // 当发送完成时执行中断程序INT125CRET // 返回Network 16 // CRC或长度出错处理// 在下列情况下,如CRC出错,或者没有收到足够字节的处理信息,除了通信复位外,寻找下一段信息,且使主机到时。LBL 255 // 标签255(跳转入口)Network 17LD SM0.0 // SM0.0总为1ATCH INT120, 10 // 开始寻找静止线,此期间ATCH INT121, 8 // 如果收到字符,那就执行中断程序INT121Network 18 // 返回// RET---------------------------------------------------------------------SBR_51 处理 Modbus 请求和传送响应该子程序在正常的梯形图扫描周期内处理Modbus请求。计算收到信息的CRC。由于收到信息中的CRC包含在计算之内,若没有接收错误,那么计算结果总是0。Network 1 // SBR 51Network 2LD SM0.0 // SM0.0总为1MOVW VW3300, AC0 // 取缓冲区长度存入AC0MOVD &VB3302, AC1 // 取缓冲区地址存入AC1,用于CRC检查CALL SBR63 // 计算 CRC.Network 3LDW= +0, AC2 // 如果(计算CRC不等于0)NOT // 那就表示有接收错误JMP 255 // 跳转到LBL255Network 4// 信息正常,决定哪个Modbus功能被请求。// 再调用返回后总是执行紧随调用之后的跳步指令。// 因为返回前子程序总设定TOS 为1LD SM0.0 // SM0.0总是1MOVB VB3303, AC0 // 从请求缓冲区中取功能号存入AC0Network 5LDB= 1, AC0 // 是功能1?CALL SBR52 // 是,执行功能1JMP 254 // 然后跳到结束(LBL 254)Network 6LDB= 2, AC0 // 是功能2?CALL SBR52 // 是,执行JMP 254 // 然后跳到结束Network 7LDB= 3, AC0 // 是功能3?CALL SBR53 // 是,执行JMP 254 // 然后跳到结束Network 8LDB= 4, AC0 // 是功能4?CALL SBR53 // 是,执行JMP 254 // 然后跳到结束Network 9LDB= 5, AC0 // 是功能5?CALL SBR54 // 是,执行JMP 254 // 然后跳到结束Network 10LDB= 6, AC0 // 是功能6?CALL SBR55 // 是,执行JMP 254 // 然后跳到结束Network 11LDB= 15, AC0 // 是功能15?CALL SBR56 // 是,执行JMP 254 // 然后跳到结束Network 12LDB= 16, AC0 // 是功能16?CALL SBR57 // 是,执行JMP 254 // 然后跳到结束Network 13LD 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 15LD SM0.0 // SM0.0总为1MOVW VW3300, AC0 // 取信息长度存入AC0MOVD &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 // 当发送完成时执行中断程序INT125CRET // 返回Network 16 // CRC或长度出错处理// 在下列情况下,如CRC出错,或者没有收到足够字节的处理信息,除了通信复位外,寻找下一段信息,且使主机到时。LBL 255 // 标签255(跳转入口)Network 17LD SM0.0 // SM0.0总为1ATCH INT120, 10 // 开始寻找静止线,此期间ATCH INT121, 8 // 如果收到字符,那就执行中断程序INT121Network 18 // 返回// RET---------------------------------------------------------------------功能3、4、5、6、15、16-------略---------------------------------------------------------------------SBR_61 产生错误响应2Network 1 // SBR 61Network 2 // 该子程序将建立响应缓冲区,并装入Modbus异常码2LD SM0.0 //MOVW +3, VW3300 // 装入错误响应长度ORW 16#80, VW3302 // 把功能MS置位1,表示出错MOVB 2, VB3304 // 装入异常码2Network 3 // 返回// RET--------------------------------------------------------------------------------------------------------------SBR_62 初始化 CRC 表该子程序产生CRC表,用来计算信息的CRC值,多项式为:: x16 + x15 + x2 + 1Network 1 // SBR 62Network 2LD 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 3LD SM1.1 // 如果移出位是1XORW 16#A001, AC0 // 则执行异或Network 4 // 内循环结束NEXTNetwork 5LD SM0.0 //INCW AC2 // 索引 (index) +1,MOVW AC0, *AC3 // 储存表字+I +2, AC3 // 表指针加2WDR // 复位看门狗Network 6 // 外循环结束NEXTNetwork 7 // 返回// RET---------------------------------------------------------------------------------------------------------------SBR_63 计算 CRC。该子程序用快速表查找方法计算出信息的CRC值。 输入:AC0 信息长度,AC1 信息指针,输AC2 CRC 值的LS字Network 1 // SBR 63Network 2LD 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 // 循环结束NEXTNetwork 4SWAP AC2 // 返回前交换CRC字节WDR // 复位看门狗Network 5 // 返回// RET-------------------------------------------------------------------------------INT_120 静止线定时器到时处理检查是否输出数超过最大值当静止线定时器到时,该中断程序执行,起动接收请求首字符的中断程序INT122,因为下一个字符应当是我们要接收信息的开始。Network 1 // INT 120Network 2LD SM0.0 //DTCH 10 // 关断静止线定时器ATCH INT122, 8 // 起动接收请求首字符的中断程序122MOVW +0, VW3300 // 把接收计数器清零MOVD &VB3302, VD3570 // 设定接收缓冲区指针Network 3 // 返回// RETI----------------------------------------------------------------------------------------------------------------------INT_121 在等待静止线定时器到时期间收到字符的处理Network 1 // INT 121Network 2 //LD SM0.0 // ,ATCH INT120, 10 // 重新使能静止线定时器Network 3 // 返回// RETI---------------------------------------------------------------------------------------------------------------------INT_122 接收请求的首字符该中断程序在寻找静止线时处理串行口中断,如果在寻找静止线期间收到字符,则重新起动静止线定时器。在静止线定时器到时后,将接收信息的第一个字节。信息的第一个字节是地址。检查是否是请求的这个地址,若是,则起动中断程序INT123接收整个信息。如果不是这个地址的信息,则返回并寻找静止线时间。注意:在执行中当加上额外代码时不支持广播地址。如果需要这个特性,该中断程序必须修改成能适应所有功能的处理器,因为广播地址不被所有功能支持。当响应已完成,发送回主机时该中断程序执行。复位中断系统,重新寻找静止线开始新的请求Network 1 // INT 122 //中断程序INT122.Network 2LD SM3.0 // 若奇偶校验错,则ATCH INT120, 10 // 开始寻找静止线,此期间ATCH INT121, 8 // 若收到一个字符,那就执行中断程序LNT121CRETI // 返回Network 3 // 否则LDB= SMB2, VB4095 // 若地址 = 我的地址MOVB SMB2, *VD3570 // 把地址写入缓冲区INCW VW3572 // 缓冲区指针加1INCW VW3300 // 接收字节计数器加1ATCH INT123, 8 // 接收其余信息ATCH INT124, 10 // 若时间到,则结束接收CRETI // 返回Network 4LD SM0.0 // 若地址不等于我的地址ATCH INT120, 10 // 重新使能静止线定时器,此期间ATCH INT121, 8 // 若收到一个字符,就执行中断程序INT121Network 5 // 返回// RETI----------------------------------------------------------------------------------------------------------------------INT_123 接收请求的其余字符这是主要字符中断服务程序。接收字符、校验奇偶错,接着存入通信缓冲区。每接收一个字符将字节计数增加1。若收到的字节数大于256,则接收失败。Network 1 // INT 123 // 中断程序INT123.Network 2LD SM0.0 //ATCH INT124, 10 // 下一个静止线定时器时间到信息完成MOVB SMB2, *VD3570 // 在缓冲区里存储收到的信息INCW VW3572 // 缓冲区指针加1INCW VW3300 // 接收字节计数器加1Network 3LD SM3.0 // 若奇偶校验错,或O V3300.0 // 缓冲区溢出ATCH INT120, 10 // 则开始寻找静止线,此期间ATCH INT121, 8 // 若收到一个字符,那就执行中断程序INT121Network 4 // 返回 // RETI--------------------------------------------------------------------------------------------------------------------INT_124 静止线定时器到时后结束请求当信息已收到,且我们已收到另一个静止线而意味着请求完成时,则这个中断程序执行。它关断静止线定时器,关断端口中断,且设置一个处理信息的反馈标志。Network 1 // INT 124Network 2LD SM0.0 //DTCH 10 // 关断静止线定时器DTCH 8 // 关断端口中断S M31.7, 1 // 设置处理信息的反馈标志(M31.7=1)Network 3 // 返回// RETI---------------------------------------------------------------------------------------------------------------------INT_125 发送完后复位静止线寻找Network 1 // INT 125Network 2LD SM0.0 //ATCH INT120, 10 // 开始寻找静止线,此期间ATCH INT121, 8 // 若收到一个字符,那就执行中断程序INT121Network 3 // 返回// RETIEND_INTERRUPT_BLOCK
1楼 0 0 回复
  • tony_k

    tony_k   |   当前状态:离线

    总积分:917  2024年可用积分:0

    注册时间: 2008-09-27

    最后登录时间: 2008-11-28

    空间 发短消息加为好友

    tony_k   发表于 2008/10/6 13:51:19

    VW3300是数据缓冲区的长度.
    VB3300-VB3359为通信缓冲区是来存储主机发送来的请求和从机应答的数据.
    LDB=   1, VB3303                   // If the function is 1 
    MOVD   &QB0, AC3                   // point to the outputs.
    LD     Always_On                   // Every scan cycle,
    BMB    *AC3, VB3340, 8             //copy the inputs/outputs 
    以1号功能为例,数据的转移是通过以上的语句完成.
    另外修正一下:VB3580-VB4091为CRC数据库
    2楼 回复本楼

    引用 tony_k 2008/10/6 13:51:19 发表于2楼的内容

总共 , 当前 /