[英]What does "transmit buffer" and "receive buffer" mean in the UART context?
我對什么是傳輸/接收緩沖區的理解主要與 ethe.net 系統有關,其中一些數據在傳輸整個數據之前存儲在緩沖區中。 這與 UART 是否相同,其中一些數據存儲在 UART 發送/接收緩沖區中,直到有 8 位(從而填滿 UART 容量)或當系統被命令從緩沖區發送數據時?
我問這個的原因是因為我正在查看一些涉及 UART 的 MSP430FR5994 MCU的 C 代碼,我想完全理解這些代碼。 如果需要更多信息來回答我的問題,請告訴我。
有問題的代碼,如果有人感興趣的話。 代碼運行良好,我只想知道緩沖區在 UART 中的作用。
#include <msp430.h>
char RXbuffer[32];
const unsigned char maxRXbytes = sizeof(RXbuffer);
unsigned char RXbytes = 0;
const char message[] = "ok\n";
const unsigned char messageLength = sizeof(message);
unsigned char TXbytes = 0;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop Watchdog
// Configure GPIO
P2SEL0 &= ~(BIT0 | BIT1);
P2SEL1 |= (BIT0 | BIT1); // USCI_A0 UART operation (p93_s)
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
// Startup clock system with max DCO setting ~8MHz
CSCTL0_H = CSKEY_H; // Unlock CS registers
CSCTL1 = DCOFSEL_3 | DCORSEL; // Set DCO to 8MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers
CSCTL0_H = 0; // Lock CS registers
// Configure USCI_A0 for UART mode
UCA0CTLW0 = UCSWRST; // Put eUSCI in reset (p788)
UCA0CTLW0 |= UCSSEL__SMCLK; // CLK = SMCLK
// Baud Rate calculation for 19200
// 8000000/(16*19200) = 26.042
// Fractional portion = 0.042
// User's Guide Table 21-4: UCBRSx = 0xD6
// UCBRFx = int ( (52.083-52)*16) = 1
UCA0BRW = 26; // 8000000/16/19200, p789
UCA0MCTLW |= UCOS16 | UCBRF_1 | 0xD600; // UCOS16 = Oversampling enable, used when high frequency clk is used, probably divides everything by 16, UCBRF = fine turner when UCOS16 is active
// 0xD600 is for first 8 bits,
UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(LPM3_bits | GIE); // Enter LPM3, interrupts enabled
__no_operation(); // For debugger
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=EUSCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(EUSCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG))
{
case USCI_NONE: break;
case USCI_UART_UCRXIFG:
if(RXbytes < maxRXbytes)
{
// Get the byte
RXbuffer[RXbytes] = UCA0RXBUF;
// Check for either ASCII carriage return '\r', or linefeed '\n' character.
// If true enable the TX interrupt to send response message
if((RXbuffer[RXbytes] == '\r') || (RXbuffer[RXbytes] == '\n'))
{
// Start message transmission
UCA0IE |= UCTXIE;
// Reset receive buffer index
RXbytes = 0;
}
else
RXbytes++;
}
break;
case USCI_UART_UCTXIFG:
// Transmit the byte
UCA0TXBUF = message[TXbytes++];
// If last byte sent, disable the interrupt
if(TXbytes == messageLength)
{
UCA0IE &= ~UCTXIE;
TXbytes = 0;
}
break;
case USCI_UART_UCSTTIFG: break;
case USCI_UART_UCTXCPTIFG: break;
default: break;
}
}
有軟件緩沖區和硬件緩沖區。
UART 硬件外設具有硬件緩沖區、接收數據等待程序處理的 rx 緩沖區和數據等待 MCU 傳輸的 tx 緩沖區(將設置 tx 完成標志)。 在某些 MCU 中,每個只有 1 個字節大。 其他人有更大的 rx 緩沖區遵循 FIFO 原則。
您的示例中的UCA0TXBUF
似乎是這個 tx 緩沖區/數據寄存器,顯然它只有 1 個字節大。 USCI_UART_UCTXIFG
似乎是傳輸完成時設置的標志,它設置為在完成時生成中斷。
示例中的RXbuffer
是 UART 驅動程序使用的軟件緩沖區。
與您的問題無關,這段代碼有幾個問題和潛在的錯誤等待爆發:
將char
用於原始數據總是不正確的,因為char
具有實現定義的符號,如果將原始數據存儲在 MSB 中,則可能會變成負數。 它不是可移植類型,除了文本字符串外,不應該用於任何其他用途。 請改用unsigned char
或uint8_t
。
您的代碼中沒有針對競爭條件的保護,因此如果主程序在 ISR 寫入RXbuffer
時訪問它,您將遇到各種奇怪的錯誤。
沒有針對不正確的編譯器優化的保護。 如果您的編譯器沒有意識到 ISR 永遠不會被軟件調用,而是由硬件調用,則優化器可能會破壞代碼。 為防止這種情況,所有共享變量都應聲明為volatile
的(如果您改用 DMA 緩沖區,情況也是如此)。
查看:
微控制器系統不會從 main() 返回,因此int main (void)
總是錯誤的。 您應該使用實現定義的形式void main (void)
(如果使用 gcc 編譯則使用-ffreestanding
)並使用for(;;) {}
循環結束main()
function。
您可能想要處理 UART 幀錯誤 = 數據損壞或波特率錯誤,以及 UART 溢出錯誤 = 硬件緩沖區在 MCU 清空之前被覆蓋。 這些通常也可以通過中斷標志獲得。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.