news 2026/6/7 1:48:45

74HC165级联扩展16路输入?手把手教你用STM32F030软件SPI搞定(避坑时序问题)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
74HC165级联扩展16路输入?手把手教你用STM32F030软件SPI搞定(避坑时序问题)

74HC165级联实战:用STM32F030软件SPI实现16路输入扩展

在嵌入式开发中,按键输入扩展是常见需求。当GPIO资源紧张时,74HC165这类并行输入串行输出(PISO)移位寄存器就成了经济高效的解决方案。本文将深入探讨如何通过级联两片74HC165实现16路输入扩展,并针对STM32F030的软件SPI实现提供完整方案。

1. 74HC165级联原理与硬件设计

74HC165的核心功能是将8位并行数据转换为串行输出。级联多片芯片时,前一片的串行输出(QH)连接到后一片的串行输入(SER),形成数据链。时钟(CLK)和锁存(PL)信号并联连接,确保同步操作。

1.1 典型级联电路设计

对于两片74HC165级联,推荐以下连接方式:

信号线连接方式
CLK(时钟)并联到所有芯片的CP引脚
PL(锁存)并联到所有芯片的PL引脚
第一片QH连接到第二片SER
第二片QH连接到MCU的MISO引脚
CE(使能)所有芯片接地(常使能)

关键点:级联时,数据从最后一片芯片输出。在读取时,先移出的是最后一片的数据,最后移出的是第一片的数据。

1.2 STM32F030引脚配置

使用软件SPI时,需要配置三个GPIO:

// 引脚定义(根据实际连接调整) #define HC165_PL_PIN GPIO_PIN_4 #define HC165_PL_PORT GPIOA #define HC165_CLK_PIN GPIO_PIN_3 #define HC165_CLK_PORT GPIOB #define HC165_DATA_PIN GPIO_PIN_6 #define HC165_DATA_PORT GPIOA

2. 软件SPI驱动实现

软件SPI相比硬件SPI的优势在于时序完全可控,特别适合74HC165这类对时序有特殊要求的器件。

2.1 基本读写时序

74HC165的标准操作流程:

  1. 拉低PL引脚,锁存并行输入
  2. 拉高PL引脚,准备移位
  3. 在CLK上升沿移位数据
  4. 循环8×N次(N为芯片数量)
