这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【ESP-IDF系列】【ESP32】使用ESP-32-S3驱动TM1637驱动四

共3条 1/1 1 跳转至

【ESP-IDF系列】【ESP32】使用ESP-32-S3驱动TM1637驱动四位数码管

工程师
2025-05-06 23:03:07     打赏

简介

数码管相信大家都不陌生, 其数码管一共分为共阴极数码管, 或者共阳极数码管. 其中的com则为公共端. 而数码管的点亮主要是通过GPIO来控制其中的某一个段的点亮. 然后通过控制不同的段点亮的组合从而来显示对一个的数字. 而对于多个数码管的点亮的话主要是通过扫描的方式在某一个时间只点亮其中的一位(节省IO资源), 但是由于扫描的速度非常快,  从而使人眼看到多个数码管点亮的情况.如果不使用任何的外置芯片控制单位数码管的点亮的话, 那么至少是需要7-9个IO. 而点亮多位数码管的话,情况会变得更加复杂.

图片来源于(侵权请联系删除): 元器件科普之LED数码管的原理和应用



TM1637简介

TM1637 是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字 接口、数据锁存器、LED 高压驱动、键盘扫描等电路. 其单颗芯片即可控制4位数码管的驱动.

image.png

其引脚定义如上所示, 最多的位输出一共支持6位输出,  即同时驱动6个数码管. 但是由于手中的数码管模块只有四个,所以其中的两位是用不上的. 

image.png

背面

image.png

通过使用TM1637只需要使用两个IO便可以控制四位数码管的显示. 接下来我们使用ESP32, 基于ESP-IDF来控制这四位数码管的显示.


1- 首先编辑idf_component.yml 增加库文件依赖

dependencies:
  protocol_examples_common:
    path: ${IDF_PATH}/examples/common_components/protocol_examples_common
  nopnop2002/tm1637:
    path: components/tm1637/
    git: https://github.com/nopnop2002/esp-idf-tm1637.git


2- 编译项目, 然后打开menuconfig, 配置对应的PIN

image.png

3- 使用esp-idf-tm1637提供的代码进行测试

