STM32 物联网智能家居 (五) 设备子系统之点亮LED灯

embedded/2025/1/19 8:15:00/

STM32 物联网智能家居 (五) 设备子系统之点亮LED灯

一、设计思路

image-20250116212623910

对于LED灯控制,我们可以设想一下LED灯的功能。首先就是灯的开关、亮度、颜色,主要大概就是这三个功能。我们如何将这三个功能抽象出来呢,无论底层的LED设备是什么,都可以用这个结构体抽象出来。

如下面所示,控制LED设备肯定需要初始化函数,控制LED设备亮灭,目前设置LED灯的颜色需要三色灯,目前不支持,控制LED灯的亮灭,可以通过给出不同占空比的PWM波进行控制亮度,目前该项目没有考虑。

typedef struct LEDDevice {int which;/* 初始化LED设备, 成功则返回0 */int (*Init)(struct LEDDevice *ptLEDDevice);/* 控制LED设备, iStatus取值: 1-亮,0-灭 */int (*Control)(struct LEDDevice *ptLEDDevice, int iStatus);/* 未实现 */void (*SetColor)(struct LEDDevice *ptLEDDevice, int iColor);/* 未实现 */void (*SetBrightness)(struct LEDDevice *ptLEDDevice, int iBrightness);
}LEDDevice, *PLEDDevice;

下面我们把LED设备分为四层,如下图:

image-20250118092011729

二、设备层

在设备层,里面有LED设备的结构体,里面列举了支持的所有的LED设备,支持白、蓝和绿灯,支持LED初始化和LED控制,如下图所示:

static LEDDevice g_tLEDDevices[] = {{LED_WHITE, 0, LEDDeviceInit, LEDDeviceControl},{LED_BLUE,  0, LEDDeviceInit, LEDDeviceControl},{LED_GREEN, 0, LEDDeviceInit, LEDDeviceControl},
};

下面是设备层的函数:LEDDeviceInit(),LEDDeviceControl(),GetLEDDevice()。

/*********************************************************************** 函数名称: KAL_LEDDeviceInit* 功能描述: 设备层的LED初始化函数* 输入参数: ptLEDDevice-哪个LED设备* 输出参数: 无* 返 回 值: 0-成功***********************************************************************/
static int LEDDeviceInit(struct LEDDevice *ptLEDDevice)
{return KAL_LEDDeviceInit(ptLEDDevice);
}/*********************************************************************** 函数名称: LEDDeviceControl* 功能描述: 设备层的LED控制函数* 输入参数: ptLEDDevice-哪个LED设备* 输入参数: iStatus, 1-亮, 0-灭* 输出参数: 无* 返 回 值: 0-成功***********************************************************************/
static int LEDDeviceControl(struct LEDDevice *ptLEDDevice, int iStatus)
{return KAL_LEDDeviceControl(ptLEDDevice, iStatus);
}/*********************************************************************** 函数名称: GetLEDDevice* 功能描述: 获取LED设备* 输入参数: which-哪个LED设备*            取值有: LED_WHITE,LED_BLUE或LED_GREEN* 输出参数: 无* 返 回 值: 成功-LEDDevice指针, 失败-NULL***********************************************************************/
PLEDDevice GetLEDDevice(int which)
{if (which >= LED_WHITE && which <= LED_GREEN)return &g_tLEDDevices[which];elsereturn NULL;
}

三、内核抽象层

在内核抽象层,我们的程序通过宏定义,可以在编译的时候设置宏来选择适用操作系统,目前分为裸机、FreeRTOS、RT-Thread。

image-20250118092652259

下面是设备层的函数:KAL_OLEDDeviceInit(),OLEDDeviceFlush(),GetLEDDevice()。

