Добавлено API для UART и TMR

This commit is contained in:
2025-12-26 18:43:40 +03:00
parent c6e1dc049f
commit 8e350e6a91
22 changed files with 4359 additions and 1854 deletions

506
Core/App/uart.c Normal file
View File

@@ -0,0 +1,506 @@
/*==============================================================================
* Инициализация тактирования с использованием бибилотеки PLIB035
*------------------------------------------------------------------------------
* ЦНИИ СЭТ, Разваляев Алексей <wot890089@mail.ru>
*==============================================================================
* ЦНИИ СЭТ
*==============================================================================
*/
//-- Includes ------------------------------------------------------------------
#include "periph_config.h"
UART_HandleTypeDef huart0;
UART_HandleTypeDef huart1;
static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode);
static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode);
//-- Defines -------------------------------------------------------------------
//-- Peripheral init functions -------------------------------------------------
void uart_init_first(void)
{
#if (USE_UART0==1)
// Настройка пинов для UART0
uart0_gpio_init();
// Включаем тактирование UART0
RCU_UARTClkConfig(UART0_Num, RCU_PeriphClk_PLLClk, 0, DISABLE);
RCU_UARTClkCmd(UART0_Num, ENABLE);
UART_DeInit(UART0);
// Инициализируем UART0
huart0.UART = UART0;
uart_init(&huart0, &uart0_config);
NVIC_EnableIRQ(UART0_TD_IRQn);
NVIC_EnableIRQ(UART0_RX_IRQn);
NVIC_EnableIRQ(UART0_TX_IRQn);
NVIC_EnableIRQ(UART0_E_RT_IRQn);
#endif
#if (USE_UART1==1)
// Настройка пинов для UART1
uart1_gpio_init();
// Включаем тактирование UART1
RCU_UARTClkConfig(UART1_Num, RCU_PeriphClk_PLLClk, 0, DISABLE);
RCU_UARTClkCmd(UART1_Num, ENABLE);
UART_DeInit(UART1);
// Инициализируем UART1
NVIC_EnableIRQ(UART1_TD_IRQn);
NVIC_EnableIRQ(UART1_RX_IRQn);
NVIC_EnableIRQ(UART1_TX_IRQn);
NVIC_EnableIRQ(UART1_E_RT_IRQn);
huart1.UART = UART1;
uart_init(&huart1, &uart1_config);
#endif
}
/**
* @brief Инициализация UART
* @param htmr указатель на хендл UART
* @param NewConfig указатель на новую конфигурацию UART, иначе используется та, что в структуре
* @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка
*/
OperationStatus uart_init(UART_HandleTypeDef *huart, UART_ExtInitTypeDef *NewConfig)
{
if(huart->UART == NULL)
{
return ERROR;
}
if(NewConfig != NULL)
{
huart->Config = NewConfig;
}
if(huart->Config == NULL)
{
return ERROR;
}
UART_Init(huart->UART, &huart->Config->UART_Init);
return OK;
}
OperationStatus uart_start(UART_HandleTypeDef *huart, UART_FIFOLevel_TypeDef TxFifoLevel, UART_FIFOLevel_TypeDef RxFifoLevel)
{
if (huart == NULL)
return ERROR;
UART_ITFIFOLevelRxConfig(huart->UART, RxFifoLevel);
UART_ITFIFOLevelTxConfig(huart->UART, TxFifoLevel);
huart->TxBufPtr = NULL;
huart->TxCount = 0;
huart->TxSize = 0;
huart->TxBusy = 0;
huart->RxBufPtr = NULL;
huart->RxCount = 0;
huart->RxSize = 0;
huart->RxBusy = 0;
UART_Cmd(huart->UART, ENABLE);
return OK;
}
OperationStatus uart_transmit(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
if (!huart || !buf || size == 0)
return ERROR;
// Если TX занят, возвращаем ERROR
if (huart->TxBusy)
return ERROR;
huart->TxBufPtr = buf;
huart->TxSize = size;
huart->TxCount = 0;
huart->TxBusy = 1;
uint32_t starttick = millis();
// Отправляем пока всё не отправится
while(__uart_fifo_transmit(huart, 0) == 0)
{
if(millis() - starttick > timeout)
return ERROR;
}
return OK;
}
OperationStatus uart_receive(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
if (!huart || !buf || size == 0)
return ERROR;
// Если RX занят, возвращаем ERROR
if (huart->RxBusy)
return ERROR;
huart->RxBufPtr = buf;
huart->RxSize = size;
huart->RxCount = 0;
huart->RxBusy = 1;
uint32_t starttick = millis();
// Принимаем всё пока всё не примется
while(__uart_fifo_transmit(huart, 0) == 0)
{
if(millis() - starttick > timeout)
return ERROR;;
}
return OK;
}
OperationStatus uart_transmit_it(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size)
{
if (!huart || !buf || size == 0)
return ERROR;
// Если TX занят, возвращаем ERROR
if (huart->TxBusy)
return ERROR;
huart->TxBufPtr = buf;
huart->TxSize = size;
huart->TxCount = 0;
huart->TxBusy = 1;
// Включаем прерывания по TX FIFO
UART_ITCmd(huart->UART, UART_ITSource_TxFIFOLevel, ENABLE);
__uart_fifo_transmit(huart, 1);
return OK;
}
OperationStatus uart_receive_it(UART_HandleTypeDef *huart,
uint8_t *buf,
uint16_t size)
{
if (!huart || !buf || size == 0)
return ERROR;
// Если RX занят, возвращаем ERROR
if (huart->RxBusy)
return ERROR;
huart->RxBufPtr = buf;
huart->RxSize = size;
huart->RxCount = 0;
huart->RxBusy = 1;
// Включаем только RX прерывания
UART_ITCmd(huart->UART,
UART_ITSource_RxFIFOLevel |
UART_ITSource_RecieveTimeout |
UART_ITSource_ErrorFrame |
UART_ITSource_ErrorParity |
UART_ITSource_ErrorOverflow |
UART_ITSource_ErrorBreak,
ENABLE);
return OK;
}
void uart_handler(UART_HandleTypeDef *huart)
{
if (!huart || !huart->UART || !huart->Config)
return;
UART_TypeDef *uart = huart->UART;
uint32_t mis = uart->MIS;
// Ошибки
if (mis & (UART_ITSource_ErrorFrame |
UART_ITSource_ErrorParity |
UART_ITSource_ErrorOverflow |
UART_ITSource_ErrorBreak))
{
if (huart->Config->ErrCallback)
huart->Config->ErrCallback();
UART_ErrorStatusClear(uart, UART_Error_All);
UART_ITStatusClear(uart, mis);
}
// RX FIFO
if (mis & UART_ITSource_RxFIFOLevel)
{
// Принимаем
if(__uart_fifo_receive(huart, 1))
{ // Когда всё приняли, флаги сбросили внутри функции
}
UART_ITStatusClear(uart, UART_ITSource_RxFIFOLevel);
}
// IDLE / Receive Timeout
if (mis & UART_ITSource_RecieveTimeout)
{
UART_ITStatusClear(uart, UART_ITSource_RecieveTimeout);
huart->RxBusy = 0;
// Выключаем RX прерывания до следующего вызова uart_receive_it
UART_ITCmd(uart,
UART_ITSource_RxFIFOLevel |
UART_ITSource_RecieveTimeout,
DISABLE);
if (huart->Config->IdleCallback)
huart->Config->IdleCallback();
}
// TX FIFO
if (mis & UART_ITSource_TxFIFOLevel)
{
// Отправляем
if(__uart_fifo_transmit(huart, 1))
{ // Когда всё отправили, флаги сбросили внутри функции
}
UART_ITStatusClear(uart, UART_ITSource_TxFIFOLevel);
}
// Конец передачи
if (mis & UART_ITSource_TransmitDone)
{
UART_ITStatusClear(uart, UART_ITSource_TransmitDone);
huart->TxBusy = 0;
if (huart->Config->TxCallback)
huart->Config->TxCallback();
}
}
/**
* @brief Установка коллбека UART
* @param htmr указатель на хендл UART
* @param cb_type Тип коллбека
* @param Callback Функция коллбека
* @retval void
*/
OperationStatus uart_set_callback(UART_HandleTypeDef* huart, UART_CallbackTypeDef cb_type, void (*Callback)(void))
{
if((huart->UART == NULL) || (huart->Config == NULL))
{
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
// Получаем структуры
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART0_GPIO_Port, UART0_Tx_Pin);
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART0_GPIO_Port, UART0_Rx_Pin);
// TX пин
if (uart0_config.UART_Init.Tx == ENABLE && tx_config != NULL)
{
GPIO_StructInit(tx_config);
tx_config->AltFunc = ENABLE;
tx_config->Digital = ENABLE;
tx_config->Pin = UART0_Tx_Pin;
GPIO_Init(UART0_GPIO_Port, tx_config);
}
// RX пин
if (uart0_config.UART_Init.Rx == ENABLE && rx_config != NULL)
{
GPIO_StructInit(rx_config);
rx_config->AltFunc = ENABLE;
rx_config->Digital = ENABLE;
rx_config->Pin = UART0_Rx_Pin;
GPIO_Init(UART0_GPIO_Port, rx_config);
}
#endif
}
void uart0_gpio_deinit(void)
{
#if USE_UART0==1
// Получаем структуры
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART0_GPIO_Port, UART0_Tx_Pin);
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART0_GPIO_Port, UART0_Rx_Pin);
// Восстанавливаем оригинальные настройки из таблицы
if (tx_config != NULL)
{
GPIO_StructInit(rx_config);
rx_config->Pin = UART0_Tx_Pin;
GPIO_Init(UART0_GPIO_Port, tx_config);
}
if (rx_config != NULL)
{
GPIO_StructInit(rx_config);
rx_config->Pin = UART0_Rx_Pin;
GPIO_Init(UART0_GPIO_Port, rx_config);
}
#endif
}
void uart1_gpio_init(void)
{
#if USE_UART1==1
// Получаем структуры
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART1_GPIO_Port, UART1_Tx_Pin);
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART1_GPIO_Port, UART1_Rx_Pin);
// TX пин
if (uart1_config.UART_Init.Tx == ENABLE && tx_config != NULL)
{
GPIO_StructInit(tx_config);
tx_config->AltFunc = ENABLE;
tx_config->Digital = ENABLE;
tx_config->Pin = UART1_Tx_Pin;
GPIO_Init(UART1_GPIO_Port, tx_config);
}
// RX пин
if (uart1_config.UART_Init.Rx == ENABLE && rx_config != NULL)
{
;
GPIO_StructInit(rx_config);
rx_config->AltFunc = ENABLE;
rx_config->Digital = ENABLE;
rx_config->Pin = UART1_Rx_Pin;
GPIO_Init(UART1_GPIO_Port, rx_config);
}
#endif
}
void uart1_gpio_deinit(void)
{
#if USE_UART1==1
// Получаем структуры
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART1_GPIO_Port, UART1_Tx_Pin);
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART1_GPIO_Port, UART1_Rx_Pin);
// Восстанавливаем оригинальные настройки из таблицы
if (tx_config != NULL)
{
GPIO_StructInit(rx_config);
rx_config->Pin = UART1_Tx_Pin;
GPIO_Init(UART1_GPIO_Port, tx_config);
}
if (rx_config != NULL)
{
GPIO_StructInit(rx_config);
rx_config->Pin = UART1_Rx_Pin;
GPIO_Init(UART1_GPIO_Port, rx_config);
}
#endif
}
static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode)
{
while (!UART_FlagStatus(huart->UART, UART_Flag_RxFIFOEmpty) &&
huart->RxCount < huart->RxSize)
{
huart->RxBufPtr[huart->RxCount++] = UART_RecieveData(huart->UART);
if (huart->RxCount == huart->RxSize)
{
huart->RxBusy = 0;
if(it_mode)
{
// Выключаем RX прерывания
UART_ITCmd(huart->UART,
UART_ITSource_RxFIFOLevel |
UART_ITSource_RecieveTimeout,
DISABLE);
}
if (huart->Config->RxCallback)
huart->Config->RxCallback();
return 1;
}
}
return 0;
}
static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode)
{
while (!UART_FlagStatus(huart->UART, UART_Flag_TxFIFOFull) &&
huart->TxCount < huart->TxSize)
{
UART_SendData(huart->UART, huart->TxBufPtr[huart->TxCount++]);
}
if (huart->TxCount == huart->TxSize)
{
if(it_mode)
{
// Выключаем FIFO прерывание
UART_ITCmd(huart->UART, UART_ITSource_TxFIFOLevel, DISABLE);
// Включаем TransmitDone прерывание, коллбек будет по нему
UART_ITCmd(huart->UART, UART_ITSource_TransmitDone, ENABLE);
}
else
{
while(!UART_FlagStatus(huart->UART, UART_Flag_TxFIFOEmpty)); // ждем пока не опустошится буфер
huart->TxBusy = 0;
if (huart->Config->TxCallback)
huart->Config->TxCallback();
}
return 1;
}
return 0;
}