STM32 HAL TM1638读取24个按键

本文分享一下天微电子的另一款数码管按键驱动芯片TM1638的单片机C语言驱动程序。

笔者采用的MCU是STM32单片机,STM32CubeMX + Keil5开发,使用了HAL库。

一、TM1638介绍

1、基础信息

TM1638属于一款LED驱动控制专用电路,其特性如下:

引脚定义如下

        在实际使用中,我们只需要使用三个单片机引脚就可以进行控制。分别是DIO、STB、CLK

在进行连接单片机时,建议单片机使用开漏模式,因为还需要给三个引脚接上拉电阻,其电路推荐接法如下:

2、串行数据传输格式

  

▲注意:读取数据时,从串行时钟CLK 的第8 个上升沿开始设置指令到CLK 下降沿读数据之间需要 一个等待时间Twait(最小1μS)。

3、TM1638寄存器

TM1638分为两种寄存器,一块是显示的寄存器,一块是按键读取的寄存器

3.1 显示寄存器

        该寄存器存储通过串行接口从外部器件传送到TM1638 的数据,地址从00H-0FH共16字节单元, 分别与芯片SGE和GRID管脚所接的LED灯对应,分配如下图:

写LED显示数据的时候,按照从显示地址从低位到高位,从数据字节的低位到高位操作。

        写LED显示数据的时候,按照从低位地址到高位地址,从字节的低位到高位操作;在运用中没有使 用到的SEG输出口,在对应的BIT地址位写0。

3.2 键扫描和键扫数据寄存器

按键扫描是通过K1\K2\K3配合KS1~KS8进行读取,其寄存器就BYTE1~BYTE4。

        键扫数据储存地址如下所示,先发读键命令后,开始读取按键数据BYTE1—BYTE4字节,读数 据从低位开始输出;芯片K和KS引脚对应的按键按下时,相对应的字节内的 BIT位为1。

二、TM1638驱动程序(读取按键)

1、CubeMX配置

        只需要将对应的三个引脚配置成开漏输出即可。

2、驱动代码

TM1638.C

