STM32与74HC165A实现高效数字输入扩展方案

发布时间:2026/7/3 14:03:45
STM32与74HC165A实现高效数字输入扩展方案 1. 项目背景与核心价值在工业控制和嵌入式系统开发中我们经常需要处理大量数字输入信号。传统方案要么占用过多MCU引脚资源要么需要复杂的外围电路设计。而采用74HC165A这款经典并行输入串行输出(PISO)移位寄存器配合STM32F412ZG的高性能SPI接口可以优雅地解决这个问题。我最近在一个工业控制器项目中需要监测32个机械开关状态。若直接使用STM32的GPIO将消耗1/3的可用引脚资源。通过级联4片74HC165A最终仅占用3个MCU引脚SPI CLK、MISO和LOAD实现了32:3的引脚扩展比。这种方案特别适合以下场景需要监测大量数字输入如按钮、限位开关、传感器系统PCB空间有限需要减少走线数量要求实时性较高STM32F4的SPI时钟可达50MHz2. 硬件设计要点2.1 芯片选型对比MC74HC165A是TI生产的8位并行输入串行输出移位寄存器主要参数工作电压2V-6V完美匹配STM32的3.3V逻辑最大时钟频率36MHz4.5V输入电流±1μA超低静态功耗封装SOIC-16易于手工焊接相比CD4021等同类芯片74HC165A具有更快的时钟响应和更低的功耗。实测在3.3V供电时可靠工作频率可达25MHz。2.2 典型电路连接以级联4片74HC165A为例扩展32路输入[VCC]---------------- | | | | 74HC165A#1 |#2 |#3 |#4 [GND] SH/LD-------------- CLK---------------- QH----- | | | --- | | ------- | ----------- | [STM32F412ZG] PA5(SPI1_SCK) PA6(SPI1_MISO) PA7(GPIO_LOAD)关键细节所有芯片的SH/LD(移位/装载)引脚并联由单个GPIO控制前级QH接后级SER(串行输入)实现级联每个PL(并行加载)引脚接10K上拉电阻VCC与GND间放置0.1μF去耦电容每片芯片独立注意级联时时钟信号要等长走线避免时序偏移。建议使用蛇形走线保持长度一致。3. 软件实现详解3.1 STM32CubeMX配置启用SPI1为主机模式Clock Prescaler: 8 (12.5MHz 100MHz系统时钟)CPOL: Low, CPHA: 1EdgeData Size: 8bitsNSS: Hardware Disabled配置PA7为GPIO_Output(LOAD信号)生成代码时勾选Generate peripheral initialization as a pair of .c/.h3.2 关键代码实现// 读取级联的74HC165A数据 uint32_t Read_74HC165s(uint8_t cascade_num) { uint32_t result 0; // 拉低LOAD引脚锁存并行输入 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); HAL_Delay(1); // 保持至少25ns(实测需要500ns稳定) // 拉高LOAD开始移位 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); // 通过SPI连续读取数据 for(uint8_t i0; icascade_num; i){ uint8_t byte; HAL_SPI_Receive(hspi1, byte, 1, 100); result (result 8) | byte; } return result; } // 使用示例读取4片级联32位输入 void main() { uint32_t inputs Read_74HC165s(4); if(inputs (15)) { // 处理第6路输入信号 } }3.3 性能优化技巧中断驱动法将LOAD信号连接外部中断引脚在下降沿触发读取DMA传输配置SPI DMA连续接收减少CPU占用软件去抖对关键输入添加以下处理逻辑#define DEBOUNCE_TIME 20 // ms uint32_t stable_inputs 0; uint32_t last_inputs 0; uint32_t change_time 0; void Check_Debounce() { uint32_t current Read_74HC165s(4); if(current ! last_inputs){ change_time HAL_GetTick(); last_inputs current; } else if(HAL_GetTick() - change_time DEBOUNCE_TIME){ stable_inputs current; } }4. 常见问题排查4.1 数据移位错位症状读取的数据位与物理输入不对应 排查步骤用逻辑分析仪抓取SPI时序确认CLK相位配置CPHA1Edge检查PCB走线是否等长级联时差异应1/4时钟周期测量电源纹波应在±5%以内4.2 输入响应延迟症状输入变化到MCU检测有100us延迟 优化方案提高SPI时钟最高不超过芯片规格的80%改用中断触发代替轮询减少级联芯片数量建议不超过8片4.3 电磁干扰问题症状长线缆输入时出现误触发 解决方案在输入端添加RC滤波100Ω100nF使用双绞线传输信号在PCB上放置TVS二极管防护5. 进阶应用实例5.1 工业控制面板扫描某纺织机械项目需要监测48个按钮状态使用6片74HC165A级联每10ms扫描一次通过TIM6定时器触发采用差分信号传输RS485芯片转换抗干扰5.2 多设备状态监测冷链监控系统中每个冷藏柜提供8路状态信号主控STM32F412ZG通过1个SPI接口级联16片74HC165A128路输入使用74HC138进行片选分区读取实测数据方案引脚占用扫描周期CPU负载直接GPIO1281ms15%74HC165A42ms3%5.3 与其它外设协同工作当SPI1被74HC165A占用时如何同时使用SPI Flashvoid Read_MultiDevices() { // 先读取74HC165A uint32_t inputs Read_74HC165s(4); // 切换片选到Flash HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(hspi1, tx_buf, rx_buf, 256, 100); HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET); // 注意需要重新配置SPI参数若Flash要求不同模式 }通过这个项目我发现74HC165A虽然是一款老芯片但在现代嵌入式系统中仍然大有用武之地。特别是在需要降低成本、减少PCB层数的场合这种数字扩展方案比使用IO扩展芯片更经济可靠。实际部署时建议在第一批板卡上预留未使用的74HC165A位置便于后期功能扩展。