当前位置: 首页 > news >正文

别再手动焊矩阵键盘了!用STM32F103C8T6驱动74HC165扩展16个按键(附完整CubeMX配置)

用STM32CubeMX快速实现74HC165按键扩展方案

在嵌入式开发中,经常会遇到需要扩展多个按键的场景。传统矩阵键盘虽然节省IO口,但存在"鬼影"问题且需要复杂的扫描逻辑。而直接使用GPIO驱动独立按键,又受限于芯片引脚数量。本文将介绍如何利用STM32F103C8T6和74HC165移位寄存器,通过CubeMX图形化配置工具快速搭建16键输入系统。

1. 硬件设计基础

1.1 74HC165工作原理

74HC165是一款8位并行输入/串行输出移位寄存器,主要特性包括:

  • 并行加载:当PL(Parallel Load)引脚为低电平时,8位并行输入数据被锁存到内部寄存器
  • 时钟控制:在CP(Clock Pulse)上升沿时,数据从Q7引脚串行输出
  • 级联能力:通过Q7'引脚可连接多片74HC165实现更多位扩展

关键参数对比

参数74HC165备注
工作电压2V-6V与3.3V STM32完美兼容
时钟频率最高36MHz远超过手动按键需求
输入电流±1μA低功耗特性
传输延迟13ns(典型值)响应速度极快

1.2 典型电路连接

两片74HC165级联实现16位输入的典型接法:

[按键矩阵] → [74HC165(1)] → [74HC165(2)] → [STM32] PL(并联) CP(并联) Q7'→DS

具体引脚连接:

  • PL:连接到STM32任意GPIO(如PC0),控制数据加载
  • CP:连接到STM32任意GPIO(如PB6),提供时钟信号
  • Q7:连接到STM32输入GPIO(如PB5),读取串行数据
  • DS:第二片的串行输入连接第一片的Q7'

注意:实际布线时应确保时钟线远离高频干扰源,并在长距离传输时考虑加入适当终端电阻。

2. CubeMX工程配置

2.1 时钟与GPIO初始化

  1. 打开STM32CubeMX,选择STM32F103C8T6芯片

  2. Pinout & Configuration选项卡中:

    • 配置系统时钟为72MHz(HSE晶振模式)
    • 设置PB5为输入模式(上拉)
    • 设置PB6和PC0为输出模式(推挽)
  3. Project Manager中:

    • 选择生成HAL库代码
    • 启用"Generate peripheral initialization as a pair of .c/.h files"

关键配置代码片段(自动生成):

