jianhong_wu 发表于 2014-11-16 00:11:02

程序就像玩积木,每编写一段代码编译通过了再写下一段代码,方便找bug。


杭州-小冯:

为什么出现这样的错啊?我检查了,没发现有错啊.鸿哥第5节内容。以下是我改写有bug的代码:

#include<reg52.h>
/* 注释一:
* 如何知道1秒钟需要多少个定时中断?
* 这个需要编写一段小程序测试,得到测试的结果后再按比例修正。
* 步骤:
* 第一步:在程序代码上先写入1秒钟大概需要200个定时中断。
* 第二步:基于以上1秒钟的基准,编写一个60秒的简单测试程序(如果编写超过
* 60秒的时间,这个精度还会更高)。比如,编写一个用蜂鸣器的声音来识别计时的
* 起始和终止的测试程序。
* 第三步:把程序烧录进单片机后,上电开始测试,手上同步打开手机里的秒表。
*         如果单片机仅仅跑了27秒。
* 第四步:那么最终得出1秒钟需要的定时中断次数是:const_time_1s=(200*60)/27=444
*/
#define const_time_05s 222    //0.5秒钟的时间需要的定时中断次数
#define const_time_1s 444    //1秒钟的时间需要的定时中断次数
#define const_time_3s 1332//3秒钟的时间需要的定时中断次数
#define const_time_6s 2664//6秒钟的时间需要的定时中断次数

#define const_voice_short 40   //蜂鸣器短叫的持续时间
#define const_voice_long200//蜂鸣器长叫的持续时间

void initial_myself();
void initial_peripheral();
void delay_long(unsigned int uidelaylong);
void led_flicker();
void alarm_run();
void T0_time();

sbit beep_dr=P2^7;
sbit led_dr=P3^5;

unsigned char ucledstep=0;
unsigned int uitimeledcnt=0;

unsigned char ucalarmstep=0;
unsigned int uitimealarmcnt=0;

unsigned int uitimevoicecnt=0;

void main()
{
   initial_myself();
   delay_long(100);
   initial_peripheral();
   while(1)
   {
   led_flicker();
       alarm_run();
    }
}


