Loading...
Searching...
No Matches
general_gpio.c
Go to the documentation of this file.
/**
**************************************************************************
* @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-------------------------
//-------------------------------------------------------------------
general_gpio.h
Заголовочный файл для модуля инициализации портов и работы с ними.
check_null_ptr_1
#define check_null_ptr_1(p1)
Проверить один указатель на NULL.
Definition mylibs_defs.h:38
check_null_ptr_3
#define check_null_ptr_3(p1, p2, p3)
Проверить три указателя на NULL.
Definition mylibs_defs.h:44
LED_PWM_TICKS
#define LED_PWM_TICKS
Количество тиков в периоде ШИМ
Definition general_gpio.h:35
local_time
#define local_time()
Локальное время
Definition mylibs_config.h:80
GPIO_Clock_Enable
HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx)
Включить тактирование порта GPIO.
Definition general_gpio.c:22
GPIO_LED_On
HAL_StatusTypeDef GPIO_LED_On(GPIO_LEDTypeDef *led)
Включить светодиод
Definition general_gpio.c:91
GPIO_LED_Fading_Start
HAL_StatusTypeDef GPIO_LED_Fading_Start(GPIO_LEDTypeDef *led, uint32_t period)
Активировать моргание светодиодом
Definition general_gpio.c:164
GPIO_LED_Off
HAL_StatusTypeDef GPIO_LED_Off(GPIO_LEDTypeDef *led)
Выключить светодиод
Definition general_gpio.c:107
GPIO_LED_Init
HAL_StatusTypeDef GPIO_LED_Init(GPIO_LEDTypeDef *led, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, uint8_t LED_ActiveLevel)
Инициализировать светодиод (структуру светодиода)
Definition general_gpio.c:73
GPIO_LED_Dynamic_Handle
void GPIO_LED_Dynamic_Handle(GPIO_LEDTypeDef *led)
Управление динамическими режимами свечения светодиода
Definition general_gpio.c:184
GPIO_LED_Set
HAL_StatusTypeDef GPIO_LED_Set(GPIO_LEDTypeDef *led, uint8_t led_state)
Выставить светодиод по переменной
Definition general_gpio.c:125
GPIO_LED_Blink_Start
HAL_StatusTypeDef GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period)
Активировать моргание светодиодом
Definition general_gpio.c:146
LED_IS_BLINKING
@ LED_IS_BLINKING
Моргание светодиодом
Definition general_gpio.h:65
LED_IS_OFF
@ LED_IS_OFF
Светодиод выключен
Definition general_gpio.h:63
LED_IS_FADING
@ LED_IS_FADING
Плавное моргание светодиодом
Definition general_gpio.h:66
LED_IS_ON
@ LED_IS_ON
Светодиод включен
Definition general_gpio.h:64
GPIO_Read_Switch
int GPIO_Read_Switch(GPIO_SwitchTypeDef *sw)
Считать состоянии кнопки
Definition general_gpio.c:278
GPIO_Switch_Init
HAL_StatusTypeDef GPIO_Switch_Init(GPIO_SwitchTypeDef *sw, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, uint8_t SW_ActiveLevel)
Инициализировать кнопку (структуру кнопки)
Definition general_gpio.c:258
GPIO_LEDTypeDef
Структура светодиода
Definition general_gpio.h:74
GPIO_LEDTypeDef::LED_Pin
uint32_t LED_Pin
GPIO пин ножки светодиода
Definition general_gpio.h:78
GPIO_LEDTypeDef::LED_Period
uint32_t LED_Period
Период моргания светодиода
Definition general_gpio.h:81
GPIO_LEDTypeDef::LED_Port
GPIO_TypeDef * LED_Port
GPIO порт ножки светодиода
Definition general_gpio.h:77
GPIO_LEDTypeDef::LED_ActiveLvl
uint8_t LED_ActiveLvl
Активный уровень ножки (при котором светодиод горит)
Definition general_gpio.h:80
GPIO_LEDTypeDef::state
GPIO_LEDStateTypeDef state
Текущий режим работы светодиода
Definition general_gpio.h:75
GPIO_SwitchTypeDef
Структура кнопки
Definition general_gpio.h:91
GPIO_SwitchTypeDef::Sw_PrevState
uint32_t Sw_PrevState
Предыдущее состояние кнопки
Definition general_gpio.h:96
GPIO_SwitchTypeDef::Sw_FilterDelay
uint32_t Sw_FilterDelay
Фильтр от дребезга (в мс)
Definition general_gpio.h:97
GPIO_SwitchTypeDef::Sw_ActiveLvl
uint8_t Sw_ActiveLvl
Активный уровень ножки (при котором кнопка нажата)
Definition general_gpio.h:95
GPIO_SwitchTypeDef::Sw_Pin
uint32_t Sw_Pin
GPIO пин ножки кнопки
Definition general_gpio.h:93
GPIO_SwitchTypeDef::Sw_Port
GPIO_TypeDef * Sw_Port
GPIO порт ножки кнопки
Definition general_gpio.h:92