Можно ли записывать UDR в обработчике прерываний USART_RXC без проверки флага UDRE в AVR ATMega32? - PullRequest
0 голосов
/ 28 мая 2018

Я пытался понять этот код, который должен отображать каждый байт, полученный на интерфейсе USART AVR с использованием прерывания.

#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

Разве не должна быть проверка для флага UDRE перед строкой UDR = ReceivedByte; внутри строки ISR?Любое понимание будет высоко ценится.

1 Ответ

0 голосов
/ 28 мая 2018

Краткий ответ - да : вы можете записать UDR в любое время, без каких-либо проверок вперед.

Но, если выходной буфер заполнен (флаг UDRE в UCSRA установленне задан), тогда записанные данные будут игнорироваться передатчиком или, другими словами, они будут потеряны.

Модуль USART имеет двойной выходной буфер.Это означает, что можно записать туда два байта впереди: один передается прямо сейчас, а другой в буфере будет передан позже.Флаги UDRE показывают, когда байт буфера пуст, а флаг TXC показывает, когда байт передачи извлечен.

Итак, если у вас есть способ убедиться, что буфер передатчика не будет переполнен, то это возможночтобы проверить этот флаг на всех.Поскольку получение байта требует ровно столько же времени, сколько и передача, вы можете быть уверены, что прерывания RXC не будут происходить чаще, чем будут передаваться байты, поэтому, если UDR не записан в другом месте, можно предположить, что выходной буфервсегда может принять хотя бы один байт, когда происходит прерывание RXC.

Тем не менее, если UDR записывается где-то еще, возможно, что выходной буфер не будет пустым, когда происходит прерывание RXC, поэтому переданный эхо-байтбудет потеряно.

С другой стороны, хорошая практика программирования - как можно скорее оставлять обработчики прерываний.Вводить циклы ожидания в процедуру обработки прерывания - плохая идея.В этом случае, если вы не можете быть уверены, что выходной буфер будет пуст в событии RXC, лучше либо иметь какой-либо выходной буфер в ОЗУ, который будет обрабатываться в прерывании UDRE, либо выполнять эхо-сигнал вне прерывания RXC.

...