|
本帖最后由 ywlzh 于 2017-2-22 18:04 编辑
从淘宝买来的,TM1638专门是控制LED的,LED组合起来就可以变成数码管,还有按键,这个我就没管了,不想管了,发这个帖子只是为了记录下经验,待以后会过头来看的时候,可以一遍就知道,所以尽量写得详细点。
手头上的项目用的是共阳极,而我买的是共阴极的,还好,全都弄出来了。
单片机怎么跟它通信,这个还得细看TM1638的数据手册,一个新的芯片到手,千万别第一时间上网找例程,先把这个片子的数据手册看一遍
TM1638.pdf
(873.68 KB, 下载次数: 324)
先截个图出来看
可以看的出来,跟单片机通信就只需要DIO,STB, CLK三根线,这三根线最好是做好上拉电阻,TM1638是不需要刷数据的,共阴极的是只需要在对应的地址上写data就OK了,它自己会去刷新数据。 先看共阴极的电路图,也就是淘宝买的这个模块的电路图
段码是SEG1-SEG8,片选是GR1-GR8 ,片选的几个正好对应着地址
从上面的图就可以看出,写这些数据进去就可以了:自动地址增加,是否显示,调节亮度...写这些命令的时候是需要先让STB信号为高电平的,写命令,再拉低STB信号,写数据到对应地址的时候,也需要先把STB信号给拉高,写地址,写数据,再拉低STB信号。
怎么写数据进去呢?就得看时序图了
基本靠STB为低,CLK的上升沿,然后来确定DIO的高低,高为1,低为0。
开始写程序吧,我用的stm32f407
先确定引脚
- #define DIO PAout(1)
- #define CLK PAout(4)
- #define STB PAout(6)
复制代码
再把引脚初始化,如果要读按键的话,就需要把DIO写成开漏模式,这样就既可以读也可以写了,
- void TM1638_GPIO_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //ê1ÄüGPIODμÄê±Öó
-
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_4;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//êä3ö
- GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //íÆíìêä3ö
- GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //éÏà-êä3ö
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //¸ßËùGPIO
- GPIO_Init(GPIOA,&GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; //DIO ¿a©Ä£ê½
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//êä3ö
- GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //¿a©êä3ö
- GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //éÏà-êä3ö
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //¸ßËùGPIO
- GPIO_Init(GPIOA,&GPIO_InitStructure);
-
- }
复制代码
引脚做好初始化后,就需要开始写怎么写一个字节了。
- void TM1638_Write(unsigned char DATA) //D′êy¾Yoˉêy
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- CLK=0;
- if(DATA&0X01)
- DIO=1;
- else
- DIO=0;
- DATA>>=1;
- CLK=1;
- }
- }
复制代码
读一个字节,我就没管了,继续下去,要向对应的地址上写入一个字节,封装一些上面的函数就可以了
- void Write_Nixie_DATA(unsigned char add,unsigned char DATA) //Ö¸¶¨μØÖ·D′èëêy¾Y
- {
- Write_COM(0x44);
- STB=0;
- TM1638_Write(0xc0|add);
- TM1638_Write(0xff&DATA); //这样不影响其他位,考虑共阳极的接法。
- STB=1;
- }
复制代码
还可以封装成写命令的函数
- void Write_COM(unsigned char cmd) //·¢ËíÃüáî×Ö
- {
- STB=0;
- TM1638_Write(cmd);
- STB=1;
- }
复制代码
这样基本就可以了,举个例子,我要让GR3对应的数码管显示0怎么办?看图
如果对应的段码显示用的SEG1-SEG8,则需要在04H地址上写0的段码就可以了,比如这样
Write_Nixie_DATA(2<<1,0x3F); //从0开始数,GR3对应着第2个数码管,左移有个好处就是在06H地址就可以表示成 3<<1
这样看程序就知道是哪个数码管需要显示什么数据,如果用的SEG9做LED驱动的,我要第6个LED亮,就是GR7做片选,SEG9要为高,对应的地址为0DH。
Write_Nixie_DATA(2*6+1,0x3F); //用2*i+1 可以一下就知道是哪个LED了。
好了,共阴极的程序基本算是完了,共阳极的怎么办,有共阴极的要共阳的干嘛?有没有考虑过共阴极的电路最多只能控制8个数码管,而共阳极的可以控制10个数码管(不用LED)。先看电路图。
咋一眼一看,很奇怪的电路,原本设计片选的GR1-GR8变成了段码输送。原本设计成段码的变成了片选。这里就得转换一下思路了,还是在对应的地址上写数据,怎么写,而且一个数码管有变动,整个地址的数据就得重新写一遍。这一点比较麻烦,花点时间想想也是可以想出来的。先看程序
- uint8_t Seg1[] = { // 第一位数码管显示码值
- 0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00, // 0
- 0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00, // 1
- 0x01,0x01,0x00,0x01,0x01,0x00,0x01,0x00, // 2
- 0x01,0x01,0x01,0x01,0x00,0x00,0x01,0x00, // 3
- 0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x00, // 4
- 0x01,0x00,0x01,0x01,0x00,0x01,0x01,0x00, // 5
- 0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x00, // 6
- 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00, // 7
- 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00, // 8
- 0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x00, // 9
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 10
- };
- uint8_t Seg2[] = { // 第二位数码管显示码值
- 0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, // 0
- 0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00, // 1
- 0x02,0x02,0x00,0x02,0x02,0x00,0x02,0x00, // 2
- 0x02,0x02,0x02,0x02,0x00,0x00,0x02,0x00, // 3
- 0x00,0x02,0x02,0x00,0x00,0x02,0x02,0x00, // 4
- 0x02,0x00,0x02,0x02,0x00,0x02,0x02,0x00, // 5
- 0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x00, // 6
- 0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00, // 7
- 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, // 8
- 0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x00, // 9
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 10
- };
复制代码
先用第一个和第二数码管做例子,
- [size=3]void TM_Disp(uint8_t num1, uint8_t num2)
- {
- Write_Nixie_DATA(0x00, Seg1[num1*8] |Seg2[num2*8] );
- Write_Nixie_DATA(0x02,Seg1[num1*8+1]|Seg2[num2*8+1]);
- Write_Nixie_DATA(0x04,Seg1[num1*8+2]|Seg2[num2*8+2]);
- Write_Nixie_DATA(0x06, Seg1[num1*8+3]|Seg2[num2*8+3]);
- Write_Nixie_DATA(0x08, Seg1[num1*8+4]|Seg2[num2*8+4]);
- Write_Nixie_DATA(0x0a, Seg1[num1*8+5]|Seg2[num2*8+5]);
- Write_Nixie_DATA(0x0c, Seg1[num1*8+6]|Seg2[num2*8+6]);
- Write_Nixie_DATA(0x0e, Seg1[num1*8+7]|Seg2[num2*8+7]);
- }[/size]
复制代码 假如要第一个数码管显示1,第二数码管显示7,就只需要 TM_Disp(1,7);就可以了
要是第三个数码管呢?在这个函数的基础上再增加个数组,应该是0x04,对应的第三位。0x08对应的第4个数码管了。
- uint8_t Seg3[] = { // 第三位数码管显示码值
- 0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00, // 0
- 0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00, // 1
- 0x04,0x04,0x00,0x04,0x04,0x00,0x04,0x00, // 2
- 0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x00, // 3
- 0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00, // 4
- 0x04,0x00,0x04,0x04,0x00,0x04,0x04,0x00, // 5
- 0x04,0x00,0x04,0x04,0x04,0x04,0x04,0x00, // 6
- 0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00, // 7
- 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00, // 8
- 0x04,0x04,0x04,0x04,0x00,0x04,0x04,0x00, // 9
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 10
- };
复制代码
函数再增加一个参数
- void TM_Disp(uint8_t num1, [/size][size=3]uint8_t [/size][size=3]num2, [/size][size=3]uint8_t [/size][size=3]num3)
- {
- Write_Nixie_DATA(0x00, Seg1[num1*8] |Seg2[num2*8] |Seg3[num3*8] );
- Write_Nixie_DATA(0x02,Seg1[num1*8+1]|Seg2[num2*8+1]|Seg3[num3*8+1]);
- Write_Nixie_DATA(0x04,Seg1[num1*8+2]|Seg2[num2*8+2]|Seg3[num3*8+2]);
- Write_Nixie_DATA(0x06, Seg1[num1*8+3]|Seg2[num2*8+3]|Seg3[num3*8+3]);
- Write_Nixie_DATA(0x08, Seg1[num1*8+4]|Seg2[num2*8+4]|Seg3[num3*8+4]);
- Write_Nixie_DATA(0x0a, Seg1[num1*8+5]|Seg2[num2*8+5]|Seg3[num3*8+5]);
- Write_Nixie_DATA(0x0c, Seg1[num1*8+6]|Seg2[num2*8+6]|Seg3[num3*8+6]);
- Write_Nixie_DATA(0x0e,Seg1[num1*8+7]|Seg2[num2*8+7]|Seg3[num3*8+7]);
- }
复制代码
以此类推,9个数码管就可以写了 上个图,做结束吧,这个是共阳极的
此内容由EEWORLD论坛网友ywlzh原创,如需转载或用于商业用途需征得作者同意并注明出处
|
|