找回密码
 立即注册

QQ登录

只需一步,快速开始

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

调试光立方踩坑经验-单片机程序跑飞原因之一

[复制链接]
跳转到指定楼层
楼主
        这几天在调光立方的程序时遇到一个令我十分困扰的问题,现象大致如下:

一开始我在对单个光立方动画调试时并没有出现问题,都是正常运行,然而我将多个动画程序写好联合在一起运行时便出现了问题,将程序烧录到单片机中后,程序可能能够正常运行好几圈没有问题,但是终究会卡死,也有可能一圈都没跑完就卡死了,有时重启单片机都是卡死的。
       出现这个问题当时真的让我很头疼,想着没道理会出现这种现象,程序本身并不复杂,也没有用大量的资源,就是占得内存多一点,但是这个问题却让我摸不着头脑,没有理由,程序能够正常运行第一圈,而第二圈却出现问题;于是我自网上看了一些相关程序跑飞的原因,如数组越界,堆栈错误,没有中断服务程序等,当时我觉得最可能是堆栈的问题,不过还没去验证这个想法,后来我便找到原因了,从事后的角度来看,首先,通过程序跑飞的现象来看肯定不是数组越界,数组越界的话,第一圈就跑不完了,会出现堆栈错误的原因没有去了解,这里也就不谈了,所以我出现跑飞的原因就是,没有中断服务程序,程序找不到中断入口而跑飞,可能大家会觉得这是个显而易见的问题,怎么会忽视呢,我先讲讲我当时的想法,我看到可能是没有中断服务程序的原因时,我首先的想法是   “我并没有使用中断啊,应该不是中断的问题”  所以我才一直怀疑是堆栈的原因,就是这么个想法,相当于自己蒙骗了自己,由于许久没有找到原因,在后来的调试中我准备把没有用到的函数都注释掉,使程序看着简洁些,顺便把警告去除了,也就在这时我看到了自己的问题,在初始化函数中我居然将定时器配置了,然而我却没有定时器的中断服务程序,看到这个,我想问题应该就在这里了。那么为什么,我没有使用定时器却开启了中断配置呢,唉!因为光立方的主板是我买的,例程是店家送的,但是我觉得店家的代码风格和我平常上课所学习不太一样就不习惯(店家所有的函数都在一个c文件中,因为动画很多程序有几千行,看着很麻烦),而且有些动画我也不喜欢,我想做一些自己的动画,于是我就将店家的程序改写成模块化的,所以基本的程序我就是copy的,问题也就这么出来了,在我写的动画和调用店家例程动画中都没有用到定时器中断(就是连 void xxx(void) interrupt x 函数都没有),所以这是一个简单的问题,然而我却没注意,在这里将这篇心得和大家分享一下,也希望有学习单片机编程但是不熟练的同学能够引以为戒。
       将这个错误改正之后一直到我写一些心得时,程序都没有再跑飞,以前一直在学习前辈们的踩坑经验,今天也轮到我给萌新们分享一点自己的经验,可能有前辈会觉得这么简单的问题,我写的这么啰嗦,但实际情况却是我因此头疼了好久,才有此感想。我将程序也放在后面可以给想做光立方的同学参考一下,但是我这个的锁存器是用的74hc595 是一个8位移位缓存器和 平时使用比较多的 573 不太一样,想要参考的同学注意下,程序文件夹中我放了一个原理图pdf可以参考。

