一、模块介绍
TM1637四位数码管模块是一种用于数字显示的模块。它可以通过接口与微控制器进行通信,并将数字信息显示在四个七段数码管上。 该模块具有以下功能:
1. 显示数字0-9:模块能够将微控制器发送的数字信息显示在数码管上,可以显示0-9的任何数字。
2. 显示符号:模块支持显示符号,如负号、小数点等。
3. 亮度调整:可以通过接口控制模块的亮度,调整数码管的显示亮度。
4. 多位数显示:模块支持同时显示多位数,最多可以同时显示四位数。
5. 节约IO资源:使用TM1637芯片,模块只需要两个IO口即可完成与微控制器的通信,相比其他数码管模块节省了IO资源。
6. 低功耗:模块具有低功耗特性,可以有效节省电力。 通过对TM1637四位数码管模块的使用,可以方便地实现数字显示功能,适用于各种需要数字显示的应用场景,如计数器、计时器、电子钟等。
二、资料获取
关注微信公众号--星之援工作室 发送关键字(TM1637)
➡️➡️
效果展示
三、代码编写
main
主要进行模块的数据刷新功能,含接线方法
/*--------------------------------------------------------*
* *
* 星之援网络科技工作室学习资料v1.0 *
* 时间:2023.7.14 *
* 程序介绍:TM1637 *
* 实现效果:驱动数码管 *
* *
*--------------------------------------------------------*
*/
/*接线
VCC-5.0
GND-GND
DIO-PB7
SCK-PB6
*/
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "TM1637.h"
//全局变量
extern unsigned char disp_num[];
extern unsigned char tab[];
int main(void)
{
u8 flag_s=0;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
// LED 端口初始化
LED_GPIO_Config();
// KEY 初始化
Key_GPIO_Config();
// 串口初始化
uart_init(115200);
//数码管初始化
TM1637_Init();
printf("init okn");
while ( 1 )
{
#if 1
LED1_TOGGLE;
delay_ms( 1000 );
LED1_TOGGLE;
flag_s = ~flag_s;
disp_num[0] = tab[0];
if( flag_s )
disp_num[1] = tab[1] | 0x80; //最高位设置为1 显示":"
else
disp_num[1] = tab[1];
disp_num[2] = tab[2];
disp_num[3] = tab[3];
TM1637_Display_INC();
TM1637_SetBrightness( 7 ); //设置亮度等级 0---7
#else //延时精确测试代码
LED1_ON;
delay_us( 1 );
LED1_OFF;
delay_us( 1 );
#endif
}
}
tm1637.c
使用模拟 IIC 通讯进行数据写入。
#include "TM1637.h"
#include "delay.h"
unsigned char tab[] =
{
0x3F,/*0*/
0x06,/*1*/
0x5B,/*2*/
0x4F,/*3*/
0x66,/*4*/
0x6D,/*5*/
0x7D,/*6*/
0x07,/*7*/
0x7F,/*8*/
0x6F,/*9*/
0x77,/*10 A*/
0x7C,/*11 b*/
0x58,/*12 c*/
0x5E,/*13 d*/
0x79,/*14 E*/
0x71,/*15 F*/
0x76,/*16 H*/
0x38,/*17 L*/
0x54,/*18 n*/
0x73,/*19 P*/
0x3E,/*20 U*/
0x00,/*21 黑屏*/
};
// 最高位设置为1时显示 数码管上的":" 符号
unsigned char disp_num[] = {0x3F, 0x06 | 0x80, 0x5B, 0x4F, 0x66, 0x6D}; //存放6个数码管要显示的内容
//端口初始化
void TM1637_Init( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( TM1637_CLK_GPIO_CLK | TM1637_DIO_GPIO_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = TM1637_CLK_GPIO_PIN | TM1637_DIO_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( TM1637_CLK_GPIO_PORT, &GPIO_InitStructure );
}
//起始位 CLK为高电平时,DIO由高变低
void TM1637_Start( void )
{
TM1637_DIO_OUT();
TM1637_CLK = 1;
TM1637_DIO = 1;
delay_us( 2 );
TM1637_DIO = 0;
}
//等待应答 传输数据正确时,在第八个时钟下降沿,芯片内部会产生一个ACK信号,将DIO管脚拉低,在第九个时钟结束之后释放DIO总线。
void TM1637_Ack( void )
{
TM1637_DIO_IN();
TM1637_CLK = 0;
delay_us( 5 ); //在第八个时钟下降沿之后延时 5us,开始判断 ACK 信号
while( TM1637_READ_DIO ); //等待应答位 这一行代码也可以不要 不影响实际使用效果 在使用软件仿真的时候需要屏蔽这句代码,否则程序就会卡在这里。
TM1637_CLK = 1;
delay_us( 2 );
TM1637_CLK = 0;
}
//停止位 CLK为高电平时,DIO由低变高
void TM1637_Stop( void )
{
TM1637_DIO_OUT();
TM1637_CLK = 0;
delay_us( 2 );
TM1637_DIO = 0;
delay_us( 2 );
TM1637_CLK = 1;
delay_us( 2 );
TM1637_DIO = 1;
}
//输入数据在CLK的低电平变化,在CLK的高电平被传输。
//每传输一个字节,芯片内部在第八个时钟下降沿产生一个ACK
// 写一个字节
void TM1637_WriteByte( unsigned char oneByte )
{
unsigned char i;
TM1637_DIO_OUT();
for( i = 0; i < 8; i++ )
{
TM1637_CLK = 0;
if( oneByte & 0x01 ) //低位在前
{
TM1637_DIO = 1;
}
else
{
TM1637_DIO = 0;
}
delay_us( 3 );
oneByte = oneByte >> 1;
TM1637_CLK = 1;
delay_us( 3 );
}
}
//写显示寄存器 地址自增
void TM1637_Display_INC( void )
{
unsigned char i;
TM1637_Start();
TM1637_WriteByte( 0x40 ); //写数据到显示寄存器 40H 地址自动加1 模式,44H 固定地址模式,本程序采用自加1模式
TM1637_Ack();
TM1637_Stop();
TM1637_Start();
TM1637_WriteByte( 0xC0 ); //地址命令设置 显示地址 00H
TM1637_Ack();
for( i = 0; i < 6; i++ ) //地址自加,不必每次都写地址
{
TM1637_WriteByte( disp_num[i] ); //发送数据 disp_num[]中存储6个数码管要显示的内容
TM1637_Ack();
}
TM1637_Stop();
#if 0
TM1637_Start();
TM1637_WriteByte( 0x88 | 0x07 ); //开显示,最大亮度-----调节脉冲宽度控制0---7 脉冲宽度14/16
TM1637_Ack();
TM1637_Stop();
#endif
}
//写显示寄存器 地址不自增
// add 数码管的地址 0--5
// value 要显示的内容
void TM1637_Display_NoINC( unsigned char add, unsigned char value )
{
TM1637_Start();
TM1637_WriteByte( 0x44 ); //写数据到显示寄存器 40H 地址自动加1 模式,44H 固定地址模式,本程序采用自加1模式
TM1637_Ack();
TM1637_Stop();
TM1637_Start();
TM1637_WriteByte( 0xC0 | add ); //地址命令设置 显示地址 C0H---C5H
TM1637_Ack();
TM1637_WriteByte( value ); //发送数据 value存储要显示的内容
TM1637_Ack();
TM1637_Stop();
#if 0
TM1637_Start();
TM1637_WriteByte( 0x88 | 0x07 ); //开显示,最大亮度-----调节脉冲宽度控制0---7 脉冲宽度14/16
TM1637_Ack();
TM1637_Stop();
#endif
}
// level : 设置亮度等级 0---7
void TM1637_SetBrightness( unsigned char level )
{
TM1637_Start();
TM1637_WriteByte( 0x88 | level ); //开显示,最大亮度-----调节脉冲宽度控制0---7 脉冲宽度14/16
TM1637_Ack();
TM1637_Stop();
}
//读按键 读按键时,时钟频率应小于 250K,先读低位,后读高位。
unsigned char TM1637_ScanKey( void )
{
unsigned char reKey, i;
TM1637_Start();
TM1637_WriteByte( 0x42 ); //读键扫数据
TM1637_Ack();
TM1637_DIO = 1; //在读按键之前拉高数据线
TM1637_DIO_IN();
for( i = 0; i < 8; i++ ) //从低位开始读
{
TM1637_CLK = 0;
reKey = reKey >> 1;
delay_us( 30 );
TM1637_CLK = 1;
if( TM1637_READ_DIO )
{
reKey = reKey | 0x80;
}
else
{
reKey = reKey | 0x00;
}
delay_us( 30 );
}
TM1637_Ack();
TM1637_Stop();
return( reKey );
}
//按键处理函数,按键数据低位在前高位在后
unsigned char TM1637_KeyProcess( void )
{
unsigned char temp;
unsigned char keyNum = 0;
temp = TM1637_ScanKey(); //读取按键返回值
if( temp != 0xff )
{
switch( temp )
{
case 0xf7 : //K1与SG1对应按键按下
keyNum = 1;
break;
case 0xf6 : //K1与SG2对应按键按下
keyNum = 2;
break;
case 0xf5 : //K1与SG3对应按键按下
keyNum = 3;
break;
case 0xf4 : //K1与SG4对应按键按下
keyNum = 4;
break;
case 0xf3 : //K1与SG5对应按键按下
keyNum = 5;
break;
case 0xf2 : //K1与SG6对应按键按下
keyNum = 6;
break;
case 0xf1 : //K1与SG7对应按键按下
keyNum = 7;
break;
case 0xf0 : //K1与SG8对应按键按下
keyNum = 8;
break;
case 0xef : //K2与SG1对应按键按下
keyNum = 9;
break;
case 0xee : //K2与SG2对应按键按下
keyNum = 10;
break;
case 0xed : //K2与SG3对应按键按下
keyNum = 11;
break;
case 0xec : //K2与SG4对应按键按下
keyNum = 12;
break;
case 0xeb : //K2与SG5对应按键按下
keyNum = 13;
break;
case 0xea : //K2与SG6对应按键按下
keyNum = 14;
break;
case 0xe9 : //K2与SG7对应按键按下
keyNum = 15;
break;
case 0xe8 : //K2与SG8对应按键按下
keyNum = 16;
break;
default :
keyNum = 0;
break;
}
}
return keyNum;
}
tm1637.h
主要放置定义的引脚部分和函数申明。
#ifndef __TM1637_H
#define __TM1637_H
#include "stm32f10x.h"
/* 定义IIC连接的GPIO端口, 用户只需要修改下面的代码即可改变控制的LED引脚 */
#define TM1637_CLK_GPIO_PORT GPIOB /* GPIO端口 */
#define TM1637_CLK_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define TM1637_CLK_GPIO_PIN GPIO_Pin_6
#define TM1637_DIO_GPIO_PORT GPIOB /* GPIO端口 */
#define TM1637_DIO_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define TM1637_DIO_GPIO_PIN GPIO_Pin_7
//使用 位带 操作
#define TM1637_CLK PBout(6)
#define TM1637_DIO PBout(7)
#define TM1637_READ_DIO PBin(7)
//IO方向设置 0011输出模式 1000上下拉输入模式
#define TM1637_DIO_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define TM1637_DIO_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
//端口初始化
void TM1637_Init( void );
//起始位 CLK为高电平时,DIO由高变低
void TM1637_Start( void );
//等待应答 传输数据正确时,在第八个时钟下降沿,芯片内部会产生一个ACK信号,将DIO管脚拉低,在第九个时钟结束之后释放DIO总线。
void TM1637_Ack( void );
//停止位 CLK为高电平时,DIO由低变高
void TM1637_Stop( void );
// 写一个字节
void TM1637_WriteByte( unsigned char oneByte );
//写显示寄存器 地址自增
void TM1637_Display_INC( void );
//写显示寄存器 地址不自增
void TM1637_Display_NoINC( unsigned char add, unsigned char value );
// level : 设置亮度等级 0---7
void TM1637_SetBrightness( unsigned char level );
//读按键 读按键时,时钟频率应小于 250K,先读低位,后读高位。
unsigned char TM1637_ScanKey( void );
#endif /* __TM1637_H */
四、参考
STM32F103单片机驱动TM1637数码管显示模块https://blog.csdn.net/qq_20222919/article/details/111571937
完整代码请关注卫星公众号进行获取和咨询
联系方式 微信号:13648103287