STM32_ExtendedLibs/STM32_General/Src/general_gpio.c
Razvalyaev 141ea6bac9 Переструктурирование:
- MyLibs - максимально платформонезависимые библиотеки (кроме разве что RTT)
- RTT
- STM32_General - библиотеки для периферии stm32
2025-10-21 05:03:54 +03:00

326 lines
11 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.

/**
**************************************************************************
* @file general_gpio.c
* @brief Модуль для инициализации портов и работы с ними.
**************************************************************************
* @details
Реализация функций для работы с GPIO:
- Включение тактирования портов
- Инициализация светодиодов и кнопок
- Управление светодиодами: включение, выключение, моргание, плавное затухание
- Чтение состояния кнопок с фильтром от дребезга
***************************************************************************/
#include "general_gpio.h"
//-------------------------------------------------------------------
//------------------------GPIO INIT FUNCTIONS------------------------
/**
* @brief Включить тактирование порта GPIO
*/
HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx)
{
if(check_null_ptr_1(GPIOx))
return HAL_ERROR;
HAL_StatusTypeDef status = HAL_OK;
// choose port for enable clock
if (GPIOx==GPIOA)
__HAL_RCC_GPIOA_CLK_ENABLE();
else if (GPIOx==GPIOB)
__HAL_RCC_GPIOB_CLK_ENABLE();
#ifdef GPIOC
else if (GPIOx==GPIOC)
__HAL_RCC_GPIOC_CLK_ENABLE();
#endif
#ifdef GPIOD
else if (GPIOx==GPIOD)
__HAL_RCC_GPIOD_CLK_ENABLE();
#endif
#ifdef GPIOE
else if (GPIOx==GPIOE)
__HAL_RCC_GPIOE_CLK_ENABLE();
#endif
#ifdef GPIOF
else if (GPIOx==GPIOF)
__HAL_RCC_GPIOF_CLK_ENABLE();
#endif
#ifdef GPIOH
else if (GPIOx==GPIOF)
__HAL_RCC_GPIOH_CLK_ENABLE();
#endif
else
status = HAL_ERROR;
return status;
}
//------------------------GPIO INIT FUNCTIONS------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//------------------------GPIO LED FUNCTIONS-------------------------
/**
* @brief Инициализировать светодиод (структуру светодиода)
* @param led Указатель на структуру светодиода
* @param GPIOx Указатель на структуру порта для светодиода
* @param GPIO_PIN_X Пин для светодиода
* @param LED_ActiveLevel Состояния пина, при котором светодиод будет включен
*/
HAL_StatusTypeDef GPIO_LED_Init(GPIO_LEDTypeDef *led, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, uint8_t LED_ActiveLevel)
{
if(check_null_ptr_3(led, GPIOx, GPIO_PIN_X))
return HAL_ERROR;
led->LED_Port = GPIOx;
led->LED_Pin = GPIO_PIN_X;
led->LED_ActiveLvl = LED_ActiveLevel;
GPIO_LED_Off(led);
return HAL_OK;
}
/**
* @brief Включить светодиод
* @param led Указатель на структуру светодиода
* @return HAL Status
*/
HAL_StatusTypeDef GPIO_LED_On(GPIO_LEDTypeDef *led)
{
if(check_null_ptr_3(led, led->LED_Port, led->LED_Pin))
return HAL_ERROR;
led->state = LED_IS_ON;
HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, led->LED_ActiveLvl);
return HAL_OK;
}
/**
* @brief Выключить светодиод
* @param led Указатель на структуру светодиода
* @return HAL Status
*/
HAL_StatusTypeDef GPIO_LED_Off(GPIO_LEDTypeDef *led)
{
if(check_null_ptr_3(led, led->LED_Port, led->LED_Pin))
return HAL_ERROR;
led->state = LED_IS_OFF;
HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, !led->LED_ActiveLvl);
return HAL_OK;
}
/**
* @brief Выставить светодиод по переменной
* @param led Указатель на структуру светодиода
* @param led_state Состояние светодиода
* @return HAL Status
*/
HAL_StatusTypeDef GPIO_LED_Set(GPIO_LEDTypeDef *led, uint8_t led_state)
{
if(check_null_ptr_3(led, led->LED_Port, led->LED_Pin))
return HAL_ERROR;
if(led_state)
{
return GPIO_LED_On(led);
}
else
{
return GPIO_LED_Off(led);
}
}
/**
* @brief Активировать моргание светодиодом
* @param led Указатель на структуру светодиода
* @param period Период плавного моргания светодиода
* @return HAL Status
* @details Функция ставит режим моргания, который после управляется в @ref GPIO_LED_Dynamic_Handle
*/
HAL_StatusTypeDef GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period)
{
if(check_null_ptr_3(led, led->LED_Port, led->LED_Pin))
return HAL_ERROR;
led->state = LED_IS_BLINKING;
led->LED_Period = period;
return HAL_OK;
}
/**
* @brief Активировать моргание светодиодом
* @param led Указатель на структуру светодиода
* @param period Период плавного моргания светодиода
* @return HAL Status
* @details Функция ставит режим моргания, который после управляется в @ref GPIO_LED_Dynamic_Handle
*/
HAL_StatusTypeDef GPIO_LED_Fading_Start(GPIO_LEDTypeDef *led, uint32_t period)
{
if(check_null_ptr_3(led, led->LED_Port, led->LED_Pin))
return HAL_ERROR;
led->state = LED_IS_FADING;
led->LED_Period = period;
return HAL_OK;
}
//uint8_t LED_PWM_FADING_DUTYS[LED_PWM_TICKS] = {0 1 2 3 4 5 6 7 8 9 10 11 12 }
/**
* @brief Управление динамическими режимами свечения светодиода
* @param Указатель на структуру светодиода
* @details Функция моргает/плавно моргает светодиодом в неблокирующем режиме
* Т.е. функцию надо вызывать постоянно, чтобы она мониторила тики
* и в нужный момент переключала светодиод
*/
void GPIO_LED_Dynamic_Handle(GPIO_LEDTypeDef *led)
{
if(check_null_ptr_3(led, led->LED_Port, led->LED_Pin))
return;
/* Режим моргания светодиода */
if(led->state == LED_IS_BLINKING)
{
uint32_t tickcurrent = local_time();
/* Ожидание истечения периода моргания */
if((tickcurrent - led->tickprev) > led->LED_Period)
{
/* Моргание */
HAL_GPIO_TogglePin(led->LED_Port, led->LED_Pin);
led->tickprev = tickcurrent;
}
}
/* Режим плавного моргания светодиода */
else if(led->state == LED_IS_FADING)
{
static unsigned direction = 0;
static int duty = 0;
uint32_t tickcurrent = local_time();
/* Ожидание момента изменения яркости */
/* Период ШИМ 20 мс, поэтому менять яроксть надо 40 раз за период (туда обратно) */
if((tickcurrent - led->tickprev) > led->LED_Period/(LED_PWM_TICKS*2))
{
/* Формирование разтухания */
if(direction == 0)
{
if(++duty >= LED_PWM_TICKS)
{
direction = 1;
duty = LED_PWM_TICKS;
}
}
/* Формирование затухания */
else
{
if(--duty <= 0)
{
direction = 0;
duty = 0;
}
}
led->tickprev = tickcurrent;
}
/* Формирование ШИМ для изменения яркости */
int duty_crt = (duty*duty/LED_PWM_TICKS);
if(tickcurrent%LED_PWM_TICKS < duty_crt)
{
HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, led->LED_ActiveLvl);
}
else
{
HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, !led->LED_ActiveLvl);
}
}
}
//------------------------GPIO LED FUNCTIONS-------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//------------------------GPIO SW FUNCTIONS-------------------------
/**
* @brief Инициализировать кнопку (структуру кнопки)
* @param sw Указатель на структуру кнопки
* @param GPIOx Указатель на структуру порта для кнопки
* @param GPIO_PIN_X Пин для кнопки
* @param SW_ActiveLevel Состояния пина, когда кнопка нажата
* @return HAL Status
*/
HAL_StatusTypeDef GPIO_Switch_Init(GPIO_SwitchTypeDef *sw, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, uint8_t SW_ActiveLevel)
{
if(check_null_ptr_3(sw, GPIOx, GPIO_PIN_X))
return HAL_ERROR;
sw->Sw_Port = GPIOx;
sw->Sw_Pin = GPIO_PIN_X;
sw->Sw_ActiveLvl = SW_ActiveLevel;
return HAL_OK;
}
/**
* @brief Считать состоянии кнопки
* @param sw Указатель на структуру кнопки
* @return 1 - если кнопка нажата,
* 0 - если отжата,
* -1 - если ошибка
* @details Функция включает в себя неблокирующую проверку на дребезг
* Т.е. функцию надо вызывать постоянно, чтобы она мониторила состояние кнопки
*/
int GPIO_Read_Switch(GPIO_SwitchTypeDef *sw)
{
if(check_null_ptr_3(sw, sw->Sw_Port, sw->Sw_Pin))
return -1;
if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == sw->Sw_ActiveLvl)
{
sw->Sw_PrevState = 1;
if(sw->Sw_FilterDelay) // если включена защита от дребезга
{
if(sw->tickprev == 0)
sw->tickprev = local_time();
if((local_time() - sw->tickprev) >= sw->Sw_FilterDelay)
{
if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == sw->Sw_ActiveLvl)
{
return 1;
}
else
{
sw->tickprev = 0;
return 0;
}
}
}
else // если нет защиты от дребезга
{
if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == sw->Sw_ActiveLvl)
{
return 1;
}
else
{
sw->tickprev = 0;
return 0;
}
}
}
else
{
sw->Sw_PrevState = 0;
}
return 0;
}
//------------------------GPIO SW FUNCTIONS-------------------------
//-------------------------------------------------------------------