用_crol_函数实现LED流水灯的调试过程

发布时间:2024-08-16  

#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填充的,并不能满足我们流水灯的定义。


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





文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    基于51单片机的智能路灯控制器设计;一.系统概述 系统使用的模块有AT89C51单片机+LCD1602显示屏+ADC0832+按键+小灯。 本次设计的智能路灯控制系统以AT89C51单片机为控制......
    弄了很长时间没弄出来,今天在大神的帮助下终于拨开云雾见天日了。 案例介绍: 利用单片机a将一段流水灯控制程序发送到单片机b,来控制单片机b的P1口,点亮8位LED灯。 案例分析: a完成发送,b完成接收。编写程序设......
    用51单片机控制的LED流水灯设计;  1.引言   当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化智能控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未见的速度被单片机智能控制系统......
    用单片机控制的LED流水灯设计;1.引言 当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化智能控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未见的速度被单片机智能控制系统......
    基于51单片机的电梯控制系统设计;一.系统概述 系统使用的模块有AT89C51单片机+LCD1602显示屏+ADC0832+按键+小灯。 本次设计的智能路灯控制系统以AT89C51单片机为控制......
    器,电路組成如图所示。电路由控制脉冲发生器、控布脉冲分配器和努灯控制输出电器组成。   51单片机流水灯电路图(六)   基于单片机设计的十六路流水灯电路原理图 ......
    流水等上下(2024-08-01)
    );               }       P2=0x00;       }                          }  */        //程序名:LLL22_4.C    //程序功能:流水灯控制左移 右移......
    移位指令和循环移位指令的区别 S7-1200移位指令的流水灯控制编程;移位指令和循环移位指令的区别 移位指令和循环移位指令是在计算机体系结构中常见的操作指令,用于......
    的电磁兼容试验与上车测试,最终再次取得车厂的认可,前装旗舰SUV车型。” 赛腾微 MCU+高压LDO组合套片自2018年从转向流水灯控制导入,至今已逐步渗透到车窗门控开关、电动换挡器、智能雨刮以及电动座椅控制器等车身控制系统......
    步进电机控制系统程序如何设计;导语:步进电机控制系统程序的设计是实现步进电机控制的重要环节。 一、确定控制要求 首先需要确定步进电机控制系统的控制要求,包括控制精度、速度、转向等方面。例如,在机......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>