#include "TM1638.h"/* DIO为输出 */
void gpio2_out()
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = TM1638_DIO_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(TM1638_DIO_GPIO_Port, &GPIO_InitStruct);
}
/* DIO为输入 */
void gpio2_in()
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = TM1638_DIO_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(TM1638_DIO_GPIO_Port, &GPIO_InitStruct);
}/******************************************************************************** 函数名:TM1638_WriteData* 功  能:TM1638写数据* 参  数:u8Data需要写入的数据* 返回值:无* 说  明:无
*******************************************************************************/
void TM1638_WriteData(uint8_t u8Data)
{uint8_t i;gpio2_out();//DIO设置为输出for(i = 0; i < 8; i++){TM1638_CLKReset();Delay_us(1);(u8Data & 0x01) ? (TM1638_DIOSet()):(TM1638_DIOReset());u8Data >>= 1;TM1638_CLKSet();Delay_us(1);}
}
/******************************************************************************** 函数名:TM1638_WriteCmd* 功  能:TM1638写命令字* 参  数:u8Cmd需要写入的命令* 返回值:无* 说  明:发送命令字时STB置0,发送完置1
*******************************************************************************/
void TM1638_WriteCmd(uint8_t u8Cmd)
{TM1638_STBReset();TM1638_WriteData(u8Cmd);TM1638_STBSet();Delay_us(2);
}
/******************************************************************************** 函数名:TM1638_ReadData* 功  能:TM1638读数据* 参  数:无* 返回值:读出的数据* 说  明:无
*******************************************************************************/
uint8_t TM1638_ReadData(void)
{uint8_t i;uint8_t Read_data=0;for(i = 0; i < 8; i++){TM1638_CLKReset();Delay_us(1);Read_data >>= 1;if(TM1638_DIORead() == 1){Read_data |= 0x80;			}TM1638_CLKSet();Delay_us(1);}return Read_data;
}/******************************************************************************** 函数名:TM1638_SetBrightness* 功  能:设置亮度* 参  数:u8Brt亮度,共8级,0~7* 返回值:无* 说  明:0x88为开显示
*******************************************************************************/
void TM1638_SetBrightness(uint8_t u8Brt)
{TM1638_WriteCmd(0x88 | u8Brt);
}/******************************************************************************** 函数名:TM1638_ReadKey* 功  能:TM1638读按键数据* 参  数:无* 返回值:读出的数据* 说  明:返回值为双字节共用体,每一个bit为一个按键;
*******************************************************************************/
uint8_t TM1638_ReadKey(void)
{uint8_t u8Data[4], i;TM1638_STBReset();TM1638_WriteData(0x42);Delay_us(3);gpio2_in();//DIO设置为输入for (i = 0; i < 4; i++){u8Data[i] = TM1638_ReadData();//读BYTE1~BYTE4的数据}Delay_us(1);TM1638_STBSet();if(u8Data[0]==0x04 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 1;}else if(u8Data[0]==0x40 && u8Data[1]==0x00 && u8Data[2]==0x00 && u8Data[3]==0x00){return 2;}else if(u8Data[0]==0x00 && u8Data[1]==0x04 && u8Data[2]==0x00 && u8Data[3]==0x00){return 3;}else if(u8Data[0]==0x00 && u8Data[1]==0x40 && u8Data[2]==0x00 && u8Data[3]==0x00){return 4;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x04 && u8Data[3]==0x00){return 5;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x40 && u8Data[3]==0x00){return 6;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x00 && u8Data[3]==0x04){return 7;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x40){return 8;}else if(u8Data[0]==0x02 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 9;}else if(u8Data[0]==0x20 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 10;}else if(u8Data[0]==0x00 && u8Data[1]==0x02 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 11;}else if(u8Data[0]==0x00 && u8Data[1]==0x20 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 12;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x02 &&u8Data[3]==0x00){return 13;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x20 &&u8Data[3]==0x00){return 14;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x02){return 15;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x20){return 16;}else if(u8Data[0]==0x01 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 17;}else if(u8Data[0]==0x10 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 18;}else if(u8Data[0]==0x00 && u8Data[1]==0x01 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 19;}else if(u8Data[0]==0x00 && u8Data[1]==0x10 && u8Data[2]==0x00 &&u8Data[3]==0x00){return 20;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x01 &&u8Data[3]==0x00){return 21;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x10 &&u8Data[3]==0x00){return 22;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x01){return 23;}else if(u8Data[0]==0x00 && u8Data[1]==0x00 && u8Data[2]==0x00 &&u8Data[3]==0x10){return 24;}else{return 0xff;}
}	
/* 根据返回的键值与自己的键值操作进行修改 */
uint8_t number_out(uint8_t key_hex,uint8_t num)
{if((key_hex == KEY_0) && (num == 1)){return 0;}else if((key_hex == KEY_1) && (num == 1)){return 1;}else if((key_hex == KEY_2) && (num == 1)){return 2;}else if((key_hex == KEY_3) && (num == 1)){return 3;}else if((key_hex == KEY_4) && (num == 1)){return 4;}else if((key_hex == KEY_5) && (num == 1)){return 5;}else if((key_hex == KEY_6) && (num == 1)){return 6;}else if((key_hex == KEY_7) && (num == 1)){return 7;}else if((key_hex == KEY_8) && (num == 1)){return 8;}else if((key_hex == KEY_9) && (num == 1)){return 9;}else if((key_hex == KEY_LAST) && (num == 1)){return 20;}else if((key_hex == KEY_NEXT) && (num == 1)){return 21;}else if((key_hex == KEY_LIFT) && (num == 1)){return 22;}else if((key_hex == KEY_RIGHT) && (num == 1)){return 23;}else if((key_hex == KEY_OK) && (num == 1)){return 24;}else if((key_hex == KEY_RETURN) && (num == 1)){return 25;}else if((key_hex == KEY_LINK1) && (num == 1)){return 27;}else if((key_hex == KEY_LINK2) && (num == 1)){return 28;}else if((key_hex == KEY_SILENCE) && (num == 1)){return 29;}else if((key_hex == KEY_SEARCH) && (num == 1)){return 30;}else if((key_hex == KEY_OK) && (num == 2)){return 40;}else if((key_hex == KEY_RETURN) && (num == 2)){return 41;}return 255;
}

TM1638.h

