#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 P2void 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 1110delay(60000);P2=P2<<1;delay(60000);P2=P2<<1;delay(60000);}                  

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

1111 1100
1111 1000

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

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

转载于:https://www.cnblogs.com/yfish/p/10858286.html

用_crol_函数实现LED流水灯的调试过程相关推荐

  1. LED闪烁和流水灯,调试教程,在线仿真器的使用

    常用的延时方法: 软件延时(使用简单但是浪费CPU资源).定时器延时(不浪费CPU资源),本次先使用软件延时. LED全亮代码: #include<reg52.h> //引用51的头文件 ...

  2. 51单片机 按键控制LED流水灯模式

    本章博客实现按键控制LED流水灯模式的功能 1.将之前文件中Delay.c.h复制过来,进行添加 2.模块化编程 3.main.c #include <REGX52.H> #include ...

  3. LED流水灯切换中断的替代法

    在老师布置作业时,遇到一个问题.用独立按键控制LED流水灯,要求按一次K1左移,按K2实现右移,持续1S.且要在当前的LED位置实现切换方向.一开始做的时候,一直要等待亮完一次之后在某个节点按下按钮才 ...

  4. 单片机led流水灯实验c语言程序,单片机LED流水灯实验及流程图源代码详解

    利用实验室提供的单片机实验开发板的最小系统电路模块.流水灯电路模块,以及Protues仿真软件搭建电路,实现I/O口循环流水灯演示效果. LED流水灯控制电路如图2-1所示,八个LED灯D0-D7(可 ...

  5. LED模块:LED流水灯

    LED模块:LED流水灯 实验现象 LED呈现先向左依次点亮再向右依次点亮的效果 单片机型号:STC89C52 硬件原理 LED 灯为发光二极管,一共有八个 LED 灯,如上图原理图,发光二极管的正极 ...

  6. 【51单片机入门】点亮多个LED流水灯

    [51单片机&入门]点亮多个LED流水灯 实验环境 功能实现 PCB原理图 代码 要点 仿真 代码 实验环境 Keil C51 Proteus 8.9 功能实现 LED流水灯依次从右向左亮起, ...

  7. C51单片机实验——LED流水灯

    实验一 LED流水灯实验报告 实验名称:LED流水灯实验 实验环境:普中实验系统:Keil μVision 4软件: 实验目的: (1)掌握uVision实验环境的使用 (2)掌握单片机I/O控制方法 ...

  8. 单片机c语言编程实现中间向两边,再从两边向中间亮的程序流程图,单片机控制LED流水灯从中间向两边.doc...

    单片机控制LED流水灯从中间向两边,从两边向中间 这个就是把 先奇数亮再偶数亮,循环三次:一个灯上下循环三次:两个分别从两边往中间流动三次:再从中间往两边流动三次:不过这个程序实现的 应该是这样的 先 ...

  9. 单片机实验:使用c语言实现LED流水灯

    单片机实验:使用c语言实现LED流水灯 目的:实现一个简单的流水灯程序 仿真软件:Portues 编程软件:Keil Portues 原理图绘制: 需要用到的模块: 单片机:AT89C51 电容:04 ...

  10. 基于51单片机的8个LED流水灯的的设计

    本设计旨在实现8个LED流水灯的设计. 原理图: 参考代码: #include<reg52.h> #include<intrins.h> #define uint unsign ...

最新文章

  1. 1000万贷款三年,到期一次性偿还1500万,这个利息算不算高?
  2. oracle修改数据库国际字符集,Oracle修改数据库字符集
  3. QDU-Training-01
  4. windows组件向导里没有internet 信息服务(iis) 的解决办法
  5. 高中职业学校计算机专业题,职业高中高考计算机专业试题3.doc
  6. 计算机博士后流动站有哪些,全国博士后流动站一览表.docx
  7. 基于python的在线考试系统-Python在线考试系统防作弊功能的思路和实现
  8. 如何将3dmax结合前端_如何将阅读与写作结合
  9. spring session 考虑问题解答
  10. 高中数学知识那些和计算机有关系,2016高中数学知识点.doc
  11. turn.js 异步请求图片资源,实现电子书翻页效果 报错 ”The page 1 dose not exist”
  12. java实现网页评分_Java web分级测试评分C级感受
  13. NetFPGA-SUME上电测试
  14. p5.js创意绘图(2)自画像
  15. 为什么你的HDMI口没信号!
  16. rdd实验——教师绩效考核
  17. 递推递归练习H - 三国佚事——巴蜀之危
  18. 索尼录音笔怎么导出录音内容_商务、学生、记者:有能把录音文件转成文字文档的软件吗?...
  19. 达梦数据库DM8版本DSC集群启停注意事项
  20. 如何评价测试人员的工作绩效?

热门文章

  1. 怎么更改计算机用户开机密码,如何更改Windows开机密码?修改电脑开机密码教程...
  2. python求excel的最大行_解决使用Pandas 读取超过65536行的Excel文件问题
  3. MAC将latex等大软件安装到移动硬盘
  4. 大容量sd卡reread之后/dev下概率性出现无设备文件
  5. windows10无法访问共享计算机,win10共享无法访问,windows无法访问共享文件
  6. win7共享xp打印机_解决共享打印机不能使用的问题
  7. Apple_Mail 登录163邮箱账号
  8. 微前端single-spa vue3 实战落地
  9. Scan Context 学习记录
  10. php中超链接怎么去下划线的,html如何去掉超链接下划线?html超链接去掉下划线的方法介绍...