51单片机(入门保姆级教程)——LED闪烁及流水灯
一、LED基本原理和知识
图1 LED共阳极原理图
1.1 LED共阴极和共阳极的含义
LED的最小单元是发光二极管。发光二极管是区分正负极的,正向导通,反向截止。共阴极就是发光二极管的负极连接在一起,共阳极就是发光二极管的正极连接在一起。
1.2 共阴极和共阳极的区别
- 耗能不一样。共阳极二极管的公共端接在高电平,需要高电平时时刻刻处在工作状态;而共阴极二极管公共端接低(GND),只需指定二极管工作时给某个二极管高电平即可,有效降低了功耗,对长时间工作LED来言有效降低了屏热。
- 线路复杂程度不同。一般在实际工程中共阴极二极管比共阳极二极管的线路复杂,共阳极不需要那么多的高电平线路驱动。
二、单个LED的闪烁
2.1 KEIL文件的建立
具体的keil工程文件创建可以参考[1]中的过程。
2.2 LED的闪烁程序
#include <reg52.h> //定义单片机的一些特殊功能寄存器
sbit led=P2^0; //定义指定LED灯的管脚void delay(unsigned int i) //延时函数。unsigned int定义无符号整型,范围0-655535
{while(i--); //i=1时,大约延时10us
}void main() //主函数,程序从这里开始执行
{while(1){led=0; //0表示低电平,共阳极二极管点亮delay(50000); //大约延时450msled=1; //1表示高电平,LED熄灭delay(50000); //大约延时450ms }
}
2.3 包含/区分/学习知识点
- #include<reg52.h>和#include"reg52.h"区别
两者来说区别不大,< >的引用是C51库函数里面的文件,而" "是引用我们自己创建的库函数里面的文件。
- while循环函数
while(i<10)
{i=i+1;
}
while函数的定义为:执行程序里面的函数文件,即i+1,执行完后判断i是否<10,若小于,继续执行,若大于等于则跳出循环。
- DELAY延时函数(掌握和学习)
在单片机中有两种延时方式,一种是软件延时,一种是硬件延时(计时器/计数器)。本知识点主要介绍软件延时函数。
void delay(unsigned int i)
{while(i--);
}
延时函数,i=1时,大约延时10us
图2 STC-ISP生成延时函数
图2所示为STC-ISP自动设置生成延时函数,所使用的晶振为11.0592MHz,以10us为例,自动生成。
void Delay10us() //@11.0592MHz
{unsigned char i;_nop_();i = 25;while (--i);
}
我们发现其中多了_nop_()指令,该指令包含在头文件#include<intrins.h>中,所以我们需要专门调用改文件。_nop_()的作用是产生下一条指令,对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数的作用是使程序执行完成后延时几微秒。nop指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1us。对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。对上述闪烁程序变换后可得如下程序。
#include <reg52.h> //定义单片机的一些特殊功能寄存器
#include <intrins.h> //定义单片机的一些特殊功能寄存器,里面包含_nop_()
sbit led=P2^0; //定义指定LED灯的管脚void main() //主函数,程序从这里开始执行
{while(1){led=0; //0表示低电平,共阳极二极管点亮_nop_(); led=1; //1表示高电平,LED熄灭_nop_(); }
}
三、LED流水灯的实现
3.1最基础最原始的流水灯实现办法
(1)概念
8个LED灯的定义,以共阳极为例,让某一个灯点亮就是让这个LED灯为低电平。从左到右依次为01111111、10111111、11011111、11101111、11110111、11111011、11111101、11111110。其中1就是高电平、0位低电平,为低电平时LED点亮。
(2)具体程序代码
#include <reg52.h> //定义单片机的一些特殊功能寄存器sbit led1=P2^0; //定义指定LED灯的管脚
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 delay(unsigned int i) //延时函数。unsigned int定义无符号整型,范围0-655535
{while(i--); //i=1时,大约延时10us
}void main() //主函数,程序从这里开始执行
{while(1){led1=0; //0表示低电平,led1点亮delay(5000); led1=1; //1表示高电平,led1熄灭delay(5000); led2=0; //0表示低电平,led2点亮delay(5000); led2=1; //1表示高电平,LED2熄灭delay(5000); led3=0; //0表示低电平,LED3点亮delay(5000); led3=1; //1表示高电平,LED3熄灭delay(5000); led4=0; //0表示低电平,LED4点亮delay(5000); led4=1; //1表示高电平,LED4熄灭delay(5000); led5=0; //0表示低电平,LED5点亮delay(5000); led5=1; //1表示高电平,LED5熄灭delay(5000); led6=0; //0表示低电平,LED6点亮delay(5000); led6=1; //1表示高电平,LED6熄灭delay(5000); led7=0; //0表示低电平,LED7点亮delay(5000); led7=1; //1表示高电平,LED7熄灭delay(5000); led8=0; //0表示低电平,LED8点亮delay(5000); led8=1; //1表示高电平,LED8熄灭delay(5000); }
}
最基础最原始的流水灯方式,就是单纯让LED按照顺序依次点亮,从而达到流水灯的效果,看似笨拙、程序繁多,却突出流水灯的思想和原理,为后面库函数、左移右移、数组索引法奠定基础。
3.2 移位法实现LED流水灯
(1)具体程序代码
左循环
#include <reg51.h>void delay(unsigned int i) //延时函数
{while(i--);
}void main(void) //主函数,程序从这里开始执行{int j; //引入变量,定义字符while(1){P2=0xfe; //即11111110,将8个LED的状态赋值给P2delay(50000);for(j=0;j<8;j++) //循环8次,因为有8个LED灯{P2=P2<<1 | 0x01; //实现程序左移1位,或运算,有1为1,全0为0delay(50000);}}}
右循环
#include <reg51.h>void delay(unsigned int i) //延时函数
{while(i--);
}void main(void) //主函数,程序从这里开始执行{int j; //定义字符while(1){P2=0x7f; //即01111111,将8个LED的状态赋值给P2delay(50000);for(j=0;j<8;j++) //循环8次,因为有8个LED灯{ P2=P2>>1 | 0x80; //实现程序右移1位,或运算,有1为1,全0为0delay(50000);}}}
(2)相关知识、逻辑解释
- 或运算( | )
基本运算规则为: 0|0=0; 0|1=1; 1|0=1; 1|1=1;只要运算中有一个为1,其值为1。
- 为什么引入j变量?
变量j:为了实现循环,让LED灯依次进行移动,文中实现LED灯左移或者右移8次。
- 左移<<和右移>>
左移和右移有其固定的形式,如P1<<1,就是让P1往左移动一位,若为P1<<2,就是让P1往左移动两位,依次推算,右移也是如此。
- 此位移法相对简单基础,存在不定性,可在此基础上增加判断和计时器,精确控制LED流水灯的形式和花样。
3.3 数组法
(1)具体程序代码
#include <reg51.h>unsigned char LED [8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义8个LED灯点亮void delay(unsigned int i) //延时函数
{while(i--);
}void main(void) //主函数,程序从这里开始执行
{int j;for(j=0; j<8; j++) //循环函数,实现流水效果{P2 = LED[j]; //赋值给LED端口delay(50000); P2 = 0xff; // 清屏,使所有LED熄灭 }
}
(2)相关知识点
- 数组的定义和表示——类型说明符 数组名 [常量表达式]
这是数组最基本的形式,比较固定。其中:
类型说明符:表示变量的长度单元格,常用为char、int、long;因为一般读取数据很少有负数,所以常用无符号整型。
数组名:定义的数组名字,即数组标识符。
常量表达式:表示定义的数组中装有元素的个数,即数组长度。
3.4 库函数法
(1)具体程序代码
#include <reg51.h>
#include <intrins.h>void delay(unsigned int i) //延时函数
{while(i--);
}void main() //主函数,程序从这里开始执行
{int i;P2 = 0xfe;for(i=0;i<7;i++) //LED左移一位{P2=_crol_(P2,1);delay(50000); //延时}for(i=0;i<7;i++) //LED右移一位{P2=_cror_(P2,1);delay(50000); //延时 }
}
(2)小修改后代码
#include <reg51.h>
#include <intrins.h>#define LED P2 //把P2口整体定义为LED,后面可以直接引用void delay(unsigned int i) //延时函数
{while(i--);
}void main() //主函数,程序从这里开始执行
{int i;LED = 0xfe;for(i=0;i<7;i++) //LED左移一位{LED=_crol_(LED,1);delay(50000); //延时}for(i=0;i<7;i++) //LED右移一位{LED=_cror_(LED,1);delay(50000); //延时 }
}
(3)相关知识点
- 移位函数(最快实现流水灯程序)
需要添加#include<intrins.h>库函数,其中_crol_表示左移(字符循环左移),_cror_表示右移(字符循环右移)。具体应用中_crol_(LED,1)表示把LED左移1位(例如:11111110执行完后为11111101),_cror_(LED,2)表示左移2位等(例如:10111111执行完后为11101111)。
- 两个程序的小区别
修改后的程序中多了#define LED P2定义,此句话意思为将P2口整体定义为LED,增加了程序的可读性。
四、小结
以上四种方法基本涵盖了流水灯的控制移动方法,可供借鉴学习,水平有限,若有不足,请理解谢谢,欢迎指出问题。
51单片机(入门保姆级教程)——LED闪烁及流水灯相关推荐
- Unified Functional Testing(UFT)15.0.2入门保姆级教程(一),图文详解。QTP
UFT入门之侦测器(ObjectSpy)及录制第一个脚本 实验说明 1.Quick Test Pro(QTP)11.5后更名为Unified Functional Testing(UFT) 2. 实验 ...
- Unified Functional Testing(UFT)15.0.2入门保姆级教程(二),图文详解。QTP
UFT入门之验证点和参数化 UFT15.0.2教程之侦测器(ObjectSpy)及脚本录制 请移步:Unified Functional Testing(UFT)15.0.2入门保姆级教程(一),图文 ...
- ROS入门保姆级教程:5-ROS计算图
ROS入门往期: ROS入门保姆级教程:1-hello world初体验 ROS入门保姆级教程:2-VScode中使用ROS ROS入门保姆级教程:3-ROS文件系统 ROS入门保姆级教程:4-ROS ...
- Shopify开发入门-保姆级教程
Shopify开发入门-保姆级教程
- 学习笔记(01):巫妖王51单片机开发板配套视频课程-LED闪烁和流水灯效果
立即学习:https://edu.csdn.net/course/play/6735/133119?utm_source=blogtoedu 2020-5-14 keil LED 闪烁,流水灯
- 51单片机(入门保姆级教程)——点亮一个LED灯
一.为什么要学习单片机? 作为一名工科学生,进入大学参加各种活动,例如:电子设计大赛.寻迹车比赛.LED电子灯比赛以及各种各样的微控.弱控强电路等,都离不开单片机的身影.电路.c语言.数电.模电.计算 ...
- 前端涨薪必读,node.js入门保姆级教程
Node.js保姆级教程 1. Node基本概念 2. 第一个node.js程序 3. node创建get请求 4. node创建post请求 1. Node基本概念 1.1 node.js是什么? ...
- 51单片机入门(2)LED点亮的背后
上一节提到了51单片机开发环境的搭建,这节我们开始正式进入51单片机的学习--点亮LED. 所有的控制类芯片学习的第一个实践就是点亮LED,这是最简单.最基本的操作,但这个实现过程却可能攘括了单片机的 ...
- LED闪烁和流水灯,调试教程,在线仿真器的使用
常用的延时方法: 软件延时(使用简单但是浪费CPU资源).定时器延时(不浪费CPU资源),本次先使用软件延时. LED全亮代码: #include<reg52.h> //引用51的头文件 ...
最新文章
- PAT(甲级)2019年秋季考试 7-2 Merging Linked Lists
- python哪一版好用-Python最好用的编辑器是哪款?北京老男孩教育
- 【题解】Luogu P2783 有机化学之神偶尔会做作弊
- Magento--判断checkout中是否使用了coupon code
- POJ3041_Asteroids
- java中包的概念及作用_Java中包的概念和使用实战
- adb shell 是这个啥东东
- 如何在form初始化时自动隐藏FOLDER列
- 【渝粤教育】国家开放大学2019年春季 1087数学分析专题研究 参考试题
- avr的c语言开发工具,AVR单片机的C语言开发简介
- 小程序发布上线全流程(包含小程序怎么通过审核)
- Debian/Ubuntu系统命令终端提示无法定位软件包解决方法
- 计算机知识技能大赛总结,计算机知识技能大赛总结
- [转]决定人生的三种成本:机会成本,沉没成本,边际成本
- 开往-友链接力handsome侧栏添加修改
- Visio绘制维恩图举例
- 霸屏综艺,牵手明星,扩列神器皮皮APP的出圈始末
- 雅典娜暴利烹饪系列(上)
- python 报错 'gbk' codec can't encode character '\xb5' in position 7431: illegal multib
- 【最短路算法】第二弹:一文弄懂Bellman-Ford(贝尔曼福特算法)
热门文章
- 笔试java--链表
- 解决Keil5中MDK与C51共存没有STC芯片型号
- keil c51如何添加STC芯片的固件库文件
- unwinding now org.apache.cxf.interceptor.Fault: Marshalling Error: null
- MIGO/CO11N 批次创建增强 自定义批次号创建规则
- 原谅帽大作战游戏程序
- mysql double转字符串_MySQL 字符串 转 int/double CAST与CONVERT 函数的用法
- txt文本文件数据转ArcGIS中的tif文件
- “数据结构基础”系列网络课程主页
- js异步和同步的区别