#ifndef __TM1638_H__
#define __TM1638_H__#include "Delay.h"
#include "main.h"
#include "stm32f1xx_hal.h"#define KEY_0		10
#define KEY_1		1
#define KEY_2		2
#define KEY_3		3
#define KEY_4		4
#define KEY_5		5
#define KEY_6		6
#define KEY_7		7
#define KEY_8		8
#define KEY_9		9
#define KEY_LAST		11
#define KEY_NEXT		19
#define	KEY_LIFT		14
#define KEY_RIGHT	16
#define KEY_OK 		15
#define KEY_RETURN	12
#define KEY_LINK1	13
#define KEY_LINK2	17
#define KEY_SEARCH 	18
#define KEY_SILENCE	20/*定义端口*/
#define TM1638_STBSet()					HAL_GPIO_WritePin(TM1638_STB_GPIO_Port, TM1638_STB_Pin, GPIO_PIN_SET)#define TM1638_STBReset()				HAL_GPIO_WritePin(TM1638_STB_GPIO_Port, TM1638_STB_Pin, GPIO_PIN_RESET)#define TM1638_CLKSet()					HAL_GPIO_WritePin(TM1638_CLK_GPIO_Port, TM1638_CLK_Pin, GPIO_PIN_SET)#define TM1638_CLKReset()				HAL_GPIO_WritePin(TM1638_CLK_GPIO_Port, TM1638_CLK_Pin, GPIO_PIN_RESET)#define TM1638_DIOSet()					HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port, TM1638_DIO_Pin, GPIO_PIN_SET)#define TM1638_DIOReset()				HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port, TM1638_DIO_Pin, GPIO_PIN_RESET)#define TM1638_DIORead()					HAL_GPIO_ReadPin(TM1638_DIO_GPIO_Port, TM1638_DIO_Pin)uint8_t TM1638_ReadKey(void);
uint8_t number_out(uint8_t key_hex,uint8_t num);#endif /* __TM1638_H__ */

目前项目需要用到的按键是20个,这里还有4个没有使用,从目前使用的情况来看,还是不错的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1424988.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

析构函数详解

目录 析构函数概念特性对象的销毁顺序 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &#x1f978;&#x1f978;&#x1f978; C语言 &#x1f43f;️&#x1f43f;️&#x1f43f;️ C语言例题 &…

两步将 CentOS 6.0 原地升级并迁移至 RHEL 7.9

《OpenShift / RHEL / DevSecOps 汇总目录》 说明 本文介绍如何将一个 CentOS 6.0 的系统升级并转换迁移到 RHEL 7.9。 本文是《在离线环境中将 CentOS 7.X 原地升级并迁移至 RHEL 7.9》阶进篇。 所有被测软件的验证操作可参见上述前文中对应章节的说明。 准备 CentOS 6.…

语言模型测试系列【8】

语言模型 文心一言星火认知大模型通义千问豆包360智脑百川大模型腾讯混元助手Kimi Chat商量C知道 这次的测试比较有针对性&#xff0c;是在使用钉钉新推出的AI助理功能之后发现的问题&#xff0c;即创建AI助理绑定自己钉钉的知识库进行问答&#xff0c;其中对于表结构的文档学…

【echart】实现echart图的富文本样式

贴源码 let xData [山西,山东,内蒙,甘肃];let averData [2, 3,1, 3];var eicon path://M480.55,252.18L318.88,498.04c-15.95,24.25,1.08,56.57,30.11,57.12l147,2.79L448.5,696.92c-14.74,43.15,39.88,75.83,70.93,42.44l216.73-233.04c21.93-23.58,5.21-61.98-27-61.98H56…

【面试干货】 两个有序数组的合并排序

【面试干货】 两个有序数组的合并排序 1、实现思想2、代码实现 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、实现思想 使用两个指针分别指向两个数组的起始位置&#xff0c;然后逐个比较两个指针所指向的元素&#xff0c;将较小的元素…

【IoTDB 线上小课 03】时序数据库 VS 实时数据库,区别是?

好评满满的【IoTDB 视频小课】系列又来了~ 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源... 你想学习的重点&#xff0c;给我们 3-5 分钟&#xff0c;清晰地讲给你听&#xff1a; 时序数据库 VS 实时数据库 工业数字化转型愈发受到重视的当…

OpenAI 发布 GPT-4o,再次巩固行业地位!

5 月 14 日凌晨 1 点&#xff08;太平洋时间上午 10 点&#xff09;&#xff0c;OpenAI 发布了其最新的 GPT-4o&#xff0c;再次巩固了其在人工智能领域的领导地位。这次发布不仅仅是一个产品的推出&#xff0c;更是向世界宣告 AI 技术已迈入一个全新的纪元。OpenAI 的 CEO 萨姆…

本机搭建RabbitMQ

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、下载安装包&#xff0c;搭建过程 二、重要概念介绍 三、创建用户 方式一&#xff1a;命令行 方式二&#xff1a;管理后台 3.1 创建用户 3.2 分配权限 3.3 提…

小程序|锁定查询功能如何使用?

学生或家长想要实现自己查询完成后&#xff0c;任何人都无法再次查询&#xff0c;老师应该如何设置&#xff1f;易查分的【锁定查询功能】就可实现&#xff0c;下面教大家如何使用吧。 &#x1f4cc;使用教程 &#x1f512;锁定查询功能介绍 ✅学生或家长自主锁定&#xff1a;开…

