You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.4 KiB
135 lines
4.4 KiB
|
3 days ago
|
#include "bsp_uart.h"
|
||
|
|
#ifdef USE_UART
|
||
|
|
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||
|
|
extern DMA_HandleTypeDef hdma_usart2_rx;
|
||
|
|
|
||
|
|
#ifdef CONFIG_UART_IT_IDLEDMA
|
||
|
|
static TUartTab g_ptUartTab[] = {
|
||
|
|
{&huart2, &hdma_usart2_rx},
|
||
|
|
{&huart1, &hdma_usart1_rx},
|
||
|
|
{&huart2, &hdma_usart2_rx},
|
||
|
|
{&huart3, &hdma_usart3_rx},
|
||
|
|
{&huart4, &hdma_usart4_rx},
|
||
|
|
{&huart5, &hdma_usart5_rx},
|
||
|
|
{&huart6, &hdma_usart6_rx},
|
||
|
|
{&huart7, &hdma_usart7_rx}
|
||
|
|
};
|
||
|
|
#else
|
||
|
|
static TUartTab g_ptUartTab[] = {
|
||
|
|
{&huart2, NULL},
|
||
|
|
{&huart1, NULL},
|
||
|
|
{&huart2, NULL},
|
||
|
|
{&huart3, NULL},
|
||
|
|
{&huart4, NULL},
|
||
|
|
{&huart5, NULL},
|
||
|
|
{&huart6, NULL},
|
||
|
|
{&huart7, NULL}
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static void bsp_uart_set_baudrate(UART_HandleTypeDef *_pUartHandle, uint32_t _uiBaudRate)
|
||
|
|
{
|
||
|
|
_pUartHandle->Init.BaudRate = _uiBaudRate;
|
||
|
|
if (HAL_UART_Init(_pUartHandle) != HAL_OK)
|
||
|
|
{
|
||
|
|
Error_Handler();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TUartUserData *UART_userdata_init(int _iID, uint32_t _uiBaudRate, uint32_t _uiSize)
|
||
|
|
{
|
||
|
|
if (_iID < 0 || _iID >= (sizeof(g_ptUartTab)/sizeof(g_ptUartTab[0])))
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
TUartUserData *ptUartUserData = (TUartUserData *)RD_CALLOC(1, sizeof(TUartUserData));
|
||
|
|
ptUartUserData->m_buf_size = (_uiSize == 0) ? CONFIG_UART_BUFFER_SIZE : _uiSize;
|
||
|
|
#ifdef CONFIG_UART_IT_IDLEDMA
|
||
|
|
uint8_t *pDMABuf = (uint8_t *)RD_CALLOC(1, ptUartUserData->m_buf_size);
|
||
|
|
ptUartUserData->m_dma_rx_buf = pDMABuf;
|
||
|
|
ptUartUserData->m_last_dma_pos = 0;
|
||
|
|
|
||
|
|
ptUartUserData->m_hdma_rx = g_ptUartTab[_iID].m_hdma_rx;
|
||
|
|
#endif
|
||
|
|
ptUartUserData->m_uart = g_ptUartTab[_iID].m_uart;
|
||
|
|
|
||
|
|
bsp_uart_set_baudrate(g_ptUartTab[_iID].m_uart, _uiBaudRate);
|
||
|
|
return ptUartUserData;
|
||
|
|
}
|
||
|
|
|
||
|
|
void UART_IT_init(TComCtrl *_ptComCtrl)
|
||
|
|
{
|
||
|
|
TUartUserData *ptUartUserData = (TUartUserData *)_ptComCtrl->m_pUserData;
|
||
|
|
#ifdef CONFIG_UART_IT_IDLEDMA
|
||
|
|
// 开启串口空闲中断 (IDLE Interrupt)
|
||
|
|
// 这是核心!DMA 负责搬运,IDLE 负责通知“一帧结束了”
|
||
|
|
__HAL_UART_ENABLE_IT(ptUartUserData->m_uart, UART_IT_IDLE);
|
||
|
|
|
||
|
|
// 启动 DMA 接收 (Circular 模式)
|
||
|
|
// 注意:这里不需要在中断里重启 DMA,因为 Circular 模式会自动循环
|
||
|
|
if (HAL_UART_Receive_DMA(ptUartUserData->m_uart, ptUartUserData->m_dma_rx_buf, ptUartUserData->m_buf_size) != HAL_OK)
|
||
|
|
{
|
||
|
|
Error_Handler();
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
HAL_UART_Receive_IT(ptUartUserData->m_uart, &ptUartUserData->m_temp, 1);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void UART_DMA_RX_IRQHandler(TComCtrl *_ptComCtrl)
|
||
|
|
{
|
||
|
|
#ifdef CONFIG_UART_IT_IDLEDMA
|
||
|
|
TUartUserData *ptUartUserData = (TUartUserData *)_ptComCtrl->m_pUserData;
|
||
|
|
// 1. 检查是否是空闲中断 (IDLE)
|
||
|
|
if (__HAL_UART_GET_FLAG(ptUartUserData->m_uart, UART_FLAG_IDLE) != RESET)
|
||
|
|
{
|
||
|
|
|
||
|
|
// 2. 清除空闲标志 (必须先读 SR 再读 DR,HAL 宏已封装好)
|
||
|
|
__HAL_UART_CLEAR_IDLEFLAG(ptUartUserData->m_uart);
|
||
|
|
|
||
|
|
// 3. 计算本次接收了多少数据
|
||
|
|
// 公式:总长度 - DMA 当前剩余未传输的数量
|
||
|
|
uint16_t current_pos = ptUartUserData->m_buf_size - __HAL_DMA_GET_COUNTER(ptUartUserData->m_hdma_rx);
|
||
|
|
|
||
|
|
uint16_t data_len = 0;
|
||
|
|
|
||
|
|
if (current_pos >= ptUartUserData->m_last_dma_pos)
|
||
|
|
{
|
||
|
|
data_len = current_pos - ptUartUserData->m_last_dma_pos;
|
||
|
|
if (data_len > 0)
|
||
|
|
{
|
||
|
|
rd_ComRecvProc(_ptComCtrl, (const char*)&ptUartUserData->m_dma_rx_buf[ptUartUserData->m_last_dma_pos], data_len);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// DMA 指针发生了回绕 (Wrap around)
|
||
|
|
// 分两段拷贝:[last_pos -> End] 和 [0 -> current_pos]
|
||
|
|
uint16_t part1 = ptUartUserData->m_buf_size - ptUartUserData->m_last_dma_pos;
|
||
|
|
uint16_t part2 = current_pos;
|
||
|
|
|
||
|
|
if (part1 > 0)
|
||
|
|
{
|
||
|
|
rd_ComRecvProc(_ptComCtrl, (const char*)&ptUartUserData->m_dma_rx_buf[ptUartUserData->m_last_dma_pos], part1);
|
||
|
|
}
|
||
|
|
if (part2 > 0)
|
||
|
|
{
|
||
|
|
rd_ComRecvProc(_ptComCtrl, (const char*)&ptUartUserData->m_dma_rx_buf[0], part2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ptUartUserData->m_last_dma_pos = current_pos; // 更新位置
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void UART_RX_IRQHandler(TComCtrl *_ptComCtrl)
|
||
|
|
{
|
||
|
|
#ifndef CONFIG_UART_IT_IDLEDMA
|
||
|
|
TUartUserData *ptUartUserData = (TUartUserData *)_ptComCtrl->m_pUserData;
|
||
|
|
rd_ComRecvProc(_ptComCtrl, (const char*)&ptUartUserData->m_temp, 1);
|
||
|
|
HAL_UART_Receive_IT(ptUartUserData->m_uart, &ptUartUserData->m_temp, 1);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|