Electronic – while ( !(UCSRA & (1<

avruart

I have question about code below :

    unsigned char USART_Recieve(void)
    {
        /* Wait for data to be received*/
        while ( !(UCSRA &  (1<<RXC)));
        /* Get and return received data from buffer*/
        return UDR;
    }

Why do we just don't write

    while (RXC == 0); 

when we want to wait until receiving data is done ? and what's the difference?
and how the first while waits until receiving is done?

I have searched for the same question but i couldn't find any, So please tell me the link.

Thanks.

Best Answer

Why do we just don't write while (RXC == 0);

Because "RXC" is a constant 7. Which is the number of the RXC bit in UCSRA register. So, while() will exit immediately, because it is expanded into while (7 == 0);

Note, that I've given you an example for ATmega32. For different controller "RCX" macro can have different value.

And just in case you are wondering, "UCSRA" and "UDR" in your code are also two macro definitions referencing another macro, _SFR_IO8.

UPDATE

For example, the macros:

#define RXC     7
#define UCSRA   _SFR_IO8(0x0B)

transform the code while (!(UCSRA & (1<<RXC))); into

while (!(_SFR_IO8(0x0B) & 0x80));

Then the macro

#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

transforms the code further into

while (!(_MMIO_BYTE((0x0B) + __SFR_OFFSET) & 0x80));

Since _MMIO_BYTE and __SFR_OFFSET are also macros, the process continues until all macro directives processed. In the end you get yourself a code that reads UCSRA register and applies mask for bit #7 in it.

The whole reason for all this is to make code more portable. For example by changing 0x0B in the UCSRA macro we can access UCSRA registers in different controllers without changing register address in our code.