Python位操作技术咨询:继电器板相关代码解析疑问
Hey there! Let's break down this relay control code piece by piece, and I'll explain exactly how bit operations tie into controlling relay boards.
1. 基础结构:relay_data类
First, the relay_data class inherits from Python's built-in dict—so it's a dictionary with some extra relay-specific logic attached. The address dictionary inside it is a key mapping:
- Keys are relay numbers ("1" to "8") or "all" for all relays
- Values are hexadecimal strings that represent the bit position of each relay in a byte. For example:
- "1" maps to "2" (hex) → which is
0b10in binary (the 1st bit, counting from 0) - "2" maps to "8" (hex) →
0b1000(the 3rd bit) - "all" maps to "FF" (hex) →
0b11111111(all 8 bits set to 1)
- "1" maps to "2" (hex) → which is
This dictionary is a quick lookup for which bit corresponds to which relay—super useful when you need to set or check a specific relay's state.
2. 核心位操作函数:testBit
The testBit function is the workhorse for checking relay states. Let's break down its logic:
def testBit(int_type, offset): mask = 1 << offset # Shift the number 1 left by 'offset' bits return(int_type & mask) # Bitwise AND between the state integer and mask
1 << offset: This creates a "mask"—a number where only theoffset-th bit is 1, and all others are 0. For example, ifoffset=1, this gives0b10(decimal 2).int_type & mask: The bitwise AND operation checks if theoffset-th bit inint_typeis 1. If it is, the result will be non-zero (equal to the mask); if not, it'll be 0.
In plain terms: this function tells you if a specific relay (represented by offset) is turned on (non-zero return) or off (zero return).
3. 获取继电器状态:get_relay_state
The get_relay_state function connects relay numbers to their corresponding bit positions using testBit:
def get_relay_state(data, relay): if relay == "1": return testBit(data, 1) if relay == "2": return testBit(data, 3) if relay == "3": return testBit(data, 5) # Matches address "20" (hex 20 = 0b100000, which is 1 shifted left 5 times) # ... and so on for relays 4-8
Each if statement maps a relay number to the correct bit offset. For example:
- Relay 1 uses offset 1 (matches the address "2" = 0b10)
- Relay 2 uses offset 3 (matches address "8" = 0b1000)
When you pass in data (the integer representing all relay states) and a relay number, this function checks if that specific relay's bit is set.
4. 位操作在继电器板中的关键作用
Relay boards (especially 8-channel ones) often use a single byte (8 bits) to communicate the state of all relays. Here's why bit operations are perfect for this:
- Efficiency: Instead of sending 8 separate values for each relay, you send one integer (1 byte) that encodes all states. This saves bandwidth in serial communication (like USB or UART to the relay board).
- Precision: Bit operations let you modify or check individual relays without affecting others. For example, to turn on relay 1, you'd do
state |= 0x2(bitwise OR with the relay's mask), and to turn it off,state &= ~0x2(bitwise AND with the inverse of the mask). - Hardware Alignment: Many relay controllers are designed to read/write bit values directly from hardware registers, so using bit operations in your code mirrors how the hardware works under the hood.
Quick Example
If the relay state data is 0x0A (hex) → 0b1010 in binary:
- Relay 1 (bit 1):
testBit(0x0A,1)→0b1010 & 0b10 = 0b10→ non-zero (relay is on) - Relay 2 (bit3):
testBit(0x0A,3)→0b1010 & 0b1000 = 0b1000→ non-zero (relay is on) - Relay 3 (bit5):
testBit(0x0A,5)→0b1010 & 0b100000 = 0→ zero (relay is off)
内容的提问来源于stack exchange,提问作者Lauren