/**
 * @file app_main.c
 * @brief 使用 TM1637 数码管的示例应用程序
 */

 #include <stdio.h>
 #include <stdbool.h>
 #include <freertos/FreeRTOS.h>
 #include <freertos/task.h>
 #include <time.h>
 #include <sys/time.h>
 #include <esp_system.h>
 #include <driver/gpio.h>
 #include <esp_log.h>
 
 #include "sdkconfig.h"
 #include "tm1637.h"
 
 #define TAG "app"
 
 // 从 menuconfig 配置中获取 CLK 和 DIO 引脚
 const gpio_num_t LED_CLK = CONFIG_TM1637_CLK_PIN;
 const gpio_num_t LED_DTA = CONFIG_TM1637_DIO_PIN;
 
 // 数码管测试任务
 void tm1637_task(void *arg)
 {
    // 初始化 TM1637 数码管
    tm1637_led_t *led = tm1637_init(LED_CLK, LED_DTA);
    if (led == NULL)
       vTaskDelete(NULL); // 初始化失败则删除任务
 
    while (true)
    {
       // **测试段选控制**:依次点亮每一段,形成流水灯效果
       uint8_t seg_data[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20};
       for (uint8_t x = 0; x < 32; ++x)
       {
          uint8_t v_seg_data = seg_data[x % 6];
          for (int i = 0; i < led->segment_max; ++i)
          {
             tm1637_set_segment_fixed(led, led->segment_idx[i], v_seg_data);
          }
          vTaskDelay(10 / portTICK_PERIOD_MS);
       }
 
       // **测试亮度调节**
       for (int x = 0; x < 7; x++)
       {
          tm1637_set_brightness(led, x);
          for (int i = 0; i < led->segment_max; ++i)
          {
             tm1637_set_segment_fixed(led, led->segment_idx[i], 0xFF); // 全亮
          }
          vTaskDelay(30 / portTICK_PERIOD_MS);
       }
       vTaskDelay(100 / portTICK_PERIOD_MS);
 
       // **测试整数显示(靠右对齐)**
       tm1637_set_number(led, 1, true, 0x00); // 显示 0001
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, 12, true, 0x00); // 显示 0012
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, 123, true, 0x00); // 显示 0123
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, 1234, true, 0x00); // 显示 1234
       vTaskDelay(100 / portTICK_PERIOD_MS);
       if (led->segment_max == 6)
       {
          tm1637_set_number(led, 12345, true, 0x00); // 显示 12345
          vTaskDelay(100 / portTICK_PERIOD_MS);
          tm1637_set_number(led, 123456, true, 0x00); // 显示 123456
          vTaskDelay(100 / portTICK_PERIOD_MS);
       }
 
       // **测试整数显示(靠左对齐)**
       tm1637_set_number(led, 1, false, 0x00); // 显示 ____1
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, 12, false, 0x00); // 显示 ___12
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, 123, false, 0x00); // 显示 __123
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, 1234, false, 0x00); // 显示 _1234
       vTaskDelay(100 / portTICK_PERIOD_MS);
       if (led->segment_max == 6)
       {
          tm1637_set_number(led, 12345, false, 0x00); // 显示 12345
          vTaskDelay(100 / portTICK_PERIOD_MS);
          tm1637_set_number(led, 123456, false, 0x00); // 显示 123456
          vTaskDelay(100 / portTICK_PERIOD_MS);
       }
 
       // **测试负数显示(靠右)**
       tm1637_set_number(led, -1, true, 0x00); // 显示 -001
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, -12, true, 0x00); // 显示 -012
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, -123, true, 0x00); // 显示 -123
       vTaskDelay(100 / portTICK_PERIOD_MS);
       if (led->segment_max == 6)
       {
          tm1637_set_number(led, -1234, true, 0x00); // 显示 -1234
          vTaskDelay(100 / portTICK_PERIOD_MS);
          tm1637_set_number(led, -12345, true, 0x00); // 显示 -12345
          vTaskDelay(100 / portTICK_PERIOD_MS);
       }
 
       // **测试负数显示(靠左)**
       tm1637_set_number(led, -1, false, 0x00); // 显示 ____-1
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, -12, false, 0x00); // 显示 ___-12
       vTaskDelay(100 / portTICK_PERIOD_MS);
       tm1637_set_number(led, -123, false, 0x00); // 显示 __-123
       vTaskDelay(100 / portTICK_PERIOD_MS);
       if (led->segment_max == 6)
       {
          tm1637_set_number(led, -1234, false, 0x00); // 显示 _-1234
          vTaskDelay(100 / portTICK_PERIOD_MS);
          tm1637_set_number(led, -12345, false, 0x00); // 显示 -12345
          vTaskDelay(100 / portTICK_PERIOD_MS);
       }
 
       // **测试文本显示**
       if (led->segment_max == 4)
       {
          tm1637_set_segment_ascii(led, "PLAY"); // 4位显示
       }
       else
       {
          tm1637_set_segment_ascii(led, " PLAY "); // 6位居中显示
       }
       vTaskDelay(100 / portTICK_PERIOD_MS);
 
       tm1637_set_segment_ascii(led, "1234567890"); // 显示前6位
       vTaskDelay(100 / portTICK_PERIOD_MS);
 
       tm1637_set_segment_ascii(led, "IP 192.168.10.20"); // 仅显示前几位
       vTaskDelay(100 / portTICK_PERIOD_MS);
 
       if (led->segment_max == 4)
       {
          tm1637_set_segment_ascii(led, "STOP");
       }
       else
       {
          tm1637_set_segment_ascii(led, " STOP ");
       }
       vTaskDelay(100 / portTICK_PERIOD_MS);
    }
 }
 
 // 主应用入口
 void app_main()
 {
    // 创建 TM1637 数码管测试任务
    xTaskCreate(&tm1637_task, "tm1637_task", 1024 * 4, NULL, 5, NULL);
 }


实验效果如下


image.png

显示 0012

image.png


总结

本文主要对数码管的工作原理进行了简要的阐述,以及对TM1637芯片进行了介绍. 同时使用ESP-IDF结合对应的组件管理器的驱动库, 对TM1637的四位数码管进行了驱动, 使其可以驱动显示数字和动画等. 大家可以下载这个工程进行尝试, 驱动库文件较为完善, 可以直接使用.


附件

TM1637.zip




关键词: ESP-IDF     ESP32     TM1637    

院士
2025-05-09 11:20:32     打赏
2楼

这是直接使用驱动库来驱动的 吗?


院士
2025-05-09 17:41:44     打赏
3楼

看着确实是上手很快。

实现起来也方便


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]