1

Atxmega-µC の USART 機能を使用したいと考えています。したがって、最初のステップとして usart-example を調べました。char を取得し、その後それを送り返すように設計されています。

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 に答える