这几天在调光立方的程序时遇到一个令我十分困扰的问题,现象大致如下:
一开始我在对单个光立方动画调试时并没有出现问题,都是正常运行,然而我将多个动画程序写好联合在一起运行时便出现了问题,将程序烧录到单片机中后,程序可能能够正常运行好几圈没有问题,但是终究会卡死,也有可能一圈都没跑完就卡死了,有时重启单片机都是卡死的。
出现这个问题当时真的让我很头疼,想着没道理会出现这种现象,程序本身并不复杂,也没有用大量的资源,就是占得内存多一点,但是这个问题却让我摸不着头脑,没有理由,程序能够正常运行第一圈,而第二圈却出现问题;于是我自网上看了一些相关程序跑飞的原因,如数组越界,堆栈错误,没有中断服务程序等,当时我觉得最可能是堆栈的问题,不过还没去验证这个想法,后来我便找到原因了,从事后的角度来看,首先,通过程序跑飞的现象来看肯定不是数组越界,数组越界的话,第一圈就跑不完了,会出现堆栈错误的原因没有去了解,这里也就不谈了,所以我出现跑飞的原因就是,没有中断服务程序,程序找不到中断入口而跑飞,可能大家会觉得这是个显而易见的问题,怎么会忽视呢,我先讲讲我当时的想法,我看到可能是没有中断服务程序的原因时,我首先的想法是 “我并没有使用中断啊,应该不是中断的问题” 所以我才一直怀疑是堆栈的原因,就是这么个想法,相当于自己蒙骗了自己,由于许久没有找到原因,在后来的调试中我准备把没有用到的函数都注释掉,使程序看着简洁些,顺便把警告去除了,也就在这时我看到了自己的问题,在初始化函数中我居然将定时器配置了,然而我却没有定时器的中断服务程序,看到这个,我想问题应该就在这里了。那么为什么,我没有使用定时器却开启了中断配置呢,唉!因为光立方的主板是我买的,例程是店家送的,但是我觉得店家的代码风格和我平常上课所学习不太一样就不习惯(店家所有的函数都在一个c文件中,因为动画很多程序有几千行,看着很麻烦),而且有些动画我也不喜欢,我想做一些自己的动画,于是我就将店家的程序改写成模块化的,所以基本的程序我就是copy的,问题也就这么出来了,在我写的动画和调用店家例程动画中都没有用到定时器中断(就是连 void xxx(void) interrupt x 函数都没有),所以这是一个简单的问题,然而我却没注意,在这里将这篇心得和大家分享一下,也希望有学习单片机编程但是不熟练的同学能够引以为戒。
将这个错误改正之后一直到我写一些心得时,程序都没有再跑飞,以前一直在学习前辈们的踩坑经验,今天也轮到我给萌新们分享一点自己的经验,可能有前辈会觉得这么简单的问题,我写的这么啰嗦,但实际情况却是我因此头疼了好久,才有此感想。我将程序也放在后面可以给想做光立方的同学参考一下,但是我这个的锁存器是用的74hc595 是一个8位移位缓存器和 平时使用比较多的 573 不太一样,想要参考的同学注意下,程序文件夹中我放了一个原理图pdf可以参考。
单片机源程序如下:
- #include "common.h"
- sbit RR=P3^6;//红
- sbit BB=P2^4;//蓝
- char data cheng;
- //void delay_1us(uint i)
- //{
- // unsigned int b;
- // for(b=0;b<i;b++);
- //}
- //void delay_1ms(uint i)
- //{
- // unsigned int j,k;
- // for(k=0;k<120;k++)
- // for(j=0;j<i;j++);
- //}
- void red (void) //红灯亮
- {
- RR=0;//红
- BB=1;//蓝
- }
- //void blue (void) //蓝灯亮
- //{
- // RR=1;//红
- // BB=0;//蓝
- //}
- void initial595() //列驱动初始化
- {
- SH_CP = 0;
- ST_CP = 0;
- DS = 0;
- }
- void initial5952() //行驱动初始化
- {
- SH_CP2 = 0;
- ST_CP2 = 0;
- DS2 = 0;
- }
- /************************************ 发送数据 ***************************************************************/
- //void send_data(unsigned char d)//发送一层当中的一行显示数据,8位
- //{
- // unsigned char i;
- // for(i=0;i<8;i++)
- // {
- // DS = d&0x80;//发送最低位
- // SH_CP = 1;
- // delay_1us(15);
- // SH_CP = 0; //移位寄存器移位
- // delay_1us(15);
- // d = d<<1; //数据移位f
- // }
- // //因为使用多个595级联,此处未做数据输出锁存,
- // //须将所有数据发送出来后再做锁存输出
- //}
- //void send_data2(unsigned char d)//发送层显示数据,8位
- //{
- // unsigned char i,j=0;
- //
- // for(i=0;i<8;i+=2)
- // {
- // DS2 = d&0x80;//发送最低位
- // SH_CP2 = 1;
- // delay_1us(15);
- // SH_CP2 = 0; //移位寄存器移位
- // delay_1us(15);
- // d = d<<1; //数据移位
- // }
- // ST_CP2 = 0; //数据输出锁存
- // delay_1us(15);
- // ST_CP2 = 1;
- // delay_1us(15);
- // ST_CP2 = 0;
- //}
- //void send_data2_1bit(unsigned char layer)//发送层显示数据,1位
- //{
- // unsigned char ceng=0;
- //
- // ceng=0x01<<layer; //行移位,
- // DS2 = ~ceng&0x01; //发送层扫描数据
- //
- // SH_CP2 = 1;
- // delay_1us(15);
- // SH_CP2 = 0; //移位寄存器移位
- // delay_1us(15);
- //
- // ST_CP2 = 0; //数据输出锁存
- // delay_1us(15);
- // ST_CP2 = 1;
- // delay_1us(15);
- // ST_CP2 = 0;
- //}
- void delay(uint i)
- {
- char b;
- while (i--)
- {
- b=1;
- while(b--);
- }
- }
- /*************************************黎明途电子************************************************************/
- /*************************************脱机动画文件************************************************/
- /*---------------------------
- //函数名:void sendbyte1 (uint num1....)
- //功能:一次发送四个数据给锁存器
- //参数:num1,num2,num3,num4
- //返回值:无
- ----------------------------*/
- void sendbyte1(unsigned int num1,unsigned int num2,unsigned int num3,unsigned int num4)
- {
- unsigned char i=0;
- for(i=0;i<8;i++)
- {
- DS = num1&0x01; //发送最低位
- SH_CP = 1;
- SH_CP = 0; //移位寄存器移位
- num1=num1>>1; //数据移位f
- }
- for(i=0;i<8;i++)
- {
- DS = num2&0x01; //发送最低位
- SH_CP = 1;
- SH_CP = 0; //移位寄存器移位
- num2 = num2>>1; //数据移位f
- }
- for(i=0;i<8;i++)
- {
- DS = num3&0x01; //发送最低位
- SH_CP = 1;
- SH_CP = 0; //移位寄存器移位
- num3 = num3>>1; //数据移位f
- }
- for(i=0;i<8;i++)
- {
- DS = num4&0x01; //发送最低位
- SH_CP = 1;
- SH_CP = 0; //移位寄存器移位
- num4 = num4>>1; //数据移位f
- }
-
- }
- /*----------------------------------------------
- //函数名 :void zhen (uchar *a,uchar V)
- //函数功能:将待显示的数据写入锁存器中并显示
- //参数:*a:待显示数据-,V循环此次数(为何循环?经验证只是增加显示时间)
- //返回值:无
- ------------------------------------------------*/
-
- void zhen(uchar *a,uchar v)
- {
- char layer;
- while(v--)//?为何需要循环???增加显示时间?√ 就是这样 。。
- {
-
- for(layer=0;layer<8;layer++) //将每层8列数码发送 循环8次8层数据依次发送
- { /* 数组的每一位是一列数据*/
- sendbyte1(~a[layer*8+7],~a[layer*8+6],~a[layer*8+5],~a[layer*8+4]);
- sendbyte1(~a[layer*8+3],~a[layer*8+2],~a[layer*8+1],~a[layer*8+0]);
- //和直接调显示函数是一个道理
- cheng=0x01<<layer;
- DS2 =~cheng&0x01; //发送最低位
- ST_CP=1;
- ST_CP=0;
- SH_CP2 = 1;
- SH_CP2 = 0; //移位寄存器移位
- ST_CP2=1;
- ST_CP2=0;
- delay(300);
- }
-
- }
- }
- void clc()//全局清屏
- {
- unsigned char k;
- for(k=0;k<64;k++)
- { //d=0xff;
-
- DS = 0; //发送最低位
- SH_CP = 1;
- SH_CP = 0; //移位寄存器移位
- // d = d<<1; //数据移位f
- }
- ST_CP=1;
- ST_CP=0;
- }
复制代码
所有资料51hei提供下载:
光立方修改.rar
(650.29 KB, 下载次数: 14)
|