社区导航

 
快捷导航
  • 首页
  • 论坛
  • 查看新帖
  • 最新回复
  • 社区活动
  • 联系管理员
  • 消灭零回复
  • E金币兑换
  • 干货
搜索
查看: 3950|回复: 3
打印 上一主题 下一主题

[原创] MCU对TM1638的控制详谈(不包括按键)

[复制链接]

1227

TA的帖子

4

TA的资源

纯净的硅(高级)

Rank: 6Rank: 6

跳转到指定楼层
楼主
发表于 2017-2-22 17:48:43 | 只看该作者 |只看大图 |倒序浏览 |阅读模式
本帖最后由 ywlzh 于 2017-2-22 18:04 编辑


    从淘宝买来的,TM1638专门是控制LED的,LED组合起来就可以变成数码管,还有按键,这个我就没管了,不想管了,发这个帖子只是为了记录下经验,待以后会过头来看的时候,可以一遍就知道,所以尽量写得详细点。
   手头上的项目用的是共阳极,而我买的是共阴极的,还好,全都弄出来了。
   单片机怎么跟它通信,这个还得细看TM1638的数据手册,一个新的芯片到手,千万别第一时间上网找例程,先把这个片子的数据手册看一遍
    TM1638.pdf (873.68 KB, 下载次数: 139)
    先截个图出来看   
   
    可以看的出来,跟单片机通信就只需要DIO,STB, clk三根线,这三根线最好是做好上拉电阻,TM1638是不需要刷数据的,共阴极的是只需要在对应的地址上写data就OK了,它自己会去刷新数据。   先看共阴极的电路图,也就是淘宝买的这个模块的电路图
   

   段码是SEG1-SEG8,片选是GR1-GR8 ,片选的几个正好对应着地址   
   
   从上面的图就可以看出,写这些数据进去就可以了:自动地址增加,是否显示,调节亮度...写这些命令的时候是需要先让STB信号为高电平的,写命令,再拉低STB信号,写数据到对应地址的时候,也需要先把STB信号给拉高,写地址,写数据,再拉低STB信号。
   怎么写数据进去呢?就得看时序图了
   
   基本靠STB为低,CLK的上升沿,然后来确定DIO的高低,高为1,低为0。
   开始写程序吧,我用的stm32f407
   先确定引脚
   
  1. #define DIO   PAout(1)
  2. #define CLK   PAout(4)
  3. #define STB   PAout(6)
复制代码


再把引脚初始化,如果要读按键的话,就需要把DIO写成开漏模式,这样就既可以读也可以写了,
  1. void TM1638_GPIO_init(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;
  4.         
  5.         rcc_ahb1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //ê1ÄüGPIODμÄê±Öó
  6.         
  7.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_4;
  8.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//êä3ö
  9.         GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;  //íÆíìêä3ö
  10.         GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_nopULL;  //éÏà-êä3ö
  11.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //¸ßËùGPIO
  12.         GPIO_Init(GPIOA,&GPIO_InitStructure);
  13.         
  14.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;  //DIO ¿a©Ä£ê½
  15.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//êä3ö
  16.         GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;  //¿a©êä3ö
  17.         GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;  //éÏà-êä3ö
  18.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //¸ßËùGPIO
  19.         GPIO_Init(GPIOA,&GPIO_InitStructure);
  20.         
  21. }
复制代码


引脚做好初始化后,就需要开始写怎么写一个字节了。
  1. void TM1638_Write(unsigned char        DATA)                        //D′êy¾Yoˉêy
  2. {
  3.         unsigned char i;
  4.         for(i=0;i<8;i++)
  5.         {
  6.                 CLK=0;
  7.                 if(DATA&0X01)
  8.                         DIO=1;
  9.                 else
  10.                         DIO=0;
  11.                 DATA>>=1;
  12.                 CLK=1;
  13.         }
  14. }
复制代码

读一个字节,我就没管了,继续下去,要向对应的地址上写入一个字节,封装一些上面的函数就可以了
  1. void Write_Nixie_DATA(unsigned char add,unsigned char DATA)                //Ö¸¶¨μØÖ·D′èëêy¾Y
  2. {
  3.         Write_COM(0x44);
  4.         STB=0;
  5.         TM1638_Write(0xc0|add);
  6.         TM1638_Write(0xff&DATA); //这样不影响其他位,考虑共阳极的接法。
  7.         STB=1;
  8. }
复制代码

还可以封装成写命令的函数
  1. void Write_COM(unsigned char cmd)                //·¢ËíÃüáî×Ö
  2. {
  3.         STB=0;
  4.         TM1638_Write(cmd);
  5.         STB=1;
  6. }
复制代码

这样基本就可以了,举个例子,我要让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变成了段码输送。原本设计成段码的变成了片选。这里就得转换一下思路了,还是在对应的地址上写数据,怎么写,而且一个数码管有变动,整个地址的数据就得重新写一遍。这一点比较麻烦,花点时间想想也是可以想出来的。先看程序
  1. uint8_t Seg1[] = {                                                                        // 第一位数码管显示码值
  2.         0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,                // 0
  3.         0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,                  // 1
  4.         0x01,0x01,0x00,0x01,0x01,0x00,0x01,0x00,                // 2
  5.         0x01,0x01,0x01,0x01,0x00,0x00,0x01,0x00,                // 3
  6.         0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x00,                // 4
  7.         0x01,0x00,0x01,0x01,0x00,0x01,0x01,0x00,                // 5
  8.         0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x00,                // 6
  9.         0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,                // 7
  10.         0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,                // 8
  11.         0x01,0x01,0x01,0x01,0x00,0x01,0x01,0x00,                // 9
  12.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 10
  13. };
  14. uint8_t Seg2[] = {                                                                        // 第二位数码管显示码值
  15.         0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,                // 0
  16.         0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,                  // 1
  17.         0x02,0x02,0x00,0x02,0x02,0x00,0x02,0x00,                // 2
  18.         0x02,0x02,0x02,0x02,0x00,0x00,0x02,0x00,                // 3
  19.         0x00,0x02,0x02,0x00,0x00,0x02,0x02,0x00,                // 4
  20.         0x02,0x00,0x02,0x02,0x00,0x02,0x02,0x00,                // 5
  21.         0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x00,                // 6
  22.         0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,                // 7
  23.         0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,                // 8
  24.         0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x00,                // 9
  25.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 10
  26. };        
