用户
 找回密码
 注册
发新帖
### DIY五级 385034
1#
跳转到指定楼层

数码管DIY的光立方V1.6版正式发布! 3D立体数字滑块推盘 3D Puzzle 4x4x4 全球首发!

[复制链接]
本帖最后由 ### 于 2017-2-22 22:38 编辑

用单片机和数码管DIY的光立方 3D立体数字滑块推盘 3D Puzzle 4x4x4 全球首发!



由4个平面推盘组成,只有一层有空区,其余的没有。
平面移动?椒ㄓ氪惩婆桃恢拢⑻逡贫椒ㄊ遣阒浣幸贫?
还原技巧以及算法比传统的更加复杂,可能会难倒世界顶级拼图还原高手!
3D数字推盘由于机械式设计非常复杂,采用单片机和数码管和按键实现了电子式设计。
修改程序可以改成数码管花样强大的闪灯。
若发现建议意见以及BUG等问题请在下面回复,谢谢合作!

制作材料及方法:
SYB-130 面包板 17板
杜邦线 10cm和20cm的若干。
若使用印刷pcb设计以上可以省略。

6CM 固定M3铜柱 48 个,pcb的可以用更短的。
0.56寸共阴数码管 128个。

74HC595和74HC138各 16片 (用于驱动共阴数码管)
STC12C5A60S2 1片
逻辑分析仪1个(用于检测接线错误或开路短路而导致的信号错误排查与处理)。
多排多P杜邦头若干(强烈建议使用,多根线接在一起防止接错线以及避免折断杜邦线公头和开路的现象的发生)。


无锁按键至少8个,用于操控6个移动方向以及随机移动和撤销或重复上次的移动记录。
尼龙扎带、热熔胶若干,够用就行。

数码管A~DP 线并联接法:15 26 37 48 25 36 47是最整洁的,按照其他接法,杜邦线可能捆不到一起。
杜邦头更换方法:将杜邦头上的小塑料片撬开后即可取出,插入杜邦头后确认杜邦头已经拔不出即可完成更换,否则将小塑料片压回或是接头插反而无法固定住杜邦头。


版本更新历史:
                V1.1        加入了6个方向随机循环移动的功能,一键打乱数字排序,按下按键自动循环打乱,放开按键则停止。
                V1.2        加入了移动成功标记位,乱移打乱效果更好,防止乱移时有些步骤移动不成功,不成功则循环重复移动,直到成功为止。
                V1.3        加入了60秒无按键操作所有数码管自动熄灭,按下按键自动唤醒,更省电。
                V1.4        加入了空闲时间自动循环计算随机数,伪随机数效果更加以假乱真。
                V1.5        加入了随机数计算相关变量上电或自动熄灭后(不含断电)自动存取到内置Eeprom中,每次上电产生的随机数都会不同。
                V1.6        加入了撤销或重复一次移动的功能,只有成功移动就会有记录,撤销则按照记录中的相反的方向移动。


