找回密码
 立即注册

QQ登录

只需一步,快速开始

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

误人子弟的程序分析

  [复制链接]
跳转到指定楼层
楼主
本帖最后由 codenew 于 2014-10-6 22:42 编辑

       下面程序是我从别的地方搞来的,最后发现很多错误。为了避免误人子弟,特地作了一下分析,开头部分for分析是我写的,程序中红色的部分我是加上去的。
        在软件仿真环境下,把晶振改成12.0MhzC51标签代码优化设为0,见图附件,测得for语句的延时为:
   for(time=0;time<1;time++);  //15us
   for(time=0;time<2;time++);  //23us
   for(time=0;time<3;time++);  //31us
   for(time=0;time<4;time++);  //39us
   for(time=0;time<5;time++);  //47us
   for(time=0;time<6;time++);  //55us
   for(time=0;time<7;time++);  //63us
   for(time=0;time<8;time++);  //71us
   for(time=0;time<9;time++);  //79us
   for(time=0;time<10;time++); //87us
   for(time=0;time<20;time++); //167us
   for(time=0;time<60ime++);  //487us
   for(time=0;time<70ime++);  //567us
   for(time=0;time<80ime++);  //647us
   for(time=0;time<100;time++);  //807us
   for(time=0;time<200;time++); //1607us
    由上可看出,成等差数列,公差d=8。一般地,如果n>man=am+8*(n-m)



/*****************************************************
函数功能:将DS18B20传感器初始化,读取应答信号
出口参数:flag
***************************************************/
bit Init_DS18B20(void)
{
       bitflag;         //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在
       DQ= 1;           //先将数据线拉高
       for(time=0;time<2;time++);//略微延时约6微秒。实际是延时23us
       DQ= 0;           //再将数据线从高拉低,要求保持480~960us
       for(time=0;time<200;time++);//略微延时约600微秒,以向DS18B20发出一持续480~960us的低电平复位脉冲。际是延时1607us,重大错误,都超过960us了。
       DQ= 1;           //释放数据线(将数据线拉高)
       for(time=0;time<10;time++);//延时约30us(释放总线后需等待15~60usDS18B20输出存在脉冲)。实际是延时87us,延时多过60us,反而能保证读到存在脉冲,这点误撞了。
       flag=DQ;          //让单片机检测是否输出了存在脉冲(DQ=0表示存在)      
       for(time=0;time<200;time++);  //延时足够长时间,等待存在脉冲输出完毕
       return(flag);    //返回检测成功标志
}
/*****************************************************
函数功能:从DS18B20读取一个字节数据
出口参数:dat
***************************************************/
unsigned char ReadOneChar(void)
{
       unsignedchar i=0;  
       unsignedchar dat;            //储存读出的一个字节数据
       for(i=0;i<8;i++)
       {
              DQ=1;                    //先将数据线拉高
              _nop_();               //等待一个机器周期   
              DQ= 0;        //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
              dat>>=1;
              _nop_();        //等待一个机器周期                 
              DQ= 1;        //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
              for(time=0;time<2;time++);//延时约6us,使主机在15us内采样。实际是延时23us,超过了15us
              if(DQ==1)
              dat|=0x80;                //如果读到的数据是1,则将1存入dat
              else
              dat|=0x00;/如果读到的数据是0,则将0存入dat,将单片机检测到的电平信号DQr
              for(time=0;time<8;time++);//延时3us,两个读时序之间必须有大于1us的恢复期。实际是延时71us。思路根本不对,读时隙至少延时60us,这里又误撞对了,把至少延时和读时隙间隔至少1us都包含进了。
           }                        
              return(dat);    //返回读出的十进制数据
}
/*****************************************************
函数功能:向DS18B20写入一个字节数据
入口参数:dat
***************************************************/  
WriteOneChar(unsigned char dat)
{
       unsignedchar i=0;
       for(i=0; i<8; i++)
       {
              DQ=1;         // 先将数据线拉高
              _nop_();     //等待一个机器周期        
              DQ=0;          //将数据线从高拉低时即启动写时序      
              DQ=dat&0x01;   //利用与运算取出要写的某位二进制数据,并将其送到数据线上等待DS18B20采样   
              for(time=0;time<10;time++);//延时约30usDS18B20在拉低后的约15~60us期间从数据线上采样。实际是延时87us
              DQ=1;          //释放数据线            
              for(time=0;time<1;time++);//延时3us,两个写时序间至少需要1us的恢复期 实际是延时15us
              dat>>=1;       //dat中的各二进制位数据右移1
       }
       for(time=0;time<4;time++);//稍作延时,给硬件一点反应时间。延时39us   
}
/*****************************************************
函数功能:做好读温度的准备
***************************************************/
void ReadyReadTemp(void)
{
       Init_DS18B20();             //DS18B20初始化
       WriteOneChar(0xCC);         // 跳过读序号列号的操作
       WriteOneChar(0x44);         // 启动温度转换        
       for(time=0;time<100;time++);//温度转换需要一点时间。延时807us
       Init_DS18B20();     //DS18B20初始化
       WriteOneChar(0xCC);//跳过读序号列号的操作
       WriteOneChar(0xBE);//读取温度寄存器,前两个分别是温度的低位和高位   
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsigned char n)
{
  unsigned char i;
       for(i=0;i<n;i++)
          delay1ms();
}
     照理说void delaynms(unsigned char n),参数n的取值范围是0~255,因是是无符号数。但在主函数中却调用delaynms(1000),明显错误,超出取值范围。

