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

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

一、设计思路

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

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

c 复制代码
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设备分为四层,如下图:

二、设备层

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

c 复制代码
static LEDDevice g_tLEDDevices[] = {
	{LED_WHITE, 0, LEDDeviceInit, LEDDeviceControl},
	{LED_BLUE,  0, LEDDeviceInit, LEDDeviceControl},
	{LED_GREEN, 0, LEDDeviceInit, LEDDeviceControl},
};

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

c 复制代码
/**********************************************************************
 * 函数名称: 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];
	else
		return NULL;
}

三、内核抽象层

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

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

c 复制代码
/**********************************************************************
 * 函数名称: 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);
    
}

四、芯片抽象层

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

c 复制代码
/**********************************************************************
 * 函数名称: 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的亮灭。

c 复制代码
/*
 *  函数名: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不断的亮灭。

c 复制代码
/**********************************************************************
 * 函数名称: 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()函数:

c 复制代码
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串口刷新

相关推荐
糖糖单片机设计6 小时前
基于单片机的热水器节能控制系统
单片机·嵌入式硬件
阿狸猿6 小时前
事件驱动架构(EDA)的设计与应用
架构
吴建旭 智宅焕6 小时前
智能家居全国交付中技术专精型执行端的架构设计与实现:不可替代性、被集成与交付确定性
智能家居
吴建旭 智宅焕6 小时前
智能家居B端客户入行的最小闭环验证架构设计与实现:从路径预设到数据驱动
智能家居
数字新视界6 小时前
数字孪生技术赋能智能化转型与创新实践
嵌入式硬件·物联网·系统架构·机房管理·动力与环境监控系统
注塑机数据采集联网7 小时前
数据采集网关入门:ZK-D1/D3从零开始构建你的数据运用
大数据·数据仓库·人工智能·物联网·数据库架构·注塑机网关
Zevalin爱灰灰7 小时前
Linux入门第二部分(ARM裸机篇) 第一章 开发环境搭建与了解
linux·arm开发·嵌入式
硅基手札7 小时前
CAN 技术系列 08 · CAN 控制器寄存器与 IP 架构
驱动开发·架构·嵌入式开发·通信协议·can总线
HQB20267 小时前
屹晶微电子 EG1195|10‑120V/10A+ 外置 MOS 异步降压控制器|ESOP‑8|电动车转换器 / 快充 / 工业电源
嵌入式硬件·硬件工程
微三云 - 廖会灵 (私域系统开发)8 小时前
企业级 SaaS 系统架构设计:单体、微服务还是模块化单体?技术选型实战
微服务·架构·系统架构