void HC165_Init(void) { // 初始化所有引脚为输出模式(除DATA) GPIO_InitTypeDef GPIO_InitStruct = {0}; // CLK和PL配置为推挽输出 GPIO_InitStruct.Pin = HC165_PL_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(HC165_PL_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = HC165_CLK_PIN; HAL_GPIO_Init(HC165_CLK_PORT, &GPIO_InitStruct); // DATA配置为输入 GPIO_InitStruct.Pin = HC165_DATA_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(HC165_DATA_PORT, &GPIO_InitStruct); // 初始状态 HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_SET); }

2.2 16位数据读取函数

对于两片级联(16位输入),读取函数需要移位16次:

uint16_t HC165_Read16Bits(void) { uint16_t data = 0; // 锁存并行数据 HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_RESET); delay_us(1); // tsu(PL)最小保持时间 HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_SET); delay_us(1); // 确保PL上升沿完成 // 读取16位数据 for(uint8_t i = 0; i < 16; i++) { data <<= 1; if(HAL_GPIO_ReadPin(HC165_DATA_PORT, HC165_DATA_PIN)) { data |= 0x01; } // 产生时钟上升沿 HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_SET); delay_us(1); // 确保时钟高电平时间 HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_RESET); delay_us(1); // 确保时钟低电平时间 } return data; }

注意:delay_us()的实现取决于你的系统时钟。对于STM32F030,可以使用DWT周期计数器或简单的空循环实现。

3. 时序优化与问题排查

软件SPI最常见的挑战是时序问题,特别是级联时数据移位不完整或错位。

3.1 关键时序参数

74HC165有几个关键时序参数需要满足:

参数符号典型值(5V)注意事项
PL脉冲宽度tW(PL)20ns确保足够锁存时间
CLK高电平时间tW(CH)20ns上升沿前保持稳定
CLK低电平时间tW(CL)20ns下降沿后保持稳定
数据建立时间tSU20ns数据在CLK↑前稳定
数据保持时间tH5ns数据在CLK↑后保持

3.2 常见问题及解决方案

  1. 数据错位

    • 现象:读取的数据位与预期不对应
    • 原因:CLK边沿抖动或PL信号不稳定
    • 解决:增加GPIO速度设置,确保时序严格
  2. 最后几位数据丢失

    • 现象:只有前8位数据正确
    • 原因:循环次数不足或时钟信号异常
    • 解决:检查for循环条件,确保移位足够次数
  3. 数据不稳定

    • 现象:相同输入读取值波动
    • 原因:时序余量不足或电源噪声
    • 解决:
      • 增加delay_us时间
      • 在PL和CLK线上加上拉电阻
      • 检查电源滤波电容

3.3 示波器调试技巧

使用示波器观察三个关键信号:

  1. PL信号:应看到清晰的低脉冲
  2. CLK信号:应有16个规整的脉冲
  3. DATA信号:应在每个CLK上升沿前稳定

典型问题波形

  • CLK频率过高→数据建立时间不足
  • PL脉冲过窄→锁存不完全
  • CLK抖动→数据采样点不稳定

4. 高级应用与优化

4.1 多片级联实现

对于超过两片芯片的级联,原理相同,只需调整移位次数:

// 读取24位(3片级联) uint32_t HC165_Read24Bits(void) { uint32_t data = 0; // 锁存并行数据 HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_RESET); delay_us(1); HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_SET); delay_us(1); for(uint8_t i = 0; i < 24; i++) { data <<= 1; if(HAL_GPIO_ReadPin(HC165_DATA_PORT, HC165_DATA_PIN)) { data |= 0x01; } HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_SET); delay_us(1); HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_RESET); delay_us(1); } return data; }

4.2 按键消抖处理

对于按键输入,需要添加消抖逻辑:

uint16_t last_key_state = 0; uint32_t last_key_time = 0; void Check_Keys(void) { uint16_t current_state = HC165_Read16Bits(); uint32_t now = HAL_GetTick(); if(current_state != last_key_state) { last_key_time = now; last_key_state = current_state; } else if((now - last_key_time) > 20) { // 20ms消抖 if(current_state != 0xFFFF) { // 有按键按下 Process_Key_Press(current_state); } } }

4.3 低功耗优化

在电池供电应用中,可以优化功耗:

  1. 仅在需要时使能74HC165(通过CE引脚)
  2. 降低采样频率
  3. 使用中断唤醒而非轮询
// 配置EXTI中断在按键变化时唤醒 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == KEY_INT_PIN) { Check_Keys(); } }

在实际项目中,74HC165级联方案不仅限于按键扫描,还可用于多路开关状态监测、DIP开关读取等场景。通过精确控制软件SPI时序,即使在资源受限的STM32F030上也能实现稳定可靠的扩展输入。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/7 1:47:39

别再只会抄实验报告了!手把手教你用Bitcoin Core 0.15.2在Windows上搭建私有测试网(附配置文件详解)

从零构建比特币私有测试网&#xff1a;Windows实战指南与深度解析 当我在大学第一次接触区块链实验时&#xff0c;面对实验手册里密密麻麻的命令行和晦涩的术语&#xff0c;那种手足无措的感觉至今记忆犹新。现在&#xff0c;我将以过来人的身份&#xff0c;带你真正理解而不仅…

作者头像 李华
网站建设 2026/6/7 1:40:22

如何用NarratoAI实现智能视频解说:从零开始的完整教程

如何用NarratoAI实现智能视频解说&#xff1a;从零开始的完整教程 【免费下载链接】NarratoAI 利用AI大模型&#xff0c;一键解说并剪辑视频&#xff1b; Using AI models to automatically provide commentary and edit videos with a single click. 项目地址: https://gitc…

作者头像 李华
网站建设 2026/6/7 1:37:48

2025年09月 GESP等级认证C++编程(一级)试题解析

【单选题】1、&#xff08;2分&#xff09;人工智能现在非常火&#xff0c;小杨就想多了解一下&#xff0c;其中就经常听人提到“大模型”。那么请问这里说的“大模型”最贴切是指&#xff1f;&#xff08; &#xff09;A、大电脑模型 B、大规模智能 C、智能的单位 D、…

作者头像 李华
网站建设 2026/6/7 1:35:56

【稀缺首发】SaaS企业AI营销选型红宝书(CSDN版):覆盖11类细分赛道验证结论,仅开放72小时免费领取完整评估模板

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;SaaS 企业适合用 CSDN AI 数字营销吗&#xff1f; CSDN AI 数字营销平台聚焦于开发者社区场景&#xff0c;其核心能力围绕技术内容分发、开发者画像建模与智能线索培育展开。对 SaaS 企业而言&#xff0c;是否…

作者头像 李华