找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5963|回复: 3
打印 上一主题 下一主题
收起左侧

制作SHOOK16摇摇棒

[复制链接]
跳转到指定楼层
楼主
    黑夜里打开摇摇棒,在空中快速的左右摇晃,神奇的事情就会出现。如果是干木材上的一点碳火,那么摇晃出来的只会是一条弧线。摇摇棒却可以让棒身上的LED灯在划过空中的适当位置显示文字和图形,这一奇迹就是单片机的杰作。单片机爱好者都会在《无线电》杂志或者网上找到关于摇摇棒制作的文章,相信许多热血沸腾的朋友已经着手制作了,最先要解决的问题是买到水银开关,它并不怎么常见,虽然价格只有1元钱。接下来是要买一块长条形洞洞板,把8个或16LED灯并排焊在上面,然后连接LED灯与单片机之间的导线。如果你觉得这样的制作太麻烦,何不试试精简设计的摇摇棒,让制作更简单,让外观更简洁。单片机、LED、电池、导线、塑料管,这5件东西可以制作什么?下面你将了解到如何用这5件材料制作可显示汉字的摇摇棒。我为这款设计取名SHOOK16摇摇棒。

制作SHOOK16摇摇棒

SHOOK16摇摇棒制作起来非常简单,而且它使用的是16LED灯来显示,可以轻松显示中文、英文和图型。程序设计上考虑了将来的字幕更换,可直接用取模软件生成你需要的字幕内容。整个制作无需PCB板,焊接容易、结构紧凑。只要把贴片LED直接焊接在单片机的引脚上就可以了。而且一般的摇摇棒多采用微动开关来切换字幕,SHOOK16摇摇棒却另有创新,它采用纵向摇动或敲击棒身来切换字幕,字幕的数量完全取决于单片机FLASH大小,SHOOK16采用的单片机是STC12C5A60S2,内部具有60K字节的FLASH空间,而程序本身才使用了2K字节,余下的58K字节可以任你发挥。  






制作SHOOK16摇摇棒
1
准备制作材料。制作SHOOK16摇摇棒所需要的材料少的可怜,通常的制作都不把电池和导线算到材料里面,而在这里算上它们也不过5种。电池、单片机、贴片LED都可以在电子市场或者网上买到,包装单片机用的塑料管可以在卖芯片的柜台找到,店家都是把它当垃圾处理的,而我们却要把它变废为宝。导线和废弃的元器件引脚不用准备,相信每一个爱好者的桌面上都有一大堆。当然了,因为制作中使用了单片机,所以你还需要准备电脑和为STC单片机烧写程序的ISP下载工具。有了这些就可以完成制作,是不是有些不可思议呢?原来电子制作可以这么简单!




                                                          制作SHOO K16摇摇棒所需要的材料

好的制作其实并不需要过多的文字说明,那就发挥我的强项,用图解的方式介绍SHOOK16摇摇棒的制作方法。首先来看一下制作SHOOK16摇摇棒所需要的材料清单。



                                                     SHOOK16摇摇棒电路原理图
SHOOK16摇摇棒的电路原理图也很简单,主要有单片机、LED、惯性开关和电池。电路图中标号相同的引脚是连接在一起的,这是网络标号的表示方法,省去了密密麻麻的连接线。其实在以下的制作过程中并不需要回头来参考原理图,因为电路制作是如此简单,以至于只看实物图片就可以完成制作。下面我们就按顺序对制作的关键节点做图文介绍。
2
    把单片机第21脚到第40脚一侧的引脚全部用钳子向外侧弯曲,目的是为了增加单片机的宽度。为什么要这样做呢?我在设计的时候是使用了电子市场中常见的包装单片机的塑料管,店家多把空出来的塑料管丢掉。我觉得它们结实而且透明,应该可以制作些什么,于是就向店家要了一些。在设计摇摇棒的时候突然想到塑料管的妙用,如果用塑料管来做摇摇棒的身体应该是很理想的。可是当我把单片机放进去的时候却发现单片机会左右、上下晃荡,这样制作出来的摇摇棒会在摇动时叮噹乱响,不知道的还以为是拨浪鼓呢。我也想过用胶带固定或是用纸填充空隙,可是会让制作变得困难,而且也不美观。所以不是缩小塑料管的宽度就是增加单片机的宽度,于是弯曲一侧引脚就可以最快速地解决问题。那为什么只弯曲第21脚到第40脚一侧的引脚呢?这里面还是有门道的,下文告诉你。




                                    用钳子弯曲单片机第21脚到第40脚一侧的引脚






                                   弯曲角度以单片机放入塑料管后不易左右移动为止
