zlyczm123 2026-01-08 21:29 采纳率: 0%
浏览 3

西门子-300编程问题,间接寻址赋值

img

img


这是多年前厂家给我们做的项目里的一个功能块FC7,程序能看懂,但对里面的寻址方式不理解。他的DB块在线dB7.DBD0读取数值是0#32A0十进制是12960,这个应该是位数除以32正好指到DBD1620,我做个程序新调用一个FC7,在线dB7.DBD0的值正好变成0#32C0,并且在地址DBD1620那个数值栏里从1每隔1秒逐渐变成5。
但我做了一个跟它一样的功能块和DB块,就是把地址改了,外置的参数数值都一样,但是我调用我的FC块后,DB块在线,DBD0的值一直在涨,其他地址的值无变化,再多调几个,还是这个现象,谁能帮解释一下吗?并且详细讲解一下它这个FC7块程序具体的寻址和赋值方式?
已知In0=1,IN1=5,in2=1,M2.0是一个每秒1HZ的时钟

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2026-01-08 21:30
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你提到的“西门子S7-300编程问题”中,涉及到间接寻址(Indirect Addressing)功能块(FC)中的地址赋值。这是一个非常典型的S7-300 PLC编程中常见的高级用法,尤其是在处理大量数据或动态访问DB块时。


    一、问题分析

    你描述了两个情况:

    1. 原厂FC7调用后,DB7.DBW0 的值为 0#32A0(十进制12960),这个值是通过某种方式指向了 DBD1620
    2. 你自己复制了一个类似的FC7,但调用后 DB7.DBW0 的值不断增长,其他地址无变化。

    这说明你在实现间接寻址时可能出现了错误,或者对某些参数的使用不准确。


    二、关键点解释:间接寻址与地址计算

    1. 间接寻址的基本原理

    在S7-300中,间接寻址通常使用以下结构:

    P#DBx.DBX0 DBD  // 指向一个DB块的起始位置
    

    例如:

    • P#DB7.DBX0 表示从 DB7 的第0位开始。
    • P#DB7.DBD0 表示从 DB7 的第0字节开始(即 DBW0DBD0)。

    你可以通过加减偏移量来动态访问不同地址。

    2. 地址转换公式

    在S7中,每个字(Word)占2个字节,每个双字(Double Word)占4个字节。

    所以:

    • DBW0 = 0
    • DBW2 = 2
    • DBW4 = 4
    • ...
    • DBD0 = 0
    • DBD4 = 4
    • DBD8 = 8
    • ...

    因此,若你有一个变量值为 12960,它代表的是:

    12960 / 32 = 405 → 第405个双字(DBD)
    

    也就是说,DBD1620 是第405个双字(因为 405 * 4 = 1620)。


    三、原厂FC7的逻辑分析

    根据你的描述:

    • DB7.DBW0 的值是 0#32A0(十进制12960)→ 指向 DBD1620
    • 调用FC7后,DBD1620 的值每隔1秒增加1,从1到5

    这说明FC7内部可能是这样写的:

    VAR
        Address: DINT;  // 存储偏移地址
        Value: DINT;
    END_VAR
    
    // 将Address转换为实际地址
    P#DB7.DBX0 + (Address * 4) -> P#DB7.DBX0 + 1620
    
    // 写入值
    DB7.DBW0 := 0#32A0;  // 指向DBD1620
    DB7.DBW0 := 0#32C0;  // 指向DBD1632
    

    或者更标准的写法是:

    // 读取地址
    P#DB7.DBX0 + (Address * 4) -> ADR;
    
    // 读取值
    MOV ADR, Value;
    
    // 写入值
    MOV Value, ADR;
    

    四、你自己的FC7的问题分析

    你提到:

    • 自己做的FC7调用后,DB7.DBW0 不断增长,其他地址不变。
    • 参数和原厂一样,但结果不同。

    这表明你在间接寻址的赋值方式上存在错误。

    可能的原因:

    ✅ 1. 错误地将 DBW0 作为地址指针使用

    如果你直接给 DB7.DBW0 赋值为某个数值(如 0#32A0),它会被当作数值而非地址,导致后续操作错误。

    正确的做法是使用 P#DB7.DBX0 + Offset 来构造地址。

    ✅ 2. 地址未正确计算

    你可能没有正确地将偏移量乘以4(因为每个双字占4字节),导致地址错位。

    ✅ 3. 地址未正确绑定到DB块

    如果 DB7 中没有定义 DBD1620 或者该地址未被正确初始化,可能会导致意外行为。


    五、解决方案(详细步骤)

    1. 确保使用正确的间接寻址语法

    VAR
        Offset: INT := 12960;  // 12960 是 DBD1620 的偏移量
        Address: POINTER;
    END_VAR
    
    // 构造地址
    Address := P#DB7.DBX0 + (Offset * 4);  // 注意乘以4
    

    2. 使用 MOV 操作进行读写

    VAR
        Value: DINT;
    END_VAR
    
    // 读取地址内容
    MOV Address, Value;
    
    // 修改值(例如+1)
    Value := Value + 1;
    
    // 写回地址
    MOV Value, Address;
    

    3. 确保DB块中有对应地址

    确保 DB7 中有 DBD1620DBD1624 等地址,否则会导致访问越界或错误。


    六、修改后的代码示例(FC7)

    FUNCTION FC7 : BOOL
        VAR_INPUT
            Offset: INT := 12960;  // 举例:指向DBD1620
        END_VAR
        VAR_OUTPUT
            Result: BOOL := TRUE;
        END_VAR
        VAR
            Address: POINTER;
            Value: DINT;
        END_VAR
    
        // 构造地址
        Address := P#DB7.DBX0 + (Offset * 4);
    
        // 读取当前值
        MOV Address, Value;
    
        // 修改值(例如+1)
        Value := Value + 1;
    
        // 写回地址
        MOV Value, Address;
    
        Result := TRUE;
    END_FUNCTION
    

    七、总结

    | 问题 | 原因 | 解决方案 | |------|------|----------| | DB7.DBW0 不断增长 | 错误地将数值当地址使用 | 使用 P#DBx.DBX0 + Offset * 4 正确构造地址 | | 地址未指向预期位置 | 偏移量计算错误 | 确保偏移量乘以4(每个双字4字节) | | 数据未更新 | 未正确读写地址 | 使用 MOV 操作进行读写 |


    八、重点提示(加粗部分

    • 间接寻址必须使用 P#DBx.DBX0 + Offset * 4 的方式构造地址
    • 不要直接对 DBW0 赋值为偏移量,而是用于构造地址
    • 地址偏移量要乘以4(双字占4字节)
    • 确保目标地址在DB块中已定义

    如有需要,我可以帮你进一步调试你的FC7程序,或者提供完整的DB块配置建议。

    评论

报告相同问题?

问题事件

  • 修改了问题 1月8日
  • 修改了问题 1月8日
  • 创建了问题 1月8日