是否可以在不检查 AVR ATMega32 中的 UDRE 标志的情况下将 UDR 写入 USART_RXC 中断处理程序?

Can UDR be written inside USART_RXC interrupt handler without checking the UDRE flag in AVR ATMega32?

我一直在努力理解这段代码,它应该使用中断回显在 AVR 的 USART 接口上接收到的每个字节。

#include 
#include 

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

int main (void)
{
   UCSRB = (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
   UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

   UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
   UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register

   UCSRB |= (1 << RCXIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
   sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed

   for (;;) // Loop forever
   {
         // Do nothing - echoing is handled by the ISR instead of in the main loop
   }   
}

ISR(USART_RXC_vect)
{
   char ReceivedByte;
   ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
   UDR = ReceivedByte; // Echo back the received byte back to the computer
}

我无法理解这部分内容

ISR(USART_RXC_vect)
    {
       char ReceivedByte;
       ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
       UDR = ReceivedByte; // Echo back the received byte back to the computer
    }

为什么不在这里检查UDRE 标志以查看是否确实可以写入新数据,而不会覆盖以前的数据?由于我们在相应的轮询方法中做了同样的事情:

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer

不应该在 ISR 中的 UDR = ReceivedByte; 行之前检查 UDRE 标志吗? 任何见解将不胜感激。

简短的回答是 - :您可以随时编写 UDR,无需任何提前检查。

但是,如果输出缓冲区已满(未设置 UCSRA 中的 UDRE 标志),则写入的数据将被发送器忽略,换句话说,它将丢失。

USART 模块有一个双输出缓冲器。这意味着可以提前两个字节写入:一个正在传输,缓冲区中的一个稍后传输。当缓冲区字节为空时UDRE标志显示,而TXC标志在传输字节被拉出时显示。

因此,如果您有办法确保发送器缓冲区不会溢出,则可以根本不检查该标志。由于字节的接收需要与传输完全相同的时间,您可以确定 RXC 中断不会比字节传输更频繁地发生,因此,如果 UDR 没有写在其他地方,则可以假设输出缓冲区当 RXC 中断发生时,总是可以接受至少一个字节。

不过,如果UDR写在其他地方,输出缓冲区可能不会为空,当RXC中断发生时,传输的回显字节将丢失。

另一方面,良好的编程习惯是尽快离开中断处理程序。将等待循环放在中断处理程序中是个坏主意。在那种情况下,如果您不能确定输出缓冲区在 RXC 事件中是否为空,最好在 RAM 中有某种输出缓冲区,它将在 UDRE 中断中处理,或者在 RXC 中断之外执行回显。