1

我想使用我的 Atxmega-µC 的 USART 功能。因此,我查看了 usart-example 的第一步。它旨在获取一个字符,然后将其发回。

while (true) {
        received_byte = usart_getchar(USART_SERIAL_EXAMPLE);
        if (received_byte == '\r') {
            for (i = 0; i < tx_length; i++) {
                usart_putchar(USART_SERIAL_EXAMPLE, tx_buf[i]);
            }
        } else
            usart_putchar(USART_SERIAL_EXAMPLE, received_byte);
    }

我想知道这是否是一个并行过程(显然不是),如果我想真正并行地发送和接收数据,我应该如何重构这段代码,而不是像上面的示例代码中按顺序显示的那样。
理论上(直到现在还没有测试)将它分成几个线程不会改善这种情况,因为 µC 只是“单核”。是否有另一种通过 USART 并行发送和接收数据的方法?

4

1 回答 1

1

你无法实现真正​​的并行性。我使用 Atmel UC3 进行了类似的设计,但我从随机的 XMega 数据表中提取以确认它们至少看起来相似,但没有详细说明。没有用于读取和写入的单独缓冲区。看寄存器说明:

USART 寄存器说明

数据寄存器为发送和接收共享。话虽如此,仍然可以使用中断和 FIFO 将全双工设计为“接近”并行。请参见下面的代码:

static void usart_int_handler(void)
{
    int result;
    while (PS_USART->csr & RX_READY)
    {
        result = fifo_push_byte(&PS_FIFO, PS_USART->rhr);
        if (result == FIFO_ERROR_OVERFLOW)
        {
            fifo_flush(&PS_FIFO);
            break;
        }
    }
    int parity_error = usart_parity_error(PS_USART);
    int framing_error = usart_framing_error(PS_USART);
    int overrun_error = usart_overrun_error(PS_USART);
    if ( parity_error || framing_error || overrun_error )
    {
        // Clear out FIFO and reset errors.
        // Then exit out and let calling object
        // timeout.
        while (PS_USART->csr & RX_READY)
        {
            result = PS_USART->rhr;
        }
        fifo_flush(&PS_FIFO);
        usart_reset_status(PS_USART);
        return;
    }
}

可以轮询 FIFO,或者您可以设置一个中断以表明它已达到数据阈值。我以这种方式处理传输:

void write_ps_serial (volatile avr32_usart_t *usart, const unsigned char *string, int size)
{
    // When using this - we needed a software workaround
    // to set and reset RTS pin.  Operation of RTS is not
    // correct.
    Disable_global_interrupt();
    gpio_set_pin_high(PS_RTS_PIN);
    for (int index = 0 ; index < size ; index++)
    {
        usart_putchar(usart, string[index]);
    }
    while ( (PS_USART->csr & TX_EMPTY) == 0 )
    {
        // Sit here waiting for the channel
        // status register to indicate TX_EMPTY
        // has gone high which means we can shut
        // off RTS.
    }
    gpio_clr_gpio_pin(PS_RTS_PIN);  
    Enable_global_interrupt();
}

我仍然认为硬件中有一些东西可以防止碰撞。即使我检查了错误,我也将模拟器打开了 3 天,同时不断地在总线上进行通信,并且从未收到过错误。但是您肯定需要对自己的协议进行编码以处理丢弃的数据包或使用更严格的 RS232 控制(此代码用于全双工 485)。如果你愿意,我有更多的代码。我希望这有帮助。

于 2015-04-19T23:49:41.033 回答