C51.jpg (87.78 KB, 下载次数: 154)

C51代码优化

C51代码优化

评分

参与人数 1黑币 +30 收起 理由
dww465757120 + 30 赞一个!

查看全部评分

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

使用道具 举报

沙发
ID:19715 发表于 2014-10-7 08:47 | 只看该作者
程序的注释,不是完全对。
程序通过返复调整得到正确代码,这是每一个程序员编程过程,
在这过程中不可能总是修改注释,
这样就导致注释的不同步。
延时函数一般情况下是线性。
原程序的运行机器周期可能不是1us
回复

使用道具 举报

板凳
ID:65751 发表于 2014-10-7 10:54 | 只看该作者
楼上,我敢保证我的想法是对的。因为把源程序原封不动写入芯片,测温是正常显示的,晶振是12Mhz。当然引脚也是对应的。
回复

使用道具 举报

地板
ID:65751 发表于 2014-10-7 11:13 | 只看该作者
这要动脑再想想哪程序错了,为什么还能正常用,的确运气很好。例如源程序的另一个延时程序又是错的,其注释思路肯定不对,但其实际效果还是接近1ms的:
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}
回复

使用道具 举报

5#
ID:19715 发表于 2014-10-7 15:37 | 只看该作者
codenew 发表于 2014-10-7 10:54
楼上,我敢保证我的想法是对的。因为把源程序原封不动写入芯片,测温是正常显示的,晶振是12Mhz。当然引脚 ...

DS18B20的读写操作需要一段时间,是不能短于时顺规定的时间,如果延时长了,只是浪费时间而已。
可以长,但是不能短
回复

使用道具 举报

6#
ID:19715 发表于 2014-10-7 15:40 | 只看该作者
codenew 发表于 2014-10-7 11:13
这要动脑再想想哪程序错了,为什么还能正常用,的确运气很好。例如源程序的另一个延时程序又是错的,其注释 ...

如果晶振是12Mhz。那么
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}
这个就不能认为是1ms,相差不只一倍
回复

使用道具 举报

7#
ID:19715 发表于 2014-10-7 15:48 | 只看该作者
你延时这样计算就有错误
看看 delay1ms()
编译出来的内码,精算一下:
delay1ms:   CLR   A                  //1T
                   MOV   R7,A            //1T
D1:             CLR   A                   //1T
                   MOV   R6,A             //1T
D2:              INC   R6                 //1T
                   CJNE  R6,#21H,D2 //2T
                   INC   R7                  //1T
                   CJNE  R7,#04H,D1 //2T
                   RET                        //2T