复制代码


先用第一个和第二数码管做例子,
  1. [size=3]void TM_Disp(uint8_t num1, uint8_t num2)
  2. {
  3.         Write_Nixie_DATA(0x00, Seg1[num1*8]  |Seg2[num2*8] );
  4.         Write_Nixie_DATA(0x02,Seg1[num1*8+1]|Seg2[num2*8+1]);
  5.         Write_Nixie_DATA(0x04,Seg1[num1*8+2]|Seg2[num2*8+2]);
  6.         Write_Nixie_DATA(0x06, Seg1[num1*8+3]|Seg2[num2*8+3]);
  7.         Write_Nixie_DATA(0x08, Seg1[num1*8+4]|Seg2[num2*8+4]);
  8.         Write_Nixie_DATA(0x0a, Seg1[num1*8+5]|Seg2[num2*8+5]);
  9.         Write_Nixie_DATA(0x0c, Seg1[num1*8+6]|Seg2[num2*8+6]);
  10.         Write_Nixie_DATA(0x0e, Seg1[num1*8+7]|Seg2[num2*8+7]);
  11. }[/size]
复制代码
假如要第一个数码管显示1,第二数码管显示7,就只需要 TM_Disp(1,7);就可以了
要是第三个数码管呢?在这个函数的基础上再增加个数组,应该是0x04,对应的第三位。0x08对应的第4个数码管了。
  1. uint8_t Seg3[] = {                                                                        // 第三位数码管显示码值
  2.         0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,                // 0
  3.         0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,                  // 1
  4.         0x04,0x04,0x00,0x04,0x04,0x00,0x04,0x00,                // 2
  5.         0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x00,                // 3
  6.         0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,                // 4
  7.         0x04,0x00,0x04,0x04,0x00,0x04,0x04,0x00,                // 5
  8.         0x04,0x00,0x04,0x04,0x04,0x04,0x04,0x00,                // 6
  9.         0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,                // 7
  10.         0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,                // 8
  11.         0x04,0x04,0x04,0x04,0x00,0x04,0x04,0x00,                // 9
  12.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 10
  13. };
复制代码

函数再增加一个参数
  1. void TM_Disp(uint8_t num1, [/size][size=3]uint8_t [/size][size=3]num2, [/size][size=3]uint8_t [/size][size=3]num3)
  2. {
  3.         Write_Nixie_DATA(0x00, Seg1[num1*8]  |Seg2[num2*8]  |Seg3[num3*8]  );
  4.         Write_Nixie_DATA(0x02,Seg1[num1*8+1]|Seg2[num2*8+1]|Seg3[num3*8+1]);
  5.         Write_Nixie_DATA(0x04,Seg1[num1*8+2]|Seg2[num2*8+2]|Seg3[num3*8+2]);
  6.         Write_Nixie_DATA(0x06, Seg1[num1*8+3]|Seg2[num2*8+3]|Seg3[num3*8+3]);
  7.         Write_Nixie_DATA(0x08, Seg1[num1*8+4]|Seg2[num2*8+4]|Seg3[num3*8+4]);
  8.         Write_Nixie_DATA(0x0a, Seg1[num1*8+5]|Seg2[num2*8+5]|Seg3[num3*8+5]);
  9.         Write_Nixie_DATA(0x0c, Seg1[num1*8+6]|Seg2[num2*8+6]|Seg3[num3*8+6]);
  10.         Write_Nixie_DATA(0x0e,Seg1[num1*8+7]|Seg2[num2*8+7]|Seg3[num3*8+7]);
  11. }
复制代码



以此类推,9个数码管就可以写了 上个图,做结束吧,这个是共阳极的




此内容由EEWORLD论坛网友ywlzh原创,如需转载或用于商业用途需征得作者同意并注明出处








此帖出自单片机论坛
收藏收藏1 收藏干货 分享分享
天地庄周马;江湖范蠡船。
个性签名还是放QQ号吧,2060347305,添加说明EEworld好友


回复

使用道具 举报

5

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

沙发
发表于 2017-7-14 15:48:58 | 只看该作者
本帖最后由 江枫三号楼 于 2017-7-14 15:55 编辑

围观,刚刚刚接触数据手册的时候,看得是一头雾水,然后来看这篇文章,感觉有那么一点意思了。 不过信号拉低或者拉高,没有最小hold时间吗?


回复

使用道具 举报

2

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

板凳
发表于 2017-7-25 10:10:49 | 只看该作者
看帖顶贴,谢楼主


回复

使用道具 举报

5

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

4
发表于 2017-11-16 10:34:31 | 只看该作者
江枫三号楼 发表于 2017-7-14 15:48
围观,刚刚刚接触数据手册的时候,看得是一头雾水,然后来看这篇文章,感觉有那么一点意思了。 不过信号拉 ...

这是我写的吗?怎么一点印象都没有了呢?


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

小黑屋|手机版|Archiver|电子工程世界 ( 京ICP证 060456

GMT+8, 2017-11-24 15:36 , Processed in 12.955952 second(s), 18 queries , Redis On.

快速回复 返回顶部 返回列表