Orange Pi Zero 2与PI4IOE5V96248 I2C扩展板引脚映射异常排查
PI4IOE5V96248 I2C扩展板引脚映射异常问题排查
我使用Orange Pi Zero 2搭配PI4IOE5V96248 48位I/O扩展板(I2C通信),编写了以下Python代码,但出现引脚映射异常:输入LED1时实际点亮引脚9,输入LED48时实际点亮引脚40,且LED1-8完全无法工作。调整状态计算逻辑后有时会出现所有LED熄灭的情况,当前代码仅能驱动LED9-48。
原代码
import smbus import time bus = smbus.SMBus(3) slave_address = 0x20 def set_led_state(states): try: bus.write_i2c_block_data(slave_address, 0x00, states) print("Address acknowledgment: Received") print("Data byte acknowledgment: Received") print(f"Address byte sent: 0x{slave_address:02X}") print(f"Data bytes sent: {[f'0x{s:02X}' for s in states]}") except IOError: print("Address acknowledgment: Not received") print("Data byte acknowledgment: Not received") # Define LED states LED_OFF = 0x00 LED_1 = 0x01 LED_2 = 0x02 LED_3 = 0x04 LED_4 = 0x08 LED_5 = 0x10 LED_6 = 0x20 LED_7 = 0x40 LED_8 = 0x80 # Prompt the user to select an LED def prompt_led_selection(): led = int(input("Enter the LED number (1-48) to switch on (0 to exit): ")) if led == 0: return None elif led < 1 or led > 48: print("Invalid LED number. Please try again.") return prompt_led_selection() else: return led # Repeat the LED selection until the user chooses to exit (0) while True: selected_led = prompt_led_selection() if selected_led is None: break # Calculate the LED state based on the selected LED number state_index = (selected_led - 1) // 8 bit_position = (selected_led - 1) % 8 # Create an array of LED states states = [LED_OFF] * 6 states[state_index] = 0x01 << bit_position set_led_state(states) # Print the selected LED number print(f"LED {selected_led} switched ON") time.sleep(0.1) # Delay for 2 seconds # Turn off all LEDs set_led_state([LED_OFF] * 6) print("All LEDs are OFF")
数据手册说明
写入操作时,主设备(微控制器)先寻址从设备,将包含从地址字节的最后一位置为逻辑0以进入写入模式。PI4IOE5V96248会发出应答,随后主设备发送第一个数据字节对应IO0_7至IO0_0。该字节得到应答后,主设备发送第二个数据字节对应IO1_7至IO1_0,以此类推。
问题根源分析
- 写入了只读的输入寄存器:PI4IOE5V96248的0x00-0x05是输入寄存器(只读),写入操作完全无效。原代码中
bus.write_i2c_block_data(slave_address, 0x00, states)将数据写入输入寄存器,直接导致LED1-8(对应PORT0)无法响应。 - 输出寄存器地址错误:该芯片的输出寄存器起始地址为0x06(对应PORT0),后续PORT1-PORT5的输出寄存器地址依次是0x07-0x0B。原代码的写入地址完全偏离了输出控制区域,这是部分引脚错位的核心原因。
- 未配置端口为输出模式:PI4IOE5V96248的配置寄存器(0x12-0x17)默认值为0xFF(所有引脚设为输入模式)。即使写入正确的输出寄存器,若未将端口配置为输出,引脚也无法驱动LED。
- 位序与手册要求反转:数据手册明确第一个数据字节对应
IO0_7至IO0_0,即字节的最高位(bit7)对应IO0_7,最低位(bit0)对应IO0_0。但原代码用0x01 << bit_position将bit0对应IO0_0,导致LED编号与实际引脚错位。
修正后的代码示例
import smbus import time bus = smbus.SMBus(3) slave_address = 0x20 # 寄存器地址定义 OUTPUT_PORT_BASE = 0x06 CONFIG_PORT_BASE = 0x12 def init_expander(): # 将所有6个端口配置为输出模式(写入0x00到配置寄存器) try: bus.write_i2c_block_data(slave_address, CONFIG_PORT_BASE, [0x00]*6) print("扩展板端口已配置为输出模式") except IOError: print("配置扩展板失败") def set_led_state(states): try: # 写入输出寄存器,起始地址为OUTPUT_PORT_BASE bus.write_i2c_block_data(slave_address, OUTPUT_PORT_BASE, states) print(f"输出数据已发送: {[f'0x{s:02X}' for s in states]}") except IOError: print("发送数据失败") def prompt_led_selection(): led = int(input("Enter the LED number (1-48) to switch on (0 to exit): ")) if led == 0: return None elif led < 1 or led > 48: print("Invalid LED number. Please try again.") return prompt_led_selection() else: return led # 初始化扩展板端口为输出 init_expander() while True: selected_led = prompt_led_selection() if selected_led is None: break port_index = (selected_led - 1) // 8 bit_position = (selected_led - 1) % 8 # 反转位序,匹配手册中IOx_7对应字节bit7的要求 reversed_bit = 7 - bit_position states = [0x00] * 6 states[port_index] = 0x01 << reversed_bit set_led_state(states) print(f"LED {selected_led} switched ON") time.sleep(0.1) # 关闭所有LED set_led_state([0x00] * 6) print("All LEDs are OFF")
内容的提问来源于stack exchange,提问作者Electro
相关产品推荐
相关产品推荐