2T + [( 2T + 33 * 3T) + 1T + 2T ] * 4 + 2T
= 2T + [ 101T + 1T + 2T ] * 4 + 2T
= 2T + [ 104 T] * 4 + 2T
= 2T + [ 104 T] * 4 + 2T
= 420T
再加上调用delay1ms()时间,需要的LCALL两个机器周期,就是:
422us
回复

使用道具 举报

8#
ID:19715 发表于 2014-10-7 16:12 | 只看该作者
   for(time=0;time<1;time++);  //15us
   for(time=0;time<2;time++);  //23us
   for(time=0;time<3;time++);  //31us
   for(time=0;time<4;time++);  //39us
   for(time=0;time<5;time++);  //47us
   for(time=0;time<6;time++);  //55us
   for(time=0;time<7;time++);  //63us
   for(time=0;time<8;time++);  //71us
   for(time=0;time<9;time++);  //79us
   for(time=0;time<10;time++); //87us
   for(time=0;time<20;time++); //167us
   for(time=0;time<60ime++);  //487us
   for(time=0;time<70ime++);  //567us
   for(time=0;time<80ime++);  //647us
   for(time=0;time<100;time++);  //807us
   for(time=0;time<200;time++); //1607us
这些原地延时是没有可变性的(当然是排除中断的骚扰),
编译出来的机器码是有固定模式的:
START:        CLR   A       //1T
                   MOV   R7,A  //1T
LOOP:         INC   R7      //1T
                   CJNE  R7,#02H,LOOP     //2T
所以延时时间:2T+time*(1T+2T)=2T+time*3T=(2+time*3)T
如果一个机器周期为:1us
  an=am+8*(n-m)这跟:
    =2+3*time差别大不大?
   for(time=0;time<1;time++);  //15us-------5us
   for(time=0;time<2;time++);  //23us-------8us
   for(time=0;time<3;time++);  //31us-------11us
   for(time=0;time<4;time++);  //39us-------14us
   for(time=0;time<5;time++);  //47us-------17us
   for(time=0;time<6;time++);  //55us-------20us
   for(time=0;time<7;time++);  //63us-------23us
   for(time=0;time<8;time++);  //71us-------26us
   for(time=0;time<9;time++);  //79us-------29us
   for(time=0;time<10;time++); //87us-------32us
   for(time=0;time<20;time++); //167us-------62us
   for(time=0;time<60ime++);  //487us-------182us
   for(time=0;time<70ime++);  //567us-------212us
   for(time=0;time<80ime++);  //647us-------242us
   for(time=0;time<100;time++);  //807us-------302us
   for(time=0;time<200;time++); //1607us-------602us
回复

使用道具 举报

9#
ID:65751 发表于 2014-10-7 20:31 | 只看该作者
本帖最后由 codenew 于 2014-10-7 20:37 编辑

楼上算错了吧。见附图,运行完359行指令res=0;时的时间点为631us;运行完360行指令 for(time=0;time<1;time++);  时的时间点为646us,注意黄色箭头指向下一条。646us-631us=15us,即为 运行for(time=0;time<1;time++); 的时间。
我反汇编 for(time=0;time<1;time++);  代码如下:
   360:         for(time=0;time<1;time++);
C:0x0005    752E00   MOV      time(0x2E),#0x00
C:0x0008    E52E     MOV      A,time(0x2E)
C:0x000A    C3       CLR      C
C:0x000B    9401     SUBB     A,#0x01
C:0x000D    5004     JNC      C:0013
C:0x000F    052E     INC      time(0x2E)
C:0x0011    80F5     SJMP     C:0008
   361:         res=0;
C:0x0013    C20B     CLR      0x21.3

d1.jpg (10.12 KB, 下载次数: 192)

d1.jpg

d2.jpg (10.55 KB, 下载次数: 189)

d2.jpg
回复

使用道具 举报

10#
ID:65751 发表于 2014-10-7 20:50 | 只看该作者
本帖最后由 codenew 于 2014-10-7 21:01 编辑

看看delay1ms(),1774us-647us=1127us,接近1ms。
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}







回复