源码免费公开,keil4编译通过:
  1. #include "STC12C5A60S2.h"
  2. #include "intrins.h"
  3. unsigned char code nbr[16]={ //共阴数码管段码数据
  4. 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,
  5. };

  6. /*
  7. 通过获取0?淖旰捅灰贫淖杲换皇凳迪忠贫墓δ芤约芭卸鲜质欠衲鼙灰贫?
  8. 若没有任何不能正常移动数字的现象,严禁修改任何1字节否则会导致某些位置的数字跳格或者无法移动还会导致数组越界等严重后果。
  9. 每4字节表示4个移动方向的与0的坐标与其他坐标进行交换实现移动。
  10.         0的坐标从左上到右下排序:
  11.         0 1 2 3
  12.         4 5 6 7
  13.         8 9 A B
  14.         C D E F
  15.         前4字节:0x04, 0x10, 0x01, 0x10
  16.         比如数值0在坐标0的位置上,
  17.                 上移将坐标4的值移入坐标0。
  18.                 下移为0x10,不能被移动。
  19.                 左移将坐标1的值移入坐标0。
  20.                 右移同样为0x10,不能被移动。
  21.                 移入的方法则是与数值0的坐标进行数值交换而实现移动。
  22.         数值0在坐标1的位置上,则获取后面的4字节进行判断,以此类推。

  23. */
  24. unsigned char code xyd[64] = {
  25.         0x04, 0x10, 0x01, 0x10, 0x05, 0x10, 0x02, 0x00, 0x06, 0x10, 0x03, 0x01, 0x07, 0x10, 0x10, 0x02,
  26.         0x08, 0x00, 0x05, 0x10, 0x09, 0x01, 0x06, 0x04, 0x0A, 0x02, 0x07, 0x05, 0x0B, 0x03, 0x10, 0x06,
  27.         0x0C, 0x04, 0x09, 0x10, 0x0D, 0x05, 0x0A, 0x08, 0x0E, 0x06, 0x0B, 0x09, 0x0F, 0x07, 0x10, 0x0A,
  28.         0x10, 0x08, 0x0D, 0x10, 0x10, 0x09, 0x0E, 0x0C, 0x10, 0x0A, 0x0F, 0x0D, 0x10, 0x0B, 0x10, 0x0E,
  29. };

  30. unsigned char l1[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //第一层拼图(最顶层)
  31. unsigned char l2[16]={16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};  //第二层拼图
  32. unsigned char l3[16]={32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47};  //第三层拼图
  33. unsigned char l4[16]={48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};  //第四层拼图(最底层)
  34. //--------计算随机数相关变量--------
  35. unsigned char rb=0;
  36. unsigned char rc=0;
  37. unsigned char rd=0;
  38. unsigned char re=0;
  39. unsigned char rf=0;
  40. unsigned char rg=0;
  41. unsigned char rh=0;
  42. unsigned char ri=0;


  43. sbit A0=P1^0; //74HC138 译码端 A0
  44. sbit A1=P1^1; //74HC138 译码端 A1
  45. sbit A2=P1^2; //74HC138 译码端 A2


  46. sbit SRCLK = P1^3;  //串行数据时钟输入
  47. sbit SER   = P1^4;  //串行数据输入
  48. sbit LATCH = P1^5;  //锁存信号输入
  49. sbit E1=P1^6; //74HC138 E1 端,与E2端同时低电平译码有效
  50. sbit E2=P1^7; //74HC138 E2 端,E3接VCC。
  51. sbit um=P3^2;         //上移按钮
  52. sbit dm=P3^3;         //下移按钮
  53. sbit lm=P3^4;         //左移按钮
  54. sbit rm=P3^5;        //右移按钮
  55. sbit im=P3^6;        //里移按钮
  56. sbit om=P3^7;        //外移按钮
  57. sbit sm=P2^0;        //乱移按钮,按住不放随机移动拼图以打乱排序。
  58. sbit cm=P2^1;        //撤销按钮,按下撤销或重复上次的移动操作。

  59. unsigned int ms5=0; //5毫秒计数

  60. bit t=0; //成功移动标记位,移动成功则为1,无法移动则为0。
  61. unsigned char c=0;        //移动记录,1~6则表示6个方向的记录,0没有记录。

  62. //---------------- 片内Eeprom驱动程序 核心代码 ----------------

  63. void eeprom_init(){
  64.         IAP_CONTR        = 0x83;
  65.         IAP_CMD         = 0x00;
  66.         IAP_ADDRH        = 0x00;
  67.         IAP_ADDRL        = 0x00;

  68. }
  69. unsigned char eeprom_read_dat(unsigned char addr_h,unsigned char addr_l){
  70.         unsigned char E_dat = 0x00;
  71.         IAP_CMD         = 0x01;
  72.         IAP_ADDRH        = addr_h;
  73.         IAP_ADDRL        = addr_l;
  74.         IAP_TRIG        = 0x5A;
  75.         IAP_TRIG        = 0xA5;
  76.         E_dat                = IAP_DATA;
  77.         return E_dat;
  78. }
  79. void eeprom_erase_dat(unsigned char addr_h,unsigned char addr_l){
  80.         IAP_CMD         = 0x03;
  81.         IAP_ADDRH        = addr_h;
  82.         IAP_ADDRL        = addr_l;
  83.         IAP_TRIG        = 0x5A;
  84.         IAP_TRIG        = 0xA5;
  85. }



  86. void eeprom_write_dat(unsigned char addr_h,unsigned char addr_l,unsigned char w_dat){
  87.         eeprom_erase_dat(addr_h,addr_l);
  88.         IAP_CMD         = 0x02;        
  89.         IAP_ADDRH        = addr_h;
  90.         IAP_ADDRL        = addr_l;
  91.         IAP_DATA        = w_dat;
  92.         IAP_TRIG        = 0x5A;
  93.         IAP_TRIG        = 0xA5;

  94. }

  95. //---------------- 随机数产生相关算法 核心代码 ----------------
  96. unsigned char rand(){ //计算随机数 算法 可移植到任何指令集的处理器平台
  97.                 rb=(rc+3)*3;rc=(rd-3)*3;rd=(re+3)*3;re=(rf-3)*3;
  98.                 rf=(rg+3)*3;rg=(rh-3)*3;rh=(ri+3)*3;ri=(rb-3)*3;

  99.         if(rb > 127) rc = rc^127;
  100.         if(rc < 127) rd = rd^127;
  101.         if(rd > 127) re = re^127;
  102.         if(re < 127) rf = rf^127;
  103.         if(rf > 127) rg = rg^127;
  104.         if(rg < 127) rh = rh^127;
  105.         if(rh > 127) ri = ri^127;
  106.         if(ri < 127) rb = rb^127;

  107.         return rb^rc^rd^re^rf^rg^rh^ri;
  108. }

  109. void srand(){ //通过Eeprom功能 实现 置随机数种子功能,每次产生的随机数都不会一样。
  110. unsigned char i=0;
  111. rb=eeprom_read_dat(0,0);
  112. rc=eeprom_read_dat(0,1);
  113. rd=eeprom_read_dat(0,2);
  114. re=eeprom_read_dat(0,3);
  115. rf=eeprom_read_dat(0,4);
  116. rg=eeprom_read_dat(0,5);
  117. rh=eeprom_read_dat(0,6);
  118. ri=eeprom_read_dat(0,7);

  119. for(i=0;i<rand();i++){
  120. rand();
  121. }
  122. eeprom_write_dat(0,0,rb);
  123. eeprom_write_dat(0,1,rc);
  124. eeprom_write_dat(0,2,rd);
  125. eeprom_write_dat(0,3,re);
  126. eeprom_write_dat(0,4,rf);
  127. eeprom_write_dat(0,5,rg);
  128. eeprom_write_dat(0,6,rh);
  129. eeprom_write_dat(0,7,ri);

  130. }



  131. //---------------- 5毫秒定时器与1毫秒动态扫描延时计数,修改晶振频率需要修改此段代码 ----------------
  132. void InitTimer0(void){ //初始化5毫秒定时器
  133.     TMOD = 0x01;
  134.     TH0 = 0x28;
  135.     TL0 = 0x00;
  136.     EA = 1;
  137.     ET0 = 1;
  138.     TR0 = 1;
  139. }


  140. void delay()               
  141. {
  142.         unsigned char i, j;

  143.         _nop_();
  144.         i = 11;
  145.         j = 190;
  146.         do
  147.         {
  148.                 while (--j);
  149.         } while (--i);
  150. }



  151. //---------------- 数码管段码显示程序 74HC595 74HC138驱动程序 核心代码 ----------------
  152. void send595(unsigned char dat){ //向74HC595写入数据
  153.         unsigned char i;
  154.         
  155.         for(i=0;i<8;i++)
  156.     {
  157.                SRCLK=0;        //先将串行时钟输入端SRCLK置成低电平
  158.                SER=dat&0x80;        //每次只取一位
  159.                dat<<=1;        //每次只取一位进行左移
  160.                SRCLK=1;        //数据在串行时钟输入端SRCLK的上升沿输入到移位寄存器中
  161.     }
  162.          
  163. }




  164. void out595(void){ //74HC595锁存指令
  165.         LATCH=0;//锁存
  166.         _nop_();//空指令
  167.         LATCH=1;//LATCH上升沿并行数据输出
  168. }

  169. void cpl595(){ //清除74HC595内部所有寄存数据
  170.         unsigned char a;
  171.         for(a=0;a<16;a++){
  172.         send595(0x00);
  173.         }
  174.         out595();
  175. }

  176. unsigned rl1(unsigned char a,bit b,bit c){
  177. if(c==1){return 0xFF;}
  178. if(l1[a] == 0){return 0x00;}
  179. if(b == 0){
  180. return nbr[l1[a]/10];
  181. } else {
  182. return nbr[l1[a]%10];
  183. }
  184. }

  185. unsigned rl2(unsigned char a,bit b,bit c){
  186. if(c==1){return 0xFF;}
  187. if(l2[a] == 0){return 0x00;}
  188. if(b == 0){
  189. return nbr[l2[a]/10];
  190. } else {
  191. return nbr[l2[a]%10];
  192. }
  193. }

  194. unsigned rl3(unsigned char a,bit b,bit c){
  195. if(c==1){return 0xFF;}
  196. if(l3[a] == 0){return 0x00;}
  197. if(b == 0){
  198. return nbr[l3[a]/10];
  199. } else {
  200. return nbr[l3[a]%10];
  201. }
  202. }

  203. unsigned rl4(unsigned char a,bit b,bit c){
  204. if(c==1){return 0xFF;}
  205. if(l4[a] == 0){return 0x00;}
  206. if(b == 0){
  207. return nbr[l4[a]/10];
  208. } else {
  209. return nbr[l4[a]%10];
  210. }
  211. }

  212. void out595dat(unsigned char a,bit c){ //向74HC595发送数码管段码数据
  213.                 //减12表示一层4组倒序发送,每组包含8个数码管,根据硬件电路进行修改。
  214.                 unsigned char b=0;
  215.                         
  216.                                 for(b=0;b<16;b+=4){
  217.                                         send595(rl1(12-b+a/2,a&1,c)); //发送第一层数据
  218.                                         }

  219.                                 for(b=0;b<16;b+=4){
  220.                                         send595(rl2(b+a/2,a&1,c)); //发送第二层数据
  221.                                         }

  222.                                 for(b=0;b<16;b+=4){
  223.                                         send595(rl3(12-b+a/2,a&1,c)); //发送第三层数据
  224.                                         }

  225.                                 for(b=0;b<16;b+=4){
  226.                                         send595(rl4(b+a/2,a&1,c)); //发送第四层数据
  227.                                         }
  228.                                 



  229.                 out595(); //74HC595执行锁存输出电平数据
  230.         }

  231. void out_nbr(bit a){
  232. cpl595();A2=0;A1=0;A0=0;out595dat(0,a);delay();
  233. cpl595();A2=0;A1=0;A0=1;out595dat(1,a);delay();
  234. cpl595();A2=0;A1=1;A0=0;out595dat(2,a);delay();
  235. cpl595();A2=0;A1=1;A0=1;out595dat(3,a);delay();
  236. cpl595();A2=1;A1=0;A0=0;out595dat(4,a);delay();
  237. cpl595();A2=1;A1=0;A0=1;out595dat(5,a);delay();
  238. cpl595();A2=1;A1=1;A0=0;out595dat(6,a);delay();
  239. cpl595();A2=1;A1=1;A0=1;out595dat(7,a);delay();

  240. }



  241. //---------------- 数字移动程序 核心代码 ----------------

  242. unsigned char get_0_lay(){ //获取0所在的层数 返回1~4
  243. unsigned char add=0;
  244.         for(add=0;add<16;add++){
  245.                 if(l1[add] == 0){
  246.                         return 1;
  247.                         }

  248.                 if(l2[add] == 0){
  249.                         return 2;
  250.                         }

  251.                 if(l3[add] == 0){
  252.                         return 3;
  253.                         }

  254.                 if(l4[add] == 0){
  255.                         return 4;
  256.                         }

  257.         }
  258.         return 0;
  259. }

  260. unsigned char get_0_pla(){ //获取0的平面坐标 返回0~15
  261. unsigned char lay=0;
  262. unsigned char add=0; //当前扫描的坐标
  263.         lay=get_0_lay(); //获取0所在的层数
  264.         for(add=0;add<16;add++){
  265.                 if(lay == 1){
  266.                         if(l1[add] == 0){
  267.                         return add;
  268.                         }
  269.                 }

  270.                 if(lay == 2){
  271.                         if(l2[add] == 0){
  272.                         return add;
  273.                         }
  274.                 }

  275.                 if(lay == 3){
  276.                         if(l3[add] == 0){
  277.                         return add;
  278.                         }
  279.                 }

  280.                 if(lay == 4){
  281.                         if(l4[add] == 0){
  282.                         return add;
  283.                         }
  284.                 }




  285.         }
  286. return 0;
  287. }
  288. //0的坐标:0~15 移动方向:1234 表示上下左右,该坐标的值会与0交换实现移动,不能移动的将返回0x10
  289. unsigned char get_adj_coo(unsigned char zero_adj,unsigned char mov_dir){ //获取相邻坐标
  290.         unsigned char dat=xyd[zero_adj*4+mov_dir-1];
  291.                 if(dat == 0x10){ //读取到0x10 不能被移动。
  292.                 t=0;
  293.                 } else { //读取到其他值,可以被移动。

  294.                 c=mov_dir; //保存移动记录
  295.                 t=1;
  296.                 }
  297.         return dat;
  298. }


  299. void pec(unsigned char s,unsigned char a,unsigned char b){ ////平面交换数字位置 层数:1~4 坐标A 坐标B
  300. unsigned char ad=0; //坐标A数据
  301. unsigned char bd=0; //坐标B数据
  302.         if(a > 15 || b > 15) {
  303.                 return;
  304.                 }
  305.                 if(s == 1){ad=l1[a];bd=l1[b];l1[a]=bd;l1[b]=ad;return;}
  306.                 if(s == 2){ad=l2[a];bd=l2[b];l2[a]=bd;l2[b]=ad;return;}
  307.                 if(s == 3){ad=l3[a];bd=l3[b];l3[a]=bd;l3[b]=ad;return;}
  308.                 if(s == 4){ad=l4[a];bd=l4[b];l4[a]=bd;l4[b]=ad;return;}
  309.         return;
  310. }


  311. void up_mov(){ //拼图上移
  312. unsigned char lay0=0;
  313. unsigned char pla0=0;
  314. unsigned char adj=0;
  315.         lay0=get_0_lay(); //获取0的坐标所在层数
  316.         pla0=get_0_pla(); //获取0的平面坐标
  317.         adj=get_adj_coo(pla0,1); //获取相邻坐标
  318.         pec(lay0,pla0,adj); //平面交换数字位置


  319. }

  320. void down_mov(){ //拼图下移
  321. unsigned char lay0=0;
  322. unsigned char pla0=0;
  323. unsigned char adj=0;
  324.         lay0=get_0_lay(); //获取0的坐标所在层数
  325.         pla0=get_0_pla(); //获取0的平面坐标
  326.         adj=get_adj_coo(pla0,2); //获取相邻坐标
  327.         pec(lay0,pla0,adj); //平面交换数字位置


  328. }

  329. void left_mov(){ //拼图左移
  330. unsigned char lay0=0;
  331. unsigned char pla0=0;
  332. unsigned char adj=0;
  333.         lay0=get_0_lay(); //获取0的坐标所在层数
  334.         pla0=get_0_pla(); //获取0的平面坐标
  335.         adj=get_adj_coo(pla0,3); //获取相邻坐标
  336.         pec(lay0,pla0,adj); //平面交换数字位置


  337. }

  338. void right_mov(){ //拼图右移
  339. unsigned char lay0=0;
  340. unsigned char pla0=0;
  341. unsigned char adj=0;
  342.         lay0=get_0_lay(); //获取0的坐标所在层数
  343.         pla0=get_0_pla(); //获取0的平面坐标
  344.         adj=get_adj_coo(pla0,4); //获取相邻坐标
  345.         pec(lay0,pla0,adj); //平面交换数字位置


  346. }

  347. void in_mov(){ //拼图里移
  348. unsigned char lay0=0; //0的坐标所在层数
  349. unsigned char pla0=0; //0的平面坐标
  350. unsigned char add=0; //累加计数
  351.         lay0=get_0_lay(); //获取0的坐标所在层数
  352.         pla0=get_0_pla(); //获取0的平面坐标
  353.                 if(lay0 < 4){ //可以被移动
  354.                         if(lay0 == 3){l3[pla0]=l4[pla0];l4[pla0]=0;}
  355.                         if(lay0 == 2){l2[pla0]=l3[pla0];l3[pla0]=0;}
  356.                         if(lay0 == 1){l1[pla0]=l2[pla0];l2[pla0]=0;}
  357.                         t=1;
  358.                         c=5;
  359.                 } else { //不能被移动
  360.                 t=0;
  361.                 }

  362. }

  363. void out_mov(){ //拼图外移
  364. unsigned char lay0=0; //0的坐标所在层数
  365. unsigned char pla0=0; //0的平面坐标
  366. unsigned char add=0; //累加计数
  367.         lay0=get_0_lay(); //获取0的坐标所在层数
  368.         pla0=get_0_pla(); //获取0的平面坐标
  369.                 if(lay0 > 1){ //可以被移动
  370.                         if(lay0 == 4){l4[pla0]=l3[pla0];l3[pla0]=0;}
  371.                         if(lay0 == 3){l3[pla0]=l2[pla0];l2[pla0]=0;}
  372.                         if(lay0 == 2){l2[pla0]=l1[pla0];l1[pla0]=0;}
  373.                         t=1;
  374.                         c=6;
  375.                 } else {//不能被移动
  376.                 t=0;
  377.                 }

  378. }
  379. void rand_mov(){ //拼图乱移
  380.                 unsigned char r=0; //随机数存储变量
  381.                         while(t == 0){ //移动不成功则重复移动,直到成功为止。

  382.                 r=rand()%6;  //随机数取余6,取值0~5,表示随机6个方向移动。
  383.                 switch(r){
  384.                 case 0:up_mov();break;
  385.                 case 1:down_mov();break;
  386.                 case 2:left_mov();break;
  387.                 case 3:right_mov();break;
  388.                 case 4:in_mov();break;
  389.                 case 5:out_mov();break;
  390.                 default:break;
  391.                 }


  392.                
  393.                 }
  394.         t=0; //清除标记,防止下次无法移动。
  395.         
  396. }

  397. void cancel_mov(){ //撤销或重复上一次的移动
  398.                 //按照记录中的相反方向进行移动
  399.                 switch(c){
  400.                 case 1:down_mov();break;
  401.                 case 2:up_mov();break;
  402.                 case 3:right_mov();break;
  403.                 case 4:left_mov();break;
  404.                 case 5:out_mov();break;
  405.                 case 6:in_mov();break;
  406.                 default:out_nbr(0);break; //没有记录则不移动
  407.                 }




  408. }



  409. void main(){ //入口函数
  410. unsigned char a=0; //计数变量
  411. AUXR |= 0x80;
  412. InitTimer0();        //初始化5毫秒定时器0
  413. eeprom_init(); //初始化片内Eeprom功能
  414. srand(); //置随机数种子
  415. E1=0;E2=0; //启用74HC138译码功能
  416.                 for(a=0;a<0x3F;a++){ //数码管全亮一段时间
  417.                         out_nbr(1); //128个数码管所有段码全亮

  418.                 }
  419.                 ms5=0;
  420. while(1){ //进入死循环
  421. rand();        //空闲时间自动循环计算随机数,以假乱真。
  422.                 if(TR0 == 1){        //点亮模式
  423.                 if(um == 0){up_mov();while(um == 0){ms5=0;out_nbr(0);}}
  424.                 if(dm == 0){down_mov();while(dm == 0){ms5=0;out_nbr(0);}}
  425.                 if(lm == 0){left_mov();while(lm == 0){ms5=0;out_nbr(0);}}
  426.                 if(rm == 0){right_mov();while(rm == 0){ms5=0;out_nbr(0);}}
  427.                 if(im == 0){in_mov();while(im == 0){ms5=0;out_nbr(0);}}
  428.                 if(om == 0){out_mov();while(om == 0){ms5=0;out_nbr(0);}}
  429.                 if(sm == 0){while(sm == 0){rand_mov();ms5=0;out_nbr(0);}}
  430.                 if(cm == 0){cancel_mov();while(cm == 0){ms5=0;out_nbr(0);}}

  431.                 out_nbr(0); //输出拼图数据


  432.                         } else { //熄灭模式
  433.                                 if(P3 != 0xFF || P2 != 0xFF){ //P3口或P2口都不全等于高电平则有按键按下
  434.                                         TR0=1;        //启用定时器0计数功能
  435.                                         ET0=1;        //启用定时器0计数溢出中断功能
  436.                                         E1=0;E2=0; //启用74HC138译码功能
  437.                                         while(P3 != 0xFF || P2 != 0xFF){ //按键按下不放??
  438.                                         ms5=0;//5毫秒计数清零
  439.                                         out_nbr(0); //输出拼图数据
  440.                                         }
  441.                                 }

  442.                         }
  443. }}


  444. void Timer0Interrupt(void) interrupt 1
  445. {
  446.     TH0 = 0x28;
  447.     TL0 = 0x00;
  448.         ms5++; //5毫秒计数加1
  449.                 if(ms5 >= 12000){        //5毫秒计数加到1万2
  450.                         srand();
  451.                         E1=1;E2=1;         //禁用74HC138译码功能
  452.                         ms5=0;             //5毫秒计数清零
  453.                         ET0=0;                //禁用定时器0计数溢出中断功能
  454.                         TR0=0;                //禁用定时器0计数功能

  455.                 }
  456. }
复制代码




IMG_20161231_224242_HHT.jpg
IMG_20170101_185408_HHT.jpg
IMG_20170101_185414_HHT.jpg
IMG_20170101_185423_HHT.jpg
IMG_20170101_190314_HHT.jpg
IMG_20170101_190318_HHT.jpg
IMG_20170101_190320.jpg
IMG_20170101_190326_HHT.jpg
IMG_20170101_190359_HHT.jpg
IMG_20170101_190426_HHT.jpg
IMG_20170101_190441_HHT.jpg

评分

参与人数 4下载币 +17 刀币 +20 收起 理由
疯爱 + 3 + 3 支持DIY精神!
diyhome + 5 + 5 很给力!
看门查水表 + 6 + 6 666
黎明之光 + 3 + 6 支持DIY精神!

查看全部评分

看着有点眼乱啊,楼主功底深厚
回复

使用道具 举报

### DIY五级  楼主 |
天下冥尊 发表于 2017-4-21 13:45
说实话 我不知道你这是干嘛的 一堆杜邦线+一堆数码管+面包板

不清楚的话仔细阅读主题内容。
回复

使用道具 举报

说实话 我不知道你这是干嘛的 一堆杜邦线+一堆数码管+面包板
回复

使用道具 举报

### DIY五级  楼主 |
ljl_1007 发表于 2017-4-10 21:54
没看明白,感觉很厉害的样子

当然没有什么人能看明白的。
回复

使用道具 举报

手艺不错啊,厉害
回复

使用道具 举报

没看明白,感觉很厉害的样子
回复

使用道具 举报

毛用?.............
回复

使用道具 举报

好手艺!我刚入道可以拜你为师吗?
回复

使用道具 举报

### DIY五级  楼主 |
郭志强 发表于 2017-3-9 23:22
个人感觉没有什么用

就算是传统的没经验的复原都要1小时以上,这种的我觉得可能要1年以上。
回复

使用道具 举报

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

本版积分规则

返回顶部