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

相关推荐
程亦寻2 小时前
物联网与前沿技术融合分析
人工智能·物联网·区块链·量子计算
云山工作室2 小时前
基于单片机的直流电机控制系统(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
拾忆,想起2 小时前
Spring Boot拦截器:掌握Web请求的“守门员”
spring boot·后端·微服务·架构
飞火流星020272 小时前
物联网在烟草行业的应用
物联网·iot·烟草行业的应用·烟䓍大数据·烟䓍云平台·物联网烟䓍融合应用
轻口味4 小时前
【HarmonyOS NAPI 深度探索10】HarmonyOS Next 中的 NAPI 的架构与原理
c++·华为·架构·harmonyos·napi·harmonyos-next
神一样的老师5 小时前
RCD-IoT:在高数据包传输率下,利用资源受限设备实现工业监测与控制
物联网
飞火流星020275 小时前
物联网常见的传感器和执行器-带表格整理
物联网·mqtt·iot·物联网传感器·物联网执行器·常见的传感器·常见的执行器
Ronin-Lotus5 小时前
嵌入式硬件篇---基本组合逻辑电路
stm32·单片机·嵌入式硬件·学习·信息可视化
Ronin-Lotus5 小时前
嵌入式硬件篇---PID控制
单片机·嵌入式硬件·mcu·学习·程序人生·算法·硬件工程