51单片机入门教程(2)——实现流水灯

  • 一、搭建流水灯电路
  • 二、流水灯程序
    • 2.1 延时程序
    • 2.2 延时函数
    • 2.3 按字节寻址
    • 2.4 逻辑移位
    • 2.5 条件判断

一、搭建流水灯电路

在Proteus中搭建流水灯电路如图

二、流水灯程序

我们可以把流水灯看作依次点亮若干个灯。
程序如下:

#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;void main()
{//点亮第一个灯led1 = 1;led2 = 0;led3 = 0;led4 = 0;led5 = 0;led6 = 0;led7 = 0;led8 = 0;//点亮第二个灯led1 = 0;led2 = 1;led3 = 0;led4 = 0;led5 = 0;led6 = 0;led7 = 0;led8 = 0;    //点亮剩余的灯//省略……while(1);
}

编译并下载程序到仿真中,观察现象发现只有第二个灯是亮的???
什么鬼???

2.1 延时程序

单片机的执行指令速度非常快,一个晶振是12MHz的单片机执行一条指令的速度是微秒级的,所以点亮第一个灯的时间太短了,以至于我们根本没有察觉。
因此我们需要一个延时的语句。
实现延时的方法就是循环执行很多次空指令。程序如下:

//延时一秒的程序
int i,j;
for(i = 0;i < 110; ++i)
{for(j = 0; j < 1000; ++j){;//什么也不做}
}

然后我们就可以把流水灯的程序改成这样的:

#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;void main()
{int i,j;//点亮第一个灯led1 = 1;led2 = 0;led3 = 0;led4 = 0;led5 = 0;led6 = 0;led7 = 0;led8 = 0;//延时1秒 for(i = 0;i < 110; ++i){for(j = 0; j < 1000; ++j){;//什么也不做}}//点亮第二个灯led1 = 0;led2 = 1;led3 = 0;led4 = 0;led5 = 0;led6 = 0;led7 = 0;led8 = 0;    //点亮剩余的灯//省略……while(1);
}

编译并下载程序到仿真中,观察现象发现首先第一个灯亮,过了一会儿第二个灯亮。

2.2 延时函数

我们剩下的任务就是依次点亮每个灯,但是每次点亮一个灯就需要写一段延时程序,很麻烦!
为了程序的可读性(toulan),可以把延时程序写成一个子函数,随时供我们使用。
C语言中子函数的定义方式如下

返回值类型 函数名 (参数1,参数2,……)
{函数体;
}

这样我们就可以把延时函数写成这样:

void delay1s()
{int i,j;for(i = 0; i<110;++i){for(j = 0; j<1000;++j){//什么也不做}}
}

几点说明:

  • void:因为该延时函数不需要返回值,所以写为void
  • delay1s:该函数的函数名,命名需要符合C语言的标识符命名规则。
  • (): 不需要传入参数,所以括号中为空
    至此我们可以把流水灯程序写为以下形式:
#include <reg52.h>sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;//延时1s
void delay1s()
{    int i ,j;for(i = 0;i<110; ++i){for(j = 0;j<1000;++j){;}}
}void main()
{//点亮第一个灯led1 = 1;led2 = 0;led3 = 0;led4 = 0;led5 = 0;led6 = 0;led7 = 0;led8 = 0;//延时1sdelay1s();//点亮第二个灯led1 = 0;led2 = 1;led3 = 0;led4 = 0;led5 = 0;led6 = 0;led7 = 0;led8 = 0;    //点亮剩余的灯//省略……while(1);
}

2.3 按字节寻址

我们可以看到,上面的代码十分冗长,每次点亮一个灯需要8条语句,那么如何简化?
比如把
led1 = 1;led2 = 0; led3 = 0; led4 = 0; led5 = 0; led6 = 0; led7 = 0; led8 = 0;
这8条语句替代为P2 = 0000 0001???
答案是可以的。代码如下

unsigned char a = 0x01;  //0x01是0000 0001的16进制形式
P2 = a;//相当于led1 = 1;led2 = 0; led3 = 0;  led4 = 0; led5 = 0; led6 = 0; led7 = 0; led8 = 0;

至此,我们可以把流水的代码优化为如下形式:

#include <reg52.h>//延时1s
void delay1s()
{    int i ,j;for(i = 0;i<110; ++i){for(j = 0;j<1000;++j){;}}
}void main()
{unsigned char a1 = 0x01 ;    // 0000 0001unsigned char a2 = 0x02;    // 0000 0010//点亮第一个灯P2 = a1;//延时1sdelay1s();//点亮第二个灯P2 = a2;    //点亮剩余的灯//省略……while(1);
}

2.4 逻辑移位

依次点亮8个灯,每点亮一个灯都需要一句赋值语句还是很麻烦 。
所以可以使用逻辑移位语句,每次赋值后,将数值左移一位。
C语言逻辑左移代码如下:

unsigned char a = 0x01;  //a = 0000 0001
unsigned char b = a<<1;  // b = 0000 0010
usingned char c = a<<3;   //c = 0000 1000

至此,我们可以把流水灯的代码优化如下:

#include <reg52.h>
//延时1s
void delay1s()
{    int i ,j;for(i = 0;i<110; ++i){for(j = 0;j<1000;++j){;}}
}void main()
{//初始化unsigned char a = 0x01;while(1){//循环点亮流水灯P2 = a;   a = a<<1;delay1s();}
}

编译并下载程序到仿真中,观察现象发现8个灯依次亮过之后不再亮了。

2.5 条件判断

因为在移位操作中,当变量a的值为1000 0000时,再次执行左移操作,a 中的1就溢出了,因此a的值变为0000 0000,此时我们需要加一个判断,使a再次恢复为0000 0001
C语言中,if条件判断使用方式如下

if(判断条件)
{//语句
}

当判断条件为真时,执行{ }中的语句。
至此,流水灯代码可改成如下形式:

#include <reg52.h>//延时1s
void delay1s()
{    int i ,j;for(i = 0;i<110; ++i){for(j = 0;j<1000;++j){;}}
}void main()
{unsigned char a = 0x01;while(1){if(a == 0x00)   //如果高位溢出{a = 0x01;      //则恢复}//循环点亮led灯P2 = a;a = a<<1;delay1s();}
}

51单片机入门教程(2)——实现流水灯相关推荐

  1. 51单片机入门学习小结(流水灯与数码管)

    51单片机入门学习小结(流水灯与数码管) 对原理图的分析 以下是我所用单片机的原理图 这块51单片机一共有4个I/O口(意思为input/output),也代表着如果我们后续都要用到这四个的话那么功能 ...

  2. 51单片机入门教程(1)——点亮一个LED灯

    51单片机入门教程(1)--点亮一个LED灯 一.什么是单片机 单片机(Microcontrollers)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU.随机存储器 ...

  3. 51单片机入门教程(5)——定时器中断

    51单片机入门教程(5)--定时器中断 一.中断的概念 二.定时器中断 2.1 软件延时的不足 2.2 中断寄存器 2.2.1 中断允许控制寄存器 IE 2.2.2 定时器工作方式寄存器 TMOD 2 ...

  4. 51单片机入门教程学习笔记

    基于江科大自化协B站教学视频<51单片机入门教程-2020版 程序全程纯手打 从零开始入门> 一.单片机介绍 单片机,英文Micro Controller Unit,简称MCU 内部集成了 ...

  5. 51单片机入门教程(6)——外部中断

    51单片机入门教程(6)--外部中断 一.外部中断 1.1 中断 1.2 外部中断 二.中断优先级 一.外部中断 1.1 中断 关于中断的概念在上一篇博客中已经提到了.(传送门:51单片机入门教程(5 ...

  6. 51单片机:外部中断实现流水灯

    51单片机:外部中断实现流水灯 作业要求: 按照给定的实验板电路图编程实现外部中断控制流水灯,初始上电时,实验板右下侧的流水灯区域只有最右侧LED灯亮,其他灯全都熄灭,每按下一次按键,流水灯从右向左流 ...

  7. 51单片机用定时器0实现流水灯

    51单片机用定时器0实现流水灯的代码如下,用P1口接led灯,代码如下都有注释就不具体解释了,英语不怎么好,有的地方将就一下喽,本次主要讲一下P1口怎么赋值.原先写的都是用查表来移位的,个人感觉不怎么 ...

  8. 51单片机入门教程(3)——数码管显示

    51单片机入门教程(3)--数码管显示 一.LED数码管简介 二.数码管静态显示 三.数码管动态显示 特别鸣谢:HFUTer-朱聪强 一.LED数码管简介 LED数码管(LED Segment Dis ...

  9. 51单片机编程与仿真_1_流水灯

    流水灯是一个很经典的入门项目,学单片机大部分都是从流水灯开始! 一.编程 先贴上代码: #include <reg51.h> #include <intrins.h>void ...

  10. 51单片机入门教程(3)——数码管显示学号

    目录 1.数码管简介 2.静态显示 3.动态显示 4.小结 相信经过了流水灯的实现,大家已经弄清楚了Keil和Proteus是如何联动使用的,并且对51单片机也有了一定的认识,在这一章里,我带大家利用 ...

最新文章

  1. 深入浅出Docker(一):Docker核心技术预览
  2. [Android Traffic] 使用缓存来避免重复的下载
  3. Java面试中,一些常见的有关多线程问题!
  4. 关于半马尔可夫(semi-markov)的一个形象解释
  5. Linux 信号signal处理函数
  6. SQL无所不能:DBA宝妈宝爸系列分享
  7. python三种等待方式_Python selenium 三种等待方式详解
  8. 深入动态人脸识别小场景应用,2019年或将迎来爆发期
  9. Aardio格式化代码工具
  10. 如何在S函数中对变量或者输入信号进行求导
  11. 学习Java8这一篇就够了
  12. Fluent:如何用Custom Field Function Calculater替代UDMI提高收敛性
  13. VMware.exe应用程序错误--应用程序无法正常启动(0xc000007b)错误解决方法
  14. No all pattern found! file already patched?
  15. 我,35岁大专,高龄入职鹅厂,试用期未过被劝退(分享java面试宝典)
  16. K8S给节点打标签和打污点
  17. Langevin dynamic 和 Hamiltonian Monte Carlo
  18. Python: queue.Queue
  19. vbo,ibo,vao
  20. javascript 省市区三级联动 附: json数据

热门文章

  1. python一次性导入依赖包_python如何导入依赖包
  2. PyTorch 音频处理教程
  3. Windows10C盘文件简单介绍
  4. java excel 创建控件_Java 添加、删除Excel表单控件
  5. 项目中集成阿里巴巴分布式定时任务
  6. 公司官网建设企业网站建设的好处,为什么要做网站?
  7. python获取图片长宽高,Python获取图片的大小/尺寸
  8. mysql事务锁死解决
  9. CentOS 7安装/卸载Redis,配置service服务管理
  10. win7打印机显示服务器脱机怎么办,手把手教你设置win7系统网络打印机脱机的修复教程...