void led_flicker()
{
switch(ucledstep)
{
    case 0:
              {
                  if(uitimeledcnt>=const_time_05s)
                  {
                   uitimeledcnt=0;
                   led_dr=1;
                   ucledstep=1;
                   }
                   break;
       case 1:
                {
                       if(uitimeledcnt>=const_time_05s)
                       {
                          uitimeledcnt=0;
                          led_dr=0;
                          ucledstep=0;
                          }
                      break;
    }
}


void alarm_run()
{
   switch(ucalarmstep)
   {
    case 0:
        if(uitimealarmcnt>=const_time_3s)
        {
       uitimealarmcnt=0;
/* 注释二:
* 只要变量uiVoiceCnt不为0,蜂鸣器就会在定时中断函数里启动鸣叫,并且自减uiVoiceCnt
* 直到uiVoiceCnt为0时才停止鸣叫。因此控制uiVoiceCnt变量的大小就是控制声音的长短。
*/

    uitimevoicecnt=const_voice_short;
        ucalarmstep=1;
        }
    break;

       case 1:
       if(uitimealarmcnt>=const_time_6s)
       {
          uitimealarmcnt=0;
          uitimevoicecnt=const_voice_long;
          ucalarmstep=2;
          }
          break;
        }
}


void T0_time() interrupt 1
{
TF0=0;
TR0=0;

if(uitimeledcnt<0xffff)
{
    uitimeledcnt++;
}
if(uitimealarmcnt<0xffff)
{
   uitimealarmcnt++;
   }
/* 注释三:
* 为什么不把驱动蜂鸣器这段代码放到main函数的循环里去?
* 因为放在定时中断里,能保证蜂鸣器的声音长度是一致的,
* 如果放在main循环里,声音的长度就有可能受到某些必须
* 一气呵成的任务干扰,得不到及时响应,影响声音长度的一致性。
*/
   if(uitimevoicecnt!=0)
   {
    uitimevoicecnt--;
        beep_dr=0;
        }
   else
   {
        ;
    beep_dr=1;
        }

   TH0=OXf8;
   TL0=0X2f;
   TR0=1;
}


void delay_long(unsigned int uidelaylong)
{
unsigned int i;
unsigned int j;
for(i=0;i<uidelaylong;i++)
{
    for(j=0;j<500;j++)
        {
          ;
       }
   }
}

void initial myself()
{
   beer_dr=1;
   led_dr=0
   TMOD=0X01;
   TH0=0xf8;
   TL0=0x2f;
}


void initial peripheral()
{
    EA=1;
    ET0=1;
        TR0=1;
}

鸿哥-深圳:
我帮你找了7处错误。以后类似的问题,我希望你自己解决,你不要一下子复制我的代码,一概一点一点来调试。程序就像玩积木,是一点点往上加的,每加一段程序,就要确保通过了,然后再添加下一段代码。以后这类问题,我抽不出时间帮你的。以后一点代码一点代码网上加。不要一气呵成,这样可以及时发现bug,不然bug累加多了不好找问题。以下是我帮你修改后并且加了注释错误标注的代码:


#include<reg52.h>
/* 注释一:
* 如何知道1秒钟需要多少个定时中断?
* 这个需要编写一段小程序测试,得到测试的结果后再按比例修正。
* 步骤:
* 第一步:在程序代码上先写入1秒钟大概需要200个定时中断。
* 第二步:基于以上1秒钟的基准,编写一个60秒的简单测试程序(如果编写超过
* 60秒的时间,这个精度还会更高)。比如,编写一个用蜂鸣器的声音来识别计时的
* 起始和终止的测试程序。
* 第三步:把程序烧录进单片机后,上电开始测试,手上同步打开手机里的秒表。
*         如果单片机仅仅跑了27秒。
* 第四步:那么最终得出1秒钟需要的定时中断次数是:const_time_1s=(200*60)/27=444
*/
#define const_time_05s 222    //0.5秒钟的时间需要的定时中断次数
#define const_time_1s 444    //1秒钟的时间需要的定时中断次数
#define const_time_3s 1332//3秒钟的时间需要的定时中断次数
#define const_time_6s 2664//6秒钟的时间需要的定时中断次数

#define const_voice_short 40   //蜂鸣器短叫的持续时间
#define const_voice_long200//蜂鸣器长叫的持续时间

void initial_myself();
void initial_peripheral();
void delay_long(unsigned int uidelaylong);
void led_flicker();
void alarm_run();
void T0_time();

sbit beep_dr=P2^7;
sbit led_dr=P3^5;

unsigned char ucledstep=0;
unsigned int uitimeledcnt=0;

unsigned char ucalarmstep=0;
unsigned int uitimealarmcnt=0;

unsigned int uitimevoicecnt=0;

void main()
{
   initial_myself();
   delay_long(100);
   initial_peripheral();
   while(1)
   {
   led_flicker();
       alarm_run();
    }
}


void led_flicker()
{
switch(ucledstep)
{
    case 0:
           //   {   第1处错误,把这个大括号删掉。
                  if(uitimeledcnt>=const_time_05s)
                  {
                   uitimeledcnt=0;
                   led_dr=1;
                   ucledstep=1;
                   }
                   break;
       case 1:
          //    {       第2处错误,把这个大括号删掉。
                       if(uitimeledcnt>=const_time_05s)
                       {
                          uitimeledcnt=0;
                          led_dr=0;
                          ucledstep=0;
                          }
                      break;
    }
}


void alarm_run()
{
   switch(ucalarmstep)
   {
    case 0:
        if(uitimealarmcnt>=const_time_3s)
        {
       uitimealarmcnt=0;
/* 注释二:
* 只要变量uiVoiceCnt不为0,蜂鸣器就会在定时中断函数里启动鸣叫,并且自减uiVoiceCnt
* 直到uiVoiceCnt为0时才停止鸣叫。因此控制uiVoiceCnt变量的大小就是控制声音的长短。
*/

    uitimevoicecnt=const_voice_short;
        ucalarmstep=1;
        }
    break;

       case 1:
       if(uitimealarmcnt>=const_time_6s)
       {
          uitimealarmcnt=0;
          uitimevoicecnt=const_voice_long;
          ucalarmstep=2;
          }
          break;
        }
}


void T0_time() interrupt 1
{
TF0=0;
TR0=0;

if(uitimeledcnt<0xffff)
{
    uitimeledcnt++;
}
if(uitimealarmcnt<0xffff)
{
   uitimealarmcnt++;
   }
/* 注释三:
* 为什么不把驱动蜂鸣器这段代码放到main函数的循环里去?
* 因为放在定时中断里,能保证蜂鸣器的声音长度是一致的,
* 如果放在main循环里,声音的长度就有可能受到某些必须
* 一气呵成的任务干扰,得不到及时响应,影响声音长度的一致性。
*/
   if(uitimevoicecnt!=0)
   {
    uitimevoicecnt--;
        beep_dr=0;
        }
   else
   {
        ;
    beep_dr=1;
        }

//TH0=OXf8; //第3处错误,这个0x是数字0,而不是字母O。
   TH0=0Xf8;
   TL0=0X2f;
   TR0=1;
}


void delay_long(unsigned int uidelaylong)
{
unsigned int i;
unsigned int j;
for(i=0;i<uidelaylong;i++)
{
    for(j=0;j<500;j++)
        {
          ;
       }
   }
}

// void initial myself()第4处错误,这两个单词之间必须有下划线
void initial_myself()
{
//beer_dr=1; 第5处错误,拼写错误是beep_dr
   beep_dr=1;
//   led_dr=0   第6处错误,漏了分号;
   led_dr=0;
   TMOD=0X01;
   TH0=0xf8;
   TL0=0x2f;
}


//void initial peripheral() 第7处错误,这两个单词之间必须有下划线
void initial_peripheral()
{
    EA=1;
    ET0=1;
        TR0=1;
}



海~~ 发表于 2014-11-16 09:29:28

关于鸿哥提到的一段段调试,是指写一个函数就调试一次吗?那么如何方便的在keil里面调试了?

jianhong_wu 发表于 2014-11-16 12:47:28

本帖最后由 jianhong_wu 于 2014-11-16 12:53 编辑

海~~ 发表于 2014-11-16 09:29
关于鸿哥提到的一段段调试,是指写一个函数就调试一次吗?那么如何方便的在keil里面调试了?
不一定是一个函数一个函数来写,反正是一点点往上加。比如,你做一个项目,有显示,有按键,有数据采集,那么你可以先调通按键的,再加显示的,调通了按键与显示之后,再做数据采集的,这样就一步步把项目做出来了。我是直接把程序下载到单片机电路板上看现象的,这个没有什么技巧,做多了就自然领悟了。

海~~ 发表于 2014-11-17 13:47:58

恩,明白了,基本上是根据一个个相关功能模块调试的。
页: [1]
查看完整版本: 程序就像玩积木,每编写一段代码编译通过了再写下一段代码,方便找bug。