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

Serial port 在不检查AVR ATMega32中的UDRE标志的情况下,是否可以在USART_RXC中断处理程序中写入UDR?,serial-port,microcontroller,avr,usart,atmega16,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 transmi

我一直在试图理解这段代码,它应该使用中断来回送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
}
为什么不在这里检查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

while((UCSRA&(1简短回答是-):您可以在任何时候编写UDR,无需事先检查

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

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

因此,如果您有办法确保发送器缓冲区不会溢出,则可以根本不检查该标志。由于接收字节需要与发送完全相同的时间,您可以确保RXC中断的发生频率不会超过发送字节的频率,因此,如果未在别处写入UDR,则可以假设,当RXC中断发生时,输出缓冲区始终可以接受至少一个字节

尽管如此,若UDR写入其他地方,当RXC中断发生时,输出缓冲区可能不会为空,所以传输的回波字节将丢失


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

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

#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
}
但是,如果输出缓冲区已满(未设置UCSRA中的UDRE标志),则变送器将忽略写入的数据,或者换句话说,写入的数据将丢失

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

因此,如果您有办法确保发送器缓冲区不会溢出,则可以根本不检查该标志。由于接收字节需要与发送完全相同的时间,您可以确保RXC中断的发生频率不会超过发送字节的频率,因此,如果未在别处写入UDR,则可以假设,当RXC中断发生时,输出缓冲区始终可以接受至少一个字节

尽管如此,若UDR写入其他地方,当RXC中断发生时,输出缓冲区可能不会为空,所以传输的回波字节将丢失


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

如果AVR是主/从协议中的从机,则可以不受影响。AVR从机处于接收模式(具有优先权)或传输模式,没有可能的重叠。由于USART的接收器和发射器将使用相同的波特率生成器/时钟,因此接收字符的时间与发送字符的时间相同。如果AVR是主/从协议中的从机,则可以不受影响。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
}