/*********************************************************************** 函数名称: KAL_LEDDeviceInit* 功能描述: 内核抽象层的LED初始化函数, 内核不一样时请修改此函数* 输入参数: ptLEDDevice-哪个LED设备* 输出参数: 无* 返 回 值: 0-成功***********************************************************************/
int KAL_LEDDeviceInit(struct LEDDevice *ptLEDDevice)
{	/* 对于裸机 */#if defined (CONFIG_NOOS)return CAL_LEDDeviceInit(ptLEDDevice);/* 对于RT-Thread */#elif defined (CONFIG_FREERTOS)return FreeRTOS_LEDDeviceInit(ptLEDDevice);/* 对于Linux */#elif defined (CONFIG_RTTHREAD)return RTThread_LEDDeviceInit(ptLEDDevice);
}/*********************************************************************** 函数名称: KAL_LEDDeviceControl* 功能描述: 内核抽象层的LED控制函数, 内核不一样时请修改此函数* 输入参数: ptLEDDevice-哪个LED设备* 输入参数: iStatus, 1-亮, 0-灭* 输出参数: 无* 返 回 值: 0-成功***********************************************************************/
int KAL_LEDDeviceControl(struct LEDDevice *ptLEDDevice, int iStatus)
{/* 对于裸机 */#if defined (CONFIG_NOOS)return CAL_LEDDeviceControl(ptLEDDevice, iStatus);/* 对于RT-Thread */#elif defined (CONFIG_FREERTOS)return FreeRTOS_LEDDeviceControl(ptLEDDevice, iStatus);/* 对于Linux */#elif defined (CONFIG_RTTHREAD)return RTThread_LEDDeviceControl(ptLEDDevice, iStatus);}

四、芯片抽象层

下面是芯片抽象层,这里只展示裸机的程序。

/*********************************************************************** 函数名称: CAL_LEDDeviceInit* 功能描述: 芯片抽象层的LED初始化函数, 芯片函数不一样时请修改此函数* 输入参数: ptLEDDevice-哪个LED设备* 输出参数: 无* 返 回 值: 0-成功***********************************************************************/
int CAL_LEDDeviceInit(struct LEDDevice *ptLEDDevice)
{	/* 对于hal *//* 已经在MX_GPIO_Init初始化了引脚 */return 0;
}/*********************************************************************** 函数名称: CAL_LEDDeviceControl* 功能描述: 芯片抽象层的LED控制函数, 芯片函数不一样时请修改此函数* 输入参数: ptLEDDevice-哪个LED设备* 输入参数: iStatus, 1-亮, 0-灭* 输出参数: 无* 返 回 值: 0-成功***********************************************************************/
int CAL_LEDDeviceControl(struct LEDDevice *ptLEDDevice, int iStatus)
{/* 对于hal */return HAL_LEDDeviceControl(ptLEDDevice, iStatus);
}

五、硬件抽象层

硬件抽象层用switch case函数,根据上层传递过来的LED结构体类型和控制状态,来不断切换LED的亮灭。

/**  函数名:int HAL_LEDDeviceControl(struct LEDDevice *ptLEDDevice, int iStatus)*  输入参数:ptLEDDevice-哪个LED*  输入参数:iStatus-LED状态, 1-亮, 0-灭*  输出参数:无*  返回值:0-成功, -1: 失败*/
int HAL_LEDDeviceControl(struct LEDDevice *ptLEDDevice, int iStatus)
{if (!ptLEDDevice)return -1;switch (ptLEDDevice->which){case LED_WHITE: {HAL_GPIO_WritePin(WHITE_GPIO_Port, WHITE_Pin, !iStatus);break;}case LED_BLUE: {HAL_GPIO_WritePin(BLUE_GPIO_Port, BLUE_Pin, !iStatus);break;}case LED_GREEN: {HAL_GPIO_WritePin(GREEN_GPIO_Port, GREEN_Pin, !iStatus);break;}default:return -1;}return 0;}

六、测试代码

下面编写测试代码,让每个LED灯间隔500ms不断的亮灭。

/*********************************************************************** 函数名称: led_test* 功能描述: 设备系统LED设备单元测试函数* 输入参数: 无* 输出参数: 无* 返 回 值: 无***********************************************************************/
void led_test(void)
{PLEDDevice p1 = GetLEDDevice(LED_WHITE);PLEDDevice p2 = GetLEDDevice(LED_BLUE);PLEDDevice p3 = GetLEDDevice(LED_GREEN);p1->Init(p1);p2->Init(p2);p3->Init(p3);while (1){p1->Control(p1, 1);p2->Control(p2, 1);p3->Control(p3, 1);KAL_Delay(500);p1->Control(p1, 0);p2->Control(p2, 0);p3->Control(p3, 0);KAL_Delay(500);}
}

在main.c函数中调用,led_test()函数:

int main(void)
{HAL_Init();  // 初始化HAL库,设置系统相关的中断和时钟。SystemClock_Config();  // 配置系统时钟,使芯片工作在目标频率。MX_GPIO_Init();  // 初始化GPIO外设,为输入输出做准备。MX_USART1_UART_Init();  // 初始化USART1,用于调试信息输出。MX_USART3_UART_Init();  // 初始化USART3,用于串口通信。ring_buffer_init(&test_buffer); // 初始化环形Buffer缓冲区。EnableDebugIRQ();printf("Hello World!\r\n");  // 打印调试信息,确认系统启动成功。while (1){//input_test();  // 进入输入测试循环,处理输入事件。led_test();  // 进入LED测试循环}
}

六、实操演示

下面将程序下载开发板里面,下面展示效果:

设备子系统之点亮LED视频

七、往期文章

STM32 物联网智能家居 (一) 方案设计STM32+ESP8266+TCP/UDP/MQTT

STM32 物联网智能家居 (二)-开发环境及工程搭建(STM32CubeMX)

STM32 物联网智能家居 (三) 输入子系统

STM32 物联网智能家居 (四) 设备子系统之分层框架

STM32 BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建

STM32 BootLoader 刷新项目 (二) 方案介绍

STM32 BootLoader 刷新项目 (三) 程序框架搭建及刷新演示

STM32 BootLoader 刷新项目 (四) 通信协议

STM32 BootLoader 刷新项目 (十三) Python上位机介绍

STM32 BootLoader 刷新项目 (十四) 所有源代码获取

BootLoader串口刷新


http://www.ppmy.cn/embedded/155173.html

相关文章

Android系统开发(六):从Linux到Android:模块化开发,GKI内核的硬核科普

引言&#xff1a; 今天我们聊聊Android生态中最“硬核”的话题&#xff1a;通用内核镜像&#xff08;GKI&#xff09;与内核模块接口&#xff08;KMI&#xff09;。这是内核碎片化终结者的秘密武器&#xff0c;解决了内核和供应商模块之间无尽的兼容性问题。为什么重要&#x…

【Django开发】django美多商城项目完整开发4.0第12篇:商品部分,表结构【附代码文档】

本教程的知识点为&#xff1a; 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计&#xff1a; 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后…

AIGC视频生成模型:Runway的Gen系列模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Runway开发的视频生成模型Gen系列&#xff0c;包括Gen-1、Gen-2和Gen3 Alpha等&#xff0c;这些模型每次发布都震惊AI圈&#xff0c;荣获多个视频生成的…

探秘Shortest与Stagehand:开启高效测试与自动化新篇

探秘Shortest与Stagehand&#xff1a;开启高效测试与自动化新篇 在数字化浪潮的推动下&#xff0c;网页自动化工具如同繁星般涌现&#xff0c;为众多行业带来了效率的变革。在这些工具中&#xff0c;Shortest和Stagehand凭借其出色的表现&#xff0c;成为了众多开发者、测试人…

51.WPF应用加图标指南 C#例子 WPF例子

完整步骤&#xff1a; 先使用文心一言生成一个图标如左边使用Windows图片编辑器编辑&#xff0c;去除背景使用正方形&#xff0c;放大图片使图标铺满图片使用格式工程转换为ico格式&#xff0c;分辨率为最大 在资源管理器中右键项目添加ico类型图片到项目里图片属性设置为始终…

“提升大语言模型推理与规划能力的策略:思维链提示与由少至多提示”

思维链提示&#xff08;Chain-of-Thought Prompting&#xff09;和由少至多提示&#xff08;Least-to-Most Prompting&#xff09;是两种提升大语言模型在推理和规划任务上表现的有效方法。下面详细介绍这两种方法的原理和应用&#xff1a; 思维链提示&#xff08;Chain-of-Th…

使用Emgu.CV将tif保存视频,并用AxWindowsMediaPlayer打开

1. 使用Emgu.CV将tif保存视频&#xff0c;非常简单 打开&#xff1a; VideoWriter writer new VideoWriter(name, VideoWriter.Fourcc(M, J, P, G), displayRate, new Size(width, height), false); 写入 writer.Write(mat); 关闭 writer.Dispose(); 完整代码如下&#…

【2024年华为OD机试】(B卷,100分)- 数据分类 (Java JS PythonC/C++)

一、问题描述 题目描述 对一个数据a进行分类&#xff0c;分类方法为&#xff1a; 此数据a&#xff08;四个字节大小&#xff09;的四个字节相加对一个给定的值b取模&#xff0c;如果得到的结果小于一个给定的值c&#xff0c;则数据a为有效类型&#xff0c;其类型为取模的值&…