3
    制作LED显示电路。把贴片LED直接焊接在刚刚被弯曲过的单片机引脚上。从单片机的21脚(P2.0)开始焊起,贴片LED的负极连接到21脚一侧,后续的LED负极也都朝向这一侧。16LED分别焊接在单片机的21脚到37脚之间。焊接LED的时间不要过长,烙铁尖不到碰到贴片LED的塑料面上,LED的排列的整齐,显示效果才会更好。










               将LED直接焊接在单片机的引脚上,LED负极都朝向单片机的21脚一侧




                                                              0805型贴片LED

有朋友可能很少接触这种0805型贴片LED,它的体积比大米粒还要小,亮度却不比直插式的LED差。这种贴片LED在各大电子市场都有销售,包装它们的是一个大圆盘里面的黑色塑料条,好像电影胶片一样,许多贴片元器件都是这么包装的。






                                                        贴片式LED灯的极性说明

贴片LED和直插LED在使用上并没有太大区别,只需要学会识别贴片LED的极性,还有就是在焊接时控制好烙铁的温度和焊接时间。贴片LED的两侧有两个电极,其中标有绿色小点的一侧为LED的负极。焊接时先将两个焊盘中的其中一个上锡,用烙铁熔化焊盘上的锡,同时用摄子轻轻地夹起贴片LED放到对应位置,撤走烙铁等锡凝固后再用常规方法焊接另一边的焊盘。初次焊接的朋友可以在洞洞板上练习,熟悉动作之后再正式焊接。 这种直接焊接的灵感来自于我之前设计的mini1608电子时钟,当我把LED点阵屏直接焊接在单片机的引脚上时,我就开始对直接焊接的制作着了迷。后来的一段时间里,我总会用身边可以找到元器件往单片机的引脚上安,其中的某一天就想到了贴片LED。但是当时并没有想到用这个方法来制作什么东西,于是存入了大脑深处,直到在写摇摇棒设计方案的时候才又把陈年的创意翻了出来。贴片LED的体积小巧,包装单片机的塑料管又是透明的,正好可以透出LED的光.如此焊接在硬件结构上确实不错,可是在电路原理和单片机编程上面是否行得通呢?嗯,这里的关键问题就是连续16个贴片LED所连接的引脚都必须是I/O接口,并且I/O接口在输出高、低电平时都可以直接驱动LED发光。也就是说,单片机I/O接口输出高电平时至少需要有20mA电流的推动能力。唯一可以做到这一点的也只有I/O接口的推挽工作方式了。恰好STC公司的101112系列的单片机都有这一配置,所以我选择了手边常用的STC12C5A60S2来实现。
    电路原理没了问题,那么如何编写LED的驱动程序呢?不仅让LED可以任意点亮,还要能控制它们在摇动过程中显示汉字和图形。老实讲,我在设计SHOOK16摇摇棒之前并没有了解过其他摇摇棒的原理和编程方法,所以编写传统设计的摇摇棒尚无把握,更何况这种从来没有试过的驱动方式了!攻下这一难关确实耗费了不少精力,值得庆幸的是N次调试之后我成功了,并滤除那些挫折与失败,仅把成功经验与你分享。
    传统的摇摇棒设计是采用传统的单片机灌电流方式点亮LED的。现在闭上眼睛,想象一下摇摇棒摇动时的1/4慢镜头,在摇摇棒处在最左边的时候,16LED灯会显示字幕数据表里最左边的一列,停留一段时间之后所有LED熄灭,等待摇摇棒的身体摇动到字幕数据中下一列的位置,然后显示、停留、熄灭。如此方法一直显示到字幕的最右边。好了,现在取消慢镜头,变成正常速度,我们的眼睛便可以看到那星星点点的亮光在浩瀚无际的夜空中形成飘浮的文字,这种显示方法应该叫做逐列显示。



                                 
逐点扫描形成列数据,然后再逐列扫描形成字幕




                                  某一I/O 接口为低电平时负极与之连接的LED点亮


SHOOK16摇摇棒在1/4慢镜头的时候看起来是逐列显示的,可是在1/16慢镜头的时候却又有不同。SHOOK16摇摇棒中单片机与LED的连接方式注定让16LED不能同时点亮,它们必须逐一点亮。同一时间内只能有1个引脚为低电平,其余引脚都必须为高电平。在摇摇棒的身体摇动到某一位置时,这一列的字幕数据表会被送入显示程序,显示程序要怎么做呢?有点麻烦,它要从上到下依次检查这一列数据中需要点亮的LED。首先检查最上边第1LED,这一列的数据中不需要它亮,那所有I/O接口输出高电平,停留一段时间再检查第2LED。嗯,第2LED需要亮,于是连接第2LED负极的引脚输出低电平,其他I/O接口输出高电平。这时第2LED正极是高电平,负极是低电平,LED点亮。因为LED
反向不导通,所以第3LED不亮,其他的LED两极都是高电平也不亮。点亮一段时间后再依此方法检查其他LED。在1/16慢镜头时,16LED就好像单片机实验板上的流水灯程序一样逐一点亮又逐一熄灭。在1/4 慢镜头的时候逐点扫描只是一瞬间的事,所以看起来它们是同时点亮的,因为它们处在不同的速度等级上。  
    编写驱动硬件的工作就只是循环将17I/O接口中的某一个变成低电平而已了。解决了贴片LED驱动的问题却又产生了新问题,我们如何让单片机知道在摇动时哪一时刻摇摇棒的身体处在最左边呢?
4
制作三向惯性开关。将一支废弃元器件引脚对折并焊接在弹性导线的一端上,弹性导线的另一端焊接在单片机的第20脚(GND)内侧,注意掌握导线长度。将第4脚(P1.3)引脚向内弯曲至芯片底部,形成惯性开关的一个触点。再用废弃元器件引脚向上延长第5脚(P1.2),使之形成与第4脚(P1.3)平行且相对的另一个触点。把第6脚(P1.4)稍微向内弯曲一点,使它可以在导线向这一侧撞击时首先接触到第6脚,这样就形成了3个触点。3个触点分别对应SHOOK16摇摇棒的三个方向,所以叫三向惯性开关。弹性导线指的是在轻微的外力作用后能够恢复原状的普通导线,也可以用细铁丝代替。调整弹性导线使之在静止状态时处于上、下两个触点的中间。导线悬空的一端应该有一定重量,增加惯性的作用力。



                                      弹性导线的另一端焊接在单片机的第20脚内侧



                           调整弹性导线使之在静止状态时处于上、下两个触点的中间





                                 三向惯性开关分别对应SHOOK16摇摇棒的3个方向
为什么要制作惯性开关呢?其实惯性开关的出现就是为了解决我们前面出现的问题——让单片机知道摇摇棒身体所处的位置。在判断棒身位置的设计中,除了为摇摇棒安装全球卫星定位系统(GPS)之外,还可以使用惯性开关。关于惯性还有这样一个笑话,话说一公共汽车里站着一个美女和一个丑男,司机突然刹车,丑男措手不及向前一拥撞到了美女,美女白了丑男一眼说:哼,德性!。丑男不好意思的笑了笑说:嘿嘿,不是德性,是惯性。SHOOK16摇摇棒上有三个美女和一个丑男,虽然这个比喻会让大家感觉妒忌,但事实就是如此。由焊接在单片机第20脚的弹性导线充当着丑男的角色,经过弯曲的第345脚分别充当着美女的角色。当向右摇晃的时候,由于惯性的作用,丑男(惯性开关柄)就会撞到左边的美女(惯性开关2),向左摇晃的时候就会撞到右边的美女(惯性开关1),向前摇晃的时候就会撞到后边的美女(字幕切换开关)。他们相撞的时候就是速度刚刚开始改变的时候,他们分开的时候也就是速度趋于稳定的时候。更多关于惯性的原理解释可以致电你的中学物理老师。单片机正是利用了这个原理来判断棒身所处的位置的,其中惯性开关1”惯性开关2”两个触点是用来判断棒身左右位置的,那字幕切换开关让摇摇棒多了一样功能——前后摇晃或敲击时切换字幕。所以这种用弹性导线制作的惯性开关不但不需要使用水银开关,而且还独具特色。
5
制作电源电路。取一段导线将一端焊接在单片机的第20脚(GND)上。导线另一端的接头处挂上大量的锡,作为电池负极的接触点。用胶带固定导线,使之在摇动时不易乱窜。再把一支废弃的元器件引脚焊接在单片机的第40脚(VCC)上,使引脚与单片机上方的导线平行且相对,它们之间的空隙就用来安放电池。将单片机连同电池一并塞进塑料管中,可用透明胶带缠绕单片机一圈并在塑料管开口处留出胶带头以方便拉出电池和单片机,摇摇棒不用时可拉出电池(或把纸片塞在两块电池中间)。最后用透明胶带把开口处包好。因摇动时的离心力向上,加之电池塞入塑料管时本来就已经很紧了,所以单片机及电池不会向下滑落,不需要设计单片机下方固定。



                                        取一段导线将一端焊接在单片机的第20脚上



                                  把一支废弃的元器件引脚焊接在单片机的第40脚上




                                             将钮扣电池重叠后放入正、负极接口处



                                              将单片机连同电池一并塞进塑料管中





