Добавлено:

- рефакторинг названий:
	- маленькие буквы - инит периферии
	- ТакойСтильФункций - API для использования
- сделаны шапки с инструкциями к функциями
- доработан ацп секвенсора
- доработан систем тики. можно настроить его на разные частоты и подключить коллбеки на разный период
- в gpio добавлены функции для кнопок и диодов
- генерация бинарника
This commit is contained in:
2025-12-27 23:20:03 +03:00
parent c7fdf6776f
commit f3e76e105a
20 changed files with 2105 additions and 6274 deletions

View File

@@ -1,28 +1,105 @@
/*==============================================================================
* Инициализация Instance с использованием бибилотеки PLIB035
*------------------------------------------------------------------------------
* ЦНИИ СЭТ, Разваляев Алексей <wot890089@mail.ru>
*==============================================================================
* ЦНИИ СЭТ
*==============================================================================
*/
/**
******************************************************************************
* @file uart.c
* @author Разваляев Алексей
* @brief Драйвер UART на основе PLIB035.
* Этот файл содержит:
* + Инициализацию UART0/UART1
* + Управление FIFO
* + Передачу и приём данных в blocking и interrupt режимах
* + Общий обработчик прерываний UART
* + Функции настройки GPIO для UART
* + Очередь передачи для предотвращения потери данных
*
******************************************************************************
* @attention
*
* Использование этого драйвера предполагает наличие корректных настроек:
* - Определены конфигурационные структуры uartx_config в periph_config.h
* - Определены пины TX/RX для UART0/UART1
*
******************************************************************************
* @verbatim
==============================================================================
##### Как использовать этот драйвер #####
==============================================================================
1. Настройка периферии (periph_config.h):
(+) Определить структуры UART_ExtInit_TypeDef для нужных UART:
uart0_config, uart1_config
(+) Настроить скорость, стоп-биты, четность, длину данных
(+) Настроить FIFO и направление (Tx, Rx или оба)
(+) Определить callback-функции (можно NULL)
(+) Определить пины TX/RX для UART0/UART1
(+) Включить/отключить очередь сообщений для отправки: USE_TX_QUEUE в uart.h
2. Инициализация UART:
(+) uart_init_first() — первичная настройка GPIO, тактирования и NVIC
(+) uart_init(&huart, &config) — инициализация конкретного UART с конфигурацией
3. Callback-функции:
(+) UART_Set_Callback(&huart, UART_Callback_Rx, Callback) — вызов при приёме данных
(+) UART_Set_Callback(&huart, UART_Callback_Tx, Callback) — вызов при завершении передачи
(+) UART_Set_Callback(&huart, UART_Callback_Idle, Callback) — вызов при событии Idle
(+) UART_Set_Callback(&huart, UART_Callback_Error, Callback) — вызов при ошибках
4. Запуск UART и FIFO:
(+) UART_Start(&huart, TxFifoLevel, RxFifoLevel) — включает UART и настраивает FIFO
5. Передача и приём данных:
- Режим Polling (blocking):
(+) UART_Transmit(&huart, buf, size, timeout) — передача данных с ожиданием
(+) UART_Receive(&huart, buf, size, timeout) — приём данных с ожиданием
- Режим Interrupt (non-blocking):
(+) UART_Transmit_IT(&huart, buf, size) — передача данных через прерывания
(+) UART_Receive_IT(&huart, buf, size) — приём данных через прерывания
6. Обработка прерываний UART:
(+) uart_irq_handler(&huart) — общий обработчик ISR для RX/TX FIFO, ошибок и Idle
- В обработчиках автоматически вызываются соответствующие callback-функции
и сбрасываются флаги
- Поддерживается очередь передачи для предотвращения потери данных
7. GPIO для UART:
(+) uart0_gpio_init()/uart0_gpio_deinit() — инициализация и деинициализация UART0
(+) uart1_gpio_init()/uart1_gpio_deinit() — инициализация и деинициализация UART1
8. Режимы работы:
(+) Polling (blocking) — функции блокируются до завершения передачи/приёма
(+) Interrupt (non-blocking) — передача/приём через прерывания, управление через callback
@endverbatim
******************************************************************************
*/
//-- Includes ------------------------------------------------------------------
#include "periph_config.h"
UART_HandleTypeDef huart0;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart0; /*!< Хендл UART0 */
UART_HandleTypeDef huart1; /*!< Хендл UART1 */
//-- Private function prototypes -----------------------------------------------
static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode);
static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode);
#if USE_TX_QUEUE==1
static void __uart_tx_queue_process(UART_HandleTypeDef *huart);
static OperationStatus __uart_tx_queue_push(UART_HandleTypeDef *huart, const uint8_t *buf, uint16_t size);
static OperationStatus __uart_tx_queue_pop(UART_HandleTypeDef *huart);
#endif
//-- Defines -------------------------------------------------------------------
//-- Peripheral init functions -------------------------------------------------
//-- UART Init functions -------------------------------------------------------
/**
* @brief Первичная инициализация UART (UART0 / UART1)
* @details Настройка UART и хендлов: GPIO, тактирование и прерывания
*/
void uart_init_first(void)
{
@@ -68,9 +145,9 @@ void uart_init_first(void)
/**
* @brief Инициализация Instance
* @param htmr указатель на хендл Instance
* @param NewConfig указатель на новую конфигурацию Instance, иначе используется та, что в структуре
* @brief Инициализация UART
* @param htmr указатель на хендл UART
* @param NewConfig указатель на новую конфигурацию UART, иначе используется та, что в структуре
* @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка
*/
OperationStatus uart_init(UART_HandleTypeDef *huart, UART_ExtInit_TypeDef *NewConfig)
@@ -92,7 +169,52 @@ OperationStatus uart_init(UART_HandleTypeDef *huart, UART_ExtInit_TypeDef *NewCo
return OK;
}
OperationStatus uart_start(UART_HandleTypeDef *huart, UART_FIFOLevel_TypeDef TxFifoLevel, UART_FIFOLevel_TypeDef RxFifoLevel)
/**
* @brief Установка коллбека UART
* @param htmr указатель на хендл UART
* @param CallbackType Тип коллбека
* @param Callback Функция коллбека
* @retval void
*/
OperationStatus UART_Set_Callback(UART_HandleTypeDef* huart, UART_CallbackTypeDef CallbackType, void (*Callback)(void))
{
if (!huart || !huart->Instance || !huart->Config)
return ERROR;
switch(CallbackType)
{
case UART_Callback_Rx:
huart->Config->RxCallback = Callback;
break;
case UART_Callback_Tx:
huart->Config->TxCallback = Callback;
break;
case UART_Callback_Idle:
huart->Config->IdleCallback = Callback;
break;
case UART_Callback_Error:
huart->Config->ErrCallback = Callback;
break;
default:
return ERROR;
}
return OK;
}
//-- UART API functions --------------------------------------------------------
/**
* @brief Запуск UART и инициализация FIFO
* @param huart указатель на хендл UART
* @param TxFifoLevel уровень прерывания TX FIFO
* @param RxFifoLevel уровень прерывания RX FIFO
* @retval OperationStatus OK - если успешно, ERROR - при ошибке
*/
OperationStatus UART_Start(UART_HandleTypeDef *huart, UART_FIFOLevel_TypeDef TxFifoLevel, UART_FIFOLevel_TypeDef RxFifoLevel)
{
if (!huart)
return ERROR;
@@ -111,12 +233,36 @@ OperationStatus uart_start(UART_HandleTypeDef *huart, UART_FIFOLevel_TypeDef TxF
huart->RxSize = 0;
huart->RxBusy = 0;
#if USE_TX_QUEUE==1
huart->TxQueue.QueueHead = 0;
huart->TxQueue.QueueTail = 0;
huart->TxQueue.QueueCount = 0;
huart->TxQueue.QueueEmpty = 1;
huart->TxQueue.QueueFull = 0;
for (uint8_t i = 0; i < TX_QUEUE_SIZE; i++)
{
huart->TxQueue.Queue[i].Buf = NULL;
huart->TxQueue.Queue[i].Size = 0;
huart->TxQueue.Queue[i].InUse = 0;
}
#endif
UART_Cmd(huart->Instance, ENABLE);
return OK;
}
OperationStatus uart_transmit(UART_HandleTypeDef *huart,
/**
* @brief Передача данных по UART (блокирующий режим)
* @param huart указатель на хендл UART
* @param buf указатель на буфер данных
* @param size размер данных в байтах
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus UART_Transmit(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
@@ -143,8 +289,15 @@ OperationStatus uart_transmit(UART_HandleTypeDef *huart,
return OK;
}
OperationStatus uart_receive(UART_HandleTypeDef *huart,
/**
* @brief Приём данных по UART (блокирующий режим)
* @param huart указатель на хендл UART
* @param buf указатель на буфер приёма
* @param size количество принимаемых байт
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus UART_Receive(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
@@ -172,14 +325,37 @@ OperationStatus uart_receive(UART_HandleTypeDef *huart,
return OK;
}
OperationStatus uart_transmit_it(UART_HandleTypeDef *huart,
/**
* @brief Передача данных по UART (прерывания)
* @param huart указатель на хендл UART
* @param buf указатель на буфер данных
* @param size размер данных в байтах
* @retval OperationStatus OK - если успешно, ERROR - если передача уже идёт
*/
OperationStatus UART_Transmit_IT(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size)
{
if (!huart || !buf || size == 0)
return ERROR;
#if USE_TX_QUEUE==1
// Автоматически используем очередь
if (huart->TxQueue.QueueFull)
return ERROR;
OperationStatus status = __uart_tx_queue_push(huart, buf, size);
if (status != OK)
return ERROR;
if (!huart->TxBusy)
{
__uart_tx_queue_process(huart);
}
return OK;
#else
// Без очереди
// Если TX занят, возвращаем ERROR
if (huart->TxBusy)
return ERROR;
@@ -195,11 +371,17 @@ OperationStatus uart_transmit_it(UART_HandleTypeDef *huart,
__uart_fifo_transmit(huart, 1);
return OK;
#endif
}
OperationStatus uart_receive_it(UART_HandleTypeDef *huart,
/**
* @brief Приём данных по UART (прерывания)
* @param huart указатель на хендл UART
* @param buf указатель на буфер приёма
* @param size количество принимаемых байт
* @retval OperationStatus OK - если успешно, ERROR - если приём уже идёт
*/
OperationStatus UART_Receive_IT(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size)
{
@@ -228,12 +410,20 @@ OperationStatus uart_receive_it(UART_HandleTypeDef *huart,
return OK;
}
void uart_handler(UART_HandleTypeDef *huart)
//-- UART Handler functions ---------------------------------------------------
/**
* @brief Общий обработчик прерываний UART
* @param huart указатель на хендл UART
* @details Обрабатывает RX/TX FIFO, ошибки и события Idle
* @retval void
*/
void uart_irq_handler(UART_HandleTypeDef *huart)
{
if (!huart || !huart->Instance || !huart->Config)
return;
// GPIO_SetBits(GPIOA, GPIO_Pin_7);
UART_TypeDef *uart = huart->Instance;
uint32_t mis = uart->MIS;
@@ -267,7 +457,7 @@ void uart_handler(UART_HandleTypeDef *huart)
UART_ITStatusClear(uart, UART_ITSource_RecieveTimeout);
huart->RxBusy = 0;
// Выключаем RX прерывания до следующего вызова uart_receive_it
// Выключаем RX прерывания до следующего вызова UART_Receive_IT
UART_ITCmd(uart,
UART_ITSource_RxFIFOLevel |
UART_ITSource_RecieveTimeout,
@@ -287,6 +477,7 @@ void uart_handler(UART_HandleTypeDef *huart)
UART_ITStatusClear(uart, UART_ITSource_TxFIFOLevel);
}
// Конец передачи
if (mis & UART_ITSource_TransmitDone)
{
@@ -295,46 +486,23 @@ void uart_handler(UART_HandleTypeDef *huart)
if (huart->Config->TxCallback)
huart->Config->TxCallback();
#if USE_TX_QUEUE==1
// Если есть очередь, обрабатываем следующий пакет
__uart_tx_queue_process(huart);
#endif
}
// GPIO_ClearBits(GPIOA, GPIO_Pin_7);
}
//-- UART GPIO functions -------------------------------------------------------
/**
* @brief Установка коллбека Instance
* @param htmr указатель на хендл Instance
* @param cb_type Тип коллбека
* @param Callback Функция коллбека
* @retval void
* @brief Инициализация GPIO для UART0
*/
OperationStatus uart_set_callback(UART_HandleTypeDef* huart, UART_CallbackTypeDef cb_type, void (*Callback)(void))
{
if (!huart || !huart->Instance || !huart->Config)
return ERROR;
switch(cb_type)
{
case UART_Callback_Rx:
huart->Config->RxCallback = Callback;
break;
case UART_Callback_Tx:
huart->Config->TxCallback = Callback;
break;
case UART_Callback_Idle:
huart->Config->IdleCallback = Callback;
break;
case UART_Callback_Error:
huart->Config->ErrCallback = Callback;
break;
default:
return ERROR;
}
return OK;
}
void uart0_gpio_init(void)
{
#if USE_UART0==1
@@ -363,7 +531,9 @@ void uart0_gpio_init(void)
}
#endif
}
/**
* @brief Деинициализация GPIO для UART0
*/
void uart0_gpio_deinit(void)
{
#if USE_UART0==1
@@ -387,7 +557,9 @@ void uart0_gpio_deinit(void)
}
#endif
}
/**
* @brief Инициализация GPIO для UART1
*/
void uart1_gpio_init(void)
{
#if USE_UART1==1
@@ -417,7 +589,9 @@ void uart1_gpio_init(void)
}
#endif
}
/**
* @brief Деинициализация GPIO для UART1
*/
void uart1_gpio_deinit(void)
{
#if USE_UART1==1
@@ -442,7 +616,13 @@ void uart1_gpio_deinit(void)
#endif
}
//-- UART private functions ----------------------------------------------------
/**
* @brief Приём данных из RX FIFO
* @param huart указатель на хендл UART
* @param it_mode режим работы (0 — polling, 1 — прерывания)
* @retval int 1 — приём завершён, 0 — данные ещё принимаются
*/
static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode)
{
while (!UART_FlagStatus(huart->Instance, UART_Flag_RxFIFOEmpty) &&
@@ -470,6 +650,12 @@ static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode)
}
return 0;
}
/**
* @brief Передача данных в TX FIFO
* @param huart указатель на хендл UART
* @param it_mode режим работы (0 — polling, 1 — прерывания)
* @retval int 1 — передача завершена, 0 — данные ещё передаются
*/
static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode)
{
while (!UART_FlagStatus(huart->Instance, UART_Flag_TxFIFOFull) &&
@@ -499,4 +685,65 @@ static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode)
return 1;
}
return 0;
}
}
#if USE_TX_QUEUE==1
static void __uart_tx_queue_process(UART_HandleTypeDef *huart)
{
if (!huart->TxBusy && !huart->TxQueue.QueueEmpty)
{
__uart_tx_queue_pop(huart);
}
}
static OperationStatus __uart_tx_queue_push(UART_HandleTypeDef *huart, const uint8_t *buf, uint16_t size)
{
if (!huart || !buf || size == 0 || huart->TxQueue.QueueFull)
return ERROR;
huart->TxQueue.Queue[huart->TxQueue.QueueHead].Buf = buf;
huart->TxQueue.Queue[huart->TxQueue.QueueHead].Size = size;
huart->TxQueue.Queue[huart->TxQueue.QueueHead].InUse = 1;
huart->TxQueue.QueueHead = (huart->TxQueue.QueueHead + 1) % TX_QUEUE_SIZE;
huart->TxQueue.QueueCount++;
huart->TxQueue.QueueEmpty = 0;
if (huart->TxQueue.QueueCount == TX_QUEUE_SIZE)
huart->TxQueue.QueueFull = 1;
return OK;
}
static OperationStatus __uart_tx_queue_pop(UART_HandleTypeDef *huart)
{
if (!huart || huart->TxQueue.QueueEmpty)
return ERROR;
const uint8_t *buf = huart->TxQueue.Queue[huart->TxQueue.QueueTail].Buf;
uint16_t size = huart->TxQueue.Queue[huart->TxQueue.QueueTail].Size;
if (huart->TxBusy)
return ERROR;
huart->TxBufPtr = buf;
huart->TxSize = size;
huart->TxCount = 0;
huart->TxBusy = 1;
UART_ITCmd(huart->Instance, UART_ITSource_TxFIFOLevel, ENABLE);
__uart_fifo_transmit(huart, 1);
huart->TxQueue.Queue[huart->TxQueue.QueueTail].Buf = NULL;
huart->TxQueue.Queue[huart->TxQueue.QueueTail].Size = 0;
huart->TxQueue.Queue[huart->TxQueue.QueueTail].InUse = 0;
huart->TxQueue.QueueTail = (huart->TxQueue.QueueTail + 1) % TX_QUEUE_SIZE;
huart->TxQueue.QueueCount--;
huart->TxQueue.QueueFull = 0;
if (huart->TxQueue.QueueCount == 0)
huart->TxQueue.QueueEmpty = 1;
return OK;
}
#endif