news 2026/4/17 13:49:21

用STM32和TM1638做个桌面小摆件:8位数码管+LED+按键的创意应用实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用STM32和TM1638做个桌面小摆件:8位数码管+LED+按键的创意应用实战

STM32+TM1638桌面互动终端:从硬件驱动到创意应用的完整指南

你是否曾想过用一块小小的单片机打造一个既实用又好玩的桌面小装置?今天我们要用STM32和TM1638模块,制作一个集时间显示、环境监测、互动灯光于一体的智能终端。这不仅仅是一个简单的数码管驱动教程,而是一个融合硬件连接、传感器集成、状态机编程和用户交互设计的完整项目。

1. 项目规划与硬件选型

1.1 核心组件介绍

这个项目的核心是STM32微控制器和TM1638显示驱动模块的组合。STM32F103C8T6,也就是我们常说的"蓝色药丸",是一款性价比极高的ARM Cortex-M3内核单片机,具有丰富的外设资源和充足的性能。而TM1638则是一款集成了LED驱动、数码管控制和键盘扫描功能的专用芯片,通过简单的三线串行接口就能控制8位数码管、8个LED和8个按键。

主要硬件清单

  • STM32F103C8T6最小系统板
  • TM1638模块(带8位数码管、8个LED和8个按键)
  • DHT11温湿度传感器(可选)
  • 面包板、杜邦线若干
  • 5V电源适配器或USB供电

1.2 硬件连接方案

TM1638模块通常有5个引脚需要连接:

  1. VCC - 接5V电源
  2. GND - 接地
  3. STB - 片选信号,接STM32任意GPIO
  4. CLK - 时钟信号,接STM32任意GPIO
  5. DIO - 数据输入输出,接STM32任意GPIO

对于DHT11传感器(如果使用):

  • VCC - 接3.3V或5V
  • GND - 接地
  • DATA - 接STM32的GPIO引脚(需上拉电阻)

提示:建议为STM32和TM1638模块准备独立的电源,特别是当使用大尺寸数码管时,电流需求可能较大。

2. TM1638驱动开发

2.1 通信协议解析

TM1638使用一种简单的同步串行协议,通过STB、CLK和DIO三根线进行通信。基本通信时序如下:

  1. STB拉低开始通信
  2. 发送命令字节(设置显示模式、地址等)
  3. 发送数据字节
  4. STB拉高结束通信

数据传输是在CLK的下降沿采样,每个字节从最低位开始发送。

2.2 基础驱动函数实现

我们需要实现几个核心驱动函数:

// 初始化函数 void TM1638_Init(void) { // GPIO初始化 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 模块初始化 TM1638_SendCommand(0x8F); // 显示开启,亮度最高 TM1638_Clear(); } // 发送单字节函数 void TM1638_SendByte(uint8_t data) { for(uint8_t i = 0; i < 8; i++) { CLK_LOW(); if(data & 0x01) DIO_HIGH(); else DIO_LOW(); data >>= 1; CLK_HIGH(); } } // 显示数字函数 void TM1638_DisplayNumber(uint32_t num, uint8_t pos) { uint8_t digits[8]; for(int i = 0; i < 8; i++) { digits[i] = num % 10; num /= 10; } STB_LOW(); TM1638_SendByte(0x44); // 固定地址写入模式 STB_HIGH(); STB_LOW(); TM1638_SendByte(0xC0 + pos*2); // 起始地址 for(int i = 0; i < 8; i++) { TM1638_SendByte(segmentTable[digits[7-i]]); } STB_HIGH(); }

2.3 按键扫描实现

TM1638内置了8×3的键盘扫描矩阵,可以通过以下函数读取按键状态:

uint8_t TM1638_ReadKeys(void) { uint8_t keys = 0; STB_LOW(); TM1638_SendByte(0x42); // 读键扫数据命令 for(int i = 0; i < 4; i++) { uint8_t temp = TM1638_ReadByte(); keys |= (temp << i); } STB_HIGH(); // 转换为按键编号(1-8) for(int i = 0; i < 8; i++) { if(keys & (1 << i)) return i+1; } return 0; }

3. 多功能终端功能实现

3.1 时间显示功能

利用STM32的RTC(实时时钟)或软件定时器,我们可以实现一个简单的时钟功能。显示格式可以设计为"HH:MM:SS"或"HH-MM-SS"。

核心代码片段

void updateClockDisplay(void) { RTC_TimeTypeDef time; HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN); // 小时 TM1638_DisplayDigit(time.Hours / 10, 0); TM1638_DisplayDigit(time.Hours % 10, 1); // 分钟 TM1638_DisplayDigit(time.Minutes / 10, 3); TM1638_DisplayDigit(time.Minutes % 10, 4); // 秒 TM1638_DisplayDigit(time.Seconds / 10, 6); TM1638_DisplayDigit(time.Seconds % 10, 7); // 闪烁冒号 static uint8_t blink = 0; if(++blink >= 10) { TM1638_SetColon(!TM1638_GetColon()); blink = 0; } }

3.2 环境数据显示

添加DHT11温湿度传感器后,我们可以周期性地显示环境数据。设计一个状态机来切换显示模式:

typedef enum { MODE_CLOCK, MODE_TEMP, MODE_HUMIDITY } DisplayMode; void updateDisplay(DisplayMode mode) { switch(mode) { case MODE_CLOCK: updateClockDisplay(); break; case MODE_TEMP: TM1638_DisplayString("TEMP"); TM1638_DisplayNumber(dht11_data.temperature, 4); break; case MODE_HUMIDITY: TM1638_DisplayString("HUMI"); TM1638_DisplayNumber(dht11_data.humidity, 4); break; } }

3.3 互动灯光效果

利用TM1638的8个独立LED,我们可以实现多种灯光效果:

  1. 呼吸灯效果:通过PWM调节亮度
  2. 跑马灯效果:LED依次点亮
  3. 音乐频谱效果:根据音频输入动态显示
  4. 按键反馈效果:按下按键时对应LED亮起

跑马灯实现示例

void runningLightEffect(void) { static uint8_t pos = 0; TM1638_SetLEDs(0); // 关闭所有LED TM1638_SetLED(pos, 1); // 点亮当前LED if(++pos >= 8) pos = 0; HAL_Delay(200); // 控制速度 }

4. 系统整合与优化

4.1 状态机设计

为了管理多种功能和用户交互,我们采用状态机设计模式:

typedef struct { DisplayMode currentMode; uint32_t lastModeChange; uint8_t brightness; uint8_t effectEnabled; } SystemState; void handleSystemState(SystemState *state) { // 模式切换逻辑 uint8_t key = TM1638_ReadKeys(); if(key != 0) { state->currentMode = (state->currentMode + 1) % 3; state->lastModeChange = HAL_GetTick(); } // 自动返回时钟模式 if(HAL_GetTick() - state->lastModeChange > 10000) { state->currentMode = MODE_CLOCK; } // 更新显示 updateDisplay(state->currentMode); // 处理灯光效果 if(state->effectEnabled) { runningLightEffect(); } }

4.2 电源管理与低功耗

对于需要长时间运行的桌面终端,电源管理很重要:

  1. 自动亮度调节:根据环境光调整显示亮度
  2. 休眠模式:无操作一段时间后进入低功耗状态
  3. 唤醒机制:按键或传感器触发唤醒

亮度调节实现

void setDisplayBrightness(uint8_t level) { if(level > 7) level = 7; TM1638_SendCommand(0x88 | level); // 亮度设置命令 }

4.3 外壳设计与制作

一个精美的外壳能让项目更加完整。可以考虑:

  1. 3D打印外壳:设计适合的3D模型并打印
  2. 亚克力激光切割:制作透明或彩色面板
  3. 木质结构:使用激光切割或CNC加工木质外壳

设计要点

  • 预留数码管、LED和按键的开口
  • 考虑散热和通风(特别是使用大功率LED时)
  • 提供方便的USB或电源接口
  • 设计支架或底座使设备稳固放置

5. 进阶功能扩展

5.1 无线连接与远程监控

通过添加ESP8266或HC-05蓝牙模块,可以实现:

  1. WiFi网络时间同步:自动校准时钟
  2. 远程数据监控:通过手机APP查看温湿度
  3. OTA固件更新:无线更新设备固件

蓝牙连接示例

void bluetoothTask(void) { if(USART2_RxFlag) { // 收到蓝牙数据 char cmd = USART2_RxBuffer[0]; switch(cmd) { case 'T': // 设置时间 setTimeFromString(&USART2_RxBuffer[1]); break; case 'B': // 设置亮度 setDisplayBrightness(atoi(&USART2_RxBuffer[1])); break; } USART2_RxFlag = 0; } }

5.2 添加更多传感器

根据需求可以集成更多传感器:

传感器类型功能接口
BMP180气压测量I2C
BH1750光照强度I2C
MQ-2烟雾检测ADC
HC-SR04距离测量GPIO

5.3 创建简单游戏

利用8位数码管和8个按键,可以开发一些简单的游戏:

  1. 记忆游戏:记住并重复LED点亮序列
  2. 反应测试:快速按下亮起的按键
  3. 简易计算器:进行基本数学运算
  4. 贪吃蛇游戏:在数码管上显示简化版

记忆游戏核心逻辑

void memoryGame(void) { static uint8_t sequence[20]; static uint8_t level = 1; // 生成随机序列 if(gameState == SHOW_SEQUENCE) { for(int i = 0; i < level; i++) { sequence[i] = rand() % 8 + 1; TM1638_SetLED(sequence[i], 1); HAL_Delay(500); TM1638_SetLED(sequence[i], 0); HAL_Delay(200); } gameState = USER_INPUT; } // 用户输入 uint8_t key = TM1638_ReadKeys(); if(key != 0) { if(key == sequence[currentInput]) { currentInput++; if(currentInput >= level) { // 通过当前关卡 level++; gameState = SHOW_SEQUENCE; } } else { // 游戏结束 gameOver(); } } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 13:47:12

如何快速掌握BepInEx游戏插件框架:面向初学者的完整指南

如何快速掌握BepInEx游戏插件框架&#xff1a;面向初学者的完整指南 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx BepInEx是一个专业的Unity游戏插件框架和模块化扩展系统&#…

作者头像 李华
网站建设 2026/4/17 13:45:13

从零到一:5个简单技巧打造你的专属游戏库界面

从零到一&#xff1a;5个简单技巧打造你的专属游戏库界面 【免费下载链接】Playnite Video game library manager with support for wide range of 3rd party libraries and game emulation support, providing one unified interface for your games. 项目地址: https://git…

作者头像 李华
网站建设 2026/4/17 13:43:15

中标麒麟系统试用到期弹窗烦人?手把手教你彻底关闭字符和图形界面提示(附sysnotify/licmanager进程清理)

中标麒麟系统试用到期弹窗终极解决方案&#xff1a;从原理到实战 每次开机都被试用到期弹窗骚扰&#xff1f;工作中频繁弹出的授权提醒打断思路&#xff1f;作为一款广泛应用于特定领域的国产操作系统&#xff0c;中标麒麟在试用期结束后确实会通过sysnotify和licmanager进程持…

作者头像 李华
网站建设 2026/4/17 13:43:12

高性能电机微控制器MCU产业新图景:2026年五家标杆厂商解读

一、引言电机控制微控制器&#xff08;MCU&#xff09;是工业自动化、汽车电子、智慧能源、智慧家电等领域动力系统的核心运算与控制单元&#xff0c;其运算实时性、外设集成度与环境可靠性&#xff0c;直接决定终端设备的能效表现、控制精度与全生命周期运行稳定性。在全球供应…

作者头像 李华
网站建设 2026/4/17 13:41:11

深入解析YouTube IFrame API:如何精准获取并应用视频时长数据

1. YouTube IFrame API基础入门 如果你正在开发一个需要处理YouTube视频的后台管理系统或内容平台&#xff0c;获取视频时长数据可能是刚需。比如用户上传了一堆YouTube链接&#xff0c;你需要自动归档这些视频的时长信息&#xff0c;或者根据时长进行内容审核&#xff08;比如…

作者头像 李华