PCA9698 GPIO扩展芯片深度解析:40位I2C端口扩展器在嵌入式系统中的应用

发布时间:2026/6/11 14:22:23

PCA9698 GPIO扩展芯片深度解析:40位I2C端口扩展器在嵌入式系统中的应用 1. 项目概述与核心价值在嵌入式开发和工业控制项目中我们常常会遇到一个经典难题主控芯片的GPIO引脚不够用了。无论是驱动几十个LED指示灯、读取多路传感器状态还是控制一组继电器阵列当项目规模稍微扩大微控制器那几十个引脚就显得捉襟见肘。这时候GPIO扩展芯片就成了我们的“救星”。今天要深入聊的这颗PCA9698就是我在多个大型工控和服务器背板项目中反复使用、验证过的一块“硬核”扩展芯片。它不仅仅是简单地把I2C信号转成并行IO更是一个集成了中断管理、输出结构可编程、多设备同步控制等高级功能的40位端口扩展器。简单来说PCA9698就像给你的主控芯片比如常见的STM32、ESP32或者树莓派外挂了一个拥有40个独立“手脚”的智能管家。你只需要占用主控的两个引脚SDA和SCL就能通过I2C总线对这40个端口进行精细化的控制。每个端口都能独立配置为输入或输出输出可以设置为推挽或开漏模式输入状态变化还能触发中断通知主控甚至还能把输入信号的逻辑极性反转后再读取。它的价值在于用极低的引脚和软件开销换来了巨大的接口扩展能力特别适合那些需要集中管理大量数字信号但对实时性和同步性又有一定要求的场景比如服务器机柜的状态监控、工业PLC的分布式IO模块或者大型仪器面板的背光控制。2. PCA9698核心架构与工作模式解析2.1 整体架构与端口组织PCA9698的内部架构可以理解为一个高度可配置的“数字开关矩阵”。其核心是将40个I/O端口IO0_0 至 IO4_7划分为5个独立的“银行”Bank每个银行包含8个端口。这种分银行管理的方式非常巧妙它使得对端口的批量操作变得高效。例如你可以一次性读取Bank 0的8个输入状态或者一次性设置Bank 2的8个输出电平而不需要逐个位操作。芯片与主控的通信完全依赖于I2C总线并且它支持高达1 MHz的Fast-mode PlusFm模式。这是什么概念比标准的100kHz模式快10倍比快速模式400kHz也快2.5倍。更高的通信速率意味着主控能更快地刷新40个端口的状态这对于需要快速响应输入变化如按键扫描或实现高速PWM调光通过OE引脚的应用至关重要。此外Fm模式允许总线上挂载更大的容性负载最高4000pF这意味着你可以在更长的走线或连接更多设备的情况下依然保持通信稳定非常适合在复杂的背板或机箱内布线。除了40个GPIO芯片还有几个关键的功能引脚INT/SMBALERT这是一个开漏输出的中断引脚。当任何被配置为输入且未屏蔽中断的端口状态发生变化时这个引脚会被拉低从而通知主控“有情况发生”主控无需持续轮询节省了CPU资源。它同时兼容SMBus Alert功能用于在多设备系统中报告异常。OE (Output Enable)输出使能引脚。当此引脚有效时所有被配置为输出的端口会进入高阻态三态。你可以通过编程改变其有效极性高有效或低有效。这个引脚的一个高级用法是接入一个PWM信号当PWM频率高于80Hz时可以轻松实现所有输出端口的同步调光或闪烁比如统一调节一排LED的亮度。RESET硬件复位引脚。拉低此引脚会将芯片所有内部寄存器恢复为上电默认值所有40个端口被设置为输入模式。这是一个可靠的“安全重启”机制。AD0, AD1, AD2这三个地址选择引脚通过上拉或下拉电阻配置可以为芯片设定64个不同的I2C从机地址之一允许你在同一条I2C总线上挂载多达64片PCA9698理论上扩展出2560个GPIO这在大型系统中是极其恐怖的扩展能力。2.2 核心寄存器组深度剖析对PCA9698的编程本质上就是对一系列寄存器的读写。理解这些寄存器是玩转这颗芯片的关键。所有寄存器都是8位宽与每个Bank的8个端口一一对应。1. 配置寄存器 (IOC0-IOC4) - 设定方向这是首先要配置的寄存器组。每个BitCx[y]控制对应端口的方向Cx[y] 0 对应IOx_y端口为输出。Cx[y] 1 对应IOx_y端口为输入。上电或复位后所有端口的默认值都是1即全部为输入状态。这是一个安全设计防止芯片一上电就驱动未知的外部电路。2. 输出端口寄存器 (OP0-OP4) - 控制输出电平当端口配置为输出后向这些寄存器的对应位写入0或1就能控制输出低电平或高电平。Ox[y] 0 输出低电平。Ox[y] 1 输出高电平。重要提示读取OP寄存器返回的是你之前写入的值即内部锁存器的值而不是引脚上实际测量到的电压。如果外部电路将引脚拉低但你写入的是1读取OP寄存器依然得到1。3. 输入端口寄存器 (IP0-IP4) - 读取输入状态无论端口被配置为输入还是输出读取这些寄存器都能获取引脚上实际的逻辑电平。Ix[y] 0 对应引脚检测到低电平。Ix[y] 1 对应引脚检测到高电平。一个实用技巧即使某个端口被配置为输出你也可以通过读取IP寄存器来监测该引脚的实际电平这在实现“线或”Wire-OR或检测输出短路时非常有用。4. 极性反转寄存器 (PI0-PI4) - 翻转输入逻辑这个功能非常贴心。有时候为了电路设计方便我们可能希望按键按下引脚接地时程序读到的是逻辑‘1’。PI寄存器就能实现这个“反向”读取。Px[y] 0 不对应端口的输入极性读IP寄存器是什么就是什么。Px[y] 1 将对应端口的输入极性反转。即引脚实际为低电平时读IP寄存器得到1实际为高电平时读到0。5. 中断屏蔽寄存器 (MSK0-MSK4) - 精细控制中断源PCA9698支持输入变化中断但并不是所有输入变化都需要打扰主控。MSK寄存器允许你屏蔽特定端口的中断。Mx[y] 0 允许中断。当对应输入端口状态变化时会触发INT引脚有效。Mx[y] 1 屏蔽中断。对应输入端口的变化不会触发INT。注意只有被配置为输入IOC寄存器对应位为1的端口其中断屏蔽设置才有效。默认所有端口的中断都是被屏蔽的MSK寄存器默认全1。2.3 高级功能寄存器详解除了上述与端口直接对应的寄存器PCA9698还有三个控制全局行为的寄存器它们提供了更高级的控制维度。1. 输出结构配置寄存器 (OUTCONF)这个寄存器决定了输出级的电路结构直接影响驱动能力和连接方式。对于Bank 0 它的4个端口对IO0_01, IO0_23, IO0_45, IO0_67可以独立配置。OUT001、OUT023、OUT045、OUT067这4个位每两位控制一对端口。对于Bank 1-4 每个Bank作为一个整体来配置。OUT1、OUT2、OUT3、OUT4分别控制整个Bank。位值含义0 配置为开漏输出。只能主动拉低高电平靠外部上拉电阻实现。最大灌电流25mA。适用于总线如I2C或需要“线或”连接的场景。1 配置为推挽输出默认。可以主动输出高电平源电流10mA或低电平灌电流25mA。驱动能力强适合直接驱动LED或继电器。2. 全Bank控制寄存器 (ALLBNK)这是一个批量操作的“快捷指令”寄存器。想象一下你需要同时点亮所有Bank中作为输出的LED如果通过写5个OP寄存器来实现需要5次I2C写入操作。而使用ALLBNK一次写入就能搞定。B0-B4位 分别对应Bank 0-4。你希望这些Bank的输出被设置成什么全局状态全0或全1。BSEL位位7 这是操作模式选择位它决定了B0-B4位的具体含义是理解这个寄存器的关键。BSEL 0 (默认) “清零”模式。当Bx0时对应Bank中所有配置为输出的端口强制输出0当Bx1时对应Bank的输出保持OP寄存器中的原值不变。BSEL 1 “置一”模式。当Bx1时对应Bank中所有配置为输出的端口强制输出1当Bx0时对应Bank的输出保持OP寄存器中的原值不变。 实操心得ALLBNK的妙用这个寄存器在实现全局闪烁、呼吸灯效果时极其高效。你不需要更新40个位的OP寄存器值只需要在BSEL0和BSEL1两种状态下向ALLBNK寄存器写入不同的值例如0x1F和0x00就能让所有输出在全亮和全灭之间切换配合OE引脚的PWM可以做出非常复杂的灯光效果。3. 模式选择寄存器 (MODE)这个寄存器集成了几个关键的全局设置。OEPOL (位0) 输出使能引脚极性选择。0低电平有效默认1高电平有效。根据你的硬件设计例如使能信号是直接来自MCU GPIO还是经过反相器来设置。OCH (位1) 输出变化时机选择。这是影响输出同步性的关键0 输出在I2C通信的STOP命令时更新。这是实现多端口、多芯片同步输出的唯一方式。主控可以依次写入多个PCA9698的多个OP寄存器最后发一个STOP所有芯片的所有端口会在同一时刻更新输出。1默认 输出在每写入一个OP寄存器后的ACK应答时立即更新。响应快但无法保证多个端口同时变化。IOAC (位3) GPIO全局呼叫使能。1使能该芯片会响应特定的“全局呼叫”I2C地址0x70写允许主控一次性向总线上所有使能了此功能的PCA9698发送相同指令。默认关闭0。SMBA (位4) SMBus Alert响应使能。1使能芯片会响应SMBus的Alert响应地址。用于高级系统管理。默认关闭0。3. 实战驱动设计与软件实现3.1 硬件连接与地址配置拿到PCA9698第一步是正确连接硬件并设置地址。芯片有TSSOP56和HVQFN56两种封装引脚较多但核心引脚很清晰。电源与地VDD接2.3V至5.5VVSS接地。特别注意芯片有多个VDD和VSS引脚必须全部连接尤其是HVQFN封装的散热焊盘务必良好接地以散热和保证电气性能。I2C总线SCL时钟和SDA数据线需要连接上拉电阻通常4.7kΩ到10kΩ上拉至VDD。地址引脚AD0,AD1,AD2这三个引脚决定了芯片的7位I2C地址。地址格式为0100 A2 A1 A0 R/W其中A2/A1/A0就是这三个引脚的电平接VDD为1接VSS为0。因此通过上下拉电阻可以设置出64个从地址0x20 到 0x7F7位地址。务必注意这三个引脚内部无上拉必须外部处理悬空会导致地址不确定。功能引脚OE 如果不用可以接VDD如果OEPOL0或VSS如果OEPOL1来永久使能输出。如果用于PWM调光则连接MCU的PWM输出。INT 开漏输出需要上拉电阻如10kΩ至VDD或系统逻辑电压。连接至MCU的外部中断引脚。RESET 通常通过一个上拉电阻如10kΩ接VDD需要复位时由MCU拉低至少一个脉冲宽度。3.2 基础驱动函数编写以C语言为例一个健壮的驱动层应该封装对寄存器的基本操作。以下代码基于模拟I2C或硬件I2C的底层i2c_write和i2c_read函数。#define PCA9698_BASE_ADDR 0x40 // 假设AD2AD1AD00 7位地址为0100000即0x40 // 命令寄存器指针设置 uint8_t pca9698_set_pointer(uint8_t reg_addr, uint8_t auto_inc) { uint8_t cmd_byte reg_addr 0x3F; // 低6位是寄存器指针 if(auto_inc) { cmd_byte | 0x80; // 设置自动递增位(AI) } return i2c_write(PCA9698_BASE_ADDR, cmd_byte, 1); } // 写入单个寄存器非自动递增模式 uint8_t pca9698_write_reg(uint8_t reg_addr, uint8_t value) { uint8_t buffer[2]; buffer[0] reg_addr 0x3F; // AI0 buffer[1] value; return i2c_write(PCA9698_BASE_ADDR, buffer, 2); } // 读取单个寄存器 uint8_t pca9698_read_reg(uint8_t reg_addr) { uint8_t value; pca9698_set_pointer(reg_addr, 0); // 先设置指针 i2c_read(PCA9698_BASE_ADDR, value, 1); return value; } // 批量读取多个寄存器利用自动递增 uint8_t pca9698_read_burst(uint8_t start_reg_addr, uint8_t *buffer, uint8_t len) { // 设置起始指针并开启自动递增 if(pca9698_set_pointer(start_reg_addr, 1) ! 0) return 1; // 连续读取 return i2c_read(PCA9698_BASE_ADDR, buffer, len); }3.3 典型应用场景代码实现场景一初始化并配置16个LED输出Bank0和Bank1其余为输入void pca9698_init_leds(void) { // 1. 配置方向 Bank0, Bank1 为输出其余保持输入默认 pca9698_write_reg(0x18, 0x00); // IOC0: Bank0全部输出 pca9698_write_reg(0x19, 0x00); // IOC1: Bank1全部输出 // 2. 配置输出结构 Bank0和Bank1为推挽输出默认即为1可省略 // OUTCONF寄存器 OUT11, OUT0xx1 (默认值0xFF) // pca9698_write_reg(0x28, 0xFF); // 3. 关闭所有LED输出低电平 pca9698_write_reg(0x08, 0x00); // OP0 pca9698_write_reg(0x09, 0x00); // OP1 // 4. 配置模式输出在STOP时更新以实现同步变化 uint8_t mode pca9698_read_reg(0x2A); mode ~(1 1); // 清除OCH位bit1设为0 pca9698_write_reg(0x2A, mode); // 5. 使能输出假设OE引脚由MCU的GPIO控制且低有效 // MCU_GPIO_SetLow(OE_PIN); }场景二读取24个按键状态Bank2,3,4并启用中断uint8_t key_status[3]; // 存放Bank2,3,4的状态 void pca9698_init_keys(void) { // 1. 配置方向 Bank2,3,4为输入默认就是但显式设置更清晰 // IOC2, IOC3, IOC4 默认就是0xFF可不写。 // 2. 配置极性假设按键按下为低电平但我们希望程序读到1 pca9698_write_reg(0x12, 0xFF); // PI2: Bank2输入全部反转 pca9698_write_reg(0x13, 0xFF); // PI3 pca9698_write_reg(0x14, 0xFF); // PI4 // 3. 配置中断屏蔽允许所有按键输入触发中断 pca9698_write_reg(0x22, 0x00); // MSK2: Bank2全部允许中断 pca9698_write_reg(0x23, 0x00); // MSK3 pca9698_write_reg(0x24, 0x00); // MSK4 // 4. 读取初始状态避免一上电就误触发中断 pca9698_read_burst(0x02, key_status, 3); // 从IP2开始读3个字节 } // 中断服务函数中读取键值 void EXTI_IRQHandler(void) { // 假设INT连接到了外部中断 if(检查是PCA9698_INT引脚触发) { uint8_t new_status[3]; pca9698_read_burst(0x02, new_status, 3); // 比较new_status和key_status找出变化的键 // ... memcpy(key_status, new_status, 3); // 清除中断标志... } }场景三使用ALLBNK实现所有LED同步闪烁void pca9698_all_leds_toggle(void) { static uint8_t led_state 0; // 使用ALLBNK寄存器一次操作控制所有Bank的输出 if(led_state 0) { // 模式BSEL0 B4-B0全1意味着所有Bank保持原OP值此时原值为0灯灭 // 实际上我们需要让灯全亮所以应该用BSEL1模式让B4-B0全1来置位所有输出 pca9698_write_reg(0x29, 0x9F); // 0b1001 1111: BSEL1, B4-B011111 led_state 1; } else { // 模式BSEL0 B4-B0全0强制所有Bank输出0 pca9698_write_reg(0x29, 0x00); // 0b0000 0000: BSEL0, B4-B000000 led_state 0; } // 注意此操作会覆盖OP寄存器的独立控制闪烁期间无法单独控制某个LED。 // 若要恢复独立控制需向ALLBNK写入0x80BSEL1 B4-B000000然后重新写入OP寄存器。 }4. 高级应用技巧与避坑指南4.1 中断处理与防抖动策略PCA9698的中断INT引脚是电平触发低电平有效的并且是开漏输出。这意味着必须连接上拉电阻否则中断线永远无法变高。当任何一个未屏蔽的输入端口状态发生变化时INT引脚就会被拉低。一旦中断发生INT引脚会保持低电平直到主控通过I2C读取了发生变化端口的输入寄存器IPx。读取操作会清除内部的中断标志INT引脚随即被释放变高。如果多个端口同时变化需要读取所有相关Bank的IP寄存器才能完全清除中断。 避坑指南中断的“读-清除”机制这是最容易出错的地方。很多开发者配置好中断后发现只能触发一次或者中断一直保持。根本原因就是没有正确清除中断源。正确的流程是MCU检测到INT引脚低电平中断。依次读取所有可能产生中断的Bank的输入寄存器IP0-IP4。即使你只关心Bank2也最好把5个Bank都读一遍确保清除所有潜在的中断标志。你可以使用pca9698_read_burst(0x00, buffer, 5)一次性读完。处理读取到的数据。中断标志清除INT引脚恢复高电平。输入防抖动PCA9698的输入端口内置了约50ns的噪声滤波器可以滤除窄毛刺。但对于机械按键几十毫秒抖动是远远不够的。必须在软件层面进行防抖处理。一个稳健的做法是在中断服务程序中只设置一个“有按键事件”的标志位然后在主循环中延迟20-50ms后再次读取端口状态进行确认。4.2 输出同步OCH位与多设备协同OCH位输出变化时机的选择对系统行为影响巨大。OCH1 (ACK时更新) 优点是实时性强写入一个字节对应端口的输出立即改变。缺点是无法保证多个端口的同步性。比如你先写Bank0让LED1亮再写Bank1让LED2亮这两个事件之间有I2C传输和处理的时间差可能达到微秒级在人眼看来可能是同时的但在精密控制时序中就是不同步的。OCH0 (STOP时更新) 这是实现硬同步的关键。你可以在一次I2C事务中以START开始STOP结束写入任意多个PCA9698的任意多个OP寄存器。只有在最后的STOP命令发出时所有被写入的寄存器才会同时更新到物理引脚上。这对于需要精确同步多个执行器如多路步进电机使能的应用至关重要。多设备同步操作将所有PCA9698的OCH位设为0。主控发起START。依次访问每个需要更新的PCA9698地址不同写入其OP寄存器。每次访问结束用Re-START重复起始条件而不是STOP。访问完所有设备后主控发出STOP命令。此刻总线上所有被访问的PCA9698的输出端口同时更新。4.3 电源与布线注意事项去耦电容 在每个PCA9698的VDD和VSS引脚附近必须放置一个100nF的陶瓷去耦电容并尽量靠近芯片引脚。如果驱动负载较重如多个LED同时开关建议再并联一个10uF的钽电容或电解电容以提供瞬时大电流。灌电流与总电流限制 每个引脚的灌电流sink能力为25mA源电流source为10mA。整个芯片的总输出电流不能超过1A。在设计驱动多个LED时必须计算总电流。例如40个端口都作为推挽输出驱动LED到高电平即使每个只消耗10mA总电流也达到400mA仍在安全范围内。但如果同时驱动继电器线圈就要仔细核算。热插拔设计 PCA9698专为PICMG工业计算机标准等支持热插拔的应用设计。其I/O引脚具有Ioff特性即在芯片未上电时输出为高阻态不会干扰总线。在背板或可插拔模块设计中这是一个关键优势。I2C总线布线 当使用1MHz Fm模式时对布线要求较高。SCL和SDA线应尽可能短等长并远离噪声源如电机、电源线。如果总线长度超过10厘米或设备超过3个建议使用示波器检查信号完整性确保上升沿和下降沿干净。4.4 常见问题排查速查表现象可能原因排查步骤与解决方案I2C通信失败无应答1. 电源未接通或电压不对。2. I2C地址错误。3. SDA/SCL上拉电阻缺失或阻值过大。4. 总线被锁死。1. 测量VDD电压2.3-5.5V。2. 用逻辑分析仪抓取I2C波形核对发送的地址字节7位地址读写位。确认AD0-2引脚电平。3. 检查SDA/SCL是否有4.7kΩ上拉至VDD。4. 尝试对总线发送多个时钟脉冲SCL以解锁或重启系统。可以写入但读取数据全为0或0xFF1. 读操作流程错误未先发送寄存器指针。2. 自动递增AI位设置混乱。3. 读操作后未发送NACK终止。1. 确认读操作遵循START - 写地址W - 写命令字节寄存器指针- Re-START - 读地址R - 读取数据 - NACK - STOP。2. 对于单次读设置命令字节时AI位应为0。3. 确保在读取最后一个字节后主控发送NACK然后发送STOP。输出端口无反应1. OE引脚未使能处于禁用状态。2. 端口方向配置错误IOC寄存器仍为输入。3. OCH模式导致输出未更新。4. 外部负载过重或短路。1. 测量OE引脚电平根据OEPOL配置确认其处于有效状态。2. 读取IOC寄存器确认对应位已设为0输出。3. 如果OCH0检查是否发送了STOP命令。4. 断开负载测量引脚空载电压。检查负载电流是否超限。中断不触发或常触发1. INT引脚未接上拉电阻。2. 中断屏蔽寄存器MSK未正确配置。3. 未读取输入寄存器以清除中断标志。4. 输入信号抖动严重。1. 检查INT引脚是否有10kΩ上拉电阻。2. 确认MSK寄存器对应位为0允许中断。3.在中断服务程序中必须读取发生变化的Bank的IP寄存器。4. 增加软件防抖或硬件RC滤波电路。使用ALLBNK后单独控制OP寄存器失效对ALLBNK寄存器的操作会覆盖OP寄存器的控制逻辑。要恢复单独控制需先将ALLBNK寄存器写为0x80BSEL1 B4-B000000此操作告诉芯片“所有Bank恢复使用OP寄存器的值”。然后再去更新OP寄存器。多片设备同时操作不同步OCH位设置错误。确保所有需要同步输出的PCA9698其MODE寄存器中的OCH位都设置为0STOP时更新。并在一次I2C事务中用Re-START连接配置完所有设备后再发统一的STOP命令。5. 项目实战构建一个智能照明控制板最后让我们用一个综合项目来串联所有知识点设计一块基于PCA9698的智能照明控制板用于控制一个拥有40个通道的LED灯带要求能实现全局调光、分组闪烁、独立控制并能监测8个按键输入。硬件设计MCU STM32F103 I2C1接口连接PCA9698。PCA9698 AD2-AD0接地地址为0x40。OE引脚连接STM32的定时器PWM输出TIM2_CH1。INT引脚连接STM32的EXTI9_5中断线PB5。输出 Bank0-Bank4的40个端口通过三极管驱动电路控制40路LED灯带的正极共阴极连接。输出结构配置为推挽。输入 Bank4的高4位IO4_4 ~ IO4_7连接4个带硬件防抖的按键低4位悬空。配置为输入极性反转按下为1启用中断。软件架构初始化// 配置I2C、GPIO、EXTI、PWM... pca9698_write_reg(0x28, 0xFF); // 所有输出为推挽 pca9698_write_reg(0x18, 0x00); // Bank0输出 pca9698_write_reg(0x19, 0x00); // Bank1输出 pca9698_write_reg(0x1A, 0x00); // Bank2输出 pca9698_write_reg(0x1B, 0x00); // Bank3输出 pca9698_write_reg(0x1C, 0xF0); // Bank4: 高4位输入低4位输出 pca9698_write_reg(0x14, 0xF0); // PI4: 高4位输入极性反转 pca9698_write_reg(0x24, 0x0F); // MSK4: 屏蔽低4位输出允许高4位中断 pca9698_write_reg(0x2A, 0x00); // MODE: OCH0 (STOP同步), OEPOL0 pca9698_read_burst(0x04, bank4_input, 1); // 读取IP4清除可能的中断调光功能 将TIM2产生的PWM信号连接到OE引脚。通过改变PWM占空比可以同时调节40路LED的亮度。占空比100%时最亮0%时全灭。频率设置在100Hz以上以避免闪烁。灯光模式引擎 在主循环中运行一个状态机根据按键指令切换模式。模式1全局呼吸 动态调整PWM占空比实现淡入淡出。使用ALLBNK寄存器快速开关所有灯0x9F和0x00。模式2流水灯 通过I2C依次更新OP0-OP4寄存器配合OCH0和最后的STOP实现40个灯依次点亮且无拖影的流畅效果。模式3分组控制 将5个Bank分为5组通过操作ALLBNK寄存器可以轻松实现0x88仅Bank0和Bank4亮、0x11仅Bank1亮等组合效果。中断服务程序void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line5) ! RESET) { uint8_t current_keys; pca9698_read_burst(0x04, current_keys, 1); // 读取IP4清除中断 current_keys 4; // 取高4位 key_event current_keys ^ last_key_state; // 检测边沿 last_key_state current_keys; // 根据key_event设置模式标志... EXTI_ClearITPendingBit(EXTI_Line5); } }通过这个项目你可以深刻体会到PCA9698如何将复杂的并行IO控制简化为清晰的I2C寄存器操作并通过其丰富的高级功能中断、同步输出、全局控制、PWM调光构建出响应迅速、效果丰富的嵌入式系统。它绝不仅仅是一个简单的端口扩展器而是一个需要你仔细阅读数据手册、理解其设计哲学才能充分发挥其威力的智能外设。

相关新闻