手把手教你用GD32单片机驱动NCA9555扩展IO(附完整代码与避坑指南)

发布时间:2026/6/13 7:07:08

手把手教你用GD32单片机驱动NCA9555扩展IO(附完整代码与避坑指南) 手把手教你用GD32单片机驱动NCA9555扩展IO附完整代码与避坑指南在嵌入式开发中IO扩展是解决单片机引脚资源不足的常见方案。NCA9555作为一款16位I2C接口的IO扩展芯片以其简单易用、成本低廉的特点受到广泛欢迎。本文将详细介绍如何使用国产GD32系列单片机以GD32F103为例通过I2C总线驱动NCA9555从硬件连接到软件实现再到常见问题排查带你完整走通整个开发流程。1. 硬件准备与电路设计1.1 元器件选型与连接NCA9555与GD32的硬件连接需要注意几个关键点电源匹配NCA9555工作电压范围2.3V-5.5V需与GD32的I/O电压一致I2C上拉电阻典型值4.7kΩ根据总线长度和速度可适当调整地址配置通过A0-A2引脚设置器件地址避免与系统中其他I2C设备冲突推荐连接方式NCA9555引脚GD32连接备注SDAPC4需配置为开漏SCLPC5需配置为开漏A0-A2GND/VCC设置器件地址INT可选中断输出1.2 GPIO模式配置GD32的I2C引脚需要正确配置为开漏模式// I2C引脚初始化示例 void I2C_GPIO_Config(void) { rcu_periph_clock_enable(RCU_GPIOC); // PC4 - SDA gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4); gpio_output_options_set(GPIOC, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_4); // PC5 - SCL gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_5); gpio_output_options_set(GPIOC, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_5); // 初始状态拉高 gpio_bit_set(GPIOC, GPIO_PIN_4 | GPIO_PIN_5); }注意开漏模式必须配合外部上拉电阻使用否则总线无法正常工作2. I2C通信基础实现2.1 软件模拟I2C时序对于没有硬件I2C外设或需要更灵活控制的情况可以采用GPIO模拟// I2C起始信号 void I2C_Start(void) { SDA_OUT(); SDA_H(); SCL_H(); delay_us(4); SDA_L(); delay_us(4); SCL_L(); } // I2C停止信号 void I2C_Stop(void) { SDA_OUT(); SDA_L(); SCL_H(); delay_us(4); SDA_H(); delay_us(4); } // 等待ACK uint8_t I2C_Wait_Ack(void) { uint8_t timeout 0; SDA_IN(); SCL_H(); delay_us(1); while(GPIO_ISTAT(GPIOC) GPIO_PIN_4) { if(timeout 250) { I2C_Stop(); return 1; } delay_us(1); } SCL_L(); return 0; }2.2 NCA9555寄存器详解NCA9555内部有多个功能寄存器主要分为两组PORT0和PORT1寄存器地址名称功能描述0x00Input Port 0读取PORT0输入状态0x01Input Port 1读取PORT1输入状态0x02Output Port 0设置PORT0输出状态0x03Output Port 1设置PORT1输出状态0x04Polarity Inversion 0PORT0极性反转设置0x05Polarity Inversion 1PORT1极性反转设置0x06Configuration 0PORT0方向设置(1输入)0x07Configuration 1PORT1方向设置(1输入)3. NCA9555驱动实现3.1 初始化配置正确的初始化流程应包括设置端口方向输入/输出配置默认输出电平设置极性反转可选#define NCA9555_ADDR 0x40 // 假设A0-A2接地 void NCA9555_Init(void) { uint8_t config[2] {0x00, 0x00}; // 全部设置为输出 uint8_t output[2] {0xFF, 0xFF}; // 初始输出高电平 // 配置端口方向 I2C_Write_Reg(NCA9555_ADDR, 0x06, config, 2); // 设置初始输出状态 I2C_Write_Reg(NCA9555_ADDR, 0x02, output, 2); } // 寄存器写入函数 uint8_t I2C_Write_Reg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len) { I2C_Start(); I2C_Send_Byte(dev_addr 0xFE); // 写操作 if(I2C_Wait_Ack()) return 1; I2C_Send_Byte(reg_addr); if(I2C_Wait_Ack()) return 1; for(uint8_t i0; ilen; i) { I2C_Send_Byte(data[i]); if(I2C_Wait_Ack()) return 1; } I2C_Stop(); return 0; }3.2 端口操作函数实现单个引脚的控制功能// 设置单个引脚状态 void NCA9555_Set_Pin(uint8_t pin, uint8_t state) { uint8_t port pin / 8; uint8_t bit pin % 8; uint8_t output[2]; // 先读取当前输出状态 I2C_Read_Reg(NCA9555_ADDR, 0x02 port, output[port], 1); // 修改指定位 if(state) { output[port] | (1 bit); } else { output[port] ~(1 bit); } // 写回寄存器 I2C_Write_Reg(NCA9555_ADDR, 0x02 port, output[port], 1); } // 读取单个引脚状态 uint8_t NCA9555_Get_Pin(uint8_t pin) { uint8_t port pin / 8; uint8_t bit pin % 8; uint8_t input; I2C_Read_Reg(NCA9555_ADDR, port, input, 1); return (input bit) 0x01; }4. 实战案例流水灯实现4.1 程序设计思路利用NCA9555的16个IO口实现流水灯效果初始化所有IO为输出设置初始状态全灭循环点亮每个LED形成流水效果4.2 完整实现代码#include gd32f10x.h #include nca9555.h #include systick.h void LED_Flow_Demo(void) { NCA9555_Init(); // 初始全灭 for(uint8_t i0; i16; i) { NCA9555_Set_Pin(i, 0); } while(1) { for(uint8_t i0; i16; i) { NCA9555_Set_Pin(i, 1); // 点亮当前LED delay_1ms(200); NCA9555_Set_Pin(i, 0); // 熄灭当前LED } } }4.3 性能优化建议使用硬件定时器替代delay函数提高系统响应采用位操作批量控制多个IO减少I2C通信次数实现中断方式检测输入变化降低CPU占用5. 常见问题与调试技巧5.1 I2C通信失败排查当通信异常时建议按以下步骤排查检查硬件连接确认电源电压正常测量SCL/SDA线上拉是否有效检查地址配置是否正确逻辑分析仪抓包观察起始信号、地址字节、ACK响应检查时钟频率是否在器件支持范围内软件调试技巧在关键位置添加调试输出分步验证每个基础函数Start/Stop/ACK等5.2 NCA9555特有注意事项上电默认状态所有端口默认为输入使用前必须先配置方向输出驱动能力单个引脚最大25mA全部引脚总和有限制热插拔问题带电插拔可能导致I2C总线锁死需增加保护电路提示遇到异常时尝试对NCA9555进行硬件复位拉低RESET引脚6. 进阶应用与扩展6.1 多设备级联通过配置不同的地址引脚可以连接多个NCA9555#define NCA9555_DEV1_ADDR 0x40 // A00,A10,A20 #define NCA9555_DEV2_ADDR 0x42 // A01,A10,A20 void Multi_Device_Example(void) { // 初始化两个设备 NCA9555_Init_Device(NCA9555_DEV1_ADDR); NCA9555_Init_Device(NCA9555_DEV2_ADDR); // 分别控制 NCA9555_Set_Pin_Device(NCA9555_DEV1_ADDR, 0, 1); NCA9555_Set_Pin_Device(NCA9555_DEV2_ADDR, 0, 1); }6.2 输入中断应用利用INT引脚实现输入状态变化检测配置输入端口设置极性反转寄存器可选使能中断输出在GD32端配置外部中断// 配置PORT0的0-3引脚为输入并启用中断 void NCA9555_Int_Config(void) { uint8_t config[2] {0x0F, 0x00}; // PORT0低4位输入 I2C_Write_Reg(NCA9555_ADDR, 0x06, config, 2); // 设置输入极性可选 uint8_t polarity[2] {0x0F, 0x00}; // 低4位输入反相 I2C_Write_Reg(NCA9555_ADDR, 0x04, polarity, 2); }6.3 省电模式优化对于电池供电设备可采取以下措施不使用的端口设为输入状态降低I2C通信频率利用NCA9555的低功耗特性待机电流典型值1μA

相关新闻