相比MAX7219,TM1638的操作更复杂,但功能更强大 |
目录
-
- TM1638简介
-
- 器件特性
- TM1638引脚图
-
- 引脚功能说明
- TM1638地址组
-
- ?显存地址
- ?键值地址
- TM1638指令表
-
- ?指令分类
- ?数据命令
- ?地址命令
- ?显示控制命令
- TM1638两种数字管的使用方法
-
- 共阴方式
- 共阳方式
- TM1638数据格式
- 按键扫描和按键扫描
-
- 按键扫描电路
- 按键复用
- 自己编写的驱动程序(C51)
TM1638简介
??TM1638是深圳市天微电子有限公司设计的带键盘扫描接口LED驱动控制专用芯片(发光二极管显示器)内部集成MCU数字接口,数据锁存器,LED主要用于冰箱、空调、键盘扫描等电路。 、高位显示屏驱动家庭影院等产品。
器件特性
- 采用功率CMOS 工艺
- 显示模式 10 段×8 位
- 键扫描(8×3bit)
- 8级辉度可调
- 串行接口(CLK,STB,DIO)
- 振荡方式:RC 振荡(450KHz 5%)
- 内置上电复位电路
- 采用SOP28封装
TM1638引脚图
引脚功能说明
- STB:片选端;沿初始化串行接口上升或下降,然后等待接收指令。STB 为高时,CLK被忽略
- DIO:数据端;沿输入/输出串行数据在时钟上升
- CLK:时钟端;输入时钟信号;
- K1~K3:键扫输入;显示周期结束后,输入脚的数据被锁定
- SEG1/KS1~SEG8/KS8:段输出;P管开漏输出也用作键扫描
- SEG9,SEG10:段输出;P管开漏输出
- GRID1~GRID8:位输出;N管开漏输出
- VDD:电源端;功能
- GND:逻辑;功能
TM1638地址组
?显存地址
??如果在显存地址中GRIDn和SEGn如果相应地址中的数据为1,则连接到GRIDn和SEGn上的LED段落将被点亮。 例如00H的数据为0X0F,则连到GIRD1和SEG1、SEG2、SEG3、SEG4上的LED段落将被点亮
?键值地址
??每个Byte里储存6个键值数据,相对应的位置为1则代表对应位置有键按下。
TM1638指令表
?指令分类
TM1638传输的8个指令B7,B六两位来区分指令类型:
B7 B6 | 指令类型 |
---|---|
0 1 | 数据命令 |
1 1 | 地址命令 |
1 0 | 显示控制命令 |
?数据命令
?地址命令
??地址命令用于设置要写入的数据的地址。有两种数据写入:自添加地址和固定地址。每次固定地址写入数据,都需要指定要写入数据的地址。
?显示控制命令
TM1638两种数字管的使用方法
??TM1638的一个优点是可以使用两种数字管,不区分共阴/共阳,但使用方法不同。 ??这里涉及到TM1638显示原理:TM1638的GRIDn端是当显存地址中对应的数据为1时,TM与1638令应来使LED导通发光。
共阴方式
??由于共阴数多个阳极用于共阴数码管GRID它总是低电平,所以只有一个GRIDn端为共阴极,8个SEG端为阳极。 ??这时每个数码管的显示数据由由显存地址关系图组成,每个非奇数地址存储一个数字管的显示数据。 ??写入共阴数字管的显存数据比写入共阴数字管方便得多即可。例如GRID1和SEG1~SEG8对应共阴LED1.让它显示 0 则只用向 00H 地址写入 0X3F; ?? ??共阴方法的缺点是不能使用SEG9和SEG10形成共阴数码管,因此共阴最多可使用8个数码管。SEG9和SEG10仍可使用,但必须采用共阳法。
共阳方式
??由于共阴数码管使用相同的阳极和多个阴极,GRID总是低电平,所以只有8个GRIDn作为阴极,一端SEG端为共阳极。 ??此时,每个数字管的显示数据由每个数字管的显示数据组成由显存地址关系图组成8位显示数据构成数字管。 ??共阳数字管的数据写入比较麻烦,每次数据写入一个数字管都需要。例如GRID1~GRID8和SEG1对应共阴LED1.要显示0,必须是000H,02H,04H,06H,08H,0AH都写入1,向0CH和0EH中写入0 ?? ??共阳方法的优点是可以使用多到10个数字管;缺点是数据的写入比较繁琐,需要增加数据转换。
TM1638数据格式
- TM1638的数据读取和发送都在CLK的上升沿进行,因为DIO在时钟的下降沿控制N管动作,此时读数不稳定。
- TM1638采取的数据格式,每次发送和读取都是,即8位二进制数据
- 每次STB拉低之后的第一个字节作为,处理指令时当前其它处理被终止。
- 模式下,只用写入一次地址即,之后依次写入数据,每次写入数据,地址自动增加0X01。数据全部写入之后,上拉STB来作为结束的信号。
- 模式下,每次写入数据需要,为要写入的数据指定写入的地址,之后写入数据,然后上拉STB结束一次写入。
- 以拉低STB写入读键值指令(0X42)作为开始,之后TM1638会按的顺序传送4byte的键值数据。读取4byte数据之后上拉STB结束读取。
按键扫描和键扫复用
按键扫描电路
电路的连接方式如下图,Kn端作为列线,KSn端作为行线,当有键按下被扫描到,数据被存入键值寄存器。 按键扫描时在端口上的波形:
按键复用
SEG1/KS1~SEG8/KS8是复用的端口,作为显示输出同时作为键扫输出端口。当存在按钮同时按下时,如S1,S2,SEG1和SEG2相当于被短路,此时D1,2D两个LED都会被点亮,从而造成显示错误。 解决方法之一是在每个按键上串联一个二极管,如下图所示,也可以换成510Ω大小的电阻。
自己编写的驱动程序(C51)
/********************************************************************************** * 程序名: TM1638驱动程序 * 作者: DaveoCKII * 日期: 2020.2.29 * 版本: STC12C5A60S2 **********************************************************************************/
#ifndef _TM1638_H_
#define _TM1638_H_
#include <STC12C5A60S3.H> // 自己修改过的STC12C5A60S2的头文件,为了区分原头文件改名S3
//------------------------------------定义列表------------------------------------//
sbit STB = P1^1; // 片选线
sbit CLK = P1^2; // 时钟线
sbit DIO = P1^3; // 数据线
unsigned char led_buffer[16]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 显示数据缓冲区
unsigned char LED_CC[16]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; // 共阴LED显示数据 '0~F'
unsigned char LED_CA[16]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; // 共阳LED显示数据 '0~F'
unsigned char x[8]={
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; // 数据转换中用来提取各位的数据
//------------------------------------函数列表------------------------------------//
void TM1638_LEDCC(unsigned char LEDnums); // TM1638 LED显示(共阴)
void TM1638_LEDCA(unsigned char LEDnums); // TM1638 LED显示(共阳)
void TM1638_Write(unsigned char DATA); // TM1638 写数据函数
void TM1638_WriteCOM(unsigned char cmd); // TM1638 写命令函数
unsigned char TM1638_Read(void); // TM1638 读数据函数
unsigned char TM1638_ReadKey(void); // TM1638 读键函数
//------------------------------------函数内容------------------------------------//
void TM1638_Write(unsigned char DATA)
{
unsigned char i;
for(i=0;i<8;i++) // 1Byte 8位数据
{
CLK=0; // 拉低时钟线
DIO=DATA&0X01; // 发送数据
DATA>>=1; // 数据格式:低位在前
CLK=1; // 拉高时钟线,写入数据
}
}
void TM1638_WriteCOM(unsigned char cmd)
{
STB=0; // 拉低片选线
TM1638_Write(cmd); // 写命令
STB=1; // 拉高片选线
}
unsigned char TM1638_Read(void)
{
unsigned char i,Data=0;
DIO=1; // 初始化数据线
for(i=0;i<8;i++)
{
Data>>=1; // 数据格式:低位在前
CLK=0;
if(DIO)
Data|=0x80;
CLK=1;
}
return Data;
}
unsigned char TM1638_ReadKey(void)
{
unsigned char c[4]; // 4Byte数据储存
unsigned char i=999; // 先用作延时
unsigned char key_value=0;
STB=0; // 拉低片选线,开始读键值
TM1638_Write(0x42); // 写'读数据'命令
while(i--) // 等待准备完毕
for(i=0;i<4;i++) // 读取4个Byte
c[i]=TM1638_Read();
STB=1; // 拉高片选线,读键值结束
// 8键 col:K3 row:KS1~KS8
if(c[0]==0x01) key_value=1;
if(c[0]==0x10) key_value=5;
if(c[1]==0x01) key_value=2;
if(c[1]==0x10) key_value=6;
if(c[2]==0x01) key_value=3;
if(c[2]==0x10) key_value=7;
if(c[3]==0x01) key_value=4;
if(c[3]==0x10) key_value=8;
return (key_value); // 返回键值
}
void TM1638_LEDCC(unsigned char LEDnums)
{
unsigned char i;
TM1638_WriteCOM(0x40); // 设置地址自增
STB=0; // 拉低片选线,开始写数据
TM1638_Write(0xc0); // 写首地址
for(i=0; i<LEDnums; i++) {
// 写显示数据
TM1638_Write(ledb[i]);
TM1638_Write(ledb[i+8]);
}
for(i=LEDnums; i<8; i++) {
TM1638_Write(0);
TM1638_Write(0);
}
STB=1; // 拉高片选线,结束写数据
}
void TM1638_LEDCA(unsigned char LEDnums)
{
unsigned char i;
unsigned char datas[16];
// 数据转换
for(i=0; i<8; i++){
datas[i]=(ledb[0]&x[i])+(ledb[1]&x[i])+(ledb[2]&x[i])+(ledb[3]&x[i])+
(ledb[4]&x[i])+(ledb[5]&x[i])+(ledb[6]&x[i])+(ledb[7]&x[i]);
}
if(LEDnums>8){
for(i=0; i<8; i++)
datas[i+8]=(ledb[8]&x[i])+(ledb[9]&x[i]);
}
else {
for(i=0; i<8; i++)
datas[i]=0x00;
}
TM1638_WriteCOM(0x40); // 设置地址自增
STB=0; // 拉低片选线,开始写数据
TM1638_Write(0xc0); // 写首地址
for(i=0; i<LEDnums; i++) {
// 写显示数据
TM1638_Write(datas[i]);
TM1638_Write(datas[i+8]);
}
for(i=LEDnums; i<8; i++) {
TM1638_Write(0);
TM1638_Write(0);
}
STB=1; // 拉低片选线,结束写数据
}
//--------------------------------------------------------------------------------//
#endif
DaveoCKII2020.3.5 |