STM32驱动TM1638代码详细说明_例程

TM1638是一个让人又爱又恨的芯片。说它让人爱,是因为它功能强大,一个芯片即可驱动十位的数码管,可以是共阴极,也可以是共阳极数码管。又能检测最多24个按键。而常用电路里连接数码管所需的限流电阻,或者常用按键电路里所需的上拉电阻全都不需要,芯片内部已经处理好了。

说它让人恨,是因为它的数据手册写的太烂了。细节写的不详细就算了,表格还经常对不齐。如果不是拉低自己的智商,你很可能看不懂。

所以这里,我只说这个芯片如何使用。如果你真的对数据手册感兴趣,可以找时间慢慢研究。

程序执行流程图,手册里提供了两种,这里以第二种为例,进行演示。如下:

看着挺复杂,简单来说,就是4个步骤:

1、初始化

2、依次设置几位数码管要显示的值

3、读取按键状态,并处理相应的按键事件

4、回到步骤2,以此循环。

有人会担心,是不是要不停的设置数码管的值,一旦停了,数码管就不显示了?

不是的!数码管的值只要写一次,就能一直显示。

所以如果你只是要显示数码管,不检测按键。那么上面的步骤,执行到第二步就行了。如果要修改数码管的值,重复第二步即可。

还有人会想,我数码管的值不怎么改,按键要经常检测,从第四步跳回第三步,不跳回第二步了,还能节约时间。可不可以?

不行!芯片会工作异常!

时序部分比较简单,就是常见的三条线:时钟、数据、片选。用过DS1302的都懂,类似,不解释。

电路部分也不难,数据手册里提供了相应的原理图,共阴极如下:

共阳极数码管接法如下:

看不清的,可以去手册看。应用电路这部分,手册画的还是很清晰,没有问题。

最关键的地方在于驱动共阳极与共阴极数码管时,你向芯片内存地址写入的数据,两者方法是完全不一样的。共阴极数码管驱动方法是比较简单的,显示什么数字送入相应的编码即可。

共阳极数码管的驱动方法堪称噩梦,我看了一天也没看懂,只能知道它大概的意思。不仅如此,网上大部分资料都是关于共阴极数码管的。而不幸的是,我当时设计电路使用的是共阳极数码管。幸好后来在网上搜到了一份资料,不然真的要跪了!

我们看下主要部分的代码:

首先是上电初始化:

void Display_Init(void)
{

	Send_Command(0x44);		//显示模式-固定地址
	Send_Command(0x40);		//写数据到显示寄存器
	//数码管和LED默认都熄灭
	LedDisplay1(0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0,0);
	
	Send_Command(0x8f);		//显示控制-显示开
}

共阳极数码管的显示代码:

void LedDisplay1(unsigned char data0,unsigned char data1,unsigned char data2,unsigned char data3,unsigned char data4,unsigned char data5,unsigned char data6,unsigned char data7)
{ //操作TM1638前八个数码管(共阳极-SEG1~SEG8)
	unsigned char  writedata0,writedata1,writedata2,writedata3,writedata4,writedata5,writedata6,writedata7;  
	MX_DIO_OUT_Init();
	//一次将SEG数值写完(SEG1|SEG2...SEG8)
	writedata0=(DispHexToSegTbl[data0]&0x01)+((DispHexToSegTbl[data1]&0x01)<<1)+((DispHexToSegTbl[data2]&0x01)<<2)+((DispHexToSegTbl[data3]&0x01)<<3)+((DispHexToSegTbl[data4]&0x01)<<4)
		+((DispHexToSegTbl[data5]&0x01)<<5)+((data6&0x01)<<6)+((data7&0x01)<<7);

	writedata1=((DispHexToSegTbl[data0]&0x02)>>1)+((DispHexToSegTbl[data1]&0x02))+((DispHexToSegTbl[data2]&0x02)<<1)+((DispHexToSegTbl[data3]&0x02)<<2)+((DispHexToSegTbl[data4]&0x02)<<3)
		+((DispHexToSegTbl[data5]&0x02)<<4)+((data6&0x02)<<5)+((data7&0x02)<<6);

	writedata2=((DispHexToSegTbl[data0]&0x04)>>2)+((DispHexToSegTbl[data1]&0x04)>>1)+((DispHexToSegTbl[data2]&0x04))+((DispHexToSegTbl[data3]&0x04)<<1)+((DispHexToSegTbl[data4]&0x04)<<2)
		+((DispHexToSegTbl[data5]&0x04)<<3)+((data6&0x04)<<4)+((data7&0x04)<<5);

	writedata3=((DispHexToSegTbl[data0]&0x08)>>3)+((DispHexToSegTbl[data1]&0x08)>>2)+((DispHexToSegTbl[data2]&0x08)>>1)+((DispHexToSegTbl[data3]&0x08))+((DispHexToSegTbl[data4]&0x08)<<1)
		+((DispHexToSegTbl[data5]&0x08)<<2)+((data6&0x08)<<3)+((data7&0x08)<<4);

	writedata4=((DispHexToSegTbl[data0]&0x10)>>4)+((DispHexToSegTbl[data1]&0x10)>>3)+((DispHexToSegTbl[data2]&0x10)>>2)+((DispHexToSegTbl[data3]&0x10)>>1)+((DispHexToSegTbl[data4]&0x10))
		+((DispHexToSegTbl[data5]&0x10)<<1)+((data6&0x10)<<2)+((data7&0x10)<<3);

	writedata5=((DispHexToSegTbl[data0]&0x20)>>5)+((DispHexToSegTbl[data1]&0x20)>>4)+((DispHexToSegTbl[data2]&0x20)>>3)+((DispHexToSegTbl[data3]&0x20)>>2)+((DispHexToSegTbl[data4]&0x20)>>1)
		+((DispHexToSegTbl[data5]&0x20))+((data6&0x20)<<1)+((data7&0x20)<<2);

	writedata6=((DispHexToSegTbl[data0]&0x40)>>6)+((DispHexToSegTbl[data1]&0x40)>>5)+((DispHexToSegTbl[data2]&0x40)>>4)+((DispHexToSegTbl[data3]&0x40)>>3)+((DispHexToSegTbl[data4]&0x40)>>2)
		+((DispHexToSegTbl[data5]&0x40)>>1)+((data6&0x40))+((data7&0x40)<<1);

	writedata7=((DispHexToSegTbl[data0]&0x80)>>7)+((DispHexToSegTbl[data1]&0x80)>>6)+((DispHexToSegTbl[data2]&0x80)>>5)+((DispHexToSegTbl[data3]&0x80)>>4)+((DispHexToSegTbl[data4]&0x80)>>3)
		+((DispHexToSegTbl[data5]&0x80)>>2)+((data6&0x80)>>1)+((data7&0x80));
     
   TM1638_WriteAddressData(0XC0,writedata0);//操作  C0地址
   TM1638_WriteAddressData(0XC2,writedata1);//操作  C2地址
   TM1638_WriteAddressData(0XC4,writedata2);//操作  C4地址
   TM1638_WriteAddressData(0XC6,writedata3);//操作  C6地址
   TM1638_WriteAddressData(0XC8,writedata4);//操作  C8地址
   TM1638_WriteAddressData(0XCa,writedata5);//操作  Ca地址
   TM1638_WriteAddressData(0XCc,writedata6);//操作  Cc地址
   TM1638_WriteAddressData(0Xce,writedata7);//操作  Ce地址
}

读按键值:

unsigned char Read_key(void)
{
	unsigned char c[4],i,key_value=0;
	Reset(STB);
	delay_us(5); 
	Send_Command(0x42);                           //读键扫数据  -命令
	for(i=0;i<4;i++)               
					c[i]=TM1638_Read();
	Set(STB);
	for(i=0;i<4;i++)
		key_value|=c[i]<<i;
	for(i=0;i<8;i++)
		if((0x01<<i)==key_value)
			break;
	return i;
}

我这里只接了三个按键,如图:

如果是共阴极数码管,写入数码管数据部分的代码如下:

void Write_DATA(unsigned char add,unsigned char DATA)		
{
	//指定地址写入数据
        Write_COM(0x44);
	STB=0;
	TM1638_Write(0xc0|add);
	TM1638_Write(DATA);
	STB=1;
}

看到了吧,共阴极与共阳极的写入数据部分的代码,复杂程度完全不一样。除了这里,按键扫描部分是完全一样的。

我分别把这两类详细代码传到了百度网盘,想要的童鞋关注公众号:单片机爱好者,回复关键词:TM1638,即可获取下载链接。

留下评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据