使用道具 举报

11#
ID:44262 发表于 2014-10-7 22:15 来自手机 | 只看该作者
我靠 太牛了 ,楼主的这个帖子对我的帮助非常大 ,佩服得五体投地 阿
回复

使用道具 举报

12#
ID:19715 发表于 2014-10-7 22:19 | 只看该作者
本帖最后由 明白 于 2014-10-7 23:59 编辑

刚才我也仿真一下:

for(time=0;time<1;time++);的话:
396-391=5个机器周期

参数1结束.png (3.38 KB, 下载次数: 153)

参数1结束.png

参数1开始.png (4.2 KB, 下载次数: 187)

参数1开始.png
回复

使用道具 举报

13#
ID:19715 发表于 2014-10-7 23:16 | 只看该作者
本帖最后由 明白 于 2014-10-8 00:25 编辑

for(time=0;time<2;time++);的话:
399-391=8个机器周期

参数2结束.png (3.08 KB, 下载次数: 175)

参数2结束.png

参数2开始.png (3.43 KB, 下载次数: 173)

参数2开始.png

原地延时机器码.jpg (16.78 KB, 下载次数: 146)

原地延时机器码.jpg
回复

使用道具 举报

14#
ID:19715 发表于 2014-10-8 00:06 | 只看该作者
本帖最后由 明白 于 2014-10-8 00:37 编辑

delay1ms()延时函数:
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}

834-412=422
看看delay1ms(),跟我上面精度计算结果也是422,一模一样。

函数调用结束.jpg (18.06 KB, 下载次数: 169)

函数调用结束.jpg

函数调用开始.jpg (26.17 KB, 下载次数: 143)

函数调用开始.jpg

函数调用延时机器码.jpg (32.77 KB, 下载次数: 166)

函数调用延时机器码.jpg
回复

使用道具 举报

15#
ID:19715 发表于 2014-10-8 00:30 | 只看该作者
全部的机器码

全部代码.jpg (88.27 KB, 下载次数: 162)

全部代码.jpg
回复

使用道具 举报

16#
ID:19715 发表于 2014-10-8 00:36 | 只看该作者
本帖最后由 明白 于 2014-10-8 00:42 编辑

你篡改了别人原c语言程序的本意,
到此为止,你也应该知道源程序哪里被你改了吧
回复

使用道具 举报

17#
ID:67070 发表于 2014-10-8 10:21 | 只看该作者
没看懂的说
回复

使用道具 举报

18#
ID:65751 发表于 2014-10-8 17:14 | 只看该作者
本帖最后由 codenew 于 2014-10-8 17:31 编辑

     认真看了一下存在的争议,主要是代码优化和全局变量出了问题。我之前发的贴,代码优化是设为0的,由于代码没有优化,存在冗余部分,所以执行时间较长。另外全局变量和局部变量也会影响执行时间。
     新建的工程代码优化默认为8,见下图所示。     

     1.晶振设为12Mhz时,代码优化为8 ,time为全局变量时,主程序如下:
#include <reg52.h>#include <intrins.h>
unsigned char time;//设置全局变量,专门用于严格延时
void main()
{
bit res;
res=1;
while(1)
{
  res=0;
  for(time=0;time<1;time++);
  res=0;
  }
}
     测得  for(time=0;time<1;time++);时间如下:
  

   


      397us-391us=6us,即for(time=0;time<1;time++);为6us。同理time<2时,为10us;time<3时,为14us。一般地,n>m,time<n,n为正整数,an=am+4*(n-m)。m=1时,an=6+4*(n-1)=4n+2。
        for(time=0;time<1;time++);  //6us
        for(time=0;time<2;time++);  //10us
       for(time=0;time<3;time++);  //14us
       for(time=0;time<4;time++);  //18us
       for(time=0;time<5;time++);  //22us
       for(time=0;time<6;time++);  //26us
       for(time=0;time<7;time++);  //30us
       for(time=0;time<8;time++);  //34us
       for(time=0;time<9;time++);  //38us
       for(time=0;time<10;time++); //42us
       for(time=0;time<20;time++); //82us
       for(time=0;time<60ime++);  //242us
       for(time=0;time<70ime++);  //282us
      for(time=0;time<80ime++);  //322us
      for(time=0;time<100;time++);  //402us
      for(time=0;time<200;time++); //802us


      2.晶振设为12Mhz时,代码优化为8 ,time为局部变量时,主程序如下:
#include <reg52.h>
#include <intrins.h>
void main()
{
unsigned char time;//设置局部变量
bit res;
res=1;
while(1)
{
  res=0;
  for(time=0;time<1;time++);
  res=0;
  }
}
         测得  for(time=0;time<1;time++);时间如下:






        396us-391us=5us,即for(time=0;time<1;time++);为5us。同理time<2时,为8us;time<3时,为11us。一般地,n>m,time<n,n为正整数,an=am+3*(n-m)。m=1时,an=5+3*(n-1)=3n+2。
        for(time=0;time<1;time++);  //5us
        for(time=0;time<2;time++);  //8us
       for(time=0;time<3;time++);  //11us
       for(time=0;time<4;time++);  //14us
       for(time=0;time<5;time++);  //17us
       for(time=0;time<6;time++);  //20us
       for(time=0;time<7;time++);  //23us
       for(time=0;time<8;time++);  //26us
       for(time=0;time<9;time++);  //29us
       for(time=0;time<10;time++); //32us
       for(time=0;time<20;time++); //62us
       for(time=0;time<60ime++);  //182us
       for(time=0;time<70ime++);  //212us
      for(time=0;time<80ime++);  //242us
      for(time=0;time<100;time++);  //302us
      for(time=0;time<200;time++); //602us      
      这点和8楼的一致。                  3.重要说明,源程序的time是全局变量!当优化代码为默认的级别8时,再回头看源程序的注释。void delay1ms()正如7楼所说,是422us,不是源程序注释所说的1ms,其它的可参照第1点全局变量time所罗列的延时时间。





回复

使用道具 举报

19#
ID:65751 发表于 2014-10-9 09:50 | 只看该作者
本帖最后由 codenew 于 2014-10-9 09:58 编辑

