独闷闷网

标题: 程序就像玩积木,每编写一段代码编译通过了再写下一段代码,方便找bug。 [打印本页]

作者: jianhong_wu    时间: 2014-11-16 00:11
标题: 程序就像玩积木,每编写一段代码编译通过了再写下一段代码,方便找bug。

杭州-小冯:

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

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

  18. #define const_voice_short 40   //蜂鸣器短叫的持续时间
  19. #define const_voice_long  200  //蜂鸣器长叫的持续时间

  20. void initial_myself();
  21. void initial_peripheral();
  22. void delay_long(unsigned int uidelaylong);
  23. void led_flicker();
  24. void alarm_run();
  25. void T0_time();

  26. sbit beep_dr=P2^7;
  27. sbit led_dr=P3^5;

  28. unsigned char ucledstep=0;
  29. unsigned int uitimeledcnt=0;

  30. unsigned char ucalarmstep=0;
  31. unsigned int uitimealarmcnt=0;

  32. unsigned int uitimevoicecnt=0;

  33. void main()
  34. {
  35.    initial_myself();
  36.    delay_long(100);
  37.    initial_peripheral();
  38.    while(1)
  39.    {
  40.      led_flicker();
  41.          alarm_run();
  42.     }
  43. }


  44. void led_flicker()
  45. {
  46.   switch(ucledstep)
  47.   {
  48.     case 0:
  49.               {
  50.                   if(uitimeledcnt>=const_time_05s)
  51.                   {
  52.                    uitimeledcnt=0;
  53.                    led_dr=1;
  54.                    ucledstep=1;
  55.                    }
  56.                    break;
  57.          case 1:
  58.                 {
  59.                          if(uitimeledcnt>=const_time_05s)
  60.                          {
  61.                           uitimeledcnt=0;
  62.                           led_dr=0;
  63.                           ucledstep=0;
  64.                           }
  65.                       break;
  66.     }
  67. }


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

  80.     uitimevoicecnt=const_voice_short;
  81.         ucalarmstep=1;
  82.         }
  83.     break;

  84.          case 1:
  85.          if(uitimealarmcnt>=const_time_6s)
  86.          {
  87.           uitimealarmcnt=0;
  88.           uitimevoicecnt=const_voice_long;
  89.           ucalarmstep=2;
  90.           }
  91.           break;
  92.         }
  93. }


  94. void T0_time() interrupt 1
  95. {
  96.   TF0=0;
  97.   TR0=0;

  98.   if(uitimeledcnt<0xffff)
  99.   {
  100.     uitimeledcnt++;
  101.   }
  102.   if(uitimealarmcnt<0xffff)
  103.   {
  104.      uitimealarmcnt++;
  105.    }
  106. /* 注释三:
  107. * 为什么不把驱动蜂鸣器这段代码放到main函数的循环里去?
  108. * 因为放在定时中断里,能保证蜂鸣器的声音长度是一致的,
  109. * 如果放在main循环里,声音的长度就有可能受到某些必须
  110. * 一气呵成的任务干扰,得不到及时响应,影响声音长度的一致性。
  111. */
  112.    if(uitimevoicecnt!=0)
  113.    {
  114.     uitimevoicecnt--;
  115.         beep_dr=0;
  116.         }
  117.    else
  118.    {
  119.         ;
  120.     beep_dr=1;
  121.         }

  122.    TH0=OXf8;
  123.    TL0=0X2f;
  124.    TR0=1;
  125. }


  126. void delay_long(unsigned int uidelaylong)
  127. {
  128.   unsigned int i;
  129.   unsigned int j;
  130.   for(i=0;i<uidelaylong;i++)
  131.   {
  132.     for(j=0;j<500;j++)
  133.         {
  134.           ;
  135.          }
  136.    }
  137. }

  138. void initial myself()
  139. {
  140.    beer_dr=1;
  141.    led_dr=0
  142.    TMOD=0X01;
  143.    TH0=0xf8;
  144.    TL0=0x2f;
  145. }


  146. void initial peripheral()
  147. {
  148.     EA=1;
  149.     ET0=1;
  150.         TR0=1;
  151. }
