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

2023-10-30

一、搭建流水灯电路

在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;

	//延时1s
	delay1s();

    //点亮第二个灯
    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 0001
	unsigned char a2 = 0x02;    // 0000 0010
    //点亮第一个灯
	P2 = a1;

	//延时1s
	delay1s();

    //点亮第二个灯
	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();
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

51单片机入门教程(2)——实现流水灯 的相关文章

  • 钉钉开放平台查询宜搭表单实例数据

    本例结合钉钉开放平台相关api实现获取宜搭表单数据 可在faas中做实现 本例采用python编写 已在本地实现 对于免登获取数据 数据归档到本地能提供参考 faas具体实现请根据实际 参考使用 采用alibabacloud dingtal
  • 【16种重要流操作】

    文章目录 前言 一 16种重要流是什么 二 输入输出流模型化 1 输入流操作 2 输出流操作 三 16种输入输出流 代码通 总结 前言 输入输出流的使用已经非常的广泛 除过采用了不同的类操作 其方法大同小异 下文针对16种重要的流进行分解
  • openEuler-22.03-LTS 安装与配置笔记

    镜像下载与安装 openEuler下载页 镜像下载 下载镜像 wget c https repo openeuler org openEuler 22 03 LTS ISO x86 64 openEuler 22 03 LTS x86 64

随机推荐

  • Recall, Precision, AP, mAP的计算方法(看一次就懂系列)

    Recall Precision AP mAP的计算方法 看一次就懂系列 mAP全称是mean Average Precision 这里的Average Precision 是在不同recall下计算得到的 所以要知道什么是mAP 要先了解
  • Vue的动画和过渡效果详解

    产品中优雅的交互动画可以吸引更多用户留存使用 对于前端的动画实现要求也越来越高了 在Vue中提供了一些快捷 方便的标签和内置属性来更加优雅的实现动画和过渡效果 今天我们来一起学习一下 基础动画效果 公众号 Code程序人生 个人网站 htt
  • 视频生成: 基于Stable Diffusion的微调方法

    chatGPT带来了几个月的AIGC热度 文本图像生成模型大行其道 但AI在视频生成任务上尚没有较好的开源仓库 并受限于 缺那么几百块A100 的资源问题 大多数人无法展开视频生成的研究 好在目前有不少针对视频生成的相关paper 也有不少
  • python在with open()函数中,如何在文件名设置中引用变量

    用format 函数 name wz age 25 with open C Users 0 1 txt format name age w encoding utf 8 as f1 f1 write hellow world 则文件名为 w
  • C++ 模板函数、模板类:如果没有被使用就不会被实例化

    C 中如果一个模板函数没有使用过 那么其局部静态变量都不会被实例化 class A public A edward print A ctor template
  • 【2】浅析Vue组件

    组件的基本概念 Vue中有一个概念叫做组件化 就是把页面分成一个个小的部分 每个部分有自己的功能 且可以复用 最外层的组件即根组件 除此之外会有很多子组件 子组件分为两种 全局组件和局部组件 全局组件 用 Vue component 组件名
  • 基础学习——numpy与tensor张量的转换

    系列文章目录 Numpy学习 创建数组及常规操作 数组创建 切片 维度变换 索引 筛选 判断 广播 Tensor学习 创建张量及常规操作 创建 切片 索引 转换 维度变换 拼接 基础学习 numpy与tensor张量的转换 基础学习 关于l
  • 怎么用微信打开wifi连接到服务器,微信一键连wifi在哪里 微信一键连wifi怎么使用...

    类型 社交聊天大小 45 4M语言 中文 评分 5 0 标签 立即下载 微信这款软件使用可以不用流量了 这款软件推出了wifi一键连小程序 帮助用户走到哪里都有无线网 但是有很多伙伴不知道在哪里 怎么连接 想知道的伙伴可以在西西看看相关的教
  • fiddler设置网速模拟弱网络测试

    在测试过程中 经常会要求测试弱网络情况时的一些特殊情况 这时候IOS还好说 在开发者选项中调整网络模式即可 但android就只能通过别的方式了 这里整理了通过fiddler抓包工具来设置弱网模式 在fiddler可以设置自己想要的网速 或
  • CTF练题(3) jpg图片隐写 使用jphs05工具和stegslove

    题目一概述 解题过程 1 根据题目提示 判断为图片隐写 800度的眼镜 我理解为不同色通道下观看图片 由此打开stegslove分析该图片 2 点击右方向键调整不同的色通道 发现乱码隐约组成六个字 我好喜欢你 如图 可能这六个字为本题fla
  • java代码编译和运行在命令行中完成

    背景 集成开发环境用多了 最近想学一下 java 基础 用命令行来编译和运行一下 发现举步维艰 于是 创作这篇文章与大家共享 基础知识梳理 在写代码之前 我们先花点时间来了解一下 java 编译和运行的过程 如下图 里面涉及到 两个 命令符
  • CentOS安装PostgreSQL

    版本信息 CentOS版本 CentOS 7 x86 64 Minimal 1810 PostgreSQL版本 PostgreSQL 10 10 64 bit 第一部分 PostgresSQL的安装 1 安装rpm文件 yum instal
  • 华为云云耀云服务器L实例评测|轻松购买 快速使用 上云如此简单【详细版】

    华为云云耀云服务器L实例评测 轻松购买 快速使用 上云如此简单 详细版 轻量级云服务器 即开即用 轻松运维 开启简单上云第一步 文章目录 华为云云耀云服务器L实例评测 轻松购买 快速使用 上云如此简单 详细版 1 云耀云服务器介绍 2 购买
  • Stable Diffusion 硬核生存指南:WebUI 中的 GFPGAN

    本篇文章聊聊 Stable Diffusion WebUI 中的核心组件 强壮的人脸图像面部画面修复模型 GFPGAN 相关的事情 写在前面 本篇文章的主角是开源项目 TencentARC GFPGAN 和上一篇文章 Stable Diff
  • scrollview中使用recyclerview莫名自动上滑

    1 scrollview中加入 android descendantFocusability blocksDescendants 2 为scrollView中的根view加入android focusableInTouchMode true
  • USB详解

    转载自http blog 163 com zhsh email blog static 19786900200611259521640 usb作为一种串行接口 应用日益广泛 如同每个工程设计人员必须掌握I2C RS232这些接口一样 我们也
  • int最大值是多少

    int最大值 根据编译器类型不同而变化 具体如下 1 对于16位编译器 int占16位 2字节 int的最大值为32767 2 对于32位和64位编译器 int占32位 4字节 int的最大值为2147483647 java语言中 int最
  • SQL语句中case、when、then的使用

    使用语法为 select pro id AS id pro title AS title pro name AS name pro ltime AS ltime pro place AS place pro linkman AS linkm
  • 【100天精通Python】Day58:Python 数据分析_Pandas时间序列数据处理,创建和解析时间数据pd.to_datetime(),.loc[],resample() 用法示例

    目录 时间序列数据处理 1 解析日期和时间数据 2 创建时间索引 3 访问时间索引数据 3 1 按年 月 日等级别访问数据 loc 3 2 使用部分日期作为索引 loc loc 3 3 使用时间索引的属性 index 4 时间索引的切片 5
  • 51单片机入门教程(2)——实现流水灯

    51单片机入门教程 2 实现流水灯 一 搭建流水灯电路 二 流水灯程序 2 1 延时程序 2 2 延时函数 2 3 按字节寻址 2 4 逻辑移位 2 5 条件判断 一 搭建流水灯电路 在Proteus中搭建流水灯电路如图 二 流水灯程序 我