51单片机教程(六)- LED流水灯

1 项目分析

  • 基于点亮LED灯、LED灯闪烁,扩展到构成最简单、花样流水灯。

2 技术准备

1 流水灯硬件及原理图

  • 流水灯是由多个LED灯组成的

    在这里插入图片描述
    在这里插入图片描述

2 C语言知识点

  • 数组
    • 数组声明:长度不可变

      • 数据类型 数组名称[长度n] // 整数型默认为0,小数型默认为0.0,字符默认为 ‘\0’,字符串默认为:NULL

    • 声明数组并初始化

      • 数据类型 数组名称[长度n] = {元素1,元素2…元素n};
      • 数据类型 数组名称[] = {元素1,元素2…元素n};

    • 访问:索引值从0开始

      • 数组名称[索引];

    • 数组长度

      • sizeof(数组名称) / sizeof(数组名称[0])

    • 修改数组中对应索引值位置的数据

      • 数组名称[0] = 元素1;
      • 数组名称[1] = 元素2;
      • 数组名称[n-1] = 元素n;

    • 遍历数组中的每个数据

      for (int i = 0; i <sizeof(array) / sizeof(arr[0]); i++)
      {arrray[i]   // 相关操作
      }
      
      // 数组的基本使用#include <stdio.h>int main()
      {// 数组的定义int score[5];// 数组的初始化(重点)int scores[5] = {34, 55, 67, 88, 19};int score1[] = {34, 55, 67, 88, 19};// 数组的索引:从0开始(重点)printf("%d ", scores[3]);// 数组的索引赋值scores[4] = 99;printf("%d ", scores[4]);// 数组的长度printf("\n长度:%d", sizeof(scores));printf("\n长度:%d", sizeof(scores) / sizeof(scores[0]));// 数组的遍历(重点)int x = 0;for(; x < 5; x++){printf(" %d ", scores[x]);}return 0;
      } 
      

3 延时

  • 介绍

    • 每条指令都占一定的时间(或者机器周期)的,如果让机器什么都不做,即空指令的话,机器就会延时,然后在计算好每次延时到底有多长,外面套一个循环(或者多重循环),根据想要的延时时间即可计算出来循环的次数,延时函数基本上都是这种原理,它的参数就是用来控制循环次数的。

    • 实现延时通常有两种方法:

      1. 硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;
      2. 软件延时,这种方法主要采用循环体进行。
  • 分类

    • 1)硬件延时: 使用定时器/计数器实现精确延时
    • 2)软件延时: 软件延时与时间计算
      • 在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。
  • 方法

    • 短暂延时 nop (intrins.h头文件)
      • 在C51中嵌套汇编程序段实现延时
    • 使用示波器确定延时时间
      • 使用反汇编工具计算延时时间

3 项目实现

方式1:常规方法

  • 实验

    • 结合多个LED灯实现流水灯效果,每个灯亮灭间隔大约2s
  • 代码

      /*代码实现思路:0 搭建代码框架1 定义8个LED灯的端口2 在while循环中,控制每个LED灯亮灭3 需要设置每个LED灯亮灭的间隔(延迟函数)*/#include <reg52.h>// 宏定义#define uint unsigned int// 1 定义8个LED灯的端口sbit led1 = P1^0;sbit led2 = P1^1;sbit led3 = P1^2;sbit led4 = P1^3;sbit led5 = P1^4;sbit led6 = P1^5;sbit led7 = P1^6;sbit led8 = P1^7;// 函数声明void delay(uint s);void main(){while(1){// 2 在while循环中,控制每个LED灯亮灭led1 = 0;  // led1 亮delay(2);led1 = 1;led2 = 0;delay(2);led2 = 1;led3 = 0;delay(2);led3 = 1;led4 = 0;delay(2);led4 = 1;led5 = 0;delay(2);led5 = 1;led6 = 0;delay(2);led6 = 1;led7 = 0;delay(2);led7 = 1;led8 = 0;delay(2);led8 = 1;}	}void delay(uint s){uint i,j,z;for(z=0;z<s;z++){for(i=0; i<183; i++){for(j=0; j<1000; j++);}}    }
    

方式2:P1口赋予十六进制

  • 实验

    • 结合多个LED灯实现流水灯效果,每个灯亮灭间隔大约2s
  • 分析
    在这里插入图片描述

  • 代码

    /*代码实现思路:0 搭建代码框架1 定义P1的端口2 在while循环中,控制P1的取值3 需要设置P1端口取值后间隔(延迟函数)
    */#include <reg52.h>// 宏定义
    #define uint unsigned int// 1 定义P1的端口
    #define led P1// 函数声明
    void delays(uint s);void main2()
    {while(1){// 2 在while循环中,控制P1的取值,集合延迟函数led = 0xfe;  // led1 亮delays(1);led = 0xfd;  // led2 亮delays(1);led = 0xfb;  // led3 亮delays(1);led = 0xf7;  // led4 亮delays(1);led = 0xef;  // led5 亮delays(2);led = 0xdf;  // led6 亮delays(2);led = 0xbf;  // led7 亮delays(2);led = 0x7f;  // led8 亮delays(2);}	
    }void delays(uint s)
    {uint i,j,z;for(z=0;z<s;z++){for(i=0; i<183; i++){for(j=0; j<1000; j++);}}    
    }
    

方式3:数组存储P1电平值

  • 实验
    • 结合多个LED灯实现流水灯效果,每个灯亮灭间隔大约2s
  • 代码
    /*代码实现思路:0 搭建代码框架1 定义P1的端口2 定义数组,存储8个P1的值3 在while循环中,再循环获取数组中的值,赋值给P14 需要设置P1端口取值后间隔(延迟函数)
    */#include <reg52.h>// 宏定义
    #define uint unsigned int// 1 定义P1的端口
    #define led P1// 2 定义数组,存储8个P1的值
    uint led_value[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};// 3.1 定义变量,用来表示索引值
    uint idx;// 函数声明
    void delay(uint s);void main()
    {while(1){// 3 在while循环中,再循环获取数组中的值,赋值给P1,配合延迟函数for(idx=0; idx < 8; idx++){	led = led_value[idx];  // ledx 亮delay(1);}}	
    }void delay(uint s)
    {uint i,j,z;for(z=0;z<s;z++){for(i=0; i<183; i++){for(j=0; j<1000; j++);}}    
    }
    

方式4: 按位左移 + 取反

  • 实验

    • 结合多个LED灯实现流水灯效果,每个灯亮灭间隔大约2s
  • 分析
    在这里插入图片描述

  • 代码

    /*代码实现思路:0 搭建代码框架1 定义P1的端口2 在while循环中,赋值给P1: ~(0x01 < n)3 需要设置P1端口取值后间隔(延迟函数)
    */#include <reg52.h>// 宏定义
    #define uint unsigned int// 1 定义P1的端口
    #define led P1// 2.1 定义变量,用来表示左移的位数
    uint n;// 函数声明
    void delay(uint s);void main()
    {while(1){// 2 在while循环中,赋值给P1: ~(0x01 < n),配合延迟函数for(n=0; n < 8; n++){	led = ~(0x01 << n);  // ledx 亮delay(2);}}	
    }void delay(uint s)
    {uint i,j,z;for(z=0;z<s;z++){for(i=0; i<183; i++){for(j=0; j<1000; j++);}}    
    }
    

4 拓展:花样流水灯

花样灯1

  • 实验

    • 流水灯:全部亮 + 奇数灯亮 + 偶数灯亮
  • 代码

    /*LED定义单个灯:控制1~3个LED   sbit ledx = P1^x;多个灯:控制8个LED     #define LED P1全亮:P1.7 ~ P1.0 对应的端口都为低电平(0),将值写成16进制:0x00 --> 0奇数灯亮(LED1 3 5 7-->P1.0 2 4 6)设置为低电平,写成16进制:0xaa偶数灯亮(LED2 4 6 8-->P1.1 3 5 7)设置为低电平,写成16进制:0x55代码的实现流程1、定义代码的基本结构2、定义P1端口,数组存储P1的值3、在while循环中,遍历数组,并将值赋值给P1,同时设置对应延时
    */#include <reg52.h>
    #include <delay.h>#define uint unsigned int// 定义P1端口
    #define LED P1// 定义数组存储P1的值
    uint values[3] = {0x00, 0xaa, 0x55};void main1()
    {uint idx;while(1){for(idx=0; idx<sizeof(values)/sizeof(values[0]); idx++){LED = values[idx];delay(1);}}
    }// file: delay.c/*延迟函数:功能:传入指定的值,延迟指定的秒数参数:s 表示当前延迟的秒数返回值:无
    */
    void delay(unsigned int s)
    {unsigned int x, i, j;for(x=0; x<s; x++){for(i=0; i<183; i++){for(j=0; j<1000; j++);}}
    }// file: delay.h
    #ifndef __DELAY_H  // if not define 如果没有定义
    #define __DELAY_H  // 定义对应头文件// 函数的声明
    void delay(unsigned int s);#endif      // 结束判断
    
     #include<reg52.h>unsigned char code table[] = {0x7f, 0xbf, 0xdf, 0xef,0xf7, 0xfb, 0xfd, 0xfe,0xff, 0xff, 0x00, 0x00,0x55, 0x55, 0xaa, 0xaa};void Delay(unsigned int t); //函数声明/*------------------------------------------------主函数------------------------------------------------*/void main(){unsigned char i;  //定义一个无符号字符型局部变量 i 取值范围 0~255while (1) {       //主循环for (i = 0; i < 16; i++) { //程序循环执行16次,表明表格中有16个元素P1 = table[i];Delay(10000);}}}/*------------------------------------------------延时函数,含有输入参数 unsigned int t,无返回值unsigned int 是定义无符号整形变量,其值的范围是 0~65535------------------------------------------------*/void Delay(unsigned int t){while (--t);}
    
    /*定时器:T1 工作在模式1:65.536ms1s: 50ms * 20    次数 * 机器周期 = 0.05s  次数:50000初值:65536 - 50000代码的实现流程1、定义代码的基本结构2、定义P1端口、记录定时器次数、数组存储P1的值3、在main函数中,定义定时器(1) 设置定时器T1的工作模式1TMOD = 0x10;(2) 设置T1的TH1 TL1的值TH1 = (65536 - 50000) / 256;TL1 = (65536 - 50000) % 256;(3) 打开“开关”EA = 1;  // 打开总开关TR1 = 1;   // 开启定时器T1ET1 = 1;   // 开启定时器T1的外部中断4、定义中断函数void 中断函数名()  interrupt 3{// 4.1 重置TH1 TL1TH1 = (65536 - 50000) / 256;TL1 = (65536 - 50000) % 256;// 4.2 定义变量,记录次数变量++;// 4.3 判断变量是否等于20if(变量==20){// 流水灯逻辑}}*/#include <reg52.h>#define uint unsigned int// 定义P1端口
    #define LED P1// 定义记录中断函数执行次数
    uint times = 0;// 定义数组存储P1的值
    uint p1_value[3] = {0x00, 0xaa, 0x55};// 定义数组的索引
    uint index = 0;void main2()
    {// (1) 设置定时器T1的工作模式1TMOD = 0x10;// (2) 设置T1的TH1 TL1的值TH1 = (65536 - 50000) / 256;TL1 = (65536 - 50000) % 256;//	(3) 打开“开关”EA = 1;TR1 = 1;ET1 = 1;while(1){}
    }// 定时器T1的中断函数
    void timer1() interrupt 3
    {// 4.1 重置TH1 TL1TH1 = (65536 - 50000) / 256;TL1 = (65536 - 50000) % 256;// 4.2 定义变量,记录次数times++;// 4.3 判断变量是否等于20if(times==20)    // 1s{// 判断index是否越界if(index > 2){index = 0;}// 流水灯逻辑LED = p1_value[index];// times重置times = 0;// 改变indexindex++;}
    }
    

花样灯2

  • 实验

    • 每次2个灯左移 + 每次2个灯右移 + 全灭 + 全亮
  • 分析
    在这里插入图片描述

  • 代码

    #include <reg52.h>
    #include <delay.h>#define uint unsigned int// 定义P1端口
    #define Led P1// 定义存储P1端口值的中间值的变量
    uint temp;void main3()
    {uint x;while(1){// 左移:Led = 0xfc;temp = 0xfc;for(x=0; x<6; x++){delay(1);temp = temp << 1 | 0x01;Led = temp;}// 右移:Led = temp;for(x=0; x<6; x++){delay(1);temp = temp >> 1 | 0x80;Led = temp;}// 全灭delay(1);Led = 0xff;delay(1);// 全亮Led = 0;delay(1);}
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/59576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyQt5实战——翻译的实现,第一次爬取微软翻译经验总结(八)

个人博客&#xff1a;苏三有春的博客 系类往期文章&#xff1a; PyQt5实战——多脚本集合包&#xff0c;前言与环境配置&#xff08;一&#xff09; PyQt5实战——多脚本集合包&#xff0c;UI以及工程布局&#xff08;二&#xff09; PyQt5实战——多脚本集合包&#xff0c;程序…

前端好用的网站分享——CSS(持续更新中)

1.CSS Scan 点击进入CSS Scan CSS盒子阴影大全 2.渐变背景 点击进入color.oulu 3.CSS简化压缩 点击进入toptal 4.CSS可视化 点击进入CSS可视化 这个强推&#xff0c;话不多说&#xff0c;看图! 5.Marko 点击进入Marko 有很多按钮样式 6.getwaves 点击进入getwaves 生…

理解Web登录机制:会话管理与跟踪技术解析(三)-过滤器Filter

在Java Web应用中&#xff0c;Filter&#xff08;过滤器&#xff09;是实现登录校验的常见方式。通过Filter&#xff0c;我们能够在请求到达实际的业务逻辑之前&#xff0c;对其进行拦截和处理&#xff0c;从而完成身份校验、权限验证等操作。本文将深入探讨登录校验的实现方法…

FreeBSD将操作系统支持时间从5年缩短为4年 继续与AMD合作

FreeBSD 项目今天发布了 2024 年第三季度进度报告&#xff0c;概述了该开源 BSD 操作系统在上一季度的改进情况。FreeBSD 开发人员仍然非常忙碌&#xff0c;他们在 2024 年第三季度取得的一些成就包括&#xff1a; FreeBSD 发布团队决定将支持时限从五年缩短为四年。 AMD 与 F…

kafka如何获取 topic 主题的列表?

大家好&#xff0c;我是锋哥。今天分享关于【kafka如何获取 topic 主题的列表&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; kafka如何获取 topic 主题的列表&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中&#xff0c;可以…

【网络-交换机】生成树协议、环路检测

路由优先级 路由优先级决定了在多种可达的路由类型中&#xff0c;哪种路由将被用来转发数据包。路由优先级值越低&#xff0c;对应路由的优先级越高&#xff0c;优先级值255表示对应的路由不可达。一般情况下&#xff0c;静态路由的优先级为1&#xff0c;OSPF路由优先级为110&a…

基于Spring Boot的在线装修管理系统的设计与实现,LW+源码+讲解

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#…

【数字图像处理】图像旋转中三种常见插值方法的效果比较:最近邻插值、双线性插值和双三次插值

引言 插值是一种数学方法&#xff0c;用于在已知的数据点之间估计新的数据点。在图像处理中&#xff0c;插值通常用于图像缩放、旋转和其他形态变换。 原始图像 最近邻插值&#xff08;Nearest-neighbor interpolation&#xff09; 这是最简单的插值方法&#xff0c;也是计算…

“方块兽神仙猿点石成金”游戏搭建开发

“方块兽神仙猿点石成金”是一款结合了策略和运气的休闲游戏。玩家需在规定时间内向不同的山头投入矿石&#xff0c;等待神仙猿降临并随机选择一座山进行“点石成金”。根据神仙猿的选择&#xff0c;玩家将获得不同的奖励。 游戏核心机制 矿石投入&#xff1a;玩家在游戏开始…

C/C++每日一练:实现选择排序

选择排序 选择排序是一种简单直观的排序算法&#xff0c;时间复杂度为&#xff0c;其中 n 是数组长度&#xff0c;不适合大数据集的排序&#xff0c;适合于元素较少且对性能要求不高的场景。 选择排序的基本思想是&#xff1a;每次从未排序部分选择最小的元素&#xff0c;将其放…

Java8新特性/java

1.lambda表达式 区别于js的箭头函数&#xff0c;python、cpp的lambda表达式&#xff0c;java8的lambda是一个匿名函数&#xff0c;java8运行把函数作为参数传递进方法中。 语法格式 (parameters) -> expression 或 (parameters...) ->{ statements; }实战 替代匿名内部类…

《现代网络技术》读书笔记:SDN数据平面和OpenFlow

本文部分内容来源于《现代网络技术&#xff1a;SDN,NFV,QoE、物联网和云计算&#xff1a;SDN,NFV,QoE,IoT,andcloud》 SDN数据平面 SDN 数据平面也称为基础设施层&#xff0c;而在ITU-T的Y3300标准中则称为资源层&#xff0c;它是网络转发设备根据 SDN控制平面的决策来执行数据…

linux centos 安装redis

安装 wget https://download.redis.io/releases/redis-7.4.0.tar.gz解压redis-7.4.0.tar.gz文件 tar -zxvf redis-7.4.0.tar.gz进入redis安装目录 cd redis-7.4.0make时报错&#xff0c;因为需要安装gcc&#xff0c;gcc安装需要联网安装 修改端口 编辑文件用vi。nano命令cen…

面向对象技术简述(含设计模式)

6.9.2 面向对象技术 面向对象 对象 分类 继承 通过消息的通信 面向对象 对象 分类 继承 通过消息的通信 面向对象对象分类继承通过消息的通信其中包括&#xff1a; 对象 运行的实体&#xff1b;既包含属性/数据&#xff0c;又包含方法/行为/操作数据的函数&#xff1b;…

yakit中的规则详细解释

官方文档 序列前置知识之高级配置 | Yak Program Language 本文章多以编写yaml模版的视角来解释 规则一览 匹配器 在编写yaml中会使用到这里两个东西 点击添加会在返回包的右下角出现匹配器 上面有三个过滤器模式&#xff0c;官方解释 丢弃&#xff1a;丢弃模式会在符合匹配…

算法每日双题精讲——双指针(移动零,复写零)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#xff01;&#x1f4aa;…

【SpringCloud】Kafka消息中间件

Kafka Kafka消息中间件对比&#xff1a;kafka介绍安装教程&#xff1a;配置以及启动顺序&#xff1a; Kafka整合微服务初级入门测试&#xff1a; Kafka整合SpringBoot①导入spring-kafka依赖信息②消息生产者③消息消费者Postman测试 Kafka 消息中间件对比&#xff1a; 消息中…

ViT模型复现项目实战

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

16通道AD采集方案,基于复旦微ARM + FPGA国产SoC处理器平台

测试数据汇总 表 1 本文带来的是基于复旦微FMQL20S400M四核ARM Cortex-A7(PS端) + FPGA可编程逻辑资源(PL端)异构多核SoC处理器设计的全国产工业评估板的AD采集案例。本次案例演示的开发环境如下: Windows开发环境:Windows 7 64bit、Windows 10 64bit PL端开发环境:P…

【Python爬虫实战】DrissionPage 与 ChromiumPage:高效网页自动化与数据抓取的双利器

&#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、DrissionPage简介 &#xff08;一&#xff09;特点 &#xff08;二&#xff09;安装 &#xff08;三…