单片机源程序如下:
  1. #include "common.h"
  2. sbit RR=P3^6;//红
  3. sbit BB=P2^4;//蓝
  4. char data cheng;
  5. //void delay_1us(uint i)
  6. //{
  7. // unsigned int b;
  8. //   for(b=0;b<i;b++);
  9. //}
  10. //void delay_1ms(uint i)
  11. //{
  12. // unsigned int j,k;
  13. //   for(k=0;k<120;k++)
  14. //    for(j=0;j<i;j++);
  15. //}
  16. void  red (void)        //红灯亮
  17. {
  18.     RR=0;//红
  19.     BB=1;//蓝
  20. }
  21. //void  blue (void)  //蓝灯亮
  22. //{
  23. //    RR=1;//红
  24. //    BB=0;//蓝
  25. //}

  26. void initial595()         //列驱动初始化
  27. {
  28.                 SH_CP = 0;
  29.                 ST_CP = 0;
  30.                 DS = 0;
  31. }
  32.   void initial5952() //行驱动初始化
  33. {
  34.                 SH_CP2 = 0;
  35.                 ST_CP2 = 0;
  36.                 DS2 = 0;
  37. }

  38. /************************************ 发送数据 ***************************************************************/
  39. //void send_data(unsigned char d)//发送一层当中的一行显示数据,8位
  40. //{
  41. //                unsigned char i;
  42. //                for(i=0;i<8;i++)
  43. //                {
  44. //                        DS = d&0x80;//发送最低位
  45. //                        SH_CP = 1;
  46. //                        delay_1us(15);
  47. //                        SH_CP = 0; //移位寄存器移位
  48. //                        delay_1us(15);
  49. //                        d = d<<1; //数据移位f
  50. //                }
  51. //                //因为使用多个595级联,此处未做数据输出锁存,
  52. //                //须将所有数据发送出来后再做锁存输出
  53. //}

  54. //void send_data2(unsigned char d)//发送层显示数据,8位
  55. //{
  56. //         unsigned char i,j=0;
  57. //
  58. //                for(i=0;i<8;i+=2)
  59. //                {
  60. //                        DS2 = d&0x80;//发送最低位
  61. //                        SH_CP2 = 1;
  62. //                        delay_1us(15);
  63. //                        SH_CP2 = 0; //移位寄存器移位
  64. //                        delay_1us(15);
  65. //                        d = d<<1; //数据移位
  66. //                }
  67. //            ST_CP2 = 0;                   //数据输出锁存
  68. //                delay_1us(15);
  69. //                ST_CP2 = 1;        
  70. //                delay_1us(15);
  71. //            ST_CP2 = 0;        
  72. //}
  73. //void send_data2_1bit(unsigned char layer)//发送层显示数据,1位
  74. //{
  75. //        unsigned char ceng=0;
  76. //
  77. //        ceng=0x01<<layer;                 //行移位,
  78. //        DS2 = ~ceng&0x01;                 //发送层扫描数据
  79. //
  80. //        SH_CP2 = 1;
  81. //        delay_1us(15);
  82. //        SH_CP2 = 0; //移位寄存器移位
  83. //        delay_1us(15);
  84. //
  85. //    ST_CP2 = 0;                   //数据输出锁存
  86. //        delay_1us(15);
  87. //        ST_CP2 = 1;        
  88. //        delay_1us(15);
  89. //    ST_CP2 = 0;        
  90. //}
  91. void delay(uint i)
  92. {                                                                                       
  93.         char b;
  94.         while (i--)
  95.         {
  96.            b=1;
  97.                 while(b--);
  98.         }
  99. }

  100. /*************************************黎明途电子************************************************************/        
  101. /*************************************脱机动画文件************************************************/



  102. /*---------------------------
  103. //函数名:void sendbyte1 (uint num1....)
  104. //功能:一次发送四个数据给锁存器
  105. //参数:num1,num2,num3,num4
  106. //返回值:无
  107. ----------------------------*/
  108. void sendbyte1(unsigned int num1,unsigned int num2,unsigned int num3,unsigned int num4)
  109. {
  110.         unsigned char i=0;
  111.         for(i=0;i<8;i++)
  112.         {
  113.                 DS = num1&0x01;         //发送最低位
  114.                 SH_CP = 1;
  115.                 SH_CP = 0;                 //移位寄存器移位
  116.            num1=num1>>1;         //数据移位f
  117.         }

  118.          for(i=0;i<8;i++)
  119.         {
  120.                 DS = num2&0x01;         //发送最低位
  121.                 SH_CP = 1;
  122.                 SH_CP = 0;                 //移位寄存器移位
  123.                 num2 = num2>>1;                 //数据移位f
  124.         }

  125.         for(i=0;i<8;i++)
  126.         {
  127.                 DS = num3&0x01;         //发送最低位
  128.                 SH_CP = 1;
  129.                 SH_CP = 0;                 //移位寄存器移位
  130.                 num3 = num3>>1;         //数据移位f
  131.         }

  132.          for(i=0;i<8;i++)
  133.         {
  134.                 DS = num4&0x01;         //发送最低位
  135.                 SH_CP = 1;
  136.                 SH_CP = 0;                 //移位寄存器移位
  137.                 num4 = num4>>1;                 //数据移位f
  138.         }
  139.    
  140. }
  141. /*----------------------------------------------
  142. //函数名  :void zhen (uchar *a,uchar V)
  143. //函数功能:将待显示的数据写入锁存器中并显示
  144. //参数:*a:待显示数据-,V循环此次数(为何循环?经验证只是增加显示时间)
  145. //返回值:无
  146. ------------------------------------------------*/
  147.                         
  148. void zhen(uchar *a,uchar v)         
  149. {
  150. char layer;

  151. while(v--)//?为何需要循环???增加显示时间?√ 就是这样 。。
  152. {
  153.   
  154.   for(layer=0;layer<8;layer++) //将每层8列数码发送 循环8次8层数据依次发送
  155.   {                                                                     /* 数组的每一位是一列数据*/
  156.         sendbyte1(~a[layer*8+7],~a[layer*8+6],~a[layer*8+5],~a[layer*8+4]);        
  157.         sendbyte1(~a[layer*8+3],~a[layer*8+2],~a[layer*8+1],~a[layer*8+0]);
  158.                                               //和直接调显示函数是一个道理
  159.         cheng=0x01<<layer;
  160.     DS2 =~cheng&0x01;         //发送最低位
  161.             ST_CP=1;        
  162.             ST_CP=0;
  163.                 SH_CP2 = 1;
  164.                 SH_CP2 = 0;                 //移位寄存器移位
  165.                 ST_CP2=1;        
  166.             ST_CP2=0;                                             
  167.                 delay(300);                                                
  168.   }

  169. }
  170. }

  171. void clc()//全局清屏
  172. {
  173.           unsigned char k;         
  174. for(k=0;k<64;k++)
  175. {        //d=0xff;
  176.    
  177.                 DS = 0;         //发送最低位
  178.                 SH_CP = 1;
  179.                 SH_CP = 0;                 //移位寄存器移位
  180.         //        d = d<<1;                 //数据移位f

  181.   }
  182.           ST_CP=1;        
  183.           ST_CP=0;         
  184. }
复制代码

所有资料51hei提供下载:
光立方修改.rar (650.29 KB, 下载次数: 12)


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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