51单片机入门(3)点灯的进阶

您所在的位置:网站首页 led灯c语言 51单片机入门(3)点灯的进阶

51单片机入门(3)点灯的进阶

2024-07-03 06:14:18| 来源: 网络整理| 查看: 265

上一节我们学习了用51单片机点亮LED,这节我们继续围绕点灯进行进一步学习——实现跑马灯效果。 跑马灯的核心就是LED闪烁,要实现LED的闪烁,那就需要周期性地控制LED的亮和灭,而亮和灭的间隔如何实现呢?这就得用到延时了,本实验的延时采用阻塞式延时(让程序不停地执行空语句,空耗处理器的时间)。

文章目录 一、单个LED闪烁实验代码编译+烧录实验效果 二、LED跑马灯实验代码实验效果 三、其他花样灯流水灯呼吸灯

先简单介绍本文将用到的硬件及软件: 硬件平台:普中51开发板-单核A2 软件:Keil5(C51)、STC-ISP(或其他ISP软件)、Proteus8.9(用于仿真,非必须) 一、单个LED闪烁

在介绍代码前,我们先来讨论延时的实现,在学习定时器之前,我们只能通过空语句的方法实现延时。接下来的内容十分枯燥,建议跳过,直接看实验代码。

我们先看看单行C代码(一行空语句)在51单片机里需要运行的时间:

_nop延时这里就不讨论了,只讨论空语句

首先使用软件调试,在空语句之前程序运行时间为0.00019550(0.1955ms)【单片机从0s开始运行】;

在这里插入图片描述

运行完一行空语句,程序运行时长为:0.00020550(0.2055ms),和上一个状态相差0.01ms,也就是10us,所以理论上(由于这是软件仿真,所以只能得出理论值),我这个51单片机一行空语句耗时10us。

在这里插入图片描述 一行空语句耗时10微秒,那我想延时1秒钟,岂不是只需要执行100000行空语句?

答案是可以实现,但时间可能并不准,网上给出的答案是(单片机中)C代码是不能实现准确延时的,只有汇编(如nop)和定时器可以,由于后两项本文暂不考虑,所以依旧使用C语言的空语句实现延时,毕竟现在不需要精准延时,同时我们也能了解一下空语句延时到底能有多大误差【这是我最感兴趣的】。

这里需要注意一点,51单片机的int类型只有2个字节,最大的数值为32767,如果用unsinged int,最大能使用65535,虽然可以用long类型(4字节),但网上说效率会降低,作为新手,我们还是保险点,尽量使用常用的类型,我就先用0.5秒做实验(50000行空语句)

同样,使用软件仿真查看,由于空语句前的运行时间和之前相同,所以我直接给出执行完50000行空语句后的运行时间,0.22529850(225.29850ms),与空语句前的运行时间的差值大约为225ms。

这和我们设想的0.5秒相差得太大了吧。其实这里我犯了一个错误-----细心的朋友会发现,之前我算的并不是空语句的运行时长,而是一个while(1--);运行的时长,即一个while语句再加一个空语句。

在这里插入图片描述 但我们发现此时的一个空语句循环的延时时间约是225/50000=0.0045ms,即4.5us。 所以我们再试试其他值是不是也满足这个规律,比如我想延时100ms,能不能用100*1000/4.5=22222(保留整数)个空语句循环实现呢?试试吧。

执行完22222行空语句循环后,运行时间为0.10024300(100.243ms),与空语句前的运行时间的差值大约为100ms。准度还行,至少ms级的延时是没问题的。

在这里插入图片描述

上面的调试都是使用Keil软件进行的,软件仿真往往只能作为参考,所以我们还需对开发板进行实测

就测试250ms延时吧,利用刚才得出的结果-----while(i--);每次循环运行耗时为4.5us(i不能太小,也不能超过65535)。

0.25s需要的循环空语句数量约为250*1000/4.5=55555(保留整数)

测试代码见下文,其实就是LED闪烁的实验代码。

实验代码

在写代码前,我们需要先创建一个Keil工程,创建工程的步骤已经在第一节讲述,传送门:🚀(点我)。这里就不进行赘述。

#include //此文件中定义了单片机的一些特殊功能寄存器 sbit led_out = P2^0; //将单片机的P2.0端口定义为led /****************************************************************************** * @ 函数名 : main * @ 功 能 : 主函数 * @ 参 数 : 无 * @ 返回值 : 无 ******************************************************************************/ void main() { unsigned int t = 55555; //250ms,t较小时,延时单位为10us,t较大时,延时单位为4.5us unsigned int i = 0; while(1) { i = t; //250ms led_out = 0; //P2.0端口设置为低电平(点亮LED) while(i--){} //空语句循环 led_out = 1; //灯灭 i = t; //250ms while(i--){} //空语句循环 } } 编译+烧录

程序编写完成后,接下来的操作就是编译+烧录了,这些步骤已经在本系列第一篇文章中讲述,传送门:🚀(点我)。不过这里还是会简单描述一下操作过程:

点击编译按钮,如果怕出现意外,可以点第三个(重新编译),编译完成后Build Output窗口会显示报错信息,如果没有错误和警告(如果这几行都有警告,那说明有问题),且生成了hex文件,说明编译成功。

在这里插入图片描述

将刚才生成的hex文件烧录到单片机中,即可看到LED在闪烁了。

在这里插入图片描述

实验效果 实际效果:可以看到右边的LED1在闪烁,闪烁间隔约为250ms(250ms为软件仿真值,下文实测值为540~660ms)。

请添加图片描述

仿真效果: 【Proteus软件的安装和使用可以参考我的另一篇博客(带安装包下载链接),传送门:🚀(点我)】

请添加图片描述

很遗憾,实际测试的时间和软件仿真相差很大,下面第一张图是灯亮到灯灭的延时时间,542ms,是250ms的两倍多。

在这里插入图片描述

第二张图是灯灭到灯亮的延时时间,相差得更大了。所以空语句的延时最好自己进行调试。

在这里插入图片描述

二、LED跑马灯

从LED闪烁的实验我们可以得知用C语言的空语句实现的延时是十分不准确的,但这些误差人眼并不能识别出来,所以本实验继续使用while循环实现延时。这次我就不进行软件仿真来调延时时间了,因为仿真的时间和真实时间相差太大。

根据上文的延时时间实测结果,空语句循环次数为55555时,延时时间大约为540ms,所以我们可以算出运行一次while(1--){}耗时约10us(这和第一次软件仿真的结果相同,奇怪了)。 同时为了提高代码简洁度,我把延时代码封装成了一个函数,这样重复调用时就更加方便了:

/****************************************************************************** * @ 函数名 : Delay_10us * @ 功 能 : 10us粗略延时 * @ 参 数 : 延时时间--单位10us * @ 返回值 : 无 ******************************************************************************/ void Delay_10us(unsigned int time) { while(time--); }

接下来就是实现跑马灯了:

跑马灯大家应该听说过,有些人喜欢叫流水灯,这里我不对它们进行区分,我要实现的就是8个LED依次亮灭,这就是核心原理了,直接上代码吧(下文)。

实验代码

下面是跑马灯的完整代码

#include //此文件中定义了单片机的一些特殊功能寄存器 #define led_out P2 //将单片机的P2端口定义为led,8个IO /****************************************************************************** * @ 函数名 : Delay_10us * @ 功 能 : 10us粗略延时 * @ 参 数 : 延时时间--单位10us * @ 返回值 : 无 ******************************************************************************/ void Delay_10us(unsigned int time) { while(time--); } /****************************************************************************** * @ 函数名 : main * @ 功 能 : 主函数 * @ 参 数 : 无 * @ 返回值 : 无 ******************************************************************************/ void main() { unsigned char i = 0; unsigned int t = 0; led_out = 0xff; //8个灯全部灭 while(1) { for(i = 0; i while(time--); } /****************************************************************************** * @ 函数名 : main * @ 功 能 : 主函数 * @ 参 数 : 无 * @ 返回值 : 无 ******************************************************************************/ void main() { unsigned char i = 0; unsigned int t = 0; led_out = 0xff; //8个灯全部灭 while(1) { for(i = 0; i while(time--); } /****************************************************************************** * @ 函数名 : Adjust_Brightness * @ 功 能 : 调节8个LED的亮度(模拟PWN占空比控制) * @ 参 数 : brightness 亮度 0--100 * @ 返回值 : 无 * @ 备 注 : 一个模拟PWM周期为10*100us(1ms) ******************************************************************************/ void Adjust_Brightness(unsigned char brightness) { unsigned char low = brightness; //点亮时间 unsigned char high = 100 - brightness; //熄灭时间 led_out = 0x00; //点亮8个LED Delay_10us(low); //点亮延时 led_out = 0xff; //熄灭8个LED Delay_10us(high); //熄灭延时 } /****************************************************************************** * @ 函数名 : main * @ 功 能 : 主函数 * @ 参 数 : 无 * @ 返回值 : 无 ******************************************************************************/ void main() { unsigned int i = 0, cnt = 1000; led_out = 0xff; //8个灯全部灭 while(1) { /* 呼吸灯逐渐变亮,持续时间为1000*1ms */ for(i = 0; i Adjust_Brightness(i / 10); } } } 实际效果:(不用管数码管)

请添加图片描述

仿真效果:惨不忍睹,呼吸灯仿真效果太差了,哪怕我把延时单位放大两倍也不行(不过软件仿真时的延时本来就比实际情况时间快1倍)。 【Proteus软件的安装和使用可以参考我的另一篇博客(带安装包下载链接),传送门:🚀(点我)】

请添加图片描述

如果文章对你有帮助,请留下你的点赞吧👍,这是我继续更新的最大动力🚀。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