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串口刷新

相关推荐
jl48638214 小时前
变比测试仪显示屏的“标杆“配置!如何兼顾30000小时寿命与六角矢量图精准显示?
人工智能·经验分享·嵌入式硬件·物联网·人机交互
清风6666664 小时前
基于单片机的智能电热水壶设计与温度控制系统
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
晚霞的不甘4 小时前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频
Balabala噗4 小时前
JLink-Cortex-M Error报错-No Cortex-M SW Device Found-解决办法整理
单片机·嵌入式硬件
点灯小铭5 小时前
基于单片机的智慧农业温度湿度滴灌自动控制系统设计与实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
陌上花开缓缓归以5 小时前
linux mtd-utils使用源码分析(ubuntu测试版)
linux·arm开发·ubuntu
代码改善世界5 小时前
CANN深度解构:中国AI系统软件的原创性突破与架构创新
大数据·人工智能·架构
晚霞的不甘6 小时前
Flutter for OpenHarmony 实现计算几何:Graham Scan 凸包算法的可视化演示
人工智能·算法·flutter·架构·开源·音视频
Tadas-Gao6 小时前
TCP粘包现象的深度解析:从协议本质到工程实践
网络·网络协议·云原生·架构·tcp
零一iTEM6 小时前
MAX98357A_音频输出测试
单片机·嵌入式硬件·开源·音视频·硬件工程