Sorry for the delay response. Hopefully you've found your answer elsewhere already.
The Modbus command you are looking for is MASK WRITE REGISTER. It accepts both an AND mask and an OR mask. In order to set a single bit in a register you will need to use the OR mask to set the bit (or clear it) and the AND mask to preserve the other remaining bits.
Let's say that you wish to set the bit having the value 0x0100 (binary 0000 0001 0000 0000, or bit 8, if you start counting at 0). The function says that bits in the AND mask are preserved, and bits in the OR mask are set, if the AND mask doesn't preserve them. It can get a bit confusing, so hopefully this example will help.
As I wrote, you want to preserve (neither set nor clear) all of the bits, except 0x0100 bit. That means your AND mask is the 1's compliment, of 0xFEFF (1111 1110 1111 1111) and your OR mask is simply the bit you wish to set.
The result is equal to
(initial_value AND AND_mask) OR (OR_mask AND ~AND_mask)
where "~" is the symbol for 1's compliment and "AND" and "OR" represent bit-wise operations. That gives
(initial_value AND 0xFEFF) OR (0x0100 AND ~0xFEFF)
(initial_value AND 0xFEFF) OR (0x0100 AND 0x0100)
(initial_value AND 0xFEFF) OR 0x0100
because x AND 1 = x, and x OR 1 = 1, the final result is (initial_value OR 0x0100).
If you wanted to clear the 0x0100 bit you would have used 0x0000 as the OR mask and the result would have been
(initial_value AND 0xFEFF) OR (0x0000 AND ~0xFEFF)
(initial_value AND 0xFEFF) OR (0x0000)
(initial_value AND 0xFEFF)
which is the same as initial_value with the 0x0100 bit cleared.
All that said, your device must support MASK WRITE REGISTER or else you will be forced to read the register, change the bit yourself in the master, then write the change back. Sadly, many devices, and most open source Modbus libraries, don't support MASK WRITE REGISTER.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
I need to write a specific bit of a inputregister while leaving the others untouched.
It is possibile?
BR, Fabian
Fabian -
Sorry for the delay response. Hopefully you've found your answer elsewhere already.
The Modbus command you are looking for is MASK WRITE REGISTER. It accepts both an AND mask and an OR mask. In order to set a single bit in a register you will need to use the OR mask to set the bit (or clear it) and the AND mask to preserve the other remaining bits.
Let's say that you wish to set the bit having the value 0x0100 (binary 0000 0001 0000 0000, or bit 8, if you start counting at 0). The function says that bits in the AND mask are preserved, and bits in the OR mask are set, if the AND mask doesn't preserve them. It can get a bit confusing, so hopefully this example will help.
As I wrote, you want to preserve (neither set nor clear) all of the bits, except 0x0100 bit. That means your AND mask is the 1's compliment, of 0xFEFF (1111 1110 1111 1111) and your OR mask is simply the bit you wish to set.
The result is equal to
(initial_value AND AND_mask) OR (OR_mask AND ~AND_mask)
where "~" is the symbol for 1's compliment and "AND" and "OR" represent bit-wise operations. That gives
(initial_value AND 0xFEFF) OR (0x0100 AND ~0xFEFF)
(initial_value AND 0xFEFF) OR (0x0100 AND 0x0100)
(initial_value AND 0xFEFF) OR 0x0100
because x AND 1 = x, and x OR 1 = 1, the final result is (initial_value OR 0x0100).
If you wanted to clear the 0x0100 bit you would have used 0x0000 as the OR mask and the result would have been
(initial_value AND 0xFEFF) OR (0x0000 AND ~0xFEFF)
(initial_value AND 0xFEFF) OR (0x0000)
(initial_value AND 0xFEFF)
which is the same as initial_value with the 0x0100 bit cleared.
All that said, your device must support MASK WRITE REGISTER or else you will be forced to read the register, change the bit yourself in the master, then write the change back. Sadly, many devices, and most open source Modbus libraries, don't support MASK WRITE REGISTER.