1.必须组件
- 1 × Arduino UNO 板
- 3 × 330欧姆电阻
- 3 × LED
2.实验成果展示
VID20251203164857
3.电路连接图
按照电路图进行连接,依次将三个LED灯接入7,8,9引脚,如下图所示。
4.程序代码
const byte LEDs[]={7,8,9}; const byte total = 3; byte index = 0; void setup() { // put your setup code here, to run once: for(byte i = 0; i < total; i++) { pinMode(LEDs[i], OUTPUT); //i的值将从0到4,依序设置7,8,9引脚为输出引脚。 } } void loop() { // put your main code here, to run repeatedly: for (byte i = 0; i < total; i++) { digitalWrite(LEDs[i], LOW); } digitalWrite(LEDs[index],HIGH); index ++; if (index == total) index = 0; delay(500); }4.1代码讲解
(一)变量与常量的定义
const byte LEDs[] = {7,8,9}; const byte total = 3; byte index = 0;1.const(常量修饰符)
含义:const即“常量”,修饰的变量/数组值不可被修改,一旦定义,程序中无法通过赋值语句改变其内容。
作用:
- 防止误操作修改关键值(如LED引脚号、设备总数);
- 提升程序可读性(用 total 代替数字3,一眼能看出是“LED总数”);
- 编译器可对常量做优化,节省内存;
反例:如果写LEDs[0] = 10;,编译器会直接报错,因为LEDs被const修饰。
2.byte(数据类型)
本质:Arduino的byte是8位无符号整数类型,等价于C语言的uint8_t,取值范围 0~255 。
优势:Arduino单片机(如Uno)的内存很小(仅2KB SRAM),byte只占1字节,而int占2字节,存储引脚号这类小数值时,用byte更节省内存。
适用场景:存储引脚号、设备数量、简单计数(不超过255)等。
3. 数组LEDs[]
数组声明语法:类型 数组名[长度] = {元素1, 元素2,...};
- 代码中 LEDs[] 省略了长度,编译器会自动根据大括号内的元素数量(3个)确定数组长度为3;
- 也可显式写 LEDs[3] = {7,8,9}; ,效果完全一致。
数组的索引规则:数组的索引从0开始,而非1。
- -LEDs[0]→ 第一个元素,值为7(对应Arduino引脚7);
- -LEDs[1]→ 第二个元素,值为8(对应Arduino引脚8);
- -LEDs[2]→ 第三个元素,值为9(对应Arduino引脚9);
- 若访问 LEDs[3] ,属于数组越界,会读取到随机的内存数据,导致程序出错。
4. 变量index
作用:作为数组的“指针”,记录当前需要点亮的LED在数组中的位置。
初始值 0:程序启动时,先点亮数组第一个元素对应的引脚(7号引脚)。
(三)setup()函数:初始化引脚模式
void setup() { for(byte i = 0; i < total; i++) { pinMode(LEDs[i], OUTPUT); } }1.for循环(固定次数循环)
语法拆解:for(初始化表达式; 条件表达式; 增量表达式) { 循环体 }
- 初始化:byte i = 0;→ 定义循环变量 i ,初始值为0(数组索引从0开始);
- 条件:i < total;→ 循环继续的条件( i 小于3时执行循环体);
- 增量:i++→ 每次循环结束后, i 自增1(i++等价于i = i + 1);
i++(后置自增)
先返回变量 i 的原始值,再执行i = i + 1的自增操作。
例:int i = 2; int a = i++;
执行后,a = 2(先取 i 的原始值赋值), i = 3 (后自增)。
++i(前置自增)
先执行i = i + 1的自增操作,再返回自增后的新值。
例:int i = 2; int a = ++i;
执行后,i = 3(先自增),a = 3(后取新值赋值)。
在for循环中++i和i++效果完全相同
- 循环次数:i 取0、1、2,共3次,刚好遍历数组所有元素。
对比:如果不用循环,需要写3行pinMode(7,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT);,循环让代码更简洁,且新增LED时只需修改数组,无需改初始化代码。
2.pinMode()(引脚模式设置函数)
函数原型:void pinMode(uint8_t pin, uint8_t mode);
参数说明:
- pin:要设置的引脚号(如7、8、9);
- mode:引脚模式,主要有两种:
- OUTPUT:输出模式,用于向外部设备(如LED)输出电信号(高/低电平);
- INPUT:输入模式,用于读取外部信号(如传感器、按键)。
硬件原理:Arduino的数字引脚默认是INPUT模式,要控制LED必须设为OUTPUT,否则引脚无法主动输出电平。
四、loop()函数:流水灯核心逻辑
void loop() { for (byte i = 0; i < total; i++) { digitalWrite(LEDs[i], LOW); } digitalWrite(LEDs[index], HIGH); index++; if (index == total) { index = 0; } delay(500); }1. 第一步:熄灭所有LED(for循环+digitalWrite)
for (byte i = 0; i < total; i++) { digitalWrite(LEDs[i], LOW); }digitalWrite()(数字电平写入函数):
函数原型:void digitalWrite(uint8_t pin, uint8_t value);
参数说明:
- pin:要写入的引脚号;
- value:电平值,HIGH(高电平,一般为5V/3.3V)或LOW(低电平,0V)。
硬件原理:LED是单向导电的半导体,当引脚输出HIGH时,电流流过LED使其点亮;LOW时无电流,LED熄灭(需注意LED要串联限流电阻,否则会烧毁)。
循环作用:遍历所有LED引脚,统一写入LOW,确保每次只有一个LED点亮,避免多个LED同时亮的混乱。
2. 第二步:点亮当前索引对应的LED
digitalWrite(LEDs[index], HIGH);- 利用index变量获取当前要点亮的引脚号(如index=0时,LEDs[0]=7,点亮7号引脚);
- - 这一步在“熄灭所有LED”之后执行,保证每次只有目标LED亮。
3. 第三步:索引自增与重置(index+++条件判断)
index++; if (index == total) { index = 0; }index++ :索引自增1,指向下一个LED(如index=0→1→2,依次对应引脚7→8→9)。
条件判断if (index == total):
- 当index增加到3(等于total=3)时,数组已遍历完毕(数组最大索引是2),此时将 index 重置为0,实现循环遍历(从第一个LED重新开始);
- 若不重置,index会继续增加到4、5…,访问LEDs[3] 、 LEDs[4]会导致数组越界,程序可能出现乱码、死机。
4. 第四步:延时(delay(500))
delay() (延时函数):
- 函数原型:void delay(unsigned long ms);
- 参数ms:延时的毫秒数,delay(500)表示程序暂停500毫秒(0.5秒);
- 作用:控制LED点亮的持续时间,若没有延时,LED切换速度会极快(单片机执行速度为微秒级),肉眼看不到流水效果。
注意:delay()是“阻塞式延时”,延时期间单片机无法执行其他操作(如读取传感器),进阶开发中会用定时器代替delay()。