STM32实战项目-数码管
创始人
2025-06-01 22:16:40

程序实现功能:

1、上电后,数码管间隔50ms计数;

2、触摸按键1调节数码管亮度,8个等级;


目录

1、硬件电路

 1.1数码管

1.2TIM1620 驱动电路

 二、技术讲解

2.1概述 

2.2特性

2.3引脚说明

 3.指令说明及配置

3.1显示模式命令设置 

 3.2写数据地址模式

 3.3显示控制命令设置

 3.4显示寄存器地址

3.5数码管显示驱动 

 4.软件编程

4.1串口高低电平配置 

 4.2数码管译码配置

 4.3写入函数

4.4初始化TIM1620函数

 4.5数码管显示函数

 4.6运行函数

 4.7回调函数-按键控制亮度


 


1、硬件电路

 1.1数码管

 

1.2TIM1620 驱动电路

 

 二、技术讲解

2.1概述 

TM1620是一种LED(发光二极管显示器)驱动控制专用IC,内部集成有MCU数字接口、数据锁存器、 LED驱动等电路。

2.2特性

• 采用CMOS工艺
• 显示模式(8 段× 6 位~10段× 4位)
• 辉度调节电路(8 级占空比可调)
• 串行接口(CLK,STB,DIN)
• 振荡方式:内置RC振荡
• 内置上电复位电路
• 内置数据锁存电路
• 内置针对LED反偏漏电导致暗亮问题优化电路
• 抗干扰能力强
• 封装形式: SOP20

2.3引脚说明

TIM1620需要通过引脚CLK、DIN、STB 控制串行数据传输,所以优先配置好GPIO串口,具体配置如下图所示:

 3.指令说明及配置

3.1显示模式命令设置 

该指令用来设置选择段和位的个数(4~6 位,8~10 段) 。当该指令被执行时,显示被强制关闭。 在显示模式不变时,显存内的数据不会被改变,显示控制命令控制显示开关。如下图所示:


 为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

/显示模式
typedef enum
{Disp_Mode_GRID4_SEG10  = 0x00,Disp_Mode_GRID5_SEG9   = 0x01,Disp_Mode_GRID6_SEG8   = 0x02,
} Disp_Mode_t;

 3.2写数据地址模式

该指令用来设置数据写和读,B1和B0位不允许设置01或11。具体如下图所示:


  为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

//写数据模式
typedef enum
{Write_Data_Addr_Fix      = 0x44,Write_Data_Addr_Auto_Add = 0x40,
} Write_Data_Addr_Mode_t;

 3.3显示控制命令设置

该指令用来设置显示的开关以及显示亮度调节。共有8级辉度可供选择进行调节。如下图所示:


 为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

//灰度等级
typedef enum
{Brightness_level_0  	= 0x80,Brightness_level_1  	= 0x88,Brightness_level_2  	= 0x89,Brightness_level_3  	= 0x8A,Brightness_level_4  	= 0x8B,Brightness_level_5  	= 0x8C,Brightness_level_6  	= 0x8D,Brightness_level_7  	= 0x8E,Brightness_level_8  	= 0x8F,
} Brightness_level_t;

 3.4显示寄存器地址

该寄存器存储通过串行接口接收从外部器件传送到TM1620的数据,最多有效地址从00H-0BH共12字节单元,
分别与芯片SEG和GRID管脚对应,具体分配如下图:写LED显示数据的时候,按照显示地址从低位到高位,数据字节从低位到高位操作
 

 

 为了移植方便,在我们的显示函数声明部分,将所以可能的选项枚举出来,具体代码如下:

//显示寄存器地址
typedef enum
{Disp_SFR_Addr_Num   = (uint8_t)12,Disp_SFR_Addr_00H  	= 0xC0,Disp_SFR_Addr_01H  	= 0xC1,Disp_SFR_Addr_02H  	= 0xC2,Disp_SFR_Addr_03H  	= 0xC3,Disp_SFR_Addr_04H  	= 0xC4,Disp_SFR_Addr_05H  	= 0xC5,Disp_SFR_Addr_06H  	= 0xC6,Disp_SFR_Addr_07H  	= 0xC7,Disp_SFR_Addr_08H  	= 0xC8,Disp_SFR_Addr_09H  	= 0xC9,Disp_SFR_Addr_0AH  	= 0xCA,Disp_SFR_Addr_0BH  	= 0xCB,
} Disp_SFR_Addr_t;

 注意: 芯片显示寄存器在上电瞬间其内部保存的值可能是随机不确定的,此时客户直接发送开屏命令,将有可能出现显示乱码。所以我司建议客户对显示寄存器进行一次上电清零操作,即上电后向12位显存地址(00H-0BH)中全部写入数据0x00。

