C51单片机驱动TM1637四位数码管

去年8月一时兴起,从淘宝上买了块由TM1637驱动的四位数据管模块,本着买来驱动着去玩一玩想法,可惜的是到货了之后没有了下文。又是一个8月,偶然看到未拆包装的这个模块,打开它花上半天时间驱动成功,驱动过程中由于使用的是1T的c51单片机,反反复复花了很长时间始终没有点亮,看芯片说明书TM1637的时序时间基本在1us以下,所以延时设定在3us左右,后来估计资料不一定准确把延时设在30us左右成功驱动模块,以下记录C51单片机(STC15W408AS)驱动TM1637四位数码管的过程,模块如下图所示。

一、模块概述:

1、数码管:

采用7段共阳极的数码管,带有时钟点,其中两个实钟点是集成在DIG2显示管上,在淘宝的评论区中看到有买家的评论问为什么不显示小数点,这种数码管不会显示小数点,管型就不支持显示。

2、芯片TM1637:

TM1637是一块带键盘扫描和数码管显示驱动的控制专用芯片。本模块仅使用芯片的显示驱动功能,通信方式采用I2C总线,大大节约单片机的IO端口,还可以通过指令调节数码管的显示亮度。

二、模块与单片机电路连接:

序号

单片机

TM1637模块

1

+5V

+5V

2

GND

GND

3

P3.5

DIO

4

P3.6

CLK

三、模块驱动协议:

   TM1637在I2C协议下工作,本文不再讨论I2C的基础协议。单片机向TM1637写数据有两种方式。

第一种是地址自动加1模式,即只需要告诉芯片首个数码管的地址,写完第一个数码管的数据后地址自动加1再,直接给第二个、第三个、第四个数据即可。

第二种是固定地址模式,即必须是一个地址对应一个数据,直至写完。

我们下面以第一种自动加1模式为基础。以下为协议。

1、分析写入过程如下:

Start信号+命令1+ACK信号+Stop信号+ Start信号+首个数码管地址数据+ACK信号+首个数码管显示数据+ ACK信号+第二个数码管显示数据+ ACK信号+第三个数码管显示数据+ ACK信号+第四个数码管显示数据+ ACK信号+ Stop信号+ Start信号+显示控制命令+ ACK信号+ Stop信号

2、命令1内容如下表:

根据上表我们需要写数据到显示寄存器,0100 0000即(0x40)

3、数据管的地址如下表:

根据上表我们需要第一个数码管的地址,1100 0000即(0xC0)

4、显示控制命令:

现在我们需要显示开到高5位10001,再需要最亮显示低3位111,合并后1000 1111即(0x8F)

四、代码部分:

1、I2C.c文件部分:

sbit SDA=P3^5;  //DIO端
sbit SCL=P3^6;  //CLK端

void Delay20us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	_nop_();
	i = 52;
	while (--i);
}

void DelayUs2x(unsigned char x)
{
	while(x--)
	{
		Delay20us();
	}
}


void I2C_Init()
{
   SDA=1;
   SCL=1;
}

//起始信号
void I2C_Start()
{
   SDA=1;  
   SCL=1;
   DelayUs2x(2);
   SDA=0;
   //Delay3us();   
}

//结束信号
void I2C_Stop()
{
   SCL=0;
   DelayUs2x(2);   
   SDA=0;
   DelayUs2x(2);
   SCL=1;
   DelayUs2x(2);
   SDA=1;
  
   
}


//发送时接收从机应答信号
void I2C_Wait_Ack()
{
   unsigned char i=0;
   SCL=0;
   SDA=1;
   DelayUs2x(2);
   while(SDA&&i<10)
   {
	i++;
     DelayUs2x(2);
	}
	SCL=1;
    DelayUs2x(2);
    SCL=0;
    DelayUs2x(2);
    
}



//接收时发送至从机应答信号
void I2C_Send_Ack(unsigned char ack)
{
   
	 if(ack==1)
	  SDA=1;
	else
	  SDA=0;	
	DelayUs2x(3);
	SCL=1;
	DelayUs2x(3);
	DelayUs2x(3);
	SCL=0;
	SDA=1;        //很关键,没有后续不能连续读
	DelayUs2x(3);
}


//发送8位字节
void I2C_Write_Byte(unsigned char c)
{
   unsigned char i;
   SCL=0;
   //DelayUs2x(2);
   for(i=0;i<8;i++)//必须从低位开始
   {
	SDA=c&0x01;
	c=c>>1;
	SCL=1;
    DelayUs2x(3);
    SCL=0;
    DelayUs2x(3);	
	}
  I2C_Wait_Ack();
}

2、main主程序部分:

bit dot1=0;

unsigned char dat[]={
	0x3F,/*0*/
	0x06,/*1*/
	0x5B,/*2*/
	0x4F,/*3*/
	0x66,/*4*/
	0x6D,/*5*/
	0x7D,/*6*/
	0x07,/*7*/
	0x7F,/*8*/
	0x6F/*9*/
};

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 22;
	j = 3;
	k = 227;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

//h1小时的十位,h0小时个位,m1分的十位,m0分的个位,dot两点,1表示显示,0表示不显
void display(unsigned char h1,unsigned char h0,unsigned char m1,unsigned char m0,unsigned char dot)
{
	unsigned char i;
	
	I2C_Start();
	I2C_Write_Byte(0x40);
	I2C_Stop();
	I2C_Start();
	I2C_Write_Byte(0xC0);	
	
	I2C_Write_Byte(dat[h1]);
	if(dot)
	{
		I2C_Write_Byte(dat[h0]|0x80);
	}
	else
	{
		I2C_Write_Byte(dat[h0]&0x7F);
	}		
	I2C_Write_Byte(dat[m1]);
	I2C_Write_Byte(dat[m0]);
	
    I2C_Stop();
    I2C_Start();
	I2C_Write_Byte(0x8f);
	I2C_Stop();

	
}
void main()
{
//输入程序代码
while(1)
	{
		display(1,2,3,0,dot1);
		Delay500ms();
		Delay500ms();
		dot1=~dot1;
	}

}

五、运行效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值