摘要 之前在网上看了一些光立方的演示视频,被它那些立体感吸引了。想到自己学单片机也这么久了,于是乎就想做一个玩玩,同时可以复习一学期以来自己的编程能力和动手的能力,一举两得是一件很不错的事情。向朋友要了一些资料,就开工了。 光立方顾名思义就是一个立方体,采用的是8*8*8的模式,整个立方大概是16cm*16cm*18cm(长.宽.高)的样子,主要分为三个模块:主控模块、驱动模块、显示模块;我所做的光立方,主控电路采用的主控芯片是STC12C5A60S2芯片,驱动电路是采用我们常用的74HC573数字芯片,以及ULN2803达林顿管。
电路原理图:
图1.电路原理图 元件的选择: (1)由于光立方的程序量比较大,而且要求相对比较高,因此经过考虑之后我们决定用51系列的增强型芯片STC12C5A60S2,选择的理由: 1.无法解密,采用第六代加密技术; 2.超强抗干扰; 3.内部集成高可靠复位电路,外部复位可用可不用; 4.速度快,比8051快8-12倍; (2)由于灯的个数比较多,因此所需要的电流相对也比较大,所以选择ULN2803,ULN2803是八重达林顿,1 至 8脚为8路输入,18 到 11脚为8路输出。驱动能力 500MA \50V。应用时9脚接地,要是驱动感性负载,10脚接负载电源V+。输入的电平信号为0,或5V。输入0是,输出达林顿管截止。输入为5V电平时,输出达林顿饱和。输出负载加在电源V+和输出口上,当输入为高电平时,输出负载工作; (3)由于在刚刚接触锁存器的时候,就接触了74HC573,对它的使用也比较成熟,因此在驱动部分使用了熟悉的74HC573,其优点有: 1.高阻态;就是输出既不是高电平,也不是低电平,而是高阻抗的状态;在这种状态下,可以多个芯片并联输出; 2.数据锁存;当输入的数据消失时,在芯片的输出端,数据仍然保持; 3.数据缓冲; 加强驱动能力; (4)LED灯的选择,出于外观和整体的形状美观,个人推荐雾面蓝光方型LED。但是由于当时去电子市场没有找到,最后用了雾面蓝光草帽型的LED灯(结果问题也是出了一大堆)。
电路的组装与焊接: 图2.电路PCB图 这是布线完成的PCB板子,由于之前选错灯的原因,我后面又在每个573的输出口加了1N4148二极管。原因是因为这种小灯的反向漏电流比较大,导致整个立方在不接负极的时候也会发光。加二极管之后,它们每个角输出就都互不影响了。同时,每片573的数据口是分别并联到P1口的,板子上没有布线,在这里我是用单股导线一条一条连上去的。 下面是板子的制作过程: 图3. 腐蚀好的PCB板子 这块板子跟上面的PCB图有点出入,图2是我调试完成之后在修改的,而图3是之前的版本做好的。 另外,没有制作PCB板条件的朋友也可以自己用万能板焊,就是麻烦一点。 图4.准备焊接材料 图5.已焊好的PCB板底层 接下来我们要焊灯了。大工程啊! 首先,我们把灯准备好,烙铁热上 图6.准备好的LED灯 图7.准备好的LED灯 在焊接之前,我觉得最好是检测一下每一个灯是否会亮,不过也可以一排一排的测试,总之,一定要保证每个灯都会正常发光。 接下来,我们要对灯做一些工作: 图8 我们把所有的LED灯的负极,也就是短的一角统一朝一个方向弯曲并与正极垂直如上图所示。 图9 我们可以借助一块大一点的万能板,用记号笔在每一个点做好标记,然后把弄好的灯正极朝下穿过万能板,再把这一排的灯的负极摆直了点上焊锡。如上图所示。 图10.焊接好的一排灯 图11焊接好的一排灯 照这种方法把所有的灯焊成一排一排的。 接下来要仔细看了 图12.焊接每一层 把焊接好的每一排凸出来的那个负极呢又统一朝着一个方向弯曲至90°,然后把每一排都按上图的方式摆好,焊接。结果如下图: 图13 这时候有朋友会问了,这样是不是不稳啊,那你就把另外一端也用同样的方法用粗一点的导线或者废弃的元器件管脚连起来就好了。如下图: 图14 如此,把每一层都焊好。如下图: 图15.焊接好的每一层 接下来呢又要对每一层的正极做一下动作了。如下图: 图16 将每一层的正极的末端2mm左右向内弯曲45°左右如上图。留下最后一层不要动,作为最底层。然后用尽你所有的招式把每一层对应的正极连起来。呵呵,也没有什么好的方法推荐。下面是焊好的光立方: 图17.18.焊接好的光立方 图19 图20
电路的调试和调试出现的问题: 完工以后抱着很激动的心情,编写了调试的程序,主要是检查全部的灯是否会亮,但是单把程序烧写进去之后,发现有两列没有点亮,还好两列的都在边上,进而如果换灯也相对容易,我们用排除法来检查电路,首先是检查灯的线路是否虚焊,断路,果真有一列的是断路了,把它接上后这一列也亮了,还剩下另外一列,我们用同样的方法来做,从驱动电路到显示的都没有问题,而且在输入那一列的电压也正常,我们就想不通了,是什么原因呢?我们怀疑是不是有灯坏了,我们又一个一个的检查了这一列灯,但是全部都会亮,经过很细心的检查,发现有一个灯的亮度和其他的灯亮度完全不同,相对比较暗,于是我们把它换了下来,接上另外一个,果然是哪个灯的问题,原来是由于灯的阻抗很大,把那一列的电平都拉低了,使灯无法亮起来 ,在电路的调试中就出现了这些的问题,相对来说还是不错的。另外由于之前没有选好灯,经过不断分析问题,最后在74HC573的每一个输出端都接一个二极管,问题才得以解决。 程序: 到这里我们的硬件就已经大功告成了,接下来呢就是软件了。由于源程序代码有2000多行,这里我就不将源程序代码做到文档里,而是打包在同一文件夹下,大家可以用keil查看整个工程。本项目完成速度比较快,在整体的电路上可以完成一下基本的演示,由于电路的限制,花样不是很多,还有待提高。 本文档足够让你独立完成一个光立方的制作,一点也不难,只是需要毅力和耐心而已。 最后你可以发挥想象,编辑你想要的花样把程序写进drive.c,并且在drive.h里面声明一下,最后就可以直接在主函数里面调用了。如果对C语言不是很了解的朋友可以请教一下别人,不懂就问,没什么不好意思的。这也是我的学习风格。最后希望我们一起学习、一起进步。 郑重声明:此文档仅供学习参考,如有雷同,纯属巧合。 视频连接:http://v.youku.com/v_show/id_XNTg2NDcxMTQ0.html
单片机源程序如下:
- #include "STC.h" //STC12C5A60S2头文件
- #include "MyType.h" //常用数据类型定义
- #include "Drive.h" //LED驱动头文件
- #include "Delay.h" //延时函数头文件
- #include "picture.h" //字模数据
- //int flag=0,flag1=0,a=0;
- void LEDIO_Init();
- //void PWM_init ();
- //void PWM0_set (uint8 set);
- //void Timer_INT();
- void main()
- {
- uint8 i;
- LEDIO_Init();
- //PWM_init();
- //Timer_INT();
-
- /* while(flag == 0)
- {
- WAIT_LOG();
- } */
-
- while(1)
- {
- for(i=0;i<3;i++)
- DOT_PWM(0,7,0,120);
- for(i=0;i<2;i++)
- {
- CUBE_LOG1();
- CUBE_LOG2();
- CUBE_LOG3();
-
- if(i==0)
- {
- LOG11();
- LOG5();
- }
- if(i==1)//scanf face
- {
- LOG6();
- LOG7();
- CUBE_LOG4();
- LOG8();
- LOG9();
- CUBE_LOG5();
- shalou1();
- catercorner();//边角的三角形
- LOG5();
- }
- LOG1(); //small cube
-
-
- if(i==0)
- {
- CUBE_LOG6(NUM2,3);// 3 2 1
- CUBE_LOG13();//一二三四五六九一一
- CUBE_LOG7(CHAR_CUBE8,88);//cube8 TeanFoo
- CUBE_LOG7(CHAR_GLF,24);//光立方 3x8=24
- }
- if(i==1)
- {
- CUBE_LOG6(NUM1,3);//i love u
- CUBE_LOG7(CHAR_DZXH,32);//电子协会 4x8=32
- }
- if(i==0)
- shalou();
- if(i==1)
- LOG12();
- LOG10();
- CUBE_LOG8();//螺旋上升
- LOG3(); //前后面
- CUBE_LOG9();//雨过天晴
- CUBE_LOG10();//音乐律动
- CUBE_LOG11();//竖直表面顺时针环绕
- CUBE_LOG12();//横向表面逆时针环绕
-
- if(i==0)
- {
- LOG4();
- LIST_LOG(); //
- LOG13();
- lightbug();
- }
-
- if(i==1)
- {
- CUBE_LOG7(CHAR_SNTU,136);//通信与电子学院 电子协会20周年 330
- LOG2(4,4);
- FIRE(1,2);
- FIRE(3,3);
- LOG2(3,4);
- FIRE(6,3);
- FIRE(2,5);
- LOG2(4,3);
- FIRE(3,5);
-
- CUBE_LOG7(CHAR_OFF,18);//OFF
- LAST_LOG();
- }
- }
- }
- }
- void LEDIO_Init()
- {
- P0M0 = 0xff;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x01;
- P2M0 = 0xff;
- P2M1 = 0x00;
- P3M0 = 0xff;
- P3M1 = 0x00;
-
- X = 0xff;//锁存
- Y = 0x00;//数据
- X = 0x00;
- Z = 0x00;//平面
- }
- /*
- void PWM_init () //PWM初始化函数,PWM模式,接P1.3接口(PWM0),强上拉.
- {
- CMOD=0x00; //设置PCA定时器0x00~0x03;
- CL=0xef;
- CH=0xef;
- CCAPM0=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)
- CCAP0L=0xef; //设置PWM0初始值与CCAP0H相同
- CCAP0H=0xff; // PWM0初始时为0
-
- CR=1; //启动PCA定时器
- }
- void PWM0_set (uint8 set) //PWM0占空比设置函数 (0x00~0xFF)
- {
- CCAP0L= set; //设置值写入CCAP0L
- CCAP0H= set; //设置值写入CCAP0H
- }
- void Timer_INT()
- {
- TMOD = 0x11; //高4位控制T/C1
- EA = 1; //开总中断
- TH1 = 0x00; //16位计数寄存器T1高8位
- TL1 = 0x00; //16位计数寄存器T1低8位
- ET1 = 1; //T/C1中断开
- //TR1 = 1; //T/C1启动
- TR1 = 0; //T/C1关闭
- }
- void LED_PWM() interrupt 3
- {
- // static uint16 x=0;
- // static uint8 flag1=1;
- TL1 = 0x55; //重装定时计数器
- TH1 = 0xe0;
- if((P1&0x02) == 0)
- {
- Delayms(10);
- if((P1&0x02) == 0)
- {
- flag1 = 1; //按下标志
- }
- }
- if(((P1&0x04) == 0) && flag1) //触摸按键被触摸
- {
- a++; //触摸按键消抖
- if((a==20) && ((P1&0x04) == 0) && flag1) //触摸按键的确被触摸
- {
- flag++; //菜单切换
- if(flag == 4) flag = 0;
- flag1 = 0;
- a=0;
- }
- }
- else if((P1&0x04) !=0)
- a=0;
- if(flag1)
- {
- if(++x==0xff)
- flag1=0;
- }
- else
- {
- if(--x==0x00)
- flag1=1;
- }
- PWM0_set(x);
- }
- */
复制代码
所有资料51hei提供下载:
光立方设计与制作.zip
(10.07 MB, 下载次数: 315)
|