Чет работает
This commit is contained in:
316
AllLibs/PeriphGeneral/Src/general_gpio.c
Normal file
316
AllLibs/PeriphGeneral/Src/general_gpio.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @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;
|
||||
|
||||
int current_level = (HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == sw->Sw_ActiveLvl);
|
||||
|
||||
if(sw->Sw_FilterDelay) // если включена защита от дребезга
|
||||
{
|
||||
// Если таймер не запущен и состояние изменилось - запускаем таймер
|
||||
if(sw->tickprev == 0 && current_level != sw->Sw_CurrentState)
|
||||
{
|
||||
sw->tickprev = local_time();
|
||||
}
|
||||
|
||||
// Если таймер запущен
|
||||
if(sw->tickprev != 0)
|
||||
{
|
||||
// Проверяем, прошел ли достаточный интервал для фильтрации
|
||||
if((local_time() - sw->tickprev) >= sw->Sw_FilterDelay)
|
||||
{
|
||||
// Обновляем состояние только если оно все еще отличается
|
||||
if(current_level != sw->Sw_CurrentState)
|
||||
{
|
||||
sw->Sw_CurrentState = current_level;
|
||||
}
|
||||
// Останавливаем таймер в любом случае
|
||||
sw->tickprev = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // если нет защиты от дребезга
|
||||
{
|
||||
sw->Sw_CurrentState = current_level;
|
||||
}
|
||||
return sw->Sw_CurrentState;
|
||||
}
|
||||
//------------------------GPIO SW FUNCTIONS-------------------------
|
||||
//-------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user