流水灯效果探索与实现

在嵌入式系统或微控制器项目中,LED流水灯是一种常见的实验项目,它不仅能够展示基本的GPIO(通用输入输出)控制,还能通过不同的模式增加趣味性。本文将探讨四种不同的流水灯效果,并通过代码示例展示如何实现它们。

效果1:依次亮(循环)

这种效果是最基本的流水灯效果,LED灯按照顺序依次亮起,当最后一个LED灯亮起后,又从头开始循环。这种效果可以通过一个简单的for循环实现,循环中依次设置每个LED灯为高电平(亮),然后延时一段时间,再设置为低电平(灭)。随后,下一个LED灯被点亮,如此循环。

代码实现:

cs 复制代码
#include "Config.h"
#include "STC8G_H_GPIO.h"
#include "STC8G_H_Delay.h"

// 每个LED灯 所代表的引脚
#define LED1		P27
#define LED2		P26
#define LED3		P15
#define LED4		P14
#define LED5		P23
#define LED6		P22
#define LED7		P21
#define LED8		P20
#define LED_SW	P45

// GPIO配置 输入/输出
void GPIO_config(void) {
    // 总开关 P4 端口下的5号引脚 推挽模式
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P4, &GPIO_InitStructure);//初始化

    // P1端口下的 4、5号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P1, &GPIO_InitStructure);//初始化

    // P2端口下的 0 到 7 号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//初始化
}


int main() {
    int i; // 定义for循环初始化下标变量
    // 1. 配置8个灯和总开关SW的引脚工作模式
    GPIO_config();
    // 2. 开启总中断
    EA = 1;
    // 4. 开启总开关
    LED_SW = 0;
    // 5. 开启流水灯
    while(1) {

        // 依次亮
        for(i = 0; i <= 8; i++) {
            // i:1,2,3,4,5,6,7,8
            LED1 = i == 0 ? 0 : 1;   // 第一个灯亮,其他灯不亮
            LED2 = i == 1 ? 0 : 1;	 // 第二个灯亮,其他灯不亮
            LED3 = i == 2 ? 0 : 1;	 // 以此类推
            LED4 = i == 3 ? 0 : 1;
            LED5 = i == 4 ? 0 : 1;
            LED6 = i == 5 ? 0 : 1;
            LED7 = i == 6 ? 0 : 1;
            LED8 = i == 7 ? 0 : 1;
            delay_ms(100);    // 延迟100ms
        }

    }

}
效果2:依次亮(顺序+逆序)

在效果1的基础上,这种效果增加了逆序循环的部分。即当LED灯按照顺序依次亮起并熄灭后,会按照逆序再次亮起并熄灭。实现这一效果需要在原有的for循环基础上增加一个逆序的循环。

代码实现:

cs 复制代码
#define LED3		P15
#define LED4		P14
#define LED5		P23
#define LED6		P22
#define LED7		P21
#define LED8		P20
#define LED_SW	P45

// GPIO配置 输入/输出
void GPIO_config(void) {
    // 总开关 P4 端口下的5号引脚 推挽模式
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P4, &GPIO_InitStructure);//初始化

    // P1端口下的 4、5号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P1, &GPIO_InitStructure);//初始化

    // P2端口下的 0 到 7 号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//初始化
}


int main() {
    int i; // 定义for循环初始化下标变量
    // 1. 配置8个灯和总开关SW的引脚工作模式
    GPIO_config();
    // 2. 开启总中断
    EA = 0;
    // 4. 开启总开关
    LED_SW = 0;
    // 5. 开启流水灯
    while(1) {

        // 依次亮 顺序
        for(i = 0; i <= 8; i++) {
            // i:1,2,3,4,5,6,7,8
            LED1 = i == 0 ? 0 : 1;   // 第一个灯亮,其他灯不亮
            LED2 = i == 1 ? 0 : 1;	 // 第二个灯亮,其他灯不亮
            LED3 = i == 2 ? 0 : 1;	 // 以此类推
            LED4 = i == 3 ? 0 : 1;
            LED5 = i == 4 ? 0 : 1;
            LED6 = i == 5 ? 0 : 1;
            LED7 = i == 6 ? 0 : 1;
            LED8 = i == 7 ? 0 : 1;
            delay_ms(100);    // 延迟100ms
        }
				
				// 逆序
				    for(i = 8; i >= 0; i--) {
            // i:8,7,6,5,4,3,2,1
            LED1 = i == 0 ? 0 : 1;   // 第一个灯亮,其他灯不亮
            LED2 = i == 1 ? 0 : 1;	 // 第二个灯亮,其他灯不亮
            LED3 = i == 2 ? 0 : 1;	 // 以此类推
            LED4 = i == 3 ? 0 : 1;
            LED5 = i == 4 ? 0 : 1;
            LED6 = i == 5 ? 0 : 1;
            LED7 = i == 6 ? 0 : 1;
            LED8 = i == 7 ? 0 : 1;
            delay_ms(100);    // 延迟100ms
        }

    }

}
效果3:逐渐亮

这种效果要求LED灯从第一个开始逐个亮起,直到所有LED灯都亮起,然后再逐个熄灭,直到所有LED灯都熄灭。这种效果可以通过两个嵌套的for循环实现,第一个循环控制亮起的LED灯的数量,第二个循环则用于设置对应数量的LED灯为高电平。在第一个循环结束后,再通过一个类似的循环将LED灯逐个熄灭。

