可以在USART_RXC中断处理程序中写入UDR而不检查AVR ATMega32中的UDRE标志吗?

时间:2018-05-27 22:39:26

标签: serial-port microcontroller avr usart atmega16

我一直试图理解这个代码,该代码应该使用中断回应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

UDR = ReceivedByte;内的ISR行之前是否应该检查UDRE标志? 任何见解都将非常感激。

1 个答案:

答案 0 :(得分:2)

简短回答是 - :您可以随时编写UDR,无需事先进行任何检查。

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

USART模块具有双输出缓冲区。这意味着可以在前面写入两个字节:一个正在立即传输,一个缓冲区将在稍后传输。 UDRE标志显示缓冲区字节为空时,TXC标志显示何时拉出传输字节。

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

但是,如果在其他地方写入UDR,则当RXC中断发生时,输出缓冲区可能不会为空,因此传输的echo字节将丢失。

另一方面,良好的编程习惯是尽快留下中断处理程序。在中断处理程序例程中放置等待循环是一个坏主意。在这种情况下,如果您无法确定RXC事件上的输出缓冲区是否为空,则最好在RAM中具有某种输出缓冲区,这将在UDRE中断中处理,或者在RXC中断之外执行回波。