复制代码

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


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

  18. #define const_voice_short 40   //蜂鸣器短叫的持续时间
  19. #define const_voice_long  200  //蜂鸣器长叫的持续时间

  20. void initial_myself();
  21. void initial_peripheral();
  22. void delay_long(unsigned int uidelaylong);
  23. void led_flicker();
  24. void alarm_run();
  25. void T0_time();

  26. sbit beep_dr=P2^7;
  27. sbit led_dr=P3^5;

  28. unsigned char ucledstep=0;
  29. unsigned int uitimeledcnt=0;

  30. unsigned char ucalarmstep=0;
  31. unsigned int uitimealarmcnt=0;

  32. unsigned int uitimevoicecnt=0;

  33. void main()
  34. {
  35.    initial_myself();
  36.    delay_long(100);
  37.    initial_peripheral();
  38.    while(1)
  39.    {
  40.      led_flicker();
  41.          alarm_run();
  42.     }
  43. }


  44. void led_flicker()
  45. {
  46.   switch(ucledstep)
  47.   {
  48.     case 0:
  49.            //   {   第1处错误,把这个大括号删掉。
  50.                   if(uitimeledcnt>=const_time_05s)
  51.                   {
  52.                    uitimeledcnt=0;
  53.                    led_dr=1;
  54.                    ucledstep=1;
  55.                    }
  56.                    break;
  57.          case 1:
  58.             //    {         第2处错误,把这个大括号删掉。
  59.                          if(uitimeledcnt>=const_time_05s)
  60.                          {
  61.                           uitimeledcnt=0;
  62.                           led_dr=0;
  63.                           ucledstep=0;
  64.                           }
  65.                       break;
  66.     }
  67. }


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

  80.     uitimevoicecnt=const_voice_short;
  81.         ucalarmstep=1;
  82.         }
  83.     break;

  84.          case 1:
  85.          if(uitimealarmcnt>=const_time_6s)
  86.          {
  87.           uitimealarmcnt=0;
  88.           uitimevoicecnt=const_voice_long;
  89.           ucalarmstep=2;
  90.           }
  91.           break;
  92.         }
  93. }


  94. void T0_time() interrupt 1
  95. {
  96.   TF0=0;
  97.   TR0=0;

  98.   if(uitimeledcnt<0xffff)
  99.   {
  100.     uitimeledcnt++;
  101.   }
  102.   if(uitimealarmcnt<0xffff)
  103.   {
  104.      uitimealarmcnt++;
  105.    }
  106. /* 注释三:
  107. * 为什么不把驱动蜂鸣器这段代码放到main函数的循环里去?
  108. * 因为放在定时中断里,能保证蜂鸣器的声音长度是一致的,
  109. * 如果放在main循环里,声音的长度就有可能受到某些必须
  110. * 一气呵成的任务干扰,得不到及时响应,影响声音长度的一致性。
  111. */
  112.    if(uitimevoicecnt!=0)
  113.    {
  114.     uitimevoicecnt--;
  115.         beep_dr=0;
  116.         }
  117.    else
  118.    {
  119.         ;
  120.     beep_dr=1;
  121.         }

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


  127. void delay_long(unsigned int uidelaylong)
  128. {
  129.   unsigned int i;
  130.   unsigned int j;
  131.   for(i=0;i<uidelaylong;i++)
  132.   {
  133.     for(j=0;j<500;j++)
  134.         {
  135.           ;
  136.          }
  137.    }
  138. }

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


  150. //void initial peripheral() 第7处错误,这两个单词之间必须有下划线
  151. void initial_peripheral()
  152. {
  153.     EA=1;
  154.     ET0=1;
  155.         TR0=1;
  156. }
复制代码




作者: 海~~    时间: 2014-11-16 09:29
关于鸿哥提到的一段段调试,是指写一个函数就调试一次吗?那么如何方便的在keil里面调试了?
作者: jianhong_wu    时间: 2014-11-16 12:47
本帖最后由 jianhong_wu 于 2014-11-16 12:53 编辑
海~~ 发表于 2014-11-16 09:29
关于鸿哥提到的一段段调试,是指写一个函数就调试一次吗?那么如何方便的在keil里面调试了?

不一定是一个函数一个函数来写,反正是一点点往上加。比如,你做一个项目,有显示,有按键,有数据采集,那么你可以先调通按键的,再加显示的,调通了按键与显示之后,再做数据采集的,这样就一步步把项目做出来了。我是直接把程序下载到单片机电路板上看现象的,这个没有什么技巧,做多了就自然领悟了。
作者: 海~~    时间: 2014-11-17 13:47
恩,明白了,基本上是根据一个个相关功能模块调试的。




欢迎光临 独闷闷网 (http://dumenmen.com/) Powered by Discuz! X3.2