想要修改 D10、D11 这两个存储单元中 32 位数据的偶数位(二进制位),同时保持奇数位的数据不变,核心是通过位运算的方式来实现这个需求。
首先需要明确:二进制位的计数通常有两种方式,这里我们统一按从 0 开始计数(最右边的位是第 0 位,属于偶数位,第 1 位是奇数位,以此类推),这是编程和硬件领域的常用计数方式。
解决思路
要实现 “偶数位修改、奇数位不变”,可以利用位掩码(Mask) + 位运算的组合:
代码实现(以 Python 为例,通用逻辑可迁移到 PLC / 单片机等平台)
下面的代码实现了对 32 位数据的偶数位修改,同时兼容处理 D10(低 16 位)和 D11(高 16 位)组合的 32 位数据场景:
python
运行
def modify_even_bits_32bit(d10, d11, new_even_bits):
"""
修改D10(低16位)+D11(高16位)组成的32位数据的偶数位,奇数位保持不变
:param d10: 低16位数据(D10存储单元的值,0~65535)
:param d11: 高16位数据(D11存储单元的值,0~65535)
:param new_even_bits: 想要设置的偶数位的二进制数据(32位范围内的整数)
:return: 新的d10值,新的d11值
"""
# 1. 组合D10和D11为32位完整数据(d11是高16位,d10是低16位)
original_32bit = (d11 << 16) | (d10 & 0xFFFF) # 0xFFFF确保d10只保留16位
# 2. 创建32位掩码:奇数位(1,3,5...)为1,偶数位(0,2,4...)为0
# 0xAAAAAAAA的二进制是:10101010 10101010 10101010 10101010(32位)
mask_odd_bits = 0xAAAAAAAA # 这是32位奇数位为1的掩码
# 3. 保留原数据的奇数位(偶数位清零)
original_odd_bits = original_32bit & mask_odd_bits # 4. 提取新数据的偶数位(奇数位清零)
# 0x55555555的二进制是:01010101 01010101 01010101 01010101(32位)
mask_even_bits = 0x55555555 # 32位偶数位为1的掩码
new_even_bits_only = new_even_bits & mask_even_bits # 5. 合并:奇数位保留原数据,偶数位使用新数据
new_32bit = original_odd_bits | new_even_bits_only # 6. 拆分回D10(低16位)和D11(高16位)
new_d10 = new_32bit & 0xFFFF # 取低16位
new_d11 = (new_32bit >> 16) & 0xFFFF # 右移16位后取低16位(高16位)
return new_d10, new_d11# 测试用例if __name__ == "__main__":
# 假设D10=0b1111111111111111(65535),D11=0b1111111111111111(65535),即32位全1
d10 = 0xFFFF # 65535
d11 = 0xFFFF # 65535
# 想要把偶数位设置为全1(实际效果:偶数位保持1,因为原数据偶数位已经是1)
# 若改为new_even=0,则偶数位会被置0,奇数位保留1
new_even = 0x0 # 想要设置的偶数位数据(这里设为0,即偶数位清零)
new_d10, new_d11 = modify_even_bits_32bit(d10, d11, new_even)
print(f"原D10: {d10:#018b}({d10}),原D11: {d11:#018b}({d11})")
print(f"新D10: {new_d10:#018b}({new_d10}),新D11: {new_d11:#018b}({new_d11})")关键部分解释
适配 PLC / 单片机的说明
如果是在 PLC(如三菱、西门子)或单片机中操作 D10、D11,逻辑完全一致,只是语法略有不同:


