Добавлено:
- рефакторинг названий: - маленькие буквы - инит периферии - ТакойСтильФункций - API для использования - сделаны шапки с инструкциями к функциями - доработан ацп секвенсора - доработан систем тики. можно настроить его на разные частоты и подключить коллбеки на разный период - в gpio добавлены функции для кнопок и диодов - генерация бинарника
This commit is contained in:
378
Core/App/gpio.c
378
Core/App/gpio.c
@@ -1,19 +1,65 @@
|
||||
/*==============================================================================
|
||||
* Инициализация портов с использованием бибилотеки PLIB035
|
||||
*------------------------------------------------------------------------------
|
||||
* ЦНИИ СЭТ, Разваляев Алексей <wot890089@mail.ru>
|
||||
*==============================================================================
|
||||
* Конфигурация портов настраивается в gpio.h
|
||||
* ЦНИИ СЭТ
|
||||
*==============================================================================
|
||||
*/
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file gpio.c
|
||||
* @author Разваляев Алексей
|
||||
* @brief Драйвер GPIO на основе PLIB035.
|
||||
* Этот файл содержит:
|
||||
* + Инициализацию портов GPIOA и GPIOB
|
||||
* + Функции для работы со светодиодами:
|
||||
* - Инициализацию структуры светодиода
|
||||
* - Включение, выключение, переключение светодиода
|
||||
* - Динамические режимы: моргание и плавное затухание
|
||||
* + Функции для работы с кнопками:
|
||||
* - Инициализацию структуры кнопки
|
||||
* - Чтение состояния кнопки с защитой от дребезга
|
||||
* + Утилитарные функции для получения конфигурации пинов
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Использование этого драйвера предполагает наличие корректных настроек:
|
||||
* - Определены массивы конфигурации gpioa_config и gpiob_config в periph_config.h
|
||||
*
|
||||
******************************************************************************
|
||||
* @verbatim
|
||||
==============================================================================
|
||||
##### Как использовать этот драйвер #####
|
||||
==============================================================================
|
||||
|
||||
1. Настройка периферии (periph_config.h):
|
||||
(+) Определить массивы GPIO_Init_TypeDef для портов:
|
||||
gpioa_config[32], gpiob_config[32]
|
||||
(+) Настроить режим пинов: Input, Output, AltFunc и другие функции
|
||||
|
||||
2. Инициализация GPIO:
|
||||
(+) gpio_init() — инициализация портов GPIOA и GPIOB
|
||||
|
||||
3. Работа со светодиодами:
|
||||
(+) GPIO_LED_Init(&led, GPIOA, GPIO_PIN_5, SET) — инициализация светодиода
|
||||
(+) GPIO_LED_On(&led) — включение светодиода
|
||||
(+) GPIO_LED_Off(&led) — выключение светодиода
|
||||
(+) GPIO_LED_Toggle(&led) — переключение светодиода
|
||||
(+) GPIO_LED_Blink_Start(&led, 500) — запуск моргания (период 500 мс)
|
||||
(+) GPIO_LED_Fading_Start(&led, 1000) — запуск плавного затухания (период 1 секунда)
|
||||
(+) GPIO_LED_Dynamic_Handle(&led) — обработка динамических режимов в основном цикле
|
||||
|
||||
4. Работа с кнопками:
|
||||
(+) GPIO_Switch_Init(&sw, GPIOB, GPIO_PIN_0, SET) — инициализация кнопки
|
||||
(+) GPIO_Read_Switch(&sw) — чтение состояния кнопки с фильтрацией
|
||||
|
||||
5. Утилитарные функции:
|
||||
(+) gpio_get_init(GPIOA, GPIO_PIN_5) — получение конфигурации пина
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
//-- Includes ------------------------------------------------------------------
|
||||
#include "periph_config.h"
|
||||
|
||||
//-- Defines -------------------------------------------------------------------
|
||||
|
||||
//-- Peripheral init functions -------------------------------------------------
|
||||
//-- GPIO init functions -------------------------------------------------------
|
||||
void gpio_init(void)
|
||||
{
|
||||
RCU_AHBClkCmd(RCU_AHBClk_GPIOA, ENABLE);
|
||||
@@ -36,43 +82,12 @@ void gpio_init(void)
|
||||
{
|
||||
GPIO_Init(GPIOB, &gpiob_config[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// GPIO_StructInit(&gpio_init);
|
||||
// gpio_init.Digital = ENABLE;
|
||||
// GPIO_Init(GPIOA, &gpio_init);
|
||||
// GPIO_Init(GPIOB, &gpio_init);
|
||||
//
|
||||
// /* Инициализация выходных пинов Пуш-Пулл */
|
||||
// gpio_init.Out = ENABLE;
|
||||
// gpio_init.OutMode = GPIO_OutMode_PP;
|
||||
//
|
||||
// gpio_init.Pin = GPIO_OUT_PP_PA_PINS;
|
||||
// GPIO_Init(GPIOA, &gpio_init);
|
||||
// gpio_init.Pin = GPIO_OUT_PP_PB_PINS;
|
||||
// GPIO_Init(GPIOB, &gpio_init);
|
||||
//
|
||||
// /* Инициализация выходных пинов Открытый сток */
|
||||
// gpio_init.Out = ENABLE;
|
||||
// gpio_init.OutMode = GPIO_OutMode_OD;
|
||||
//
|
||||
// gpio_init.Pin = GPIO_OUT_OD_PA_PINS;
|
||||
// GPIO_Init(GPIOA, &gpio_init);
|
||||
// gpio_init.Pin = GPIO_OUT_OD_PB_PINS;
|
||||
// GPIO_Init(GPIOB, &gpio_init);
|
||||
}
|
||||
|
||||
|
||||
GPIO_Init_TypeDef *gpio_get_init(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
|
||||
{
|
||||
uint8_t pin_index = __builtin_ctz(GPIO_Pin);
|
||||
uint8_t pin_index = (31 - __CLZ(GPIO_Pin & -GPIO_Pin));
|
||||
|
||||
if (GPIOx == GPIOA)
|
||||
{
|
||||
@@ -93,3 +108,282 @@ GPIO_Init_TypeDef *gpio_get_init(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-- GPIO LED functions --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Инициализировать светодиод (структуру светодиода)
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @param GPIOx Указатель на структуру порта для светодиода
|
||||
* @param GPIO_PIN_X Пин для светодиода
|
||||
* @param LED_ActiveLevel Состояния пина, при котором светодиод будет включен
|
||||
*/
|
||||
OperationStatus GPIO_LED_Init(GPIO_LEDTypeDef *led, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, BitState LED_ActiveLevel)
|
||||
{
|
||||
if(!led || !GPIOx ||!GPIO_PIN_X)
|
||||
return ERROR;
|
||||
|
||||
led->LED_Port = GPIOx;
|
||||
led->LED_Pin = GPIO_PIN_X;
|
||||
led->LED_ActiveLvl = LED_ActiveLevel;
|
||||
|
||||
GPIO_LED_Off(led);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Включить светодиод
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @return Operation Status
|
||||
*/
|
||||
OperationStatus GPIO_LED_On(GPIO_LEDTypeDef *led)
|
||||
{
|
||||
if(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return ERROR;
|
||||
|
||||
led->state = LED_IS_ON;
|
||||
GPIO_WriteBit(led->LED_Port, led->LED_Pin, led->LED_ActiveLvl);
|
||||
|
||||
|
||||
return OK;
|
||||
}
|
||||
/**
|
||||
* @brief Выключить светодиод
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @return Operation Status
|
||||
*/
|
||||
OperationStatus GPIO_LED_Off(GPIO_LEDTypeDef *led)
|
||||
{
|
||||
if(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return ERROR;
|
||||
|
||||
led->state = LED_IS_OFF;
|
||||
BitState offstate = (led->LED_ActiveLvl == SET)? CLEAR: SET;
|
||||
GPIO_WriteBit(led->LED_Port, led->LED_Pin, offstate);
|
||||
|
||||
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Переключить светодиод
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @return Operation Status
|
||||
*/
|
||||
OperationStatus GPIO_LED_Toggle(GPIO_LEDTypeDef *led)
|
||||
{
|
||||
if(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return ERROR;
|
||||
|
||||
|
||||
if(led->state == LED_IS_ON || led->state == LED_IS_OFF)
|
||||
{
|
||||
if(led->state == LED_IS_OFF)
|
||||
led->state = LED_IS_ON;
|
||||
else
|
||||
led->state = LED_IS_OFF;
|
||||
|
||||
GPIO_ToggleBits(led->LED_Port, led->LED_Pin);
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Выставить светодиод по переменной
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @param led_state Состояние светодиода
|
||||
* @return Operation Status
|
||||
*/
|
||||
OperationStatus GPIO_LED_Set(GPIO_LEDTypeDef *led, uint8_t led_state)
|
||||
{
|
||||
if(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return ERROR;
|
||||
|
||||
if(led_state)
|
||||
{
|
||||
return GPIO_LED_On(led);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GPIO_LED_Off(led);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Активировать моргание светодиодом
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @param period Период плавного моргания светодиода
|
||||
* @return Operation Status
|
||||
* @details Функция ставит режим моргания, который после управляется в @ref GPIO_LED_Dynamic_Handle
|
||||
*/
|
||||
OperationStatus GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period)
|
||||
{
|
||||
if(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return ERROR;
|
||||
|
||||
led->state = LED_IS_BLINKING;
|
||||
led->LED_Period = period;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Активировать моргание светодиодом
|
||||
* @param led Указатель на структуру светодиода
|
||||
* @param period Период плавного моргания светодиода
|
||||
* @return Operation Status
|
||||
* @details Функция ставит режим моргания, который после управляется в @ref GPIO_LED_Dynamic_Handle
|
||||
*/
|
||||
OperationStatus GPIO_LED_Fading_Start(GPIO_LEDTypeDef *led, uint32_t period)
|
||||
{
|
||||
if(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return ERROR;
|
||||
|
||||
led->state = LED_IS_FADING;
|
||||
led->LED_Period = period;
|
||||
|
||||
|
||||
return 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(!led || !led->LED_Port || !led->LED_Pin)
|
||||
return;
|
||||
|
||||
/* Режим моргания светодиода */
|
||||
if(led->state == LED_IS_BLINKING)
|
||||
{
|
||||
uint32_t tickcurrent = millis();
|
||||
/* Ожидание истечения периода моргания */
|
||||
if((tickcurrent - led->tickprev) > led->LED_Period)
|
||||
{
|
||||
/* Моргание */
|
||||
GPIO_ToggleBits(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 = millis();
|
||||
/* Ожидание момента изменения яркости */
|
||||
/* Период ШИМ 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)
|
||||
{
|
||||
GPIO_WriteBit(led->LED_Port, led->LED_Pin, led->LED_ActiveLvl);
|
||||
}
|
||||
else
|
||||
{
|
||||
BitState offstate = (led->LED_ActiveLvl == SET)? CLEAR: SET;
|
||||
GPIO_WriteBit(led->LED_Port, led->LED_Pin, offstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-- GPIO Switch functions -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Инициализировать кнопку (структуру кнопки)
|
||||
* @param sw Указатель на структуру кнопки
|
||||
* @param GPIOx Указатель на структуру порта для кнопки
|
||||
* @param GPIO_PIN_X Пин для кнопки
|
||||
* @param SW_ActiveLevel Состояния пина, когда кнопка нажата
|
||||
* @return Operation Status
|
||||
*/
|
||||
OperationStatus GPIO_Switch_Init(GPIO_SwitchTypeDef *sw, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, BitState SW_ActiveLevel)
|
||||
{
|
||||
if(!sw || !GPIOx || !GPIO_PIN_X)
|
||||
return ERROR;
|
||||
|
||||
sw->Sw_Port = GPIOx;
|
||||
sw->Sw_Pin = GPIO_PIN_X;
|
||||
sw->Sw_ActiveLvl = SW_ActiveLevel;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Считать состоянии кнопки
|
||||
* @param sw Указатель на структуру кнопки
|
||||
* @return 1 - если кнопка нажата,
|
||||
* 0 - если отжата,
|
||||
* -1 - если ошибка
|
||||
* @details Функция включает в себя неблокирующую проверку на дребезг
|
||||
* Т.е. функцию надо вызывать постоянно, чтобы она мониторила состояние кнопки
|
||||
*/
|
||||
int GPIO_Read_Switch(GPIO_SwitchTypeDef *sw)
|
||||
{
|
||||
if(!sw || !sw->Sw_Port || !sw->Sw_Pin)
|
||||
return -1;
|
||||
|
||||
int current_level = (GPIO_ReadBit(sw->Sw_Port, sw->Sw_Pin) == sw->Sw_ActiveLvl);
|
||||
|
||||
if(sw->Sw_FilterDelay) // если включена защита от дребезга
|
||||
{
|
||||
// Если таймер не запущен и состояние изменилось - запускаем таймер
|
||||
if(sw->tickprev == 0 && current_level != sw->Sw_CurrentState)
|
||||
{
|
||||
sw->tickprev = millis();
|
||||
}
|
||||
|
||||
// Если таймер запущен
|
||||
if(sw->tickprev != 0)
|
||||
{
|
||||
// Проверяем, прошел ли достаточный интервал для фильтрации
|
||||
if((millis() - 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user