3.5数码管显示驱动 

关于小数点是否启动,也将其封装起来,代码如下:

typedef enum
{Disp_DP_OFF  = 0x01,Disp_DP_ON   = 0x02,
} Disp_DP_Status_t;

 4.软件编程

4.1串口高低电平配置 

为了方便串口数据传输,我们使用宏定义 将串口的读写重新定义,具体代码如下:

//TM1620穿行通讯口
#define	SET_STB		HAL_GPIO_WritePin(TM1620_STB_GPIO_Port,TM1620_STB_Pin,GPIO_PIN_SET)
#define	CLR_STB		HAL_GPIO_WritePin(TM1620_STB_GPIO_Port,TM1620_STB_Pin,GPIO_PIN_RESET)#define	SET_DIN		HAL_GPIO_WritePin(TM1620_DIN_GPIO_Port,TM1620_DIN_Pin,GPIO_PIN_SET)
#define	CLR_DIN		HAL_GPIO_WritePin(TM1620_DIN_GPIO_Port,TM1620_DIN_Pin,GPIO_PIN_RESET)#define	SET_CLK		HAL_GPIO_WritePin(TM1620_CLK_GPIO_Port,TM1620_CLK_Pin,GPIO_PIN_SET)
#define	CLR_CLK		HAL_GPIO_WritePin(TM1620_CLK_GPIO_Port,TM1620_CLK_Pin,GPIO_PIN_RESET)

 4.2数码管译码配置

没有单独配置小数点,函数内部需要小数点的话,单独加上即可。

uint8_t Disp_Decode[16]    = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};  //数码管译码 0 - 9

 4.3写入函数

 

 根据时序图写函数,首先在传输八位数据之前,需要将STB置零拉低,因为是使用库函数,有一定的延时,所不用额外加延时函数,开始一个一个bit传的时候也需要拉低CLK,拉高CLK,用每个bit位与1&从而确定每个bit是高低电平,发出信号。具体代码如下:

static void TM1620_Write_Byte(uint8_t dat) 
{uint8_t i = 0;//参考数据手册时序图CLR_STB;for(i=0;i<8;i++){CLR_CLK;//准备数据位if((dat & BIT0) == BIT0) //BIT0为宏定义值为0x01SET_DIN;elseCLR_DIN;dat = dat >> 1; //移位,准备下一个bit//时钟上升沿发送下一个数据	SET_CLK;	__nop();}	
}

4.4初始化TIM1620函数

芯片显示寄存器在上电瞬间其内部保存的值可能是随机不确定的,此时客户直接发送开屏命令,将有可能出现显示乱码 ,所以要进行清零操作,因为芯片内部有配置可以自动地址增加,具体如下图示:

具体配置代码如下:

static void TM1620_Init() 
{uint8_t i = 0;//设置显示模式TM1620_Write_Byte(Disp_Mode_GRID6_SEG8); SET_STB;  //地址自动增加TM1620_Write_Byte(Write_Data_Addr_Auto_Add); SET_STB;//清除显示寄存器TM1620_Write_Byte(Disp_SFR_Addr_00H); //设置首地址for(i=0;i

 4.5数码管显示函数

数码管是一个个显示的,不需要自动增加地址,需要固定地址,如下图所示:

 

具体配置代码如下; 

static void Disp(Disp_NUM_t Disp_NUM,uint8_t Dat,Disp_DP_Status_t Disp_DP_Status) 
{//参数范围检查if(Dat > 0x0F){System.Assert_Failed();}//设置显示模式TM1620_Write_Byte(Disp_Mode_GRID6_SEG8); SET_STB;//地址固定TM1620_Write_Byte(Write_Data_Addr_Fix); SET_STB;//写地址TM1620_Write_Byte(Disp_NUM);//写数据if(Disp_DP_Status == Disp_DP_ON)TM1620_Write_Byte(Disp_Decode[Dat] + 0x80);elseTM1620_Write_Byte(Disp_Decode[Dat]);SET_STB;//显示TM1620_Write_Byte(Display.Brightness);SET_STB; 
}

 4.6运行函数

static void Run()
{static uint32_t Cnt = 0;//数码管显示计数值Display.Disp(Disp_NUM_1,Cnt%10,      Disp_DP_OFF); //个位Display.Disp(Disp_NUM_2,Cnt/10%10,   Disp_DP_OFF); //十位Display.Disp(Disp_NUM_3,Cnt/100%10,  Disp_DP_OFF); //百位Display.Disp(Disp_NUM_4,Cnt/1000%10, Disp_DP_OFF); //千位Display.Disp(Disp_NUM_5,Cnt/10000%10,Disp_DP_OFF); //万位Display.Disp(Disp_NUM_6,Cnt/100000,  Disp_DP_OFF); //十万位//更新计数值if(++Cnt > 999999)Cnt = 0;//延时50msHAL_Delay(50);
}

 4.7回调函数-按键控制亮度

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin == KEY1_Pin){LED.LED_Flip(LED2);switch(Display.Brightness){case Brightness_level_1: Display.Brightness = Brightness_level_2; break;case Brightness_level_2: Display.Brightness = Brightness_level_3; break;case Brightness_level_3: Display.Brightness = Brightness_level_4; break;case Brightness_level_4: Display.Brightness = Brightness_level_5; break;case Brightness_level_5: Display.Brightness = Brightness_level_6; break;case Brightness_level_6: Display.Brightness = Brightness_level_7; break;case Brightness_level_7: Display.Brightness = Brightness_level_8; break;case Brightness_level_8: Display.Brightness = Brightness_level_1; break;default: Display.Brightness = Brightness_level_3;}}
}

 