选择适合的电池是决定整个设计成败的又一关键。最初的我采用的是35号碱性电池,因为我总觉得碱性电池的能量是很大的,可以让SHOOK16摇摇棒使用的更长久一些。于是我在单片机的正、负极上引出两条导线,通过中空塑料管延长到手柄握着的一端,然后把大大的电池盒用胶带绑在塑料管上。这样一来既不美观也不好操作,和前面的巧妙设计形成了很大的反差。必须重新设计电池方案,那怕做出一些牺牲。正巧手边有前不久为录制LED点阵屏测试方法视频节目时而购买的钮扣电池,型号是CR2032。我拿出电池往塑料管里塞了塞,虽然有点紧,可以还是可以牢固的塞进去。我大喜!这不正是我想要的样子吗?马上用短一点的导线把两节钮扣电池夹在中间,一并塞进塑料管里。哈哈,那电池、那塑料管、那单片机,就好像老天爷为它们保了媒一样,那么的般配、适合。不过两节CR2032串联的电压是6V,单片机的工作电压是4.5~5.5V,这样连接会不会损坏单片机呢?其实并不会,首先电路中存在一定压降,加之钮扣电池可提供的电流并不大,二者相配有惊无险。而且因为单片机第21脚到第40脚向外弯曲,使得另外一侧的引脚紧贴塑料管内壁,让引脚内侧空出一大块空间,正好是给惯性开关预留的位置。这也正是我要弯曲单片机第21脚到第40脚一侧引脚的原因。



                                               SHOOK16摇摇棒在夜间的显示效果

现在,SHOOK16摇摇棒制作完成。在宁静的夜晚,招集家里的亲朋好友坐在沙发上,关灯,然后把摇摇棒上LED的一面对着他们匀速摇晃,那空中飘浮的文字一定会让在场的观众惊叹不已。敲击棒身,的一声,字幕改变了内容,再敲击——“”——又变了。表演结束后,打开灯,其中某位观众站起身来气愤的说:你要换字幕就换嘛,为什么用棒子打我的头?!没错,SHOOK16摇摇棒可以为你的生活带来更多精彩和乐趣。