【SQL】SQL常见面试题总结(1)

目录 1、检索数据1.1、从 Customers 表中检索所有的 ID1.2、检索并列出已订购产品的清单1.2、检索所有列 2、排序检索数据2.1、检索顾客名称并且排序2.2、对顾客 ID 和日期排序2.3、按照数量和价格排序2.4、检查 SQL 语句 3、过滤数据3.1、返回固定价格的产品3.2、返回产品并且…

高效协同,智慧绘制:革新型流程图工具全解析

流程图&#xff0c;作为一种直观展示工作过程和系统运作的工具&#xff0c;在现代办公和项目管理中发挥着不可或缺的作用。 其优势在于能够清晰、直观地呈现复杂的过程和关系&#xff0c;帮助人们快速理解并掌握关键信息。同时&#xff0c;流程图也广泛应用于各种场景&#xf…

STM32HAL库-中断篇

中断 中断简介 中断是一种事件处理机制&#xff0c;可以暂停主程序的运行&#xff0c;转而处理特定事件程序。 中断的作用和意义&#xff1a; 实时控制 在确定事件内对响应事件做出相应 故障处理 检测到故障需要第一时间处理 数据传输 如串口通信&#xff0c;不确定数…

独家|暴雨推出基于国产X86芯片的四路服务器

伴随着智慧计算时代的到来和企业数字化转型的深入&#xff0c;人工智能、大数据、虚拟化等创新技术在应用普及的过程中&#xff0c;也在不断地细分和深化&#xff0c;使得企业的业务系统日趋复杂&#xff0c;数据量、数据类型更加庞大&#xff0c;对计算平台的性能要求“水涨船…

CET6级(笔试备考)

CET6笔试 做题技巧 备考注意 感觉考前一个月还是要多刷几套真题啊&#xff0c;刷个10套吧。 参考链接&#xff1a;https://blog.csdn.net/m0_57656758/article/details/130707582

Spring实现数据库读写分离(MySQL实现主从复制)

目录 1、背景 2、方案 2.1 应用层解决: 2.2 中间件解决 3、使用Spring基于应用层实现 3.1 原理 3.2 DynamicDataSource 3.3 DynamicDataSourceHolder 3.4 DataSourceAspect 3.5 配置2个数据源 3.5.1 jdbc.properties 3.5.2 定义连接池 3.5.2 定义DataSource 3.6…

Cadence 16.6 PCB Edito如何将鼠标中键反向拉拽改为正向拖拽

Cadence 16.6 PCB Editor如何将鼠标中键反向拉拽改为正向拖拽 Cadence 16.6 PCB Editor默认鼠标中键是反向的拉拽&#xff0c;让我很不适应&#xff0c;在网上找的可行的方法&#xff0c;在这里总结出来&#xff0c;希望能帮到其他工程师。 按照以下步骤进行操作&#xff1a; …

数字化智能:Web3时代的物联网创新之路

引言 随着科技的不断发展&#xff0c;物联网&#xff08;IoT&#xff09;技术正在迅速普及和应用。而随着Web3时代的到来&#xff0c;物联网将迎来新的发展机遇和挑战。本文将探讨Web3时代的物联网创新之路&#xff0c;深入分析其核心技术、应用场景以及未来发展趋势。 Web3时…

4.线性代数

深度学习作为一门前沿的、应用广泛的学科&#xff0c;对于数学基础的要求非常高。 线性代数 线性代数在深度学习中扮演着至关重要的角色。它不仅是描述和理解数据的基础工具&#xff0c;也是构建和训练神经网络的核心组件。例如&#xff0c;在深度学习中&#xff0c;我们经常…

RAW转换和图像编辑工具:Capture One 23 Pro (win/mac)中文专业版

Capture One 23是一款功能强大的桌面版照片编辑软件&#xff0c;由丹麦PHASE ONE飞思数码公司开发。 以下是该软件的一些主要特点&#xff1a; 强大的RAW处理功能&#xff1a;Capture One 23支持多种品牌的相机和镜头&#xff0c;提供了丰富的RAW处理工具&#xff0c;包括曝光、…

【Python】图像批量合成视频,并以文件夹名称命名合成的视频

一个文件夹中有多个子文件夹&#xff0c;子文件夹中有多张图像。如何把批量把子文件夹中的图像合成视频&#xff0c;视频名称是子文件夹的名称&#xff0c;生成的视频保存到指定文件夹&#xff0c;效果记录。 代码 import os import cv2def create_video_from_images(image_f…