Files
DTU-LCD/Drivers/BSP/LED/led.c

262 lines
8.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
******************************************************************************
* @文件 led.c
* @作者 阜阳师范大学物电学院
* @版本 V0.3
* @日期 2026-01-15
* @简介 LED 驱动 - 基于结构体的高可移植性实现
* @说明 通过修改LED配置数组即可适配不同的硬件连接无需修改其他代码
* 所有硬件相关参数(端口、引脚、极性、速度、上拉下拉)都集中在配置数组中
****
*/
#include "led.h"
/* ============================================================================
* LED配置数组 - 在此处修改硬件连接配置
* 格式说明:
* {端口, 引脚, 极性, 默认状态, 速度, 上拉下拉}
*
* 示例:
* {GPIOA, GPIO_PIN_0, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}
* {GPIOB, GPIO_PIN_5, LED_POLARITY_HIGH_ACTIVE, GPIO_PIN_RESET, GPIO_SPEED_FREQ_MEDIUM, GPIO_NOPULL}
* ============================================================================ */
static const LED_Config_t led_config[LED_COUNT] = {
/* LED1 低电平有效 */
{GPIOC, GPIO_PIN_8, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED2 低电平有效 */
{GPIOC, GPIO_PIN_9, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED3 低电平有效 */
{GPIOA, GPIO_PIN_9, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED4 低电平有效 */
{GPIOA, GPIO_PIN_11, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED5 低电平有效 */
{GPIOA, GPIO_PIN_15, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED6 低电平有效 */
{GPIOC, GPIO_PIN_11, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED7 低电平有效 */
{GPIOD, GPIO_PIN_0, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED8 低电平有效 */
{GPIOD, GPIO_PIN_2, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED9 低电平有效 */
{GPIOD, GPIO_PIN_4, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED10 低电平有效 */
{GPIOD, GPIO_PIN_6, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED11 低电平有效 */
{GPIOC, GPIO_PIN_7, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED12 低电平有效 */
{GPIOA, GPIO_PIN_8, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED13 低电平有效 */
{GPIOA, GPIO_PIN_10, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED14 低电平有效 */
{GPIOA, GPIO_PIN_12, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED15 低电平有效 */
{GPIOC, GPIO_PIN_10, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED16 低电平有效 */
{GPIOC, GPIO_PIN_12, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED17 低电平有效 */
{GPIOD, GPIO_PIN_1, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED18 低电平有效 */
{GPIOD, GPIO_PIN_3, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED19 低电平有效 */
{GPIOD, GPIO_PIN_5, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
/* LED20 低电平有效 */
{GPIOD, GPIO_PIN_7, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP},
};
/* LED状态数组 - 使用枚举类型提高类型安全性 */
static LED_State_t led_state[LED_COUNT];
/**
* @brief 使能GPIO时钟
* @param port: GPIO端口
* @retval 无
* @note 使用switch-case结构代码更简洁清晰支持所有GPIO端口A-G
*/
static void LED_GPIO_ClockEnable(GPIO_TypeDef *port)
{
switch ((uint32_t)port) {
case (uint32_t)GPIOA: __HAL_RCC_GPIOA_CLK_ENABLE(); break;
case (uint32_t)GPIOB: __HAL_RCC_GPIOB_CLK_ENABLE(); break;
case (uint32_t)GPIOC: __HAL_RCC_GPIOC_CLK_ENABLE(); break;
case (uint32_t)GPIOD: __HAL_RCC_GPIOD_CLK_ENABLE(); break;
case (uint32_t)GPIOE: __HAL_RCC_GPIOE_CLK_ENABLE(); break;
case (uint32_t)GPIOF: __HAL_RCC_GPIOF_CLK_ENABLE(); break;
case (uint32_t)GPIOG: __HAL_RCC_GPIOG_CLK_ENABLE(); break;
default: break;
}
}
/**
* @brief LED初始化
* @param 无
* @retval 无
* @note 自动初始化所有配置的LED所有硬件参数从配置数组中读取
* 无需手动逐个配置,修改硬件连接只需修改配置数组
*/
void LED_Init(void)
{
GPIO_InitTypeDef gpio_init_struct;
uint8_t i;
/* 遍历配置数组初始化所有LED */
for (i = 0; i < LED_COUNT; i++) {
/* 使能对应GPIO时钟 */
LED_GPIO_ClockEnable(led_config[i].port);
/* 从配置数组中读取GPIO参数 */
gpio_init_struct.Pin = led_config[i].pin;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出模式 */
gpio_init_struct.Speed = led_config[i].speed; /* 速度配置 */
gpio_init_struct.Pull = led_config[i].pull; /* 上拉下拉配置 */
/* 初始化GPIO引脚 */
HAL_GPIO_Init(led_config[i].port, &gpio_init_struct);
/* 设置默认状态 */
HAL_GPIO_WritePin(led_config[i].port, led_config[i].pin, led_config[i].default_state);
/* 初始化状态数组(根据默认状态和极性计算逻辑状态) */
if (led_config[i].polarity == LED_POLARITY_LOW_ACTIVE) {
led_state[i] = (led_config[i].default_state == GPIO_PIN_RESET) ? LED_ON : LED_OFF;
} else {
led_state[i] = (led_config[i].default_state == GPIO_PIN_SET) ? LED_ON : LED_OFF;
}
}
LED_POW(LED_ON); /*上电指示灯亮*/
}
/**
* @brief 点亮LED
* @param led_id: LED ID (0 ~ LED_COUNT-1)
* @retval 无
*/
void LED_On(uint8_t led_id)
{
GPIO_PinState pin_state;
if (led_id >= LED_COUNT) {
return;
}
/* 根据极性设置引脚状态 */
if (led_config[led_id].polarity == LED_POLARITY_LOW_ACTIVE) {
pin_state = GPIO_PIN_RESET; /* 低电平有效,输出低电平点亮 */
} else {
pin_state = GPIO_PIN_SET; /* 高电平有效,输出高电平点亮 */
}
HAL_GPIO_WritePin(led_config[led_id].port, led_config[led_id].pin, pin_state);
led_state[led_id] = LED_ON;
}
/**
* @brief 熄灭LED
* @param led_id: LED ID (0 ~ LED_COUNT-1)
* @retval 无
*/
void LED_Off(uint8_t led_id)
{
GPIO_PinState pin_state;
if (led_id >= LED_COUNT) {
return;
}
/* 根据极性设置引脚状态 */
if (led_config[led_id].polarity == LED_POLARITY_LOW_ACTIVE) {
pin_state = GPIO_PIN_SET; /* 低电平有效,输出高电平熄灭 */
} else {
pin_state = GPIO_PIN_RESET; /* 高电平有效,输出低电平熄灭 */
}
HAL_GPIO_WritePin(led_config[led_id].port, led_config[led_id].pin, pin_state);
led_state[led_id] = LED_OFF;
}
/**
* @brief 翻转LED状态
* @param led_id: LED ID (0 ~ LED_COUNT-1)
* @retval 无
*/
void LED_Toggle(uint8_t led_id)
{
if (led_id >= LED_COUNT) {
return;
}
HAL_GPIO_TogglePin(led_config[led_id].port, led_config[led_id].pin);
/* 翻转LED状态 - 使用显式条件判断,提高类型安全性 */
led_state[led_id] = (led_state[led_id] == LED_ON) ? LED_OFF : LED_ON;
}
/**
* @brief 设置LED状态
* @param led_id: LED ID (0 ~ LED_COUNT-1)
* @param state: LED状态 (LED_ON 或 LED_OFF)
* @retval 无
*/
void LED_Set(uint8_t led_id, LED_State_t state)
{
if (state == LED_ON) {
LED_On(led_id);
} else {
LED_Off(led_id);
}
}
/**
* @brief 获取LED状态
* @param led_id: LED ID (0 ~ LED_COUNT-1)
* @retval LED状态 (LED_ON 或 LED_OFF)
*/
LED_State_t LED_GetState(uint8_t led_id)
{
if (led_id >= LED_COUNT) {
return LED_OFF;
}
return led_state[led_id];
}
/**
* @brief 输出LED状态
* @param ledbuf 状态字节
* @retval 无
*/
void LED_Printf(uint8_t* ledbuf)
{
uint32_t leddata = (ledbuf[3]<<24) |(ledbuf[2]<<16) | (ledbuf[1]<<8) | ledbuf[0];
uint32_t i = 0;
LED_State_t state; /* 使用枚举类型,提高类型安全性 */
LED_POW(LED_ON); /* 默认上电亮灯 */
for(i=1; i<LED_COUNT; i++)
{
/* 将位掩码结果转换为枚举类型非0 -> LED_ON, 0 -> LED_OFF */
state = (leddata & (1UL << i)) ? LED_ON : LED_OFF;
LED_Set((uint8_t)i, state);
}
}