找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 21884|回复: 28
收起左侧

51单片机入门经验分享3-通过流水灯讲解for循环语句 取反 与或非运算

  [复制链接]
ID:74187 发表于 2018-10-13 08:41 | 显示全部楼层 |阅读模式
接上一篇帖子,继续来看,既然我们会点亮一个小灯,并可以让其闪烁了,那么我们就尝试着点亮流水灯好了,让8个小灯,从左到右,从右往左来回流动,还是在上一个程序的基础上来修改,很简单依次赋值即可实现。
  1. while(1)
  2.         {
  3.              P2 = 0XFE;//1111_1110;
  4.                  Delay500ms();//500ms延时 11.0592MHZ
  5.                  P2 = 0XFD;//1111_1101;
  6.                  Delay500ms();//500ms延时 11.0592MHZ
  7.                  P2 = 0XFB;//1111_1011;
  8.                  Delay500ms();//500ms延时 11.0592MHZ
  9.                  P2 = 0XF7;//1111_0111;
  10.                  Delay500ms();//500ms延时 11.0592MHZ
  11.                  P2 = 0XEF;//1110_1110;
  12.                  Delay500ms();//500ms延时 11.0592MHZ
  13.                  P2 = 0XDF;//1101_1111;
  14.                  Delay500ms();//500ms延时 11.0592MHZ
  15.                  P2 = 0XBF;   //1011_1110;
  16.                  Delay500ms();//500ms延时 11.0592MHZ
  17.                  P2 = 0X7F;   //0111_1111;
  18.                  Delay500ms();//500ms延时 11.0592MHZ

  19.                  P2 = 0XBF;     //1011_1110;
  20.                  Delay500ms();  //500ms延时 11.0592MHZ
  21.                  P2 = 0XDF;     //1101_1111;
  22.                  Delay500ms();  //500ms延时 11.0592MHZ
  23.                  P2 = 0XEF;     //1110_1110;
  24.                  Delay500ms();  //500ms延时 11.0592MHZ
  25.                  P2 = 0XF7;     //1111_0111;
  26.                  Delay500ms();  //500ms延时 11.0592MHZ
  27.                  P2 = 0XFB;     //1111_0111;
  28.                  Delay500ms();  //500ms延时 11.0592MHZ
  29.                  P2 = 0XFD;     //1111_1101;
  30.                  Delay500ms();  //500ms延时 11.0592MHZ

  31.         }
复制代码




这样弄,虽然很好理解,但是代码显得太冗长了,我们接触下for循环语句,先用for语句来实现我们想要的功能。代码修改如下:
  1.   for(i = 0; i < 8;i++)
  2.                 {
  3.                         P2 = ~(0X01 << i);
  4.                         Delay500ms();//500ms延时 11.0592MHZ
  5.                 }

  6.                 for(i = 0; i < 6;i++)
  7.                 {
  8.                         P2 = ~(0X40 >> i);
  9.                         Delay500ms();//500ms延时 11.0592MHZ
  10.                 }
复制代码


用了for循环左移和右移的办法,配合取反实现的,还有一种办法,更简单可以实现来回循环,这便是循环左移和循环右移指令
  1. /*******************************************************************
  2. * 文件名 main函数入口
  3. * 描述:        
  4. * 功 能
  5. * 作者:大核桃
  6. * 版本号:V1.00(2018.09.17)
  7. ********************************************************************/
  8. void main(void)
  9. {
  10.     uint8 i = 0;
  11.         uint8 temp;

  12.         MCU_Port_Init();//端口模式初始化函数
  13.         //上电IO默认是0
  14.         LED0 = 1;//输出1
  15.         LED1 = 0;
  16.         LED2 = 0;
  17.         LED3 = 0;
  18.         LED4 = 0;
  19.         LED5 = 0;
  20.         LED6 = 0;
  21.         LED7 = 0;//

  22.         temp = 0XFE;

  23.         while(1)
  24.         {

  25.            for(i = 0; i < 7;i++)
  26.                 {
  27.                     P2 = temp;
  28.                         temp = _crol_(temp,1);         
  29.                         Delay500ms();//500ms延时 11.0592MHZ
  30.                 }

  31.                 for(i = 0; i < 7;i++)
  32.                 {                              
  33.                     P2 = temp;
  34.                         temp = _cror_(temp,1);
  35.                         Delay500ms();//500ms延时 11.0592MHZ
  36.                 }
  37. }
复制代码




这一节,用到了for循环这个知识点,for语句的用法在C语言课本的第120页,详细的了解可以看C语言这本书,我们只列举一个实际例子来说明C语言的流程,就拿下面的代码来说吧。
  1.   for(i = 0; i < 8;i++)
  2.                 {
  3.                         P2 = ~(0X01 << i);
  4.                         Delay500ms();//500ms延时 11.0592MHZ
  5.                 }
复制代码


首先i = 0;是给变量赋初值,i<8是循环条件,i++是变量累加,先来看看i = 0;的时候,这个时候判断下语句P2 = 0XFE,然后0 < 8条件成立,i++;
  1. //  i = 0;的时候
  2. for(i = 0; i < 8;i++)
  3. {
  4.         P2 = ~(0X01 << 0);
  5.         Delay500ms();//500ms延时 11.0592MHZ
  6. }
  7. //  i = 1;的时候
  8. for(i = 0; i < 8;i++)
  9. {
  10.         P2 = ~(0X01 << 1);
  11.         Delay500ms();//500ms延时 11.0592MHZ
  12. }
复制代码



当 i= 1;的时候,P2 = 0XFD,依然1<8成立,然后i++;
当 i= 2;的时候,P2 = 0XFB,依然2<8成立,然后i++;
当 i= 3;的时候,P2 = 0XF7,依然3<8成立,然后i++;
当 i= 4;的时候,P2 = 0XEF,依然4<8成立,然后i++;
当 i= 5;的时候,P2 = 0XDF,依然5<8成立,然后i++;
当 i= 6;的时候,P2 = 0XBF,依然6<8成立,然后i++;

当 i= 7;的时候,P2 = 0X7F,依然7<8成立,然后i++;
当 i= 8;的时候,8<8不成立,跳出循环执行下面的语句;

这样我们就把for循环的流程给分解了,首先就是赋初值,然后执行循环,循环完之后变量累加,回过头看条件是否成立,如果条件继续成立,则继续循环,累加变量,直到条件不满足为止。
     关于取反符号
~这个符号,可以读作取反,注意这不是!(非),数字电路中的 &(按位与) , |  (按位或),!(非)和 &&(逻辑与),||(逻辑或),和~(取反)是不一样的,按位与顾名思义,是位和位之间运算,他们运算是能够得出一个具体的结果的,而逻辑与是对左右两个表达式的真假进行判断,得出的结果不是真就是假。
    关于与或非的真值表
与或非是数字电路最基本的知识点,必须要掌握这个知识点。
    &, 就好比乘法一样,如果A和B都为1,那么结果就是1,如果有一个为0,则输出都是0,。
    |,   就好比加法运算,如果A或者B有一个是1,那么结果就是1,否则就是0;

    !,     输入为0时,输出为1,输入为1时,输出为0;
   !|,或非门,只有A和B输入全部位0时,输出才为1,否则全为0;
   !&,与非门,只有A和B全部输入为1时,输出才为0,否则全为1;
   异或门,如果A和B相等时,输出都是0,否则输出都是1。


好了,今天就到这里吧,明天继续。。。代码奉献上。。。

001 LED点亮.rar (25.11 KB, 下载次数: 59)
回复

使用道具 举报

ID:371529 发表于 2018-10-13 15:25 | 显示全部楼层
真好,感谢楼主
回复

使用道具 举报

ID:74187 发表于 2018-10-14 14:54 | 显示全部楼层

谢谢,一起进步
回复

使用道具 举报

ID:403231 发表于 2018-10-15 14:37 | 显示全部楼层
有位老师说,尽量不要用延时的习惯。
回复

使用道具 举报

ID:74187 发表于 2018-10-15 19:37 | 显示全部楼层
一片到 发表于 2018-10-15 14:37
有位老师说,尽量不要用延时的习惯。

你说的对,后面我们基本都是用定时器了,延时确实不实用
回复

使用道具 举报

ID:410857 发表于 2018-10-18 16:14 | 显示全部楼层
收了下
回复

使用道具 举报

ID:410857 发表于 2018-10-18 16:14 | 显示全部楼层
真好,感谢楼主
回复

使用道具 举报

ID:414974 发表于 2018-10-30 12:23 | 显示全部楼层
延时要的,CPU处理太快了
回复

使用道具 举报

ID:85743 发表于 2018-11-1 14:17 | 显示全部楼层

真好,感谢楼主
回复

使用道具 举报

ID:203000 发表于 2018-11-12 23:29 | 显示全部楼层
感谢楼主。讲的很好!
回复

使用道具 举报

ID:439493 发表于 2018-12-4 19:27 | 显示全部楼层

真好,感谢楼主
回复

使用道具 举报

ID:421232 发表于 2018-12-13 11:39 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:461889 发表于 2019-1-23 15:04 | 显示全部楼层
感谢楼主
回复

使用道具 举报

ID:471375 发表于 2019-2-16 22:26 来自手机 | 显示全部楼层
不错不错,直击要点
回复

使用道具 举报

ID:370231 发表于 2019-3-6 11:56 | 显示全部楼层
感谢楼主
回复

使用道具 举报

ID:500153 发表于 2019-3-28 20:00 | 显示全部楼层
感谢  小白学习
回复

使用道具 举报

ID:507107 发表于 2019-4-8 16:22 | 显示全部楼层
真好谢谢
回复

使用道具 举报

ID:580838 发表于 2019-7-9 15:50 | 显示全部楼层
太棒了,感谢!
回复

使用道具 举报

ID:524818 发表于 2019-7-24 18:13 | 显示全部楼层
真好,讲的很透彻,受益匪浅啊!
回复

使用道具 举报

ID:706724 发表于 2020-3-19 21:01 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:815248 发表于 2020-8-21 15:25 | 显示全部楼层
第二组代码那,i是要小于6吗,不应该小于7吗,左移一共要点亮8个灯,右移的时候点亮7个灯,这里没看懂,希望楼主能解答一下,谢谢、
回复

使用道具 举报

ID:825397 发表于 2020-12-13 14:26 | 显示全部楼层
清晰透彻,初学者的好资料
回复

使用道具 举报

ID:582255 发表于 2021-2-9 22:49 | 显示全部楼层
楼主没有讲循环移位啊
回复

使用道具 举报

ID:17204 发表于 2021-3-13 18:09 | 显示全部楼层
是STC单片机吗,谢谢
回复

使用道具 举报

ID:896253 发表于 2021-3-28 20:38 | 显示全部楼层
这个直接用循环移位函数就好了 ,直接一个循环
回复

使用道具 举报

ID:986337 发表于 2021-12-2 16:44 | 显示全部楼层
虽然现在不是很理解其中意思,但是很谢谢楼主
回复

使用道具 举报

ID:1007039 发表于 2022-3-4 23:16 | 显示全部楼层
受益匪浅,感谢楼主
回复

使用道具 举报

ID:1049825 发表于 2022-10-31 20:15 | 显示全部楼层
楼主提供的学习资料很有用,可惜我没那么多下载币,继续努力!。。
回复

使用道具 举报

ID:77589 发表于 2022-11-11 17:05 | 显示全部楼层
还可以定义数组方式,把所有状态都存放在数组里,用一个for循环调用就可以了。
这种可扩展性强,把数组定义到程序flash里,扩展状态数量取决于flash大小。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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