STM32 物联网智能家居 (五) 设备子系统之点亮LED灯
一、设计思路
对于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设备分为四层,如下图:
二、设备层
在设备层,里面有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。
下面是设备层的函数: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 BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建
STM32 BootLoader 刷新项目 (二) 方案介绍
STM32 BootLoader 刷新项目 (三) 程序框架搭建及刷新演示
STM32 BootLoader 刷新项目 (四) 通信协议
STM32 BootLoader 刷新项目 (十三) Python上位机介绍
STM32 BootLoader 刷新项目 (十四) 所有源代码获取
BootLoader串口刷新