除文章中的提示外,你还需要注意以下几个问题:
1.  在开始制作之前,先要将SHOOK16摇摇棒的HEX文件烧写到单片机里。
3.  用STC-ISP软件烧写HEX文件时需要有步骤4”中选择内部RC振荡器
4.  本制作采用STC12C5A60S2单片机,不可使用其他系列的单片机替代。
5.  如果遇到制作上的问题可以在网上向我提问,我会尽量帮助你解决。

  1. /*********************************************************************************************
  2. 程序名:    SHOOK16摇摇棒控制程序
  3. 编写人:    杜洋 
  4. 编写时间:  11月12日
  5. 硬件支持:  STC12C5A60S2 内部RC时钟
  6. 接口说明:  单片机P0、P2侧并行排列16个贴片LED(自P2.0开始(-))  
  7. 修改日志:
  8. [TEST测试版]  
  9.   1-200911122244 在主函数写入简单程序测试惯性开关是否正常,通过测试并备份。(备)
  10.         2-200911130112 往返摇动双重显示实验成功,目前已经达到摇摇棒功能的基本要求。(备)
  11. [V1正式版]
  12.         3-200911130309 加入了3个字幕内容,通过敲击切换字幕。(备)
  13.         4-200911131910 为网站照片重新设计方案并重定义了IO接口。(备)                                                               
  14. /*********************************************************************************************
  15. 说明:

  16. 了解字幕的修改方法,请参考《mini1608字模设计方法》

  17. V1正式版

  18. # 硬件制作只需要单片机、LED、电池和导线,制作非常简单。
  19. # 采用STC增强型单片机。



  20. /*********************************************************************************************/


  21. #include <STC12C5A60S2.H> //单片机头文件

  22. unsigned char MENU;
  23. #define DY_DELAY                5 //设置每一个点显示的时间长度(1~20)

  24. sbit KEY1 = P1 ^ 2; //摇动惯性开关
  25. sbit KEY2 = P1 ^ 3;
  26. sbit KEY3 = P1 ^ 4; //选择键(大力横向碰击触发)

  27. sbit LED1 = P0 ^ 3; //LED灯定义,低电平时亮(自上到下)
  28. sbit LED2 = P0 ^ 4;
  29. sbit LED3 = P0 ^ 5;
  30. sbit LED4 = P0 ^ 6;
  31. sbit LED5 = P0 ^ 7;
  32. sbit LED6 = P4 ^ 6;
  33. sbit LED7 = P4 ^ 5;
  34. sbit LED8 = P4 ^ 4;
  35. sbit LED9 = P2 ^ 7;
  36. sbit LED10 = P2 ^ 6;
  37. sbit LED11 = P2 ^ 5;
  38. sbit LED12 = P2 ^ 4;
  39. sbit LED13 = P2 ^ 3;
  40. sbit LED14 = P2 ^ 2;
  41. sbit LED15 = P2 ^ 1;
  42. sbit LED16 = P2 ^ 0;

  43. /*********************************************************************************************/
  44. unsigned char code logo[] =  {            // (取码:从上到下从左到右,纵向8位下高位)
  45. 0x00,0x00,0x10,0x0E,0xD0,0x01,0xFF,0xFF,//杜
  46.       0xFF,0xFF,0x90,0x01,0x10,0x43,0x40,0x40,
  47.       0x40,0x40,0x40,0x40,0xFF,0x7F,0xFE,0x7F,
  48.       0x40,0x40,0x60,0x40,0x40,0x60,0x00,0x40,

  49.         0x00,0x00,0x10,0x04,0xE1,0x78,0x4E,0xFE,//洋
  50.       0x8C,0x63,0x60,0x00,0x00,0x04,0x49,0x04,
  51.       0x4A,0x04,0x4E,0x04,0xF8,0xFF,0xFC,0xFF,
  52.       0x4E,0x04,0x6B,0x04,0x4A,0x06,0x00,0x04,

  53.         0x00,0x00,0x00,0x40,0x04,0x40,0x04,0x40,//工
  54.       0x04,0x40,0x04,0x40,0x04,0x40,0xFC,0x7F,
  55.       0xFC,0x7F,0x04,0x40,0x04,0x40,0x04,0x40,
  56.       0x06,0x40,0x04,0x60,0x00,0x40,0x00,0x00,

  57.         0x00,0x00,0x80,0x00,0x60,0x00,0xF8,0xFF,//作
  58.       0xEF,0x7F,0x06,0x00,0x40,0x00,0x30,0x00,
  59.       0x1C,0x00,0xFF,0xFF,0xFA,0xFF,0x48,0x04,
  60.       0x48,0x04,0x68,0x04,0x4C,0x06,0x08,0x04,

  61.         0x00,0x00,0x08,0x00,0x1C,0x80,0x0E,0x81,//室
  62.       0x94,0x8B,0xD4,0x89,0x75,0x89,0x37,0xFF,
  63.       0x16,0xFF,0x34,0x89,0xD4,0x89,0x94,0x8B,
  64.       0x1C,0x81,0x0E,0xC0,0x04,0x80,0x00,0x00
  65. };
  66. /*********************************************************************************************/
  67. unsigned char code logo1[] =  {            // “DoYoung” (取码:从上到下从左到右,纵向8位下高位)
  68.         0x04,0x08,0xFC,0x0F,0xFC,0x0F,0x04,0x08,  // -D-
  69.         0x0C,0x0C,0xF8,0x07,0xF0,0x03,0x00,0x00,

  70.         0xC0,0x07,0xE0,0x0F,0x20,0x08,0x20,0x08,  // -o-
  71.         0x20,0x08,0xE0,0x0F,0xC0,0x07,0x00,0x00,

  72.         0x00,0x00,0x3C,0x00,0x7C,0x08,0xC0,0x0F,  // -Y-
  73.         0xC0,0x0F,0x7C,0x08,0x3C,0x00,0x00,0x00,

  74.         0xC0,0x07,0xE0,0x0F,0x20,0x08,0x20,0x08,  // -o-
  75.         0x20,0x08,0xE0,0x0F,0xC0,0x07,0x00,0x00,

  76.         0xE0,0x07,0xE0,0x0F,0x00,0x08,0x00,0x08,  // -u-
  77.         0xE0,0x07,0xE0,0x0F,0x00,0x08,0x00,0x00,

  78.         0x20,0x00,0xE0,0x0F,0xC0,0x0F,0x20,0x00,  // -n-
  79.         0x20,0x00,0xE0,0x0F,0xC0,0x0F,0x00,0x00,

  80.         0xC0,0x27,0xE0,0x6F,0x20,0x48,0x20,0x48,  // -g-
  81.         0xC0,0x7F,0xE0,0x3F,0x20,0x00,0x00,0x00,

  82.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //空格

  83.         0x18,0x06,0x3C,0x0E,0x64,0x08,0x44,0x08,  // -S-
  84.         0xC4,0x08,0x9C,0x0F,0x18,0x07,0x00,0x00,

  85.         0x20,0x00,0x20,0x00,0xF8,0x07,0xFC,0x0F,  // -t-
  86.         0x20,0x08,0x20,0x0C,0x00,0x04,0x00,0x00,

  87.         0xE0,0x07,0xE0,0x0F,0x00,0x08,0x00,0x08,  // -u-
  88.         0xE0,0x07,0xE0,0x0F,0x00,0x08,0x00,0x00,

  89.         0x80,0x07,0xC0,0x0F,0x60,0x08,0x24,0x08,  // -d-
  90.         0xFC,0x07,0xFC,0x0F,0x00,0x08,0x00,0x00,

  91.         0x00,0x00,0x00,0x00,0x20,0x08,0xEC,0x0F,  // -i-
  92.         0xEC,0x0F,0x00,0x08,0x00,0x00,0x00,0x00,

  93.         0xC0,0x07,0xE0,0x0F,0x20,0x08,0x20,0x08,  // -o-
  94.         0x20,0x08,0xE0,0x0F,0xC0,0x07,0x00,0x00,
  95. };
  96. /*********************************************************************************************/
  97. unsigned char code logo2[] =  {            // “与电子爱好者同行” (取码:从上到下从左到右,纵向8位下高位)
  98. 0x00,0x00,0x00,0x08,0x00,0x08,0x80,0x08,
  99.       0xFF,0x09,0xFE,0x08,0x88,0x08,0x88,0x08,
  100.       0x88,0x08,0x88,0x08,0x88,0x0C,0x88,0x48,
  101.       0x88,0xC0,0x8C,0x7F,0xC8,0x3F,0x80,0x00,

  102.         0x00,0x00,0x00,0x00,0xF8,0x0F,0xF0,0x07,
  103.       0x90,0x04,0x90,0x04,0x90,0x04,0xFF,0x7F,
  104.       0xFE,0xFF,0x90,0xC4,0x90,0xC4,0x90,0xC4,
  105.       0xF0,0xCF,0xF8,0xC7,0x10,0xF0,0x00,0x40,

  106.         0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
  107.       0x82,0x00,0x82,0x00,0x82,0x40,0x82,0x40,
  108.       0xE2,0xFF,0xF2,0x7F,0x9A,0x00,0x8E,0x00,
  109.       0x87,0x00,0x82,0x00,0xC0,0x00,0x80,0x00,

  110.         0x00,0x00,0x40,0x00,0xE0,0x40,0x74,0x20,
  111.       0xA4,0x98,0xAC,0x8E,0xFA,0x47,0xE2,0x6F,
  112.       0xBE,0x3A,0xAA,0x12,0xB2,0x3A,0xBF,0x6E,
  113.       0xAB,0x67,0xE2,0xC2,0x70,0xC0,0x20,0x40,

  114.         0x00,0x00,0x20,0x80,0x20,0x63,0xF8,0x37,
  115.       0xFF,0x1C,0x26,0x0F,0xF0,0x7B,0xE0,0x30,
  116.       0x82,0x00,0x82,0x20,0x82,0x40,0xF2,0xFF,
  117.       0xEA,0x7F,0x8E,0x00,0xC7,0x00,0x82,0x00,

  118.         0x00,0x00,0x40,0x04,0x40,0x04,0x44,0x02,
  119.       0x44,0xFF,0x44,0x7F,0xC4,0x49,0xFF,0x49,
  120.       0x7F,0x49,0x64,0x49,0x66,0x49,0x54,0xFF,
  121.       0xD8,0x7F,0x4E,0x01,0x64,0x00,0x40,0x00,

  122.         0x00,0x00,0x00,0x00,0xFF,0xFF,0xFE,0x7F,
  123.       0x12,0x00,0xD2,0x1F,0x92,0x0F,0x92,0x08,
  124.       0x92,0x08,0x92,0x1F,0xDA,0x4F,0x92,0x40,
  125.       0xFE,0xFF,0xFF,0x7F,0x02,0x00,0x00,0x00,

  126.         0x00,0x00,0x20,0x04,0x10,0x02,0x8C,0xFF,
  127.       0xE7,0x7F,0x42,0x00,0x00,0x00,0x20,0x00,
  128.       0x22,0x00,0x22,0x40,0x22,0x40,0xE2,0xFF,
  129.       0xE2,0x7F,0x23,0x00,0x32,0x00,0x20,0x00
  130. };
  131. /*********************************************************************************************
  132. 函数名:LED显示用延时函数
  133. 调  用:delay(?);
  134. 参  数:1~65535(参数不可为0)
  135. 返回值:无
  136. 结  果:占用CPU方式延时与参数数值相同的毫秒时间
  137. 备  注:应用于1T单片机时i<600,应用于12T单片机时i<125
  138. /*********************************************************************************************/
  139. void delay (unsigned int a){ // 用于点扫描的延时
  140.         unsigned int i;
  141.         while( --a != 0){
  142.                 for(i = 0; i < 1; i++);
  143.         }                                      
  144. }
  145. /*********************************************************************************************/

  146. /*********************************************************************************************
  147. 函数名:毫秒级CPU延时函数
  148. 调  用:DELAY_MS (?);
  149. 参  数:1~65535(参数不可为0)
  150. 返回值:无
  151. 结  果:占用CPU方式延时与参数数值相同的毫秒时间
  152. 备  注:应用于1T单片机时i<600,应用于12T单片机时i<125
  153. /*********************************************************************************************/
  154. void DELAY_MS (unsigned int a){
  155.         unsigned int i;
  156.         while( --a != 0){
  157.                 for(i = 0; i < 600; i++);
  158.         }
  159. }
  160. /*********************************************************************************************/

  161. /*********************************************************************************************
  162. 函数名:关闭所有LED灯(操作硬件)
  163. 调  用:DISPLAY_OFF();
  164. 参  数:无
  165. 返回值:无
  166. 结  果:所有LED灯熄灭
  167. 备  注:
  168. /**********************************************************************************************/
  169. void DISPLAY_OFF (void){
  170.         delay(DY_DELAY);//显示停留
  171.         P0 = 0xff;
  172.         P2 = 0xff;
  173.         P4 = 0xff;
  174. }
  175. /**********************************************************************************************/

  176. /*********************************************************************************************
  177. 函数名:单帧数据送入显示(操作硬件)
  178. 调  用:DISPLAY_PIN(?,?);
  179. 参  数:16位显示数据(下高位)(d:上面8位,e:下面8位)
  180. 返回值:无
  181. 结  果:点亮对应数据的LED灯
  182. 备  注:
  183. /**********************************************************************************************/
  184. void DISPLAY_PIN (unsigned char d,unsigned char e){ //第1列横向显示程序
  185.         unsigned char i;
  186.         i = d & 0x01;
  187.         if(i == 0x01){LED1 = 0;}DISPLAY_OFF();
  188.         i = d & 0x02;
  189.         if(i == 0x02){LED2 = 0;}DISPLAY_OFF();
  190.         i = d & 0x04;
  191.         if(i == 0x04){LED3 = 0;}DISPLAY_OFF();
  192.         i = d & 0x08;
  193.         if(i == 0x08){LED4 = 0;}DISPLAY_OFF();
  194.         i = d & 0x10;
  195.         if(i == 0x10){LED5 = 0;}DISPLAY_OFF();
  196.         i = d & 0x20;
  197.         if(i == 0x20){LED6 = 0;}DISPLAY_OFF();
  198.         i = d & 0x40;
  199.         if(i == 0x40){LED7 = 0;}DISPLAY_OFF();
  200.         i = d & 0x80;
  201.         if(i == 0x80){LED8 = 0;}DISPLAY_OFF();

  202.         i = e & 0x01;
  203.         if(i == 0x01){LED9 = 0;}DISPLAY_OFF();
  204.         i = e & 0x02;
  205.         if(i == 0x02){LED10 = 0;}DISPLAY_OFF();
  206.         i = e & 0x04;
  207.         if(i == 0x04){LED11 = 0;}DISPLAY_OFF();
  208.         i = e & 0x08;
  209.         if(i == 0x08){LED12 = 0;}DISPLAY_OFF();
  210.         i = e & 0x10;
  211.         if(i == 0x10){LED13 = 0;}DISPLAY_OFF();
  212.         i = e & 0x20;
  213.         if(i == 0x20){LED14 = 0;}DISPLAY_OFF();
  214.         i = e & 0x40;
  215.         if(i == 0x40){LED15 = 0;}DISPLAY_OFF();
  216.         i = e & 0x80;
  217.         if(i == 0x80){LED16 = 0;}DISPLAY_OFF();
  218. }
  219. /*********************************************************************************************
  220. 函数名:初始化程序
  221. 调  用:init();
  222. 参  数:无
  223. 返回值:无
  224. 结  果:设计IO接口为强推方式并全部置1
  225. 备  注:
  226. /**********************************************************************************************/
  227. void init (void){
  228.         P4SW = 0xff; //启动P4接口
  229.         P0M0 = 0xff; //接口设置为强推
  230.         P2M0 = 0xff;
  231.         P4M0 = 0xff;
  232.         P1 = 0xff; //初始IO接口状态
  233.         P0 = 0xff;
  234.         P2 = 0xff;
  235.         P4 = 0xff;
  236. }
  237. /**********************************************************************************************/

  238. /*********************************************************************************************
  239. 函数名:主函数
  240. 调  用:无
  241. 参  数:无
  242. 返回值:无
  243. 结  果:程序开始处,无限循环
  244. 备  注:
  245. /**********************************************************************************************/
  246. void main (void){
  247.         unsigned char a,c;
  248.         init();//初始程序
  249.         while(1){
  250.                 if(MENU > 2){
  251.                         MENU = 0;
  252.                 }
  253.                 if(MENU == 0){ //字幕1
  254.                          if(KEY2 == 0){
  255.                                 DELAY_MS(20);
  256.                                 while(KEY2 == 0);
  257.                                 c = 0;
  258.                                 for(a=1;a<80;a++){ //这里的“80”是这个字幕需要扫描的列数,修改字幕时必须修改此参数。
  259.                                         DISPLAY_PIN (logo[c],logo[c+1]); //“LOGO”是第一个字幕的数据表名
  260.                                         c=c+2;//产生显示行移位
  261.                                 }
  262.                         }
  263.                         if(KEY1 == 0){
  264.                                 DELAY_MS(20);
  265.                                 while(KEY1 == 0);
  266.                                 c = 158;
  267.                                 for(a=1;a<80;a++){
  268.                                         DISPLAY_PIN (logo[c],logo[c+1]);
  269.                                         c=c-2;//产生显示行移位
  270.                                 }
  271.                         }
  272.                         if(KEY3 == 0){
  273.                                 DELAY_MS(20);
  274.                                 while(KEY3 == 0);
  275.                                 MENU++;
  276.                         }
  277.                 }
  278.                 if(MENU == 1){ //字幕2
  279.                          if(KEY2 == 0){
  280.                                 DELAY_MS(20);
  281.                                 while(KEY2 == 0);
  282.                                 c = 0;
  283.                                 for(a=1;a<108;a++){
  284.                                         DISPLAY_PIN (logo1[c],logo1[c+1]);
  285.                                         c=c+2;//产生显示行移位
  286.                                 }
  287.                         }
  288.                         if(KEY1 == 0){
  289.                                 DELAY_MS(20);
  290.                                 while(KEY1 == 0);
  291.                                 c = 214;
  292.                                 for(a=1;a<108;a++){
  293.                                         DISPLAY_PIN (logo1[c],logo1[c+1]);
  294.                                         c=c-2;//产生显示行移位
  295.                                 }
  296.                         }
  297.                         if(KEY3 == 0){
  298.                                 DELAY_MS(20);
  299.                                 while(KEY3 == 0);
  300.                                 MENU++;
  301.                         }
  302.                 }
  303.                 if(MENU == 2){ //字幕3
  304.                          if(KEY2 == 0){
  305.                                 DELAY_MS(20);
  306.                                 while(KEY2 == 0);
  307.                                 c = 0;
  308.                                 for(a=1;a<128;a++){
  309.                                         DISPLAY_PIN (logo2[c],logo2[c+1]);
  310.                                         c=c+2;//产生显示行移位
  311.                                 }
  312.                         }
  313.                         if(KEY1 == 0){
  314.                                 DELAY_MS(20);
  315.                                 while(KEY1 == 0);
  316.                                 c = 254;
  317.                                 for(a=1;a<128;a++){
  318.                                         DISPLAY_PIN (logo2[c],logo2[c+1]);
  319.                                         c=c-2;//产生显示行移位
  320.                                 }
  321.                         }
  322.                         if(KEY3 == 0){
  323.                                 DELAY_MS(20);
  324.                                 while(KEY3 == 0);
  325.                                 MENU++;
  326.                         }
  327.                 }
  328.         }
  329. }
  330. /**********************************************************************************************

  331. /**********************************************************************************************/

  332. /*************************************************************
  333. * 杜洋工作室 DoYoung Studio
  334. * 与电子爱好者同行 www.DoYoung.net
  335. /*************************************************************/
复制代码



原理图:


单片机源代码和hex文件下载:
SHOOK16_SC_V1.zip (24.28 KB, 下载次数: 14)
SHOOK16_V1_HEX.rar (1.34 KB, 下载次数: 6)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2016-8-24 16:53 | 只看该作者
51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:136460 发表于 2016-8-24 20:10 来自触屏版 | 只看该作者
有你更精彩
回复

使用道具 举报

地板
ID:166768 发表于 2017-9-12 13:22 | 只看该作者
这不是杜洋的资料吗
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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