当前位置: 首页 > 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.zskr.cn/news/1457358.html

相关文章:

  • EduCoder实训答案查询网站是怎么建起来的?从想法到上线的技术栈分享
  • 别再让空压机‘抽风’了!手把手教你设置SMC继电器的迟滞模式(附压力值计算)
  • FPGA调试避坑:ILA核的OOC综合模式,为什么你的时钟约束总对不上?
  • 深度解析:技术型中小企业如何实现差异化增长
  • 告别重复编码:用快马平台aigc自动生成vue组件,提升开发效率
  • 2026年宠物粮压块机性价比排名,多少钱合理? - mypinpai
  • 迅为RK3568开发板扫码远程控制探索神奇820集原创视频教程
  • 小程序毕业设计-基于微信小程序的个性化音乐系统基于springboot+微信小程序的在线音乐个性化推荐APP的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • 2026年好用的地图编制专业公司排名 - mypinpai
  • HyperMesh网格划分许可不够用?一变多技术让1个License同时支撑多个前处理任务
  • 小程序毕业设计-基于SpringBoot+vue的体育馆预约管理系统基于springboot+微信小程序的体育馆预约系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • FANUC CNC数据采集实战:从API连接到关键参数获取的完整避坑指南(C++版)
  • 别再只改XDC了!Vivado中ILA核时钟频率设置的正确姿势(避坑Timing 38-316)
  • Simulink打开模型报错?可能是字符编码在捣鬼(附slCharacterEncoding函数用法)
  • 如何区分真问题还是伪需求
  • 第 37 篇 k8s之调度进阶:亲和性、污点与容忍
  • 2026年四向穿梭式货架生产厂排名,哪家性价比高? - 工业品牌热点
  • VoLTE通话失败别抓瞎:手把手教你用拆线原因代码定位问题(附常见场景排查)
  • 从芯片手册到手上模块:手把手拆解SX1308升压电路,看懂每个元件的作用
  • 2026优选:浙江区域独立站定制服务商实力排行 - 奔跑123
  • 【AI模型监控黄金标准】:20年SRE专家亲授5大必控指标与实时告警闭环实践
  • 腾讯云快直播浏览器推流深度解析:从 WebRTC 原理到 480p 落地方案
  • 利用 Origin 表格系统开展生命科学数据可视化与统计分析
  • 3步掌握MouseTooltipTranslator:你的多语言浏览终极指南
  • CYUSB3014芯片开发入门:手把手搞定FX3 SDK安装与驱动识别(附常见问题排查)
  • Java初学者练手项目:纯内存版校园图书借阅管理系统(Swing GUI源码)
  • 汽车电子EMC整改实战:从频谱图‘包’和‘尖’到PCB走线,手把手教你定位传导辐射超标点
  • 毕业设计实战复盘:用DHT11/DHT12和51单片机DIY温湿度监测系统(附完整源码与避坑指南)
  • 如何快速提升Minecraft画质?BetterRenderDragon完整配置指南
  • 终极Windows 11精简优化指南:让臃肿系统秒变流畅