//下面的time在源程序中都是全局变量!
/*****************************************************
函数功能:将DS18B20传感器初始化,读取应答信号
出口参数:flag
***************************************************/
bit Init_DS18B20(void)
{
       bitflag;         //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在
       DQ= 1;           //先将数据线拉高
       for(time=0;time<2;time++);//略微延时约6微秒。实际是延时10us,局部变量时为8us,不是注释所说的6us。
       DQ= 0;           //再将数据线从高拉低,要求保持480~960us
       for(time=0;time<200;time++);//略微延时约600微秒,以向DS18B20发出一持续480~960us的低电平复位脉冲。实际是延时802us,time为局部变量时才为602us,即约600us。这点作者明显误撞了,幸好802us还在范围内。
       DQ= 1;           //释放数据线(将数据线拉高)
       for(time=0;time<10;time++);//延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)。实际是延时42us,time为局部变量时才为 32us,即约32us。明显作者又错了,把time当作局部变量了,幸好 42us还在范围内。实际最好延时60us,确保能读到存在脉冲。
       flag=DQ;          //让单片机检测是否输出了存在脉冲(DQ=0表示存在)      
       for(time=0;time<200;time++);  //延时足够长时间,等待存在脉冲输出。延时802us。
       return(flag);    //返回检测成功标志
}
/*****************************************************
函数功能:从DS18B20读取一个字节数据
出口参数:dat
***************************************************/
unsigned char ReadOneChar(void)
{
       unsignedchar i=0;  
       unsignedchar dat;            //储存读出的一个字节数据
       for(i=0;i<8;i++)
       {
              DQ=1;                    //先将数据线拉高
              _nop_();               //等待一个机器周期   
              DQ= 0;        //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
              dat>>=1;
              _nop_();        //等待一个机器周期                 
              DQ= 1;        //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
              for(time=0;time<2;time++);//延时约6us,使主机在15us内采样。实际是延时10us,局部变量时为8us,都不是注释的6us。
              if(DQ==1)
              dat|=0x80;                //如果读到的数据是1,则将1存入dat
              else
              dat|=0x00;/如果读到的数据是0,则将0存入dat,将单片机检测到的电平信号DQ、r
              for(time=0;time<8;time++);//延时3us,两个读时序之间必须有大于1us的恢复期。实际是延时34us,与3us差很多。
           }                        
              return(dat);    //返回读出的十进制数据
}
/*****************************************************
函数功能:向DS18B20写入一个字节数据
入口参数:dat
***************************************************/  
WriteOneChar(unsigned char dat)
{
       unsignedchar i=0;
       for(i=0; i<8; i++)
       {
              DQ=1;         // 先将数据线拉高
              _nop_();     //等待一个机器周期        
              DQ=0;          //将数据线从高拉低时即启动写时序      
              DQ=dat&0x01;   //利用与运算取出要写的某位二进制数据,并将其送到数据线上等待DS18B20采样   
              for(time=0;time<10;time++);//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样。实际是延时42us,局部变量时才为32us。
              DQ=1;          //释放数据线            
              for(time=0;time<1;time++);//延时3us,两个写时序间至少需要1us的恢复期 。实际是延时6us,局部变量时才为5us。
              dat>>=1;       //将dat中的各二进制位数据右移1位
       }
       for(time=0;time<4;time++);//稍作延时,给硬件一点反应时间。延时18us。   
}
/*****************************************************
函数功能:做好读温度的准备
***************************************************/
void ReadyReadTemp(void)
{
       Init_DS18B20();             //将DS18B20初始化。既然Init_DS18B20();有返回值flag,不判断其值是否成功就写命令了,又笔误。
       WriteOneChar(0xCC);         // 跳过读序号列号的操作
       WriteOneChar(0x44);         // 启动温度转换        
       for(time=0;time<100;time++);//温度转换需要一点时间。延时402us。
       Init_DS18B20();     //将DS18B20初始化
       WriteOneChar(0xCC);//跳过读序号列号的操作
       WriteOneChar(0xBE);//读取温度寄存器,前两个分别是温度的低位和高位   
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsigned char n)
{
  unsigned char i;
       for(i=0;i<n;i++)
          delay1ms();
}
    // 照理说void delaynms(unsigned char n),参数n的取值范围是0~255,因是是无符号数。但在主函数中却调用delaynms(1000),明显错误,超出取值范围。/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay1ms()
{
   unsigned char i,j;        
         for(i=0;i<4;i++)
          for(j=0;j<33;j++);               
}
//实际延时422us,代码优化为0时才接近1ms。


回复

使用道具 举报

20#
ID:92810 发表于 2015-10-18 14:20 | 只看该作者
好的,谢谢分享了。。。
回复

使用道具 举报

21#
ID:99672 发表于 2015-12-28 10:09 | 只看该作者
有没有完整的对的程序u
回复

使用道具 举报

22#
ID:101595 发表于 2016-1-10 21:04 来自手机 | 只看该作者
18b20有时候跟硬件关系很大,不同硬件程序跑出来不一样,还有中断也会影响到它的测量
回复

使用道具 举报

23#
ID:134697 发表于 2016-7-23 12:13 | 只看该作者
楼主人好,技术不错。
回复

使用道具 举报

24#
ID:141210 发表于 2016-10-3 15:54 | 只看该作者
看不懂呀,有完整程序啊


回复

使用道具 举报

25#
ID:196669 发表于 2017-5-5 10:54 | 只看该作者
完整的有吗?
回复

使用道具 举报

26#
ID:149451 发表于 2017-5-10 09:52 | 只看该作者
钦佩做事认真的人,因为曾有伟人说过,“世界上怕就怕认真二字”,科学来不得半点马虎。
回复

使用道具 举报

27#
ID:450849 发表于 2020-4-1 08:29 | 只看该作者
阻塞式延时都是垃圾,,哈哈
回复

使用道具 举报

28#
ID:675145 发表于 2020-4-1 10:44 | 只看该作者
神仙打架
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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