51入门之LED

news2025/1/16 16:16:32

        

目录

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);
	}
}

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

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

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

相关文章

go juc 线程中的子类

1.go test() 主死随从 package mainimport ("fmt""strconv""time" )func test() {for i : 1; i < 10; i {fmt.Println("hello " strconv.Itoa(i))//阻塞time.Sleep(time.Second)} } func main() {//开启协程go test()for i : 1; …

GT收发器64B66B协议(2)自定义PHY设计

文章目录 前言一、设计框图二、GT_module三、PHY_module3.1、PHY_tx模块3.2、PHY_rx_bitsync模块3.3、PHY_rx模块 四、上板测试 前言 有了对64B66B协议的认识以及我们之前设计8B10B自定义PHY的经验&#xff0c;本文开始对64B66B自定义PHY的设计 一、设计框图 二、GT_module …

什么是redis缓存的雪崩、穿透以及击穿

缓存雪崩 举个例子&#xff0c;例如在双十一中&#xff0c;一点进去。访问量大&#xff0c;所以它很多数据是放在redis区缓存起来&#xff0c;对应redis的100个key。然后假设设置缓存失效时间是三小时。当双十一期间&#xff0c;购物超过这个三小时之后。这个首页的redis缓存会…

Excel、PowerQuery 和 ChatGPT 终极手册(上)

原文&#xff1a;Ultimate ChatGPT Handbook for Enterprises 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 序言 在不断发展的数据管理和分析领域中&#xff0c;掌握 Excel 的查找功能不仅是一种技能&#xff0c;更是高效数据处理的基石。《使用 Power Query 和 Ch…

Red Hat Enterprise Linux release 8.4安装Jenkins

1. 查看安装 1.1 显示 Linux 系统的详细信息&#xff0c;包括内核版本、操作系统版本和其他相关信息 uname -a1.2 查看 Red Hat Linux 系统的版本 cat /etc/redhat-release # 或者 cat /etc/os-release1.3 查看 JDK 是否安装 java -version #查看安装路径 echo $JAVA_HOME1…

Docker 哲学 - docker swarm

Docker Swarm 模式下的集群管理和服务恢复机制 Docker Swarm 是 Docker 的集群管理和编排功能。在 Swarm 模式下&#xff0c;你可以将多个 Docker 主机组合成一个虚拟主机&#xff0c;称为 Swarm 集群。Swarm 集群由一个或多个管理节点&#xff08;manager nodes&#xff09;和…

前端开发基础(HTML5 + CSS3)【第一篇】:HTML标签之文字排版、图片、链接、音频、视频 涵盖了两个综合案例 做到了基础学得会,实战写的出

点击前往前端开发基础专栏&#xff1a; 文章目录 HTML5 CSS3 开发一、开发环境搭建下载 VS Code1. 2 插件的下载1.3 项目和文件的下载 二、 什么是 HTML2.1 标签的语法2.2 代码演示&#xff1a;2.3 小结 三 、HTML基本骨架3.1 快捷键生成HTML骨架3.2 代码展示3.3 小结 四、标…

【游戏逆向】逆向基础之寄存器和内存

寄存器是中央处理器内的组成部分 它们可用来暂存指令、数据和地址。 具有这样功能还有内存 我们这里说的内存都是指虚拟内存。 寄存器和虚拟内存的主要区别在于它的存储和读取速度更快&#xff0c;那么有的同学会说&#xff0c;那我们全用寄存器就好了&#xff0c;但是&…

NOI - OpenJudge - 2.5基本算法之搜索 - 1490:A Knight‘s Journey - 超详解析(含AC代码)

点赞关注吧~ 1490:A Knights Journey 查看提交统计提问 总时间限制: 1000ms 内存限制: 65536kB 描述 Background The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey around the world. When…

数据仓库面试总结

文章目录 1.什么是数据仓库&#xff1f;2.ETL是什么&#xff1f;3.数据仓库和数据库的区别&#xff08;OLTP和OLAP的区别&#xff09;4.数据仓库和数据集市的区别5.维度分析5.1 什么是维度&#xff1f;5.2什么是指标&#xff1f; 6.什么是数仓建模&#xff1f;7.事实表7.维度表…

StarRocks实战——华米科技埋点分析平台建设

目录 前言 一、原有方案及其痛点 二、引入StarRocks 三、方案改造 3.1 架构设计 3.2 数据流程 3.3 性能指标 3.4 改造收益 前言 华米科技是一家基于云的健康服务提供商&#xff0c;每天都会有海量的埋点数据&#xff0c;以往基于HBase建设的埋点计算分析项目往往效率上…

号卡极团分销管理系统 index.php SQL注入漏洞复现

0x01 产品简介 号卡极团分销管理系统,同步对接多平台,同步订单信息,支持敢探号一键上架,首页多套UI+商品下单页多套模板,订单查询支持实时物流信息、支持代理商自定义域名、泛域名绑定,内置敢探号、172平台、号氪云平台第三方接口以及号卡网同系统对接! 0x02 漏洞概述…

在ssh 工具 Linux screen会话中使用鼠标进行上下滚动

经过几次发现 除xshell外&#xff0c; WindTerm finalshell MobaXterm 都是进入会话后&#xff0c;发现其界面无法滚动屏幕向上查看 如果想要在Linux screen会话中使用鼠标进行上下滚动。必须首先进入该screen的回滚(scrollback模式)才能进行上下滚动 第一步&#xff…

RobotFramework测试框架(2)-测试用例

创建测试数据 测试数据语法 这里的测试数据就是指的测试用例。 测试文件组织 测试用例的组织层次结构如下&#xff1a; 在测试用例文件&#xff08; test case file &#xff09;中建立测试用例 一个测试文件自动的建成一个包含了这些测试用例的测试集&#xff08; test s…

TCP/IP协议、HTTP协议和FTP协议等网络协议包简介

文章目录 一、常见的网络协议二、TCP/IP协议1、TCP/IP协议模型被划分为四个层次2、TCP/IP五层模型3、TCP/IP七层模型 三、FTP网络协议四、Http网络协议1、Http网络协议简介2、Http网络协议的内容3、HTTP请求协议包组成4、HTTP响应协议包组成 一、常见的网络协议 常见的网络协议…

A First Course in the Finite Element Method【Daryl L.】|PDF电子书

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

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

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

超越聊天机器人:语言模型揭秘

原文&#xff1a;More than a Chatbot 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 致谢 我要感谢激励我写这本书的跨学科项目合作伙伴&#xff0c;特别是“BIAS&#xff1a;减轻劳动力市场 AI 多样性偏见”地平线欧洲项目&#xff0c;以及我的研究小组和其他研究同…

MySQL-逻辑架构:逻辑架构分析、SQL执行流程、数据库缓冲池

逻辑架构 1. 逻辑架构剖析 1.1 第1层&#xff1a;连接层 系统&#xff08;客户端&#xff09;访问MySQL服务器前&#xff0c;做的第一件事就是建立TCP连接。 经过三次握手建立连接成功后&#xff0c;MySQL服务器对TCP传输过来的账号密码做身份认证、权限获取。 用户名或密码…

玩转ChatGPT:Kimi测评(图片识别)

一、写在前面 ChatGPT作为一款领先的语言模型&#xff0c;其强大的语言理解和生成能力&#xff0c;让无数用户惊叹不已。然而&#xff0c;使用的高门槛往往让国内普通用户望而却步。 最近&#xff0c;一款由月之暗面科技有限公司开发的智能助手——Kimi&#xff0c;很火爆哦。…