zoukankan      html  css  js  c++  java
  • 用_crol_函数实现LED流水灯的调试过程

    #include "reg52.h"
    #include "intrins.h"
    typedef unsigned int u16;
    typedef unsigned char u8;
    #define led P2
    u16 ret;
    
    void delay(u16 i)
    {
        while(i--)
        {};
    }
    
    void main(void)
    {
    
        
    
        while(1)
        {
           led=0xfe;                //D1亮 ,其它灯不亮
           delay(60000);
           
           _crol_(led,1);            //0xFD  D2亮,其它不亮 
           delay(60000);
        
        }
    
    }

    我最开始的代码大概是上面这个样子的,我的预期是先是D1亮,然后是D1灭,D2亮,结果是始终是D1亮。百思不得其解,于是开始了漫长的调试。

    感觉问题应该出在_crol_这个函数的前后,F9下了两个断点

    ctrl+F5开启调试

    在watch中添加P2这个寄存器,led是P2的别名,因为我们想看它的值。

    F10步过_crol_函数之后发现P2的值更本没有改变,P2的值初始化是0xFF,然后经过我们的赋值,它是0xFE,经过_crol_它的值还是0xFE, 这就很奇怪了,然后我就想着是不是这个函数有什么问题

    于是定义了一个变量ret来接受_crol_函数的返回值,并把ret也作为watch的对象,看一下它的值是怎么变化的。

    经过调试发现最后ret的值正好是0xFD,所以_crol_的返回值才是我们要的结果。

    _crol_(led,1)并不会修改led的值,它是把led的值复制一份,然后修改之后把这个结果以返回值的方式存放起来。

    所以产生这个问题的原因是没有阅读_crol_的官方文档,不知道被操作数的结果是以什么形式返回的。

    这里是_crol_函数的官方解释:

    http://www.keil.com/support/man/docs/c51/c51__crol_.htm?_ga=2.234590429.235304523.1557741929-1916941500.1557741929

    #include "reg52.h"
    #include "intrins.h"
    typedef unsigned int u16;
    typedef unsigned char u8;
    #define led P2
    
    
    void delay(u16 i)
    {
        while(i--)
        {};
    }
    
    void main(void)
    {
    
        
    
        while(1)
        {
           led=0xfe;                //D1亮 ,其它灯不亮
           delay(60000);
           
           led=_crol_(led,1);        //0xFD  D2亮,其它不亮 
           delay(60000);
    
           led=_crol_(led,1);       //D3亮
           delay(60000);
    
           led=_crol_(led,1);       //D4亮
           delay(60000);
    
           led=_crol_(led,1);       //D5亮
           delay(60000);
    
           led=_crol_(led,1);       //D6亮
           delay(60000);
    
           led=_crol_(led,1);       //D7亮
           delay(60000);
    
           led=_crol_(led,1);       //D8亮
           delay(60000);
    
           //让D7开始亮 一直到D1
    
           led=_cror_(led,1);      //D7亮
           delay(60000);
    
           led=_cror_(led,1);      //D6亮
           delay(60000);
    
           led=_cror_(led,1);      //D5亮
           delay(60000);
    
           led=_cror_(led,1);      //D4亮
           delay(60000);
    
           led=_cror_(led,1);      //D3亮
           delay(60000);
    
           led=_cror_(led,1);      //D2亮
           delay(60000);
        
        }
    
    }

    这个程序的while循环最后一点代码要解释一下当D2亮起之后,P2的位状态是1111 1101,然后delay一下,然后就到了循环开始的部分了,这里让led初始化fe了,所以第一个灯又亮了,

    也就是每循环一次,led就被初始化一次。

    这个代码是可以继续优化的,D2到D8亮起来用的是同样的代码,我们可以放在一个for循环里面 D7到D2也可以放在一个for循环里面。

    比如for (i=0;i<7;i++)

    {

      led=_crol(led,1);

    }

     for (i=0;i<6;i++)

    {

      led=_cror(led,1);

    }

    这里有个很重要的点,就是为什么我们可以通过循环右移和循环左移来控制灯的亮灭?

    其实就是从原理图来的,我们看下图再说。

    有图可知,P2的第0位控制D1,等等等 P2的第7位控制D8,而且只需要将P2的第0位设置位低电平就可以让D1亮起来,设置高电平就可以让D1灭了。

    P2是什么它是一个寄存器的名字,它有8个位,从第0位到第7位

    根据流水灯的定义,先让D1亮起来,那么此时需要P2的值是1111 1110 然后需要D2亮起来,此时需要P2的值是1111 1101,然后需要D3亮起来,此时需要P2的值是1111 1110

    .。。。需要D8亮起来,需要P2的值是0111 1111

    从1111 1101 到1111 1101 到1111 1011 再到0111 1111 是不是发现就是0的位置向左移动了?_crol_就有这种功能啊。

    _crol_的实现是这样的,它叫做循环左移,你把1111 1110  左移一位之后 ,那么新生成的那个数是1111110X,最末尾的这个X是多少呢?就是1111 11110 最高位被挤出去的那一位,然后补回到了1111110X的最低位,也就是最后的结果是1111 1101  ,循环左移,这个循环很重要。

    我画了一张图解释这个过程,循环右移也是一样的。

    C语言中还有左移和右移的操作,能不能用在这里呢?

          while(1)
              {
                
                 P2=0xFE; //1111 1110
                 delay(60000);
                 P2=P2<<1;
                 delay(60000);
                 P2=P2<<1;
                 delay(60000);
    
    
    
              }                  

    从0xFE(1111 1110)每次左移一位的结果

    1111 1100
    1111 1000

    可以看出左移运算符是把高位挤出去之后,新生成的数的低位是用0填充的,并不能满足我们流水灯的定义。

    所以最符号我们要求的就是循环左移函数和循环右移函数。

  • 相关阅读:
    JDK -GET,POST
    (三十四)什么是自动化测试模型之模块化驱动测试实例
    Linux 运维命令及知识
    python_检测一些特定的服务端口有没有被占用
    程序员常用网站
    网络安全与CTF在线学习资源网站
    MySQL_语句
    python脚本实现自动安装nginx
    超赞的Linux软件
    Python运维中常用的_脚本
  • 原文地址:https://www.cnblogs.com/yfish/p/10858286.html
Copyright © 2011-2022 走看看