8266+DS3231时钟之显示TM1638的使用【四】上

今天继续8266+DS3231时钟项目的显示部分功能的详解。
这个时钟系列目前五篇分别是:

《8266+DS3231时钟之开发个时钟遇到的N个坑【一】》
《8266+ds3231时钟之arduino官网发布的DS3231库的分析【二】》
《8266+DS3231时钟之DS3231具体实现及代码【三】》
《8266+DS3231时钟之显示TM1638的使用【四】上》
《8266+DS3231时钟之显示TM1638的使用【四】下》
《8266+DS3231时钟之语音MP3-TF-16P模块使用【五】》
有兴趣的可以去看看,如果觉得对你有帮助,请点个赞。

一、概述

时钟采用TM1638芯片去驱动数码管和按键。由于同时要驱动十个数码管和8个按键,这里采用TM1638这个强大的数码管驱动芯片。功能上,十个数码管分别显示月、日、时、分共8个数码管,温度占用2个数码管。其中月、日、时、分的显示采用共阴管,而温度显示采用共阳管。这里大家可以先看看成品电路的效果,具体如下图:
在这里插入图片描述
由于板子是半成品,还没有做外壳,所以这里先用红字标上管的显示内容,以期能理解。至于为什么有共阴也有共阳的数码管,这里主要是因为TM1638的显示能力是8位10段。由于8个数码管我们实际只用到了7段(a、b、c、d、e、f、g)就够显示了,所以每个管还剩3段的显示能力,也就是3段*8位。这样我在设计时把这3段的显示能力中,一段分配给了秒的显示(如上图),二段8位用于温度的显示。这里看不明白不要紧,具体在下面理解完芯片的引脚能力会,就自然明白了。

二、TM1638的数据手册介绍

以下内容是摘自TM1638的数据手册,放在这里是为了方便阅读,当然也可以自已去度娘下载。要用好TM1638必须清楚数据手册里讲的内容,否则在后面的驱动程序的部分是没法看明白的。由于原文的例子中有些有错误,我在摘录时已修改,因此有原文的人在阅读原文时要注意。

TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集
成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。

1、 特性说明

• 采用功率CMOS 工艺
• 显示模式 10 段×8 位
• 键扫描(8×3bit)
• 辉度调节电路(占空比8 级可调)
• 串行接口(CLK,STB,DIO)
• 振荡方式:RC 振荡(450KHz+5%)
• 内置上电复位电路
• 采用SOP28封装

2、管脚定义

在这里插入图片描述

在这里插入图片描述
注意:DIO口输出数据时为N管开漏输出,在读键的时候需要外接1K-10K的上拉电阻。推荐10K的
上拉电阻。DIO在时钟的下降沿控制N管的动作,此时读数时不稳定,你可以参考图(6),在时钟的上升沿读数才时稳定。
在这里插入图片描述

3、显示寄存器地址和显示模式

显示寄存器地址和显示模式:
该寄存器存储通过串行接口从外部器件传送到TM1638 的数据,地址从00H-0FH共16字节单元,
分别与芯片SGE和GRID管脚所接的LED灯对应,分配如下图:
(写LED显示数据的时候,按照从显示地址从低位到高位,从数据字节的低位到高位操作。)
在这里插入图片描述
(这里表格产生了向左的错位,我用箭头标出了错位的对应界限,看时请注意)
写LED显示数据的时候,按照从低位地址到高位地址,从字节的低位到高位操作;在运用中
没有使用到的SEG输出口,在对应的BIT地址位写0。
这里,我用一个具体的例子来说明,就比较好明白上表的使用方法了。
数码管的段的定义如下:
在这里插入图片描述
如果此时要显示0这个数,那么对应的需要点亮的段为A、B、C、D、E、F这六个段
在这里插入图片描述

4、键扫描和键扫数据寄存器

键扫矩阵为8×3bit,如图(3)所示:
在这里插入图片描述
键扫数据储存地址如下所示,先发读键命令后,开始读取按键数据BYTE1—BYTE4字节,
读数据从低位开始输出;芯片K和KS引脚对应的按键按下时,相对应的字节内的 BIT位为1。
在这里插入图片描述
注意:
1、TM1638最多可以读4个字节,不允许多读。
2、读数据字节只能按顺序从BYTE1-BYTE4读取,不可跨字节读。例如:硬件上的K2与KS8
对应按键按下时,此时想要读到此按键数据,必须需要读到第4个字节的第5BIT位,才可读出数据;当K1与KS8,K2与KS8,K3与KS8三个按键同时按下时,此时BYTE4所读数据的B4,B5,B6位均为1
3、组合键只能是同一个KS,不同的K引脚才能做组合键;同一个K与不同的KS引脚不可以
做成组合键使用。

5、指令说明

指令用来设置显示模式和LED 驱动器的状态。
在STB下降沿后由DIO输入的第一个字节作为一条指令。经过译码,取最高B7、B6两位比特位以区别不同的指令。
在这里插入图片描述
如果在指令或数据传输时STB被置为高电平,串行通讯被初始化,并且正在传送的指令或数据
无效(之前传送的指令或数据保持有效)。

数据命令设置

该指令用来设置数据写和读,B1和B0位不允许设置01或11。
在这里插入图片描述
总结上表,实际用到的命令码如下:
在这里插入图片描述

地址命令设设置

在这里插入图片描述
该指令用来设置显示寄存器的地址。 如果地址设为10H 或更高,数据被忽略,直到有效地址被设定。
上电时,地址默认设为00H。
总结:上表由于B7位和B6位设定为1,因此实际就决定了基地址为1100 0000即C0H。B0-B3则定义了偏移地址。在实际地址命令设置时应当是基地址+偏移地址。

显示控制

在这里插入图片描述
【注意】B3位在设置亮度时应置1.

6、串行数据传输格式

读取和接收1个BIT都在时钟的上升沿操作。

6.1 数据接收(写数据)

在这里插入图片描述
注意:字节写入时,是按B0-B7的低位到高位的顺序。

6.2 数据读取(读数据)

在这里插入图片描述
▲注意:读取数据时,从串行时钟CLK 的第8 个上升沿开始设置指令到CLK 下降沿读数据之间需要
一个等待时间Twait(最小1μS)。

注意:字节读入时,是按B0-B7的低位到高位的顺序。

7、显示和按键:

(1) 显示:

1、驱动共阴数码管:
在这里插入图片描述
图7给出共阴数码管的连接示意图,如果让该数码管显示“0”,那你需要在GRID1为低电平
的时候让SEG1,SEG2,SEG3,SEG4,SEG5,SEG6为高电平,SEG7为低电平,
查看图(2)显示地址表格,只需在00H地址单元里面写数据3FH就可以让数码管显示“0”。
2、驱动共阳数码管
在这里插入图片描述
图8给出共阳数码管的连接示意图,如果让该数码管显示“0”,那你需要在GRID1,GRID2,
GRID3,GRID4,GRID5,GRID6为低电平的时候让SEG1为高电平,在GRID7为低电平的时候让SEG1为低电平。要向地址单元00H,02H,04H,06H,08H,0AH里面分别写数据01H,其余的地址单元全部写数据00H。
在这里插入图片描述
注意:SEG1-10为P管开漏输出,GRID1-8为N管开漏输出,在使用时候,SEG1-10只能接LED的阳极,GRID只能接LED的阴极,不可反接。

(2)键盘扫描:

你可以按照图(9)用示波器观察观察SEG1/KS1和SEG2/KS2的输出波形,SEGN/KSN
输出的波形见图(10)。
在这里插入图片描述
IC在键盘扫描的时候SEGN/KSN的波形:
在这里插入图片描述
Tdisp和IC工作的振荡频率有关,TM1638经过多次完善,振荡频率不完全一致。500US
仅仅提供参考,以实际测量为准。
一般情况下使用图(11),可以满足按键设计的要求。
在这里插入图片描述
当S1被按下的时候,在第1个字节的B2读到“1”。如果多个按键被按下,将会读到多个“1”,
当S2,S3被按下的时候,可以在第1个字节的B1,B6读到“1”。
▲注意:复合键使用注意事项:
SEG1/KS1-SEG10/KS10是显示和按键扫描复用的。以图(12)为例子,显示需要D1亮,D2灭,需要让SEG1为“0”,SEG2为“1”状态,如果S1,S2同时被按下,相当于SEG1,SEG2被短路,这时D1,D2都被点亮。
在这里插入图片描述
解决方案:
1、在硬件上,可以将需要同时按下的键设置在不同的K线上面如图(13)所示,
在这里插入图片描述
2、在SEG1—SEG N上面串联电阻如图(14)所示,电阻的阻值应选在510欧姆,太大会造成
按键的失效,太小可能不能解决显示干扰的问题。
在这里插入图片描述
3、或者串联二极管如图(15)所示。
在这里插入图片描述

8、应用时串行数据的传输:

1 地址增加模式

使用地址自动加1模式,设置地址实际上是设置传送的数据流存放的起始地址。起始地址命令
字发送完毕,“STB”不需要置高紧跟着传数据,最多14BYTE,数据传送完毕才将“STB”置高。
在这里插入图片描述

2 固定地址模式

使用固定地址模式,设置地址其实际上是设置需要传送的1BYTE数据存放的地址。地址发送完
毕,“STB”不需要置高,紧跟着传1BYTE数据,数据传送完毕才将“STB”置高。然后重新设置第2
个数据需要存放的地址,最多14BYTE数据传送完毕,“STB”置高。
在这里插入图片描述

3 读按键时序

在这里插入图片描述

4 程序设计流程图

采用地址自动加1的程序设计流程图:
在这里插入图片描述
采用固定地址的程序设计流程图:
在这里插入图片描述

9、应用电路

1 TM1638驱动共阳数码屏硬件电路,如图(16):
在这里插入图片描述

2 TM1638驱动共阴数码屏硬件电路,如图(17):
在这里插入图片描述
▲注意: 1、VDD、GND之间滤波电容在PCB板布线应尽量靠近TM1629芯片放置,加强滤波效果。
2、连接在DIO、CLK、STB通讯口上三个100P电容可以降低对通讯口的干扰。
3、因蓝光数码管的导通压降压约为3V,因此TM1629供电应选用5V。

三、具体时钟显示和按键电路设计思路

1、数码管的选择

月份和日期的显示分别是采用了两个2位共阴数码管。管脚的定义如下:
在这里插入图片描述
时分秒的显示采用的是一个4位共阴数码管。管脚定义如下:
在这里插入图片描述
由于时分秒显示采用的是4位管,4位用于时分的显示,秒的闪烁是两个LED灯,在图中是第3脚连接的D5、D6。
在这里插入图片描述

温度显示采用的是一个2位共阳数码管。管脚定义如下:
在这里插入图片描述
具体原理图:
在这里插入图片描述
LED_2_green1 和 LED_2_green2 是对应月日的显示
LED_2_node对应的是温度显示
LED_clock_4是时分秒的显示

接线对应表:
在这里插入图片描述
以上所有涉及硬件的部分已完成,要想完成正常的显示,接下来就是软件部分。考虑到篇幅问题,将在下一篇详细分析TM1638的驱动代码,以及驱动的具体应用。

#include //1638he165合并程序 2018/5/26 #include #include #define uchar unsigned char #define uint unsigned int sbit SU0=P2^0; //计数脉冲识别 sbit SU1=P2^1; //计数脉冲识别 sbit SU2=P2^2; sbit DJ1=P1^0; sbit DJ2=P1^1; sbit QH=P3^2; //输出端 sbit CK=P3^3; //时钟 上升沿有效 sbit PL=P3^4; //移位控制 低电平有效 uchar temp; uchar temp1; uchar tempH; uchar tempL; bit weia; bit weib; bit ding; unsigned char num[8]; //各个数码管显示的值 unsigned int dingshiqi=0; unsigned int num1,num2; unsigned int su1_a,su1_b; unsigned int su2_a,su2_b; unsigned int su2,su4,su1; unsigned char wei,wei1; unsigned int k; void delay1ms(uint i) //1ms延时程序 { uchar j; while(i--) { for(j=0;j0; j--); } uint read_int165(void) { uchar i=0; uint read_data=0; PL=0; //置数,读入并行输入数据 _nop_(); PL=1; //移位,并口被锁存,串行转换开始 _nop_(); for(i=0;i<16;i++) //设定16位输入 { read_data<<=1; if(QH) { read_data|=QH; } CK=0; //下降沿 _nop_(); CK=1; _nop_(); //上升沿 } return read_data; } void init_t0() { TMOD = 0x02; //8位自动载定时器 TH0 = 0x06; TL0 = 0x06; TR0 = 1; //启动定时器 ET0=1; //允许定时器0中断 EA=1; //开总中断 } void main(void) { unsigned char i; init_t0(); init_TM1638(); for(i=0;i<8;i++) Write_DATA(i<>8); //获取高八位,存在tempH tempL=(uchar)temp; //获取低八位存在tempL P2=tempH; //接收的字节高八位显示在P2 P1=tempL; //接收的低八位显示在P1 } { i=Read_key(); switch(i) { case 0: //1--1 { while(Read_key()==i); //等待按键释放 su1_a = 0; su2_a = 0; wei=0; weia=1; ding=0; }break; case 1: { while(Read_key()==i); //等待按键释放 weia=0; wei++; if(wei>=3)wei = 0; }break; case 2: { while(Read_key()==i); //等待按键释放 if(wei==1) su1_b++; if(su1_b>5500) su1_b=0; if(wei==2) su2_b++; if(su2_b>5500) su2_b=0; }break; case 3: { while(Read_key()==i); //等待按键释放 if(wei==1) { if(su1_b>0)su1_b--; } if(wei==2) { if(su2_b>0)su2_b--; } }break; case 4: { while(Read_key()==i); //等待按键释放 ding=~ding; }break; case 5:{ while(Read_key()==i); }break; case 6:{ while(Read_key()==i); } break; case 7:{ while(Read_key()==i); }break; } if(wei==0) //脉冲输入计数 { if((ding==0)&&(weia==1)) { if(SU0 ==0) { delay(1); if(SU0==0) { while(!SU0); su1_a++; } } if(SU1 ==0) { delay(1); if(SU1==0) { while(!SU1); su2_a++; } } if(su1_a==su1_b) su1_a = 0; if(su2_a==su2_b) { ding = 1; } } Write_DATA(3*2,tab[su1_a]); Write_DATA(2*2,tab[su1_a0/10]); Write_DATA(1*2,tab[su1_a00/100]); Write_DATA(0*2,tab[su1_a000/1000]); Write_DATA(7*2,tab[su2_a]); Write_DATA(6*2,tab[su2_a0/10]); Write_DATA(5*2,tab[su2_a00/100]); Write_DATA(4*2,tab[su2_a000/1000]); } if(wei==1) //左边数码管设置 { k++; if(k>40)k = 0; if(k>10) { Write_DATA(3*2,tab[su1_b]); Write_DATA(2*2,tab[su1_b0/10]); Write_DATA(1*2,tab[su1_b00/100]); Write_DATA(0*2,tab[su1_b000/1000]); } else { Write_DATA(0*2,tab[20]); Write_DATA(1*2,tab[20]); Write_DATA(2*2,tab[20]); Write_DATA(3*2,tab[20]); } } if(wei==2) //右边数码管设置 { Write_DATA(3*2,tab[su1_a]); Write_DATA(2*2,tab[su1_a0/10]); Write_DATA(1*2,tab[su1_a00/100]); Write_DATA(0*2,tab[su1_a000/1000]); k++; if(k>40)k = 0; if(k>10) { Write_DATA(7*2,tab[su2_b]); Write_DATA(6*2,tab[su2_b0/10]); Write_DATA(5*2,tab[su2_b00/100]); Write_DATA(4*2,tab[su2_b000/1000]); } else { Write_DATA(4*2,tab[20]); Write_DATA(5*2,tab[20]); Write_DATA(6*2,tab[20]); Write_DATA(7*2,tab[20]); } } } } } void time0() interrupt 1 //使用的是定时器T0 { dingshiqi++; if(dingshiqi>=3686) { dingshiqi = 0; } }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑牛唱剧本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值