Доработна документация в целом - добавелн main page - исправлены ошибки в шапках и коментах - добавлен граф инклюдов
326 lines
11 KiB
C
326 lines
11 KiB
C
/**
|
||
**************************************************************************
|
||
* @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 = HAL_GetTick();
|
||
/* Ожидание истечения периода моргания */
|
||
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 = HAL_GetTick();
|
||
/* Ожидание момента изменения яркости */
|
||
/* Период ШИМ 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 = HAL_GetTick();
|
||
|
||
if((HAL_GetTick() - 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-------------------------
|
||
//-------------------------------------------------------------------
|