1

我正在从我的 PC 向我的 atmega16 串行发送 4 个字节的数据。我使用UART。一种技术是使用数据表中给出的函数,但它们在使用轮询时会阻止其余代码。所以我正在使用一个while循环。但是当while循环开始时我无法理解代码的结构..请帮助我。谢谢

#include <avr/io.h>
#define FOSC 1843200// Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

void UART_Init( unsigned int ubrr)
{
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

int main( void )
{   
int i = 0;
unsigned char my_data [4];

UART_Init ( MYUBRR );

while (1)
{   
    if (UCSRA & (1<<RXC)) 
    {
        my_data[i] = UDR;
    }
    i++;

    if (i == 3)
    {
        /*my next code here and once thats done, its again in uart receive mode*/
    i = 0;
    }
}
}
4

2 回答 2

2

我已经使用了 while 循环并在它们旁边放了评论,所以希望你能理解它:)

while (1)
{   
    if (UCSRA & (1<<RXC)) //If Usart control and status register A and Receive complete flag are true (Comparing the register with the value of RXC, which is a bit in the register)
    {
        my_data[i] = UDR; //Read Usart Data Register, which is 1 byte
        i++; //Like Joachim Pileborg said, this should be in the if statement
    }

    if (i == 3) //If received your 4 bytes.
    {
        /*my next code here and once thats done, its again in uart receive mode*/
        //Do something with the data
        i = 0;
    }
}

我希望现在很清楚!顺便说一句:你现在也在不断地轮询数据,所以这和我想的没有什么不同。

于 2012-05-24T07:45:59.920 回答
1

如果您不想使用阻塞轮询,则需要对传入数据进行中断驱动处理。基本上,你会用你的代码编写一个 RX-Complete-ISR:

    my_data[i] = UDR; //Read Usart Data Register, which is 1 byte
    i++; //Like Joachim Pileborg said, this should be in the if statement

(当然,您通常需要打开中断 ( sei();) 并且 USART 接收到完整的中断,然后才能接收任何数据。)

然后,在您的主循环中,您可以执行其他任务并通过

if (i == 3) //If received your 4 bytes.
{
    /*my next code here and once thats done, its again in uart receive mode*/
    //Do something with the data
    i = 0;
}

如果您的 ISR 已收到所有字节。

您可能需要注意一些同步问题,例如将 i 声明为volatile,但这是以最高效的方式完成的。

于 2012-05-24T09:29:25.823 回答