UART至UART桥接STM32

时间:2019-06-20 21:20:37

标签: c microcontroller stm32 uart stm32f1

有没有一种简单的方法可以通过软件“桥接”两条U(S)ART线(STM32F107上为USART1和UART5)?

我需要将USART1传入的数据转发到UART5并反转。

当前的MCU是STM32F107VCT7

我要这样做的主要原因是通过连接到我的MCU的UART更新设备。 MCU连接到PC。

PC --- STM32 ---其他设备

4 个答案:

答案 0 :(得分:1)

您能将数据写到适当的usart寄存器中吗?也就是说,如果在usart1线上有一个字节通过并将其存储在usart1数据寄存器中,请对其进行读取并将其写入usart5数据寄存器,然后将该位置1以使芯片知道它已准备好传输该字节。对usart5到usart1的桥进行相同的操作。

如果您担心读/写多个字节,请考虑添加发送和接收缓冲区以处理此问题。

如果我们要使用一种轮询方法,则代码应类似于(注意:我主要处理AVR,因此我可能不使用寄存器名,但该方法应遵循以下原则):



// Check to see if data has been written to usart1 and transfer it usart5.
if(USART1_CR1&(1 << USART1_SR_RXNE))
{
    // May want to avoid race conditions, so disable interrupts.
    // Write the data in usart1 to usart5
    USART5_DR = USART1_DR;

    // Set the data ready bit on the usart5 control register.
    USART5_CR1 |= (1 << USART_SR_RXNE);
    // Enable interrupts.
}

我将this tutorial用于STM32语言。禁用中断不是重点。您可能还想写入缓冲区。

答案 1 :(得分:0)

仅将字节从一个UART复制到另一个UART是不会的。

如果发送方(PC串行适配器)仅比MCU快0.1%,它将在第1000个字节之后开始丢弃字节。数据表中的室温下,STM32F107内部时钟的频率精度为-1.1%至+ 1.8%,因此它可能更早发生,另外两个参与者也可能不是十分准确。

将固件更新中间的字节删除到否则无法访问的部分不会很有趣。

您都需要循环(FIFO)缓冲区

缓冲区的大小由数据包的大小以及参与设备中频率误差的总和决定。例如。如果一个块中有64 kB数据,并且两个设备的频率精度均为+/- 2%,则您至少需要65536 * 0.04〜2622字节的缓冲区。

无休止地执行此操作

  • 检查RXNE中的USART1->SR
  • 如果已设置,请从USART1->DR中读取数据并将其放在缓冲区的开头(如果缓冲区已满,请大声抱怨)
  • 在UART5-> SR中检查TXE
  • 如果已设置,并且缓冲区不为空,则将缓冲区尾部的字节写入UART5->DR
  • 对另一个方向做同样的事情

答案 2 :(得分:0)

简单的双向通信方法,假设两个UART的速度相同。

volatile uint8_t data[2];

void USART1_IRQHandler(void)
{
    if(USART1 -> SR & USART_SR_RXNE)
    {
        data[0] = USART1 -> DR;
        USART5 -> CR1 |= USART_CR1_TXEIE;
    }

    if( (USART1 -> CR1 & USART_CR_TXEIE) && (USART1 -> SR & USART_SR_TXE))
    {
        USART1 -> CR1 &= ~USART_CR1_TXEIE;
        USART1 -> DR = data[1];
    }
}

void USART5_IRQHandler(void)
{
    if(USART5 -> SR & USART_SR_RXNE)
    {
        data[1] = USART5 -> DR;
        USART1 -> CR1 |= USART_CR1_TXEIE;
    }

    if( (USART5 -> CR1 & USART_CR_TXEIE) && (USART5 -> SR & USART_SR_TXE))
    {
        USART5 -> CR1 &= ~USART_CR1_TXEIE;
        USART5 -> DR = data[0];
    }
}

答案 3 :(得分:0)

我从上面尝试了一下答案,但做了一些小改动:

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  if(USART1 -> SR & USART_SR_RXNE)
     {
         data[0] = USART1 -> DR;
         UART5 -> CR1 |= USART_CR1_TXEIE;
     }

     if( (USART1 -> CR1 & USART_CR1_TXEIE) && (USART1 -> SR & USART_SR_TXE))
     {
         USART1 -> CR1 &= ~USART_CR1_TXEIE;
         USART1 -> DR = data[1];
     }
  /* USER CODE END USART1_IRQn 1 */
}




/**
  * @brief This function handles UART5 global interrupt.
  */
void UART5_IRQHandler(void)
{
  /* USER CODE BEGIN UART5_IRQn 0 */

  /* USER CODE END UART5_IRQn 0 */
  HAL_UART_IRQHandler(&huart5);
  /* USER CODE BEGIN UART5_IRQn 1 */

  if(UART5 -> SR & USART_SR_RXNE)
     {
         data[1] = UART5 -> DR;
         USART1 -> CR1 |= USART_CR1_TXEIE;
     }

     if( (UART5 -> CR1 & USART_CR1_TXEIE) && (UART5 -> SR & USART_SR_TXE))
     {
         UART5 -> CR1 &= ~USART_CR1_TXEIE;
         UART5 -> DR = data[0];
     }

  /* USER CODE END UART5_IRQn 1 */
}

但是两条UART线之间没有通信。