相关内容

热门资讯

【实验报告】实验一 图像的... 实验目的熟悉Matlab图像运算的基础——矩阵运算;熟悉图像矩阵的显示方法࿰...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
大模型落地比趋势更重要,NLP... 全球很多人都开始相信,以ChatGPT为代表的大模型,将带来一场NLP领...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
kuernetes 资源对象分... 文章目录1. pod 状态1.1 容器启动错误类型1.2 ImagePullBackOff 错误1....
STM32实战项目-数码管 程序实现功能: 1、上电后,数码管间隔50ms计数; 2、...
TM1638和TM1639差异... TM1638和TM1639差异说明 ✨本文不涉及具体的单片机代码驱动内容,值针对芯...
Qt+MySql开发笔记:Qt... 若该文为原创文章,转载请注明原文出处 本文章博客地址:https://h...
Java内存模型中的happe... 第29讲 | Java内存模型中的happen-before是什么? Java 语言...
《扬帆优配》算力概念股大爆发,... 3月22日,9股封单金额超亿元,工业富联、鸿博股份、鹏鼎控股分别为3.0...
CF1763D Valid B... CF1763D Valid Bitonic Permutations 题目大意 拱形排列࿰...
SQL语法 DDL、DML、D... 文章目录1 SQL通用语法2 SQL分类3 DDL 数据定义语言3.1 数据库操作3.2 表操作3....
文心一言 VS ChatGPT... 3月16号,百度正式发布了『文心一言』,这是国内公司第一次发布类Chat...
CentOS8提高篇5:磁盘分...        首先需要在虚拟机中模拟添加一块新的硬盘设备,然后进行分区、格式化、挂载等...
Linux防火墙——SNAT、... 目录 NAT 一、SNAT策略及作用 1、概述 SNAT应用环境 SNAT原理 SNAT转换前提条...
部署+使用集群的算力跑CPU密... 我先在开头做一个总结,表达我最终要做的事情和最终环境是如何的,然后我会一...
Uploadifive 批量文... Uploadifive 批量文件上传_uploadifive 多个上传按钮_asing1elife的...
C++入门语法基础 文章目录:1. 什么是C++2. 命名空间2.1 域的概念2.2 命名...
2023年全国DAMA-CDG... DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义...
php实现助记词转TRX,ET... TRX助记词转地址网上都是Java,js或其他语言开发的示例,一个简单的...
【分割数据集操作集锦】毕设记录 1. 按要求将CSV文件转成json文件 有时候一些网络模型的源码会有data.json这样的文件里...
Postman接口测试之断言 如果你看文字部分还是不太理解的话,可以看看这个视频,详细介绍postma...
前端学习第三阶段-第4章 jQ... 4-1 jQuery介绍及常用API导读 01-jQuery入门导读 02-JavaScri...
4、linux初级——Linu... 目录 一、用CRT连接开发板 1、安装CRT调试工具 2、连接开发板 3、开机后ctrl+c...
Urban Radiance ... Urban Radiance Fields:城市辐射场 摘要:这项工作的目标是根据扫描...
天干地支(Java) 题目描述 古代中国使用天干地支来记录当前的年份。 天干一共有十个,分别为:...
SpringBoot雪花ID长... Long类型精度丢失 最近项目中使用雪花ID作为主键,雪花ID是19位Long类型数...
对JSP文件的理解 JSP是java程序。(JSP本质还是一个Servlet) JSP是&#...
【03173】2021年4月高... 一、单向填空题1、大量应用软件开发工具,开始于A、20世纪70年代B、20世纪 80年...
LeetCode5.最长回文子... 目录题目链接题目分析解题思路暴力中心向两边拓展搜索 题目链接 链接 题目分析 简单来说࿰...