STM32串口桥

STM32 Uart Bridge

我在一个项目中工作,我需要在与 uart 之间架起一座桥梁。我使用的是 STM32F072CB 基本上,我接收到 uart1 rx 的所有数据都必须由 uart2 tx 发送。以同样的方式,我在 uart2 rx 中收到的内容必须通过 uart1 tx 发送。(两个 UART 具有相同的波特率)。我不知道我可以在 rx uarts 上接收多少数据。

这就是想法

Uart1 rx --------> Uart2 tx
Uart1 tx <-------- Uart2 rx

我将 DMA 与 HAL_UARTEx_ReceiveToIdle_DMA 结合使用以减少 cpu 处理。

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart2_rx;

#define RXBuffSize 10

uint8_t RxBuff1[RxBuffSize];
uint8_t RxBuff2[RxBuffSize];

int main(void)
{
HAL_Init();
SystemClock_Config();

MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();

HAL_UARTEx_ReceiveToIdle_DMA(&huart1,RxBuff1,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RxBuff2,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);

while (1)
 {}
}

下面是我的DMA中断回调函数

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == USART1)
    {   
    HAL_UART_Transmit(&huart2,RxBuff1,RxBuffSize,1);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart1,RxBuff1,RxBuffSize);
    __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
    } 
    else if (huart->Instance == USART2)
    {
    HAL_UART_Transmit(&huart1,RxBuff2,RxBuffSize,1);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RxBuff2,RxBuffSize);
    __HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
    }
}

代码在输入到 rx 的数据为低电平时运行。如果我在另一个 uart 的 tx 中发送太多数据,我会得到第一个字节,但会丢失最后一个字节。我也尝试做 RXBuffSize = 1 ,也就是说接收一个字符并发送它但我得到相同的结果。

因为HAL_UART_Transmit“轮询”方式运行,所以它会在该点停止,直到所有字符串都被传输。

因此,如果在HAL_UART_Transmit执行的过程中有另外的字符串进来,中断不执行,输入的字符串丢失。

激活cubemx中每个uart的TX DMA后,尝试应用如下所示的代码。

#include <string.h>

uint8_t TxBuff1[RxBuffSize];
uint8_t TxBuff2[RxBuffSize];

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    Size = Size > RxBuffSize ? RxBuffSize : Size;

    if (huart->Instance == USART1)
    {   
        memcpy(TxBuff2, RxBuff1, Size);
        HAL_UART_Transmit_DMA(&huart2, TxBuff2, Size);
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, RxBuff1, RxBuffSize);
        __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
    } 
    else if (huart->Instance == USART2)
    {
        memcpy(TxBuff1, RxBuff2, Size);
        HAL_UART_Transmit_DMA(&huart1, TxBuff1, Size);
        HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuff2, RxBuffSize);
        __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
    }
}

直接传输RxBuff是危险的。当发送时从UART接收到一个字符,TX DMA可能会发送一个不正确的值,因为RX DMA改变了相应内存中的值。

因此,当RX DMA停用时,最好将相应的内存值复制到另一个位置后再启用。