0
\$\begingroup\$

Note: I am a beginner :) MCU: Atmega328p

I am struggling to understand how reading registers using while loops work in Embed C:

For example AVR-C USART Protocol:

while (!(UCSRnA & (1<<UDREn)))
;
/* Put data into buffer, sends the data */
UDRn = data;`

Equally:

while (( UCSR0A & (1<<UDRE0))  == 0){}
UDR0 = data;

    

In this case as when UDREO bit is equal to 1 the data should be loaded into the buffer and sent. The logic seems to say the opposite, it seems to say that when UDRO is full load the data which contradicts the datasheets explanation.

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$
while (( UCSR0A & (1<<UDRE0))  == 0) {} // NOTE THE CLOSED BRACKETS BREAK THE LOOP
UDR0 = data;

Equally:

while (!(UCSRnA & (1<<UDREn))) 
  ; // <---- NOTE THE SEMI-COLON BREAKS THE LOOP
UDR0 = data;` 
/* Put data into buffer, sends the data */
UDRn = data;

Clearer version of the code: The while loops runs with no code block in the body until the !(UCSRnA & (1<<UDREn) condition is violated which stops the looping and runs the next line UDRn = data.

while (!(UCSRnA & (1<<UDREn))) {
} 
UDRn = data;
\$\endgroup\$
5
  • 1
    \$\begingroup\$ You don't need a semicolon after the brackets... while (condition) {} is the same as while condition();, but while(condition){}; the semicolon is redundant since the brackets denote the end of the code block. In your first example, the ; does not break the code loop, the } of the bracket set does. \$\endgroup\$
    – Ron Beyer
    Jan 4, 2021 at 22:14
  • \$\begingroup\$ Your examples would be more clear if you fixed the indentation. \$\endgroup\$
    – The Photon
    Jan 4, 2021 at 22:59
  • 1
    \$\begingroup\$ UDRn = data; is not inside the while loop, so it should not be indented ... it should be at the same indent level as while (...... ... this applies to the second and third listing in your answer .... you had it indented correctly in your question, but you messed it up in your answer ... let me guess, you copied the code in your question from somewere \$\endgroup\$
    – jsotola
    Jan 5, 2021 at 1:17
  • \$\begingroup\$ Correct, when I've seen this code it usually appears indented on the datasheet and other places so I thought I would keep it the same, as part of the problem is that the indentation makes it look part of the while loop \$\endgroup\$ Jan 5, 2021 at 1:39
  • \$\begingroup\$ A while loop like that might not be a bad place to use "continue." \$\endgroup\$
    – user57037
    Jan 5, 2021 at 4:19
0
\$\begingroup\$

Both versions of the code do the same. There is an empty while loop waiting for the USART Data Register Empty bit of the USART Control and Status Register to become 1.

The while loop

For the compiler, it doesn't matter how you write an empty loop body.

while (/* any condition */)
    ;

and

while (/* any condition */) {}

are equivalent.

You can even write

while
    (
        /* any condition */
    )
{
}

or

while (/* any condition */);

or

while (/* any condition */) {
}

or

while(/*any condition*/);

or

while(/*any condition*/){}

C is a language that accepts line breaks as whitespace, just as blanks and tabs. Language elements as { or } don't even need whitespace around them.

Since an empty loop body "smells" for some people, you have several options.

while (/* any condition */) {
    // empty, nothing to do here
}

or (but I never saw this in professional production code)

while (/* any condition */) {
    continue;
}

The condition

Both conditions will be compiled to the same machine code, most probably. It depends on the specific compiler, but nowadays compilers are really smart.

(UCSR0A & (1 << UDRE0)) == 0 is in my eyes the better expression, because it shows the intention:

  1. Use the mask 1 << UDRE0 to obtain just the bit UDRE0.
  2. Obtain this bit from the register UCSR0A.
  3. Compare the result with 0. If the bit is 1, the result will be non-zero.

!(UCSR0A & (1 << UDRE0)) works because C interprets any non-zero value as true. The operator ! inverts the boolean value. The complete expression is true, if bit UDRE0 is 0.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.