/* GPIO Ports Clock Enable */ __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); /*Configure GPIO pins : PB6 PC0 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin : PB5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

2.2 定时器配置(可选)

为按键消抖可配置一个基本定时器:

  1. 选择TIM2,配置为:
    • Prescaler: 7199 (100Hz @72MHz)
    • Counter Mode: Up
    • Period: 9 (10ms中断)
  2. 生成中断并启用NVIC

3. 驱动程序实现

3.1 基本读写函数

#define HC165_PL_PIN GPIO_PIN_0 #define HC165_PL_PORT GPIOC #define HC165_CLK_PIN GPIO_PIN_6 #define HC165_CLK_PORT GPIOB #define HC165_DATA_PIN GPIO_PIN_5 #define HC165_DATA_PORT GPIOB uint16_t HC165_ReadData(void) { uint16_t data = 0; // 加载并行数据 HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_RESET); HAL_Delay(1); // 保持PL低电平至少20ns HAL_GPIO_WritePin(HC165_PL_PORT, HC165_PL_PIN, GPIO_PIN_SET); // 读取第一位(MSB) if(HAL_GPIO_ReadPin(HC165_DATA_PORT, HC165_DATA_PIN)) data |= 0x8000; // 移位读取剩余15位 for(uint8_t i=0; i<15; i++) { data >>= 1; HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_RESET); HAL_Delay(1); HAL_GPIO_WritePin(HC165_CLK_PORT, HC165_CLK_PIN, GPIO_PIN_SET); if(HAL_GPIO_ReadPin(HC165_DATA_PORT, HC165_DATA_PIN)) data |= 0x8000; } return data; }

3.2 按键消抖处理

利用定时器中断实现硬件消抖:

volatile uint16_t rawKeys = 0; volatile uint16_t stableKeys = 0; volatile uint8_t debounceCnt[16] = {0}; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) { rawKeys = ~HC165_ReadData(); // 取反使按下为1 for(uint8_t i=0; i<16; i++) { if(rawKeys & (1<<i)) { if(debounceCnt[i] < 10) debounceCnt[i]++; if(debounceCnt[i] == 5) stableKeys |= (1<<i); } else { if(debounceCnt[i] > 0) debounceCnt[i]--; if(debounceCnt[i] == 0) stableKeys &= ~(1<<i); } } } }

4. 应用层实现技巧

4.1 按键事件检测

uint16_t prevKeys = 0; void CheckKeyEvents(void) { uint16_t keyChanges = stableKeys ^ prevKeys; uint16_t keyPress = keyChanges & stableKeys; uint16_t keyRelease = keyChanges & (~stableKeys); for(uint8_t i=0; i<16; i++) { if(keyPress & (1<<i)) { // 处理按键按下事件 printf("Key %d pressed\n", i); } if(keyRelease & (1<<i)) { // 处理按键释放事件 printf("Key %d released\n", i); } } prevKeys = stableKeys; }

4.2 多键组合功能实现

#define KEY_COMBO_MASK ( (1<<0) | (1<<1) ) // 按键0和1组合 void HandleKeyCombinations(void) { static uint32_t comboStartTime = 0; if((stableKeys & KEY_COMBO_MASK) == KEY_COMBO_MASK) { if(comboStartTime == 0) { comboStartTime = HAL_GetTick(); } else if(HAL_GetTick() - comboStartTime > 1000) { printf("Combo key held for 1s\n"); comboStartTime = 0; // 防止重复触发 } } else { comboStartTime = 0; } }

在实际项目中,这种方案相比传统矩阵键盘有以下优势:

  • 无鬼影问题,支持全键无冲
  • 软件实现简单,无需复杂扫描算法
  • 扩展性强,可轻松级联更多按键
  • 抗干扰能力强,适合工业环境
http://www.jsqmd.com/news/945876/

相关文章:

  • EduCoder实训答案查询网站是怎么建起来的?从想法到上线的技术栈分享
  • 别再让空压机‘抽风’了!手把手教你设置SMC继电器的迟滞模式(附压力值计算)
  • FPGA调试避坑:ILA核的OOC综合模式,为什么你的时钟约束总对不上?
  • GNN与XGBoost融合的野火风险评估框架解析
  • DeepONet非线性算子学习实战指南:从理论到应用的完整解决方案
  • 深度解析:技术型中小企业如何实现差异化增长
  • 技术笔记:20260603
  • 告别重复编码:用快马平台aigc自动生成vue组件,提升开发效率
  • 面试潜规则⑥:面试官桌下那张“评估表”,到底在打什么分?
  • 2026年地图制作靠谱品牌推荐,哪家更权威? - mypinpai
  • 河北工程测量多少钱?三友测绘价格实惠 - mypinpai
  • STL缩略图终极解决方案:Windows资源管理器中的3D模型即时预览
  • 《从0到1带你Obsidian接入DeepSeek》
  • 从CrystalMaker到WPS PPT:我是如何把复杂的晶体学数据变成一张清晰科普图的
  • YOLOv3推理时,置信度、类别概率和NMS到底怎么‘打架’?一个Debug案例讲清楚
  • 告别构建卡顿:为Jenkins配置国内镜像源与Maven私服的全流程指南(基于PHPStudy环境)
  • 第 36 篇 k8s之资源管理:Requests、Limits 与 QoS
  • 迅为RK3568开发板扫码远程控制探索神奇820集原创视频教程
  • LangChain 实战指南:从调用模型到构建 AI 应用
  • 2026年宠物粮压块机性价比排名,多少钱合理? - mypinpai
  • 小程序毕业设计-基于微信小程序的个性化音乐系统基于springboot+微信小程序的在线音乐个性化推荐APP的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • 终极宝可梦存档管理指南:7个PKSM核心功能让你轻松掌控所有世代游戏
  • FANUC CNC数据采集实战:从API连接到关键参数获取的完整避坑指南(C++版)
  • HyperMesh网格划分许可不够用?一变多技术让1个License同时支撑多个前处理任务
  • STM32G030C8T6实战驱动包:OLED界面+温湿度/DHT11/超声波/舵机/步进电机/ESP8266全接入
  • 2026年好用的地图编制专业公司排名 - mypinpai
  • STM32F407 SPI通信避坑指南:时钟相位、星型拓扑与HAL库回调函数详解
  • 别再只改XDC了!Vivado中ILA核时钟频率设置的正确姿势(避坑Timing 38-316)
  • 小程序毕业设计-基于SpringBoot+vue的体育馆预约管理系统基于springboot+微信小程序的体育馆预约系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • AI - Function-Call函数调用