我一直试图理解这个代码,该代码应该使用中断回应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标志?
任何见解都将非常感激。
答案 0 :(得分:2)
简短回答是 - 是:您可以随时编写UDR,无需事先进行任何检查。
但是,如果输出缓冲区已满(UCSRA中的UDRE标志未设置),则发送器将忽略写入的数据,换句话说,它将丢失。
USART模块具有双输出缓冲区。这意味着可以在前面写入两个字节:一个正在立即传输,一个缓冲区将在稍后传输。 UDRE标志显示缓冲区字节为空时,TXC标志显示何时拉出传输字节。
因此,如果您有办法确保发送器缓冲区不会溢出,则可能根本不检查该标志。由于接收字节所需的时间与发送完全相同,因此可以确保RXC中断不会比发送字节更频繁地发生,因此,如果UDR未写入其他地方,则可以假设输出缓冲区当RXC中断发生时,总是可以接受至少一个字节。
但是,如果在其他地方写入UDR,则当RXC中断发生时,输出缓冲区可能不会为空,因此传输的echo字节将丢失。
另一方面,良好的编程习惯是尽快留下中断处理程序。在中断处理程序例程中放置等待循环是一个坏主意。在这种情况下,如果您无法确定RXC事件上的输出缓冲区是否为空,则最好在RAM中具有某种输出缓冲区,这将在UDRE中断中处理,或者在RXC中断之外执行回波。