51入门之LED

        

目录

1.配置文件

2.点亮一个LED

2.1单个端口操作点亮单个LED

2.2整体操作点亮LED

3.LED闪烁

4.LED实现流水灯

        4.1使用for循环和移位实现

4.1.1移位操作符       

4.1.2使用移位操作和for循环实现

        4.2使用移位函数实现LED流水灯


        众所周知,任何一个硬件工程师都是从点亮一个LED开始的,点亮一个LED,相当于软件中的第一个Hello World,都是一个最基础的东西,今天就开始点亮一个LED,探寻单片机的奥秘,

1.配置文件

        首先,我们需要使用的开发板是普中的51单片机开发板,其次,我们使用的编写程序的软件是Keil5,使用C语言编程。现在就来开始点亮一个LED吧!

        首先我们需要建立一个项目,我们的项目建立之后会有很多的散乱的小文件,所以我们就要建立一个大文件夹,再在里面建立一个子文件夹,把我们的项目放在里面。

        首先,打开Keil5

然后把我们的项目建立到刚刚的子文件夹里面就行了。

保存之后,会出现下面的这样的窗口:

        我们使用的51单片机型号是STC89C52,这里找不到,但是我们可以找到型号匹配的,就是AT89C52,我们可以使用AT89C52来创建我们的新项目

我们可以像这样点击Atmel里面找到AT89C52,也可以在上面的搜索框里面直接搜索AT89C52,点击OK,会弹出一个页面

点击否就行了。

我们左边的窗口就出现了我们的项目

鼠标右击Source Group1

点击Add New Item

选择C语言,然后命名即可 

成功创建之后,我们的左边就会出现这样的东西

这说明我们的文件已经常见成功,可以开始写代码了。 

2.点亮一个LED

        GPIO(general purpose intput output)是通用输入输出端口的简称,可 以通过软件来控制其输入和输出。

这就是我们芯片的引脚图,一共有40个引脚,这些引脚可以用分为下面几个大类:

  1. 电源引脚:引脚图中的 VCC、 GND 都属于电源引脚。
  2. 晶振引脚:引脚图中的 XTAL1、XTAL2 都属于晶振引脚。
  3. 复位引脚:引脚图中的 RST/VPD 属于复位引脚,不做其他功能使用。
  4. 下载引脚:51 单片机的串口功能引脚(TXD、RXD)可以作为下载引脚 使用。
  5. GPIO 引脚:引脚图中带有 Px.x 等字样的均属于 GPIO 引脚。

我们需要使用的就是P2端口

        在开发板上,我们的LED就是这样排列的,P20到P27我们可以统称为P2端口,我们只需要给P2端口赋值就可以得到我们想要的LED效果。

        我们都知道,LED是一个二级管一样的东西,就上面的图片而言,我们的迪纳留只能从VCC流向P2端口,所以我们如果想要LED发光,我们就需要保证LED左右有电位差,左边是正极,右边是我们控制的P2端口,我们就需要在软件中给它们一个数字0表示低电平,这样我们的LED才会点亮。

        现在我们只想要D1点亮,我们就可以把其它的几个P2端口全部设置为高电平,P20端口设置为低电平(也可以只设置P20端口,因为引脚默认都是上拉的,也就是所有端口默认都是高电平)。

        这里我们可以有两种方式点亮这个D1,一个是单个操作,一个是整体操作:

2.1单个端口操作点亮单个LED

        

        在所有操作之前,我们要包含一个头文件,我们可以右键单击点击直接插入头文件,也可以自己写一个出来,总之就要包含整个头文件,因为这个头文件里面有我们所有的关于引脚的定义。头文件里的名字也可以写成reg52.h,大小写不会造成影响

        然后我们需要使用一个关键词sbit,就可以定义单个引脚,sbit LED1 = P2^0;这样就完成了对一个引脚的重定义,我们就可以直接对LED1赋值间接对P20端口赋值。当然,只要你喜欢,这里的LED1只是一个名字,你可以换成任何非关键字的名字,然后使用。

        这里就得到代码:

#include <REGX52.H>
sbit LED1=P2^0;
void main()
{
	LED1 = 0;
}

        我们想要把这个代码烧入到我们的单片机上,我们就要安装驱动,连接数据线,下载软件,这里就不演示了,网上有很多的资料和视频,买开发板的时候商家也会赠送这些东西。

        这里使用的是普中官方的软件使用它就可以把我们电脑上的编译链接生成的文件烧入到开发板上,在此之前,我们还要先生成这个文件。

        左上角有三个按钮,第一个是只编译不生成文件,第二个是只编译最新更改的文件,第三个是编译所有文件,一般来说我们使用第二个用到比较多,因为当我们的代码数量众多的时候,每次全部编译效率就会很慢,所以最好使用中间的。

        

        我们点击一次之后下面就会出现这样的提示, 0 Error(s), 0 Warning(s) 就是让人兴奋的事情,这说明我们的程序没有问题,可以使用了,然后我们需要使用烧入的软件找到生成的hex文件,但是程序默认是不会生成hex文件的,我们就要再配置一下

        点击魔术棒,然后再点击Output,再点击生成hex文件,然后我们再点击一次编译

        我们发现多了这样的一条提示,这样就说明我们的我呢见成功生成了,我们就可以使用烧入软件开始烧入了

点击”打开文件“

找到hex文件之后开始配置其他的东西,比如选择插入了USB线的串口(需要有CH340驱动的标注),还有芯片类型和波特率

        然后就是把板子上电,并点击”程序下载“

出现了这样的程序下载成功就说明我们成功把东西下载到了板子上,你就成功点亮了一个LED!

2.2整体操作点亮LED

        整体操作就是直接对P2端口操作,这样我们只要对P2端口就可以点亮一个LED,或者是多个LED,就不需要我们反复使用sbit定义端口了。

        具体操作就是直接对P2赋值,假设我们想要让第一个灯亮,其他灯不亮,我们就要确保其他的都是高电平,而第一个灯是低电平,表示出来就是 : 0111 1111  但是这里有一个问题就是,我们的软件不会把它当作二进制处理,而是默认当作十进制处理,这样就和我们原本的意愿相悖了。一般我们使用的话,就会把它转化成十六进制:0111当作一位,1111当作一位,处理成为十六进制

        不过这里还有个问题:那就是我们的数据是按照类似数据结构中的栈处理的,也就是它按照0111 1111的顺序进入的话,它拿出来的时候是1111 1110,然后会出现一个问题,就是我们的开发板上亮的就不是我们想要的LED1,而是LED8,所以我们想要LED1亮的话,我们就要使用反向推理,也就是我们需要提前把这个我们想要的数据反抓一下,我们单片机得到的就是正确的数据了,比如我们就可以使用1111 1110输入,转换成十六进制就是0xfe(这里的大小写没有影响),这样我们就得到了LED1亮的情况了。

        所以我们就可以写出代码:

#include <REGX52.H>

void main()
{
	P2 = 0XFE;
}

然后上电烧入程序就行了

3.LED闪烁

        我们想要一个LED闪烁,也就是可以简化成把一个LED在点亮和熄灭之间反复切换,但是单片机操作的速度是很快的,肉眼无法观察到它的闪烁,所以我们就要使用一个暂停函数来让它们之间有一定的时间暂停不动,之后再进行下一个操作,这样我们就可以观察到它的闪烁了。

        我们要实现这样的暂停函数,可以借助另外一个工具

这个也是一个软件,可以用来烧入,而且功能丰富,但是我更喜欢用另外一个,因为操作简单点。

        这个软件也是板子配套的软件,我们可以使用它生成暂停函数

        我们可以在上面找到”软件延时计时器“

        选择好相应的系统频率和定时长度,然后点击生成C代码,再点击复制代码,然后我们在Keil里粘贴这个代码。

        到这里还不能直接使用,我们还要包含一个头文件#include <INTRINS.H>,这样函数里的_nop_函数才能够使用。

        之后,我们就可以把代码放在主函数中使用了。像这样:

void main()
{
	P2 = 0XFE;//点亮LED1
	Delay500ms();
	P2 = 0XFF;//熄灭LED1
	Delay500ms();
}

        然后就可以看到板子上LED1在不停闪烁了。

        但是这个代码还不完善,在单片机内部,其实是在不断调用main函数的,这并不太规范,我们可以加上一个while(1) 的死循环使它进入了main函数就不退出,并且能一直执行我们的闪烁指令。从某种意义上,提高了一点效率。

        完整代码就是这样:

#include <REGX52.H>
#include <INTRINS.H>
void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 22;
	j = 3;
	k = 227;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	while(1)
	{
		P2 = 0XFE;
		Delay500ms();
		P2 = 0XFF;
		Delay500ms();
	}
}

        但是我们突然想要把闪烁频率加快怎么办呢?再重新生成代码吗?

        我们可以生成一个1ms的函数,然后再通过形参调控我们想要的时间。

#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	while(xms--)
	{
		unsigned char i, j;
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	while(1)
	{
		P2 = 0XFE;
		Delay1ms(500);
		P2 = 0XFF;
		Delay1ms(500);
		
		P2 = 0XFE;
		Delay1ms(100);
		P2 = 0XFF;
		Delay1ms(100);
	}
}

        这样我们就可以十分灵活使用暂停函数控制闪烁时间和频率了。

4.LED实现流水灯

        LED实现流水灯其实就是上面实现闪烁的改版,我们只要计算出每个灯亮的时候它的对应的指令,然后闪烁,延时,再下一个,反复循环就得到了流水灯。

        但是这样的写法很是费劲,难道我们每次都要这样生成吗?那样多麻烦!

        这个写法很好理解,但是肯定不是最好的写法。

        4.1使用for循环和移位实现

4.1.1移位操作符       

        我们C语言中有一个操作符:<<(左移位)和 >>(右移位),移位左边是一个数,右边是需要移动的位数。

        而移位又分为算数移位和逻辑移位,移位是对一个二进制数的操作,这里讲一下基础的知识。

        首先:二进制中比如1000 1111 这个数如果是有符号整型的话,它的第一位1就是它的符号位,1表示负,0表示正。

        这里的逻辑位移就不考虑符号位,只是单纯的进行移位操作。比如1010 0101进行逻辑左移一位之后,把首位1移除后在最后面补0,得到0100 1010,再左移2位,得到0010 1000,我们发现,它并不会管我们的移除的数字是什么,它只知道移除之后补上0就行了,右移也是同样的道理。

        算数位移很相似,但是有一点不一样,算数位移的首位(符号位)不变,其他的遵循逻辑位移的规律,比如1100 1111右移1位,得到的就是1010 0111,符号位不变,其他位就按照逻辑位移的操作。

        在C51使用的时候,默认的是逻辑位移,就是没有符号位的位移,而且我们还要把它们转化成十六进制,再使用移位操作符。

4.1.2使用移位操作和for循环实现

        这里有一点不好实现的就是,我们使用P2端口定义的时候,比如我们想让它从LED1流水到LED8,这样的话我们初始的就是1111 1110,左移位一次会变成1111 1100,这样就不是只有LED2亮了,所以我们就要换个思路:假如我们的数只有一个1,其他位都是0是不是会更好处理?

        我们就可以把1111 1110取反,得到0000 0001,这样我们控制的时候就可以很精确的控制位了,取反操作符是~,加在我们需要取反的数的前面,比如~(0000 0001)得到的就是1111 1110这样,我们就可以使用取反和移位操作符实现流水灯了。

        我们把初始设定成P2 =~(0x01<<0)(即P2=~0000 0001)),下一个就是P2 = ~(0x01<<1)(即P2 = ~0000 0010),直到LED1到LED8都进行了一次闪烁,回归原位,就完成了流水灯循环。这里我们使用for循环实现。

#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	while(xms--)
	{
		unsigned char i, j;
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	unsigned int i = 0;
	while(1)
	{
		for(i = 0;i<8;i++)
		{
			P2 =~(0x01<<i);
			Delay1ms(300);
		}
	}
}

        这样我们就完成了对流水灯的实现。

        4.2使用移位函数实现LED流水灯

        除了使用 for 循环语句实现移位,KEIL C51 软件内还有对应的移位库函数, 左移函数是_crol_(),右移函数是_cror_(),而且这里要注意它们需要包含头文件#include <INTRINS.H>才可以使用,这两个函数和左移右移操作符的区别就是它们移位之后不会让多余的位补上0,而是顺延移出位的数,比如1001 1100左移一位,得到的是0011 1001,相当于我们把整体的数字往前推了一位,把推出的数字放回到末尾,这样的函数使得我们对流水灯的理解更加简便,我们不再需要使用取反符号,只要使用移位操作就好了。

        我们原本的数字是1111 1110,只要使用左移函数_crol_()就可以实现流水灯效果,即使用P2接收P2左移一位的返回值,直接改变P2,循环反复即可

#include <REGX52.H>
#include <INTRINS.H>
void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	while(xms--)
	{
		unsigned char i, j;
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	P2 = 0xfe;
	Delay1ms(100);
	while(1)
	{
		P2 = _crol_(P2,1);
		Delay1ms(100);
	}
}

        这样就实现了流水灯,还是比较简单的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pycharm和Spyder多行注释快捷键

1.选取注释内容 2.pycharm&#xff1a;使用Ctrl/ 3.Spyder&#xff1a;使用Ctrl1 效果图

1.k8s架构

k8s集群架构 一个Kubernetes集群至少包含一个控制平面(control plane)&#xff0c;以及一个或多个工作节点(worker node)。控制平面(Control Plane) : 控制平面负责管理工作节点和维护集群状态。所有任务分配都来自于控制平面。工作节点(Worker Node) : 工作节点负责执行由控制…

Centos-Linux安装部署MySQL-8.0

linux搭建mysql 1.使用系统的root账户 2.切换到 /usr/local 目录下 3.下载mysql wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz也可以直接在官方下载最新版本 官方下载 选择linux 4.解压mysql tar xvJf mysql-8.0.21-l…

Redux Toolkit+TypeScript最佳实践

Redux-Toolkit是为了简化使用Redux繁琐的步骤&#xff0c;可以j降低使用useReducer与useContext管理状态的频率&#xff0c;而且起到项目中状态管理规范和约束化的效果。 阅读本文需要的前置知识&#xff1a;React、Redux、Typescript、Redux hooks。 Redux-Toolkit使用步骤 …

【GO语言卵细胞级别教程】11.探索Go语言的面向对象编程之美(含源码仅此一份,先到先得)

【GO语言卵细胞级别教程】11.探索Go语言的面向对象编程之美&#xff08;含源码仅此一份&#xff0c;先到先得&#xff09; 目录 【GO语言卵细胞级别教程】11.探索Go语言的面向对象编程之美&#xff08;含源码仅此一份&#xff0c;先到先得&#xff09;1.面向对象的引用1.1简介1…

Day79:服务攻防-中间件安全IISApacheTomcatNginx弱口令不安全配置CVE

目录 中间件-IIS-短文件&文件解析&蓝屏&写权限 HTTP.SYS&#xff08;CVE-2015-1635&#xff09;主要用作蓝屏破坏&#xff0c;跟权限不挂钩 IIS短文件(iis全版本都可能有这个问题) IIS文件解析 IIS写权限 中间件-Nginx-文件解析&目录穿越漏洞&CRLF …

C++ //练习 11.14 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子的名和生日。

C Primer&#xff08;第5版&#xff09; 练习 11.14 练习 11.14 扩展你在11.2.1节练习&#xff08;第378页&#xff09;中编写的孩子姓到名的map&#xff0c;添加一个pair的vector&#xff0c;保存孩子的名和生日。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#x…

【大数据存储】实验七 Spark RDD

Spark RDD操作实验 一、实验目的 &#xff08;1&#xff09;掌握使用Spark访问本地文件和HDFS文件的方法 &#xff08;2&#xff09;熟练掌握在Spark Shell中对Spark RDD的操作方法 &#xff08;3&#xff09;掌握Spark应用程序的编写、编译打包和运行方法 二、.实验平台 …

自动化测试框架Robot Framework入门

什么是RF RF是一个基于 Python 的、可扩展的关键字驱动的自动化 验收测试框架、验收测试驱动开发 &#xff08;ATDD&#xff09;、 行为驱动开发 &#xff08;BDD&#xff09; 和机器人流程自动化 &#xff08;RPA&#xff09;。它 可用于分布式、异构环境&#xff0c;其中自动…

VUE3和SpringBoot实现ChatGPT页面打字效果SSE流式数据展示

在做这个功能之前&#xff0c;本人也是走了很多弯路&#xff08;花了好几天才搞好&#xff09;&#xff0c;你能看到本篇博文&#xff0c;那你就是找对地方了。百度上很多都是使用SseEmitter这种方式&#xff0c;这种方式使用的是websocket&#xff0c;使用这种方式就搞复杂了&…

STM32 PWM方式读取AS5600磁编码器数据

HAL STM32 PWM方式读取AS5600磁编码器获取角度例程 &#x1f4cd;相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》 &#x1f4cc;《HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程》 &#x1f341;先通过IIC读取的角度值和逻辑分析仪抓取的AS5600 OUT引脚…

MySQL - 基础二

6、表的增删改查 CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 6.1、Create 语法&#xff1a; INSERT [INTO] table_name[(column [, column] ...)]VALUES (value_list) [, (value_list)] ...value_list: v…

SQL注入---盲注

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.盲注概述 注是一种SQL注入攻击的形式&#xff0c;在这种攻击中&#xff0c;攻击者向目标应用程序发送恶意注入代码&#xff0c;然后通过观察应用程序的响应来推断出数据库中的信息。与常规的…

@Order和@DependsOn的区别

这里写自定义目录标题 一、区别二、demo演示1、Order2、DependsOn 一、区别 Order&#xff1a;改变Bean注入的顺序DependsOn&#xff1a;改变Bean创建的顺序 二、demo演示 1、Order 类 A B 都实现了接口 I &#xff0c;且 A B都由Spring容器创建并且管理 public class A im…

【Qt】:常用控件(二:QWidget核心属性)

常用控件&#xff08;二&#xff09; 一.cursor&#xff08;光标形状&#xff09;二.font&#xff08;字体信息&#xff09;三.toolTip&#xff08;提示显示&#xff09;四.focusPolicy&#xff08;焦点&#xff09;五.styleSheet&#xff08;文本样式&#xff09; 一.cursor&a…

Windows Docker 部署 Firefly III 开源记账软件

一、简介 Firefly III是一款开源的记账软件&#xff0c;支持全球多种语言。它可以帮助用户追踪和管理个人账目、预算和账单&#xff0c;减少支出&#xff0c;节省更多。该软件支持多种货币、银行账户和投资账户&#xff0c;并提供了丰富的报表功能&#xff0c;帮助用户更好地了…

预处理指令详解

前言 上一节我们了解了文件操作的相关内容&#xff0c;本节我们来了解一下预处理指令&#xff0c;那么废话不多说&#xff0c;我们正式开始今天的学习 预定义符号 在C语言中&#xff0c;设置了一些预定义的符号&#xff0c;可以供我们直接使用&#xff0c;预定义符号是在程序…

拓扑排序--有向无环图中一个节点的所有祖先

题目描述 给你一个正整数 n &#xff0c;它表示一个 有向无环图 中节点的数目&#xff0c;节点编号为 0 到 n - 1 &#xff08;包括两者&#xff09;。 给你一个二维整数数组 edges &#xff0c;其中 edges[i] [fromi, toi] 表示图中一条从 fromi 到 toi 的单向边。 请你返…

基于SpringBoot和Vue的金融融资管理系统的设计和实现【附源码】

1、系统演示视频&#xff08;演示视频&#xff09; 2、需要交流和学习请联系

图像处理入门 3(how to get the pixel pitch / 如何获得单个像素的尺寸)

在这里一节里面&#xff0c;将记录如何获得一个相机传感器中单个像素点的尺寸&#xff0c;为了实现不同相机照片之间的匹配。 如果我们知道了相机传感器的尺寸和分辨率的大小&#xff0c;自然就可以求出单个像素的大小。 在这里插入图片描述&#xff1a; 如何获得相机传感器的…