江协科技/江科大-51单片机入门教程——P[2-2] LED闪烁P[2-3] LED流水灯

ops/2025/3/3 16:26:01/

本节实现LED周期闪烁和LED流水灯。

目录

一、LED闪烁

二、LED流水灯


一、LED闪烁

首先来实现让一个 LED 以 1 秒为周期闪烁。下面是具体步骤。

首先,新建一个工程,在外面再次新建一个名为 “2 - 2 led 闪烁” 的文件夹,工程名设为 “project”。然后选择器件,可搜索 “at”,选择Atmel的 89C52,点击 “OK”。启动文件点击否,右键添加新的 C 文件main.c,点击 “add”。

在右侧编写 C 文件代码,先右键添加一个头文件,一般会添加常见的头文件。接着编写主函数 “void main ()”,加上一对花括号,并按 “Tab” 键缩进。

先把上一节点亮一个 LED 的代码 “P2 = 0xfe” 写出来,若要熄灭 LED,则使用 “P2 = 0xff” ,二进制的 8 个 1 表示所有 LED 都不亮。

下面设置一个主循环的死循环 “while (1)”,在这个循环里要实现 LED 的亮灭循环。将点亮和熄灭 LED 的代码放到 “while (1)” 循环中,并注意代码对齐,选中这两行按 “Tab” 键缩进。

编译代码后,每次建工程都要在选项里选择创建 HEX 文件,再次点击编译。

点击打开程序文件,找到 LED 闪烁的程序并下载。此时会发现 LED 始终亮着,只是亮度不是特别亮,这是因为单片机运行速度是兆赫兹等级,每秒能运行 100 万次,亮灭代码执行得特别快,LED 闪烁速度太快,肉眼难以察觉。

为了让 LED 以 1 秒为周期闪烁,需要在亮灭代码执行后分别进行 500 毫秒的延时。

可以使用 STC-ISP 里的软件延时计算器来生成延时代码,选择定时长度为 500 毫秒,同时要注意系统频率,开发板上的晶振是 12 兆赫兹,所以将系统频率改成 12.000 兆赫兹。指令级默认选的 “Y5” 适用于 15 系列,而我们的单片机是 89 系列,要改成 “Y1”,它适用于 89C、89L 等。

void Delay500ms() //@12.000MHz{unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);}

点击复制代码,在主函数上面粘贴,会生成一个延时子函数。函数左边的返回值 “void” 表示函数执行后没有返回值,括号里若不写传入参数则默认是 “void”。生成的函数里定义了几个变量,通过 “do - while” 循环兜圈子计数来达到延时目的,其中还有个 “nop” 函数。

编译时会出现一个错误,提示 “nop” 没有函数原型,解决办法是添加一个名为 “” 的头文件,该头文件里定义了一些函数,包括 “nop”,它是一个空语句。

再次编译又会出现警告,提示 “未调用段”,意思是定义了 “delay500 毫秒” 子函数但未调用。

在主函数里调用这个子函数,即 “Delay500 ms ();” ,在点亮和熄灭 LED 代码后分别调用。

如下为完整代码:

#include#includevoid Delay500ms() //@12.000MHz{unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);}void main(){while(1){P2=0xFE; //1111 1110Delay500ms();P2=0xFF; //1111 1111Delay500ms();}}

点击编译,没有错误和警告,将代码下载到单片机,就能看到 LED 以 1 秒为周期闪烁。

二、LED流水灯

有了前两个代码的经验,我们可以完成第三个 LED 流水灯程序。具体步骤如下:

首先,重新建一个工程,点击新建,创建一个名为 “2 - 3 LED 流水灯” 的文件夹,工程名设为 “project”,选择器件 “at89c52”,点击 “OK”。新建并添加新的 C 文件。

接下来复习前两个的代码,先添加头文件,然后编写主函数 “void main ()”,加上一对花括号并回车,按 “Tab” 键缩进,确保括号匹配并在同一列,遇到花括号进行缩进。在主函数里写一个 “while (1)” 循环,添上花括号

把上一个 LED 以 1 秒为周期闪烁的代码写出来,即 “P2 = 0xFE” ,这是点亮第一个 LED,然后进行延时 “Delay 500ms ();”。“Delay 500ms” 函数需要提前定义,在stc-isp选好相关设置后点击 “生成代码”复制代码粘贴过来。代码里的 “nop” 可以删掉(不删更加精确),如果不删则要在上面包含头文件 “” ,这个头文件大小写要求不严格,但标识符大小写区分。

#include#includevoid Delay500ms() //@12.000MHz{unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);}void main(){while(1){P2=0xFE;//1111 1110Delay500ms();}}

延时之后,复制点亮和延时的两行代码,多次粘贴。原本是 LED 亮灭,现在要实现流水灯效果。第一个 LED 点亮是二进制的 “1111 1110”,第二个是 “1111 1101”,第三个是 “1111 1011” ,以此类推,通过复制粘贴让 “0” 左移,实现流水灯的二进制表示。再将二进制转化为十六进制,如 “1111 1110” 是 “fe”,“1111 1101” 是 “fd” 等,多转化几次就能记住转换方法。

#include#includevoid Delay500ms() //@12.000MHz{unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);}void main(){while(1){P2=0xFE;//1111 1110Delay500ms();P2=0xFD;//1111 1101Delay500ms();P2=0xFB;//1111 1011Delay500ms();P2=0xF7;//1111 0111Delay500ms();P2=0xEF;//1110 1111Delay500ms();P2=0xDF;//1101 1111Delay500ms();P2=0xBF;//1011 1111Delay500ms();P2=0x7F;//0111 1111Delay500ms();}}

点击编译代码,若下载时发现没有文件,需要在选项的 “output” 里创建 HEX 文件,重新编译后点击下载

重启电源开关,就能看到 LED 以 500 毫秒为间隔向左移动。这里使用的是复制粘贴的方式,如果花样多,可能要复制很多行代码,之后会介绍更高级的操作方式。

第三个 LED 流水灯程序完成后保存。当前程序是以 500 毫秒为变化时间,如果想让流水灯走得更快,以 200 毫秒为变化间隔,就需要重新写延时函数,这会使代码不灵活。为解决这个问题,可以改造代码,让一个函数能根据传入的参数实现不同时长的延时。

重新建立一个名为 “2 - 4 LED 流水灯 plus” 的工程,选择 “at89C52” ,右键添加新的 C 文件。添加头文件,编写主函数基本框架。

把 500 毫秒的延时函数改造成能根据传入参数延时的函数,先生成一个 12 兆和 1 毫秒的延时函数,复制代码粘贴过来。

原本函数括号里没写入口参数,现在要写一个参数,比如 “xms”,并指定变量类型。

单片机在存储和执行代码时,变量运算很重要,需要用 “数据小盒子” 来存储数据。常见的数据类型有:

  • “int”(整数形):用 16 位二进制表示一个十进制数字,在单片机系统里是 16 位,在计算机里是 32 位。默认是有符号的 “signed int” ,范围是 - 32768 到 32767;若要表示无符号整数,用 “unsigned int”,表示正整数范围是 0 到 65535。
  • “long”(长整形):能表示更大的数,对应的无符号类型是 “unsigned long”。
  • “float”(单精度浮点型)和 “double”(双精度浮点型):用于表示小数,使用科学计数法,没有无符号的实形。
  • “char”(字符型):有符号的 “char” 和无符号的 “unsigned char”,以 8 位二进制表示数字,范围是 0 到 255,常用于存放字符,也可存数字。

在函数里,将 “xms” 定义为 “unsigned int” 类型的变量。

函数里使用 “while” 循环,判断 “xms” 是否非零,若非零则执行循环内容,每次循环将 “xms” 减 1,减 1 之前进行 1 毫秒的延时。“x 毫秒 = x 毫秒 - 1” 可缩写为 “x 毫秒 --”。

在主函数里调用这个带参数的延时函数,先编译确保代码正确。把上一节的流水灯代码复制粘贴过来,若打开方式有问题,可选择记事本打开。将原来无参数的延时 500 毫秒函数替换成新的带参数函数,如 “delay1ms (500);” ,替换完所有相关代码后编译,在工程选项里勾选 HEX 文件,再次编译并下载代码,重启后能看到 LED 流水灯效果。

完整main.c程序如下

#includevoid Delay1ms(unsigned int xms); //@12.000MHzvoid main(){while(1){P2=0xFE;//1111 1110Delay1ms(1000);P2=0xFD;//1111 1101Delay1ms(1000);P2=0xFB;//1111 1011Delay1ms(100);P2=0xF7;//1111 0111Delay1ms(100);P2=0xEF;//1110 1111Delay1ms(100);P2=0xDF;//1101 1111Delay1ms(100);P2=0xBF;//1011 1111Delay1ms(100);P2=0x7F;//0111 1111Delay1ms(100);}}void Delay1ms(unsigned int xms) //@12.000MHz{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}

使用带参数的子函数更灵活,比如把延时参数改成 100 毫秒,再次编译下载,流水灯就会变快。

还能设置不同的延时长度,如前两个是 1 秒,后面是 100 毫秒,这样就能随心所欲地调节流水灯的延时。


http://www.ppmy.cn/ops/162811.html

相关文章

Eureka的缓存原理分析

上一篇介绍了Eureka的缓存机制,Eureka的缓存机制就像个"善意的谎言"——它为了让系统更抗压,会悄悄把服务信息藏在小本本里。咱们今天就扒开它的口袋,看看里面到底揣着什么秘密~ 扒开Eureka的缓存小棉袄:源码里的温柔陷…

Android Studio2024版本安装环境SDK、Gradle配置

由于许多学友在看此教程还是出许多错误,特此录制教程👉视频教程 若觉得自己不用看教程,直接往下翻👇 一、软件版本,安装包附上 👉android-studio-2024.1.2.12-windows.exe👈 👉百…

基因枷锁下的太空梦 —— 千钧一发电影观后感

目录 1 人物介绍 2 电影名解读 3 电影开头 3.1 电影开头的两段话 3.2 片头设计 4 电影正文 4.1 “杰罗米”各种诡异的行为 4.2 文森特 – 失败的man 4.3 真正的杰罗米以及假基因身份证 4.4 文森特新征程 4.5 基因人的不容易 4.6 睫毛被查出有问题 4.7 文森特身份初…

pandas 数据合并

数据的合并 使用merge函数合并两个 DataFrame数据结构表 函数的使用方法: # 引用pandas import pandas as pd # marge 使用方法 pd.marge(df1,df2,on ,how )参数1和参数2: df1和df2 是要合并的两个 DataFrame 数据表参数3: on 用于指定合并的列索引 需要是两个数…

【图像亮度、对比度调整,直方图均衡化及图像平滑】

图像增强与基本处理 目录 图像增强与基本处理目标知识点1. 亮度调整2. 对比度调整3. 直方图均衡化4. 图像平滑(高斯滤波)5. 图像平滑(中值滤波) 目标 学习图像增强的基本方法,包括亮度调整、对比度调整、直方图均衡化…

Java进阶——常用工具类

日常开发中,Arrays、Collections 和 Objects 是非常实用的工具类,提供了丰富的功能,从而可以更高效地处理数组、集合和对象。本文将详细介绍这三个工具类的重要知识细节。 本文目录 一、 Arrays数组转集合并行排序优化Stream 支持 二、 Colle…

DeepSeek 助力 Vue3 开发:打造丝滑的网格布局(Grid Layout)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…

Qt中应用程序框架的体系说明 及应用程序类QApplication类深度解析与应用分析

作为Qt开发者,我们肯定经常见到过QApplication类,有时候可能你看到了都没注意,也没太关心这个类做什么用。那你只需随便建个窗体程序的工程,在自动生成的工程文件main.cpp中就能看到,像这样: #include &qu…