TM1637数码模块
01 TM1637数码管
一、前言
手边这个LED数码管, 包括有四个七段数码管。 它的驱动芯片在电路板的背后。 芯片的型号为 TM1637。 下面对其进行测试。 它使用串口进行控制, 电源电压5V。 使用自制 STC32F 单片机进行测试。
二、实验测试
根据TM1637数据手册的介绍, 可以知道它可以支持共阳七段数码管的驱动, 总共可以驱动 8 乘以 6 段。 同时还可以读取 16个按键的状态。 它的接口采用与 I2C 总结的形式, 可以完成双向数据的传送。 在数据手册后面, 给出了基于 51 单片机的应用范例。 下面就使用这个范例进行测试。
下面, 将LED数码管模块通过面包板接入 STC32F 单片机。 利用它的 P1.0, P1.1 两个管脚 模拟 I2C 总线的 始终和数据端口。 由于STC32F 的端口可以有四种模式, 包括推拉输出、准双向输出、OC输出以及输入, 所以在模拟的 I2C 总线上就没有是踹死上拉 电阻。 通过软件测试可以知道数码管的每一段点亮与数据位之间的关系。 对应的位如果是 1 则相应的 LED 段点亮, 由此可以得到 0 到 9 各个数码对应的编码。 这个表格给出了 每个数字对应的编码。
▲ 图1.2.1 点亮的对应BIT
▲ 图1.2.2 0-9数字编码
这里需要说明一下, 原来数据手册中给出的程序实例中存在的一个问题。 由于现在实验平台所使用的单片机 为 STC32F 单片机, 它的运行速度非常快。 所以在原来程序中, I2C 的 始终数据线变低之后, 紧接着改变数据位, 在STC32F 单片机下, 这其中时间延迟不够。 造成 数码管无法正确接收到数据位的状态。 因此,需要在 CLK 变成 0 之后, 增加一个延迟指令, 这样便可以正确实现 I2C 通讯协议。 经过修改之后, 数码管便可以正常进行显示了。 这里给出了测试结果。
三、代码
/*
**==============================================================================
** TM1637.C: -- by Dr. ZhuoQing, 2023-06-28
**
**==============================================================================
*/
#include "STC32F.H"
#include "intrins.h"
#include "stdio.h"
#include "MAIN.H"
#include "c251basic.h"
#include "control.h"
#include "STC32FX.H"
//------------------------------------------------------------------------------
#define TM1637_GLOBALS 1 // Define the global variables
#include "TM1637.H"
//------------------------------------------------------------------------------
void TM1637Init(void) {
ON(TM1637_CLK);
ON(TM1637_DIO);
PM_PP(TM1637_CLK);
PM_PP(TM1637_DIO);
g_ucTM1632DoubleDot = 0x0;
}
//------------------------------------------------------------------------------
void TM1637DelayUS(unsigned int i) {
unsigned char j;
for(; i > 0; i --) {
for(j = 0; j < 20; j ++)
_nop_();
}
}
void TM1637I2CStart(void) {
ON(TM1637_CLK);
ON(TM1637_DIO);
TM1637DelayUS(2);
OFF(TM1637_DIO);
}
void TM1637I2CAsk(void) {
unsigned int i;
PM_BIDIR(TM1637_DIO);
ON(TM1637_DIO);
OFF(TM1637_CLK);
TM1637DelayUS(5);
for(i = 0; i < 1000; i ++) {
if(VAL(TM1637_DIO) == 0) break;
TM1637DelayUS(10);
}
ON(TM1637_CLK);
TM1637DelayUS(2);
OFF(TM1637_CLK);
PM_PP(TM1637_DIO);
}
void TM1637I2CStop(void) {
OFF(TM1637_CLK);
TM1637DelayUS(2);
OFF(TM1637_DIO);
TM1637DelayUS(2);
ON(TM1637_CLK);
TM1637DelayUS(2);
ON(TM1637_DIO);
}
//------------------------------------------------------------------------------
void TM1637I2CWriteByte(unsigned char oneByte) {
unsigned char i;
for(i = 0; i < 8; i ++) {
OFF(TM1637_CLK);
TM1637DelayUS(2);
if(oneByte & 0x1) {
ON(TM1637_DIO);
} else OFF(TM1637_DIO);
TM1637DelayUS(1);
oneByte = oneByte >> 1;
ON(TM1637_CLK);
TM1637DelayUS(3);
}
}
unsigned char TM1637ScanKey(void) {
unsigned char rekey, i;
TM1637I2CStart();
TM1637I2CWriteByte(0x42); // Read key command
TM1637I2CAsk();
ON(TM1637_DIO);
PM_BIDIR(TM1637_DIO);
for(i = 0; i < 8; i ++) {
OFF(TM1637_CLK);
rekey = rekey >> 1;
TM1637DelayUS(30);
ON(TM1637_CLK);
if(VAL(TM1637_DIO)) {
rekey = rekey | 0x80;
}
TM1637DelayUS(30);
}
TM1637I2CAsk();
TM1637I2CStop();
PM_PP(TM1637_DIO);
return rekey;
}
void TM1637Display(unsigned char * pSeg) {
unsigned char i;
TM1637I2CStart();
TM1637I2CWriteByte(0x40); // 40H : Address auto inc
TM1637I2CAsk();
TM1637I2CStop();
TM1637I2CStart();
TM1637I2CWriteByte(0xc0);
TM1637I2CAsk();
for(i = 0; i < 6; i ++) {
TM1637I2CWriteByte(*(pSeg + i));
TM1637I2CAsk();
}
TM1637I2CStop();
TM1637I2CStart();
TM1637I2CWriteByte(0x8f); // Open display, maximum light
TM1637I2CAsk();
TM1637I2CStop();
}
//------------------------------------------------------------------------------
unsigned char Num2Seg(unsigned char ucNum) {
if(ucNum == 0x0) return 0x3f;
else if(ucNum == 0x1) return 0x06;
else if(ucNum == 0x2) return 0x5B;
else if(ucNum == 0x3) return 0x4F;
else if(ucNum == 0x4) return 0x66;
else if(ucNum == 0x5) return 0x6D;
else if(ucNum == 0x6) return 0x7D;
else if(ucNum == 0x7) return 0x07;
else if(ucNum == 0x8) return 0x7F;
else if(ucNum == 0x9) return 0x4F;
else return 0;
}
//------------------------------------------------------------------------------
void TM1637ShowInt16(unsigned int nNumber) {
unsigned char ucSeg[4];
ucSeg[3] = Num2Seg((unsigned char)(nNumber % 10));
nNumber /= 10;
ucSeg[2] = Num2Seg((unsigned char)(nNumber % 10));
nNumber /= 10;
ucSeg[1] = Num2Seg((unsigned char)(nNumber % 10)) | g_ucTM1632DoubleDot;
nNumber /= 10;
ucSeg[0] = Num2Seg((unsigned char)(nNumber % 10));
TM1637Display(ucSeg);
}
//------------------------------------------------------------------------------
//==============================================================================
// END OF FILE : TM1637.C
//------------------------------------------------------------------------------
/*
**==============================================================================
** TM1637.H: -- by Dr. ZhuoQing, 2023-06-28
**
** Description:
**
**==============================================================================
*/
#ifndef __TM1637__
#define __TM1637__
//------------------------------------------------------------------------------
#ifdef TM1637_GLOBALS
#define TM1637_EXT
#else
#define TM1637_EXT extern
#endif // TM1637_GLOBALS
//------------------------------------------------------------------------------
#define TM1637_CLK 1,1
#define TM1637_DIO 1,0
//==============================================================================
void TM1637Init(void);
//------------------------------------------------------------------------------
void TM1637DelayUS(unsigned int i);
void TM1637I2CStart(void);
void TM1637I2CAsk(void);
void TM1637I2CStop(void);
void TM1637I2CWriteByte(unsigned char oneByte);
unsigned char TM1637ScanKey(void);
void TM1637Display(unsigned char * pSeg);
//------------------------------------------------------------------------------
unsigned char Num2Seg(unsigned char ucNum);
void TM1637ShowInt16(unsigned int nNumber);
TM1637_EXT unsigned char g_ucTM1632DoubleDot;
#define TM1637_DOUBLEDOT_SET (g_ucTM1632DoubleDot = 0x80)
#define TM1637_DOUBLEDOT_CLEAR (g_ucTM1632DoubleDot = 0x00)
//==============================================================================
// END OF FILE : TM1637.H
//------------------------------------------------------------------------------
#endif // __TM1637__
※ 总 结 ※
本文测试了利用 STC32F 通过模拟 I2C 端口来驱动TM1637数码管功能。 根据STC32F运行速度快, 调整了 I2C模拟时序的长短, 完成了TM1637的控制命令的传输。
■ 相关文献链接:
● 相关图表链接: