/** ****************************************************************************** * @文件 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: PD6 - 低电平有效 */ {GPIOD, GPIO_PIN_6, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED2: PD5 - 低电平有效 */ {GPIOD, GPIO_PIN_5, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED3: PD4 - 低电平有效 */ {GPIOD, GPIO_PIN_4, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED4: PD3 - 低电平有效 */ {GPIOD, GPIO_PIN_3, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED5: PD2 - 低电平有效 */ {GPIOD, GPIO_PIN_2, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED6: PD1 - 低电平有效 */ {GPIOD, GPIO_PIN_1, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED7: PD0 - 低电平有效 */ {GPIOD, GPIO_PIN_0, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED8: PC12 - 低电平有效 */ {GPIOC, GPIO_PIN_12, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED9: PA12 - 低电平有效 */ {GPIOA, GPIO_PIN_12, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED10: PA11 - 低电平有效 */ {GPIOA, GPIO_PIN_11, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED11: PA10 - 低电平有效 */ {GPIOA, GPIO_PIN_10, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED12: PA9 - 低电平有效 */ {GPIOA, GPIO_PIN_9, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED13: PA8 - 低电平有效 */ {GPIOA, GPIO_PIN_8, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED14: PC9 - 低电平有效 */ {GPIOC, GPIO_PIN_9, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED15: PC8 - 低电平有效 */ {GPIOC, GPIO_PIN_8, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED16: PC7 - 低电平有效 */ {GPIOC, GPIO_PIN_7, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED17: PE3 - 低电平有效 */ {GPIOE, GPIO_PIN_3, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED18: PE4 - 低电平有效 */ {GPIOE, GPIO_PIN_4, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED19: PE2 - 低电平有效 */ {GPIOE, GPIO_PIN_2, LED_POLARITY_LOW_ACTIVE, GPIO_PIN_SET, GPIO_SPEED_FREQ_HIGH, GPIO_PULLUP}, /* LED20: PE5 - 低电平有效 */ {GPIOE, GPIO_PIN_5, 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_ON, 0 -> LED_OFF */ state = (leddata & (1UL << i)) ? LED_ON : LED_OFF; LED_Set((uint8_t)i, state); } }