代码实现:

cs 复制代码
#include "Config.h"
#include "STC8G_H_GPIO.h"
#include "STC8G_H_Delay.h"

// 每个LED灯 所代表的引脚
#define LED1		P27
#define LED2		P26
#define LED3		P15
#define LED4		P14
#define LED5		P23
#define LED6		P22
#define LED7		P21
#define LED8		P20
#define LED_SW	P45

// GPIO配置 输入/输出
void GPIO_config(void) {
    // 总开关 P4 端口下的5号引脚 推挽模式
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P4, &GPIO_InitStructure);//初始化

    // P1端口下的 4、5号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P1, &GPIO_InitStructure);//初始化

    // P2端口下的 0 到 7 号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//初始化
}


int main() {
    int i; // 定义for循环初始化下标变量
    // 1. 配置8个灯和总开关SW的引脚工作模式
    GPIO_config();
    // 2. 开启总中断
    EA = 1;
    // 4. 开启总开关
    LED_SW = 0;
    // 5. 开启逐渐亮流水灯
    while(1) {
			// 逐渐亮
			for(i = 8; i >= 0; i--) {
            // 依次点亮前i个灯
            LED1 = i >= 1; // 如果i >= 1,则LED1亮(),否则不亮
            LED2 = i >= 2; // 如果i >= 2,则LED2亮,否则不亮
            LED3 = i >= 3; // 以此类推
            LED4 = i >= 4;
            LED5 = i >= 5;
            LED6 = i >= 6;
            LED7 = i >= 7;
            LED8 = i >= 8;
            delay_ms(100);    // 延迟100ms
        }

        // 逐渐灭
        for(i = 0; i <= 8; i++) {
            // 依次点亮前i个灯
            LED1 = i >= 1; // 如果i >= 1,则LED1亮,否则不亮
            LED2 = i >= 2; // 如果i >= 2,则LED2亮,否则不亮
            LED3 = i >= 3; // 以此类推
            LED4 = i >= 4;
            LED5 = i >= 5;
            LED6 = i >= 6;
            LED7 = i >= 7;
            LED8 = i >= 8;
            delay_ms(100);    // 延迟100ms
        }

    }

}
效果4:奇偶亮

这种效果要求LED灯按照奇偶顺序亮起。首先,所有奇数编号的LED灯(如1、3、5、7)亮起,然后熄灭;接着,所有偶数编号的LED灯(如2、4、6、8)亮起,然后熄灭。这种效果可以通过两个独立的循环实现,一个用于控制奇数LED灯,另一个用于控制偶数LED灯。

代码实现:

cs 复制代码
#include "Config.h"
#include "STC8G_H_GPIO.h"
#include "STC8G_H_Delay.h"

// 每个LED灯 所代表的引脚
#define LED1		P27
#define LED2		P26
#define LED3		P15
#define LED4		P14
#define LED5		P23
#define LED6		P22
#define LED7		P21
#define LED8		P20
#define LED_SW	P45

// GPIO配置 输入/输出
void GPIO_config(void) {
    // 总开关 P4 端口下的5号引脚 推挽模式
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P4, &GPIO_InitStructure);//初始化

    // P1端口下的 4、5号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P1, &GPIO_InitStructure);//初始化

    // P2端口下的 0 到 7 号引脚  准双向口模式
    GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//初始化
}


int main() {
    int i; // 定义for循环初始化下标变量
    // 1. 配置8个灯和总开关SW的引脚工作模式
    GPIO_config();
    // 2. 开启总中断
    EA = 1;
    // 4. 开启总开关
    LED_SW = 0;
   // 5. 开启奇偶流水灯  
    while(1) {  
        // 奇数LED亮(1, 3, 5, 7)  
        for(i = 1; i <= 8; i += 2) { // 从1开始,每次增加2  
            LED1 = (i == 1);  
            LED3 = (i == 3);  
            LED5 = (i == 5);  
            LED7 = (i == 7);  
            LED2 = LED4 = LED6 = LED8 = 0; // 确保其他LED关闭  
            delay_ms(100); // 延迟100ms  
        }  
  
        // 偶数LED亮(2, 4, 6, 8)  
        for(i = 2; i <= 8; i += 2) { // 从2开始,每次增加2  
            LED2 = (i == 2);  
            LED4 = (i == 4);  
            LED6 = (i == 6);  
            LED8 = (i == 8);  
            LED1 = LED3 = LED5 = LED7 = 0; // 确保其他LED关闭  
            delay_ms(100); // 延迟100ms  
        }  
    }  
}
总结

通过以上四种流水灯效果的实现,我们可以看到微控制器在控制LED灯方面的强大能力。这些效果不仅展示了基本的GPIO控制技术,还通过不同的模式增加了项目的趣味性和实用性。在实际应用中,我们可以根据具体需求选择合适的流水灯效果,并通过调整参数和添加功能来进一步优化项目。

相关推荐
代码游侠14 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
CODECOLLECT18 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen18 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠21 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_21 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技1 天前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计1 天前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
小龙报1 天前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业1 天前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能1 天前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微