0

I want to send messages via UART interface, I had the following program:

#ifndef F_CPU
#error "F_CPU has to be defined"
#endif

#ifndef CONSOLE_BAUD
#pragma message "CONSOLE_BAUD was not defined, using 9600"
#define CONSOLE_BAUD 9600
#endif
#define UBRR_VALUE F_CPU/16/CONSOLE_BAUD-1

// init
UBRRH = (unsigned char)(UBRR_VALUE >> 8);
UBRRL = (unsigned char)UBRR_VALUE;
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << USBS) | (3 << UCSZ0);

// send
while (!(UCSRA & (1 << UDRE)));
UDR = 'A';

This doesn't work. The HEX being sent is 00.

I changed that to the following:

#ifndef F_CPU
#error "F_CPU has to be defined"
#endif

#ifndef CONSOLE_BAUD
#pragma message "CONSOLE_BAUD was not defined, using 9600"
#define CONSOLE_BAUD 9600
#endif
#define UBRR_VALUE F_CPU/16/CONSOLE_BAUD-1

// init
unsigned int ubrr = UBRR_VALUE; // changed
UBRRH = (unsigned char)(ubrr >> 8); // changed
UBRRL = (unsigned char)ubrr; // changed
UCSRB = (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << USBS) | (3 << UCSZ0);

// send
while (!(UCSRA & (1 << UDRE)));
UDR = 'A';

And it started to work. Why is that? What's the difference between assigning the preprocessor directive directly to UBRRX and having an intermediary variable?

// EDIT The question was marked as a duplicate although I had no chance to find the linked duplicate, since I did not see the issue (lack of parentheses) in the first place. I think that marking my question as a duplicate is unfair.

mnj
  • 2,539
  • 3
  • 29
  • 58
  • 6
    This is why I always put parentheses around my value defines. – Michael Myers Dec 20 '22 at 16:53
  • 1
    @Gerhardh You can see `#define UBRR_VALUE F_CPU/16/CONSOLE_BAUD-1` in both code snippets above – Nathan Pierson Dec 20 '22 at 16:56
  • @MichaelMyers How does the original code work for you with 1 change: `#define (UBRR_VALUE F_CPU/16/CONSOLE_BAUD-1)`? `()` added. – chux - Reinstate Monica Dec 20 '22 at 16:56
  • mnj, Posting the definitions of `UBRR_VALUE F_CPU`, `CONSOLE_BAUD` would be useful. – chux - Reinstate Monica Dec 20 '22 at 17:01
  • With 16-bit `int/unsigned`, `UBRR_VALUE >> 8` may be a _signed_ shift vs. `ubrr >> 8`, an _unsigned_ shift. If `UBRR_VALUE < 0`, then different results. – chux - Reinstate Monica Dec 20 '22 at 17:03
  • Note that bit shifting is commonly specifically done on unsigned rather than signed values. Of concern is right shift of a negative value, as it is implementation defined whether an arithmetic or logical shift is done in that case. – Avi Berger Dec 20 '22 at 17:03
  • @Barmar, closure reason is premature. Yet only [crickets](https://www.youtube.com/watch?v=CpGtBnVZLSk) from OP. – chux - Reinstate Monica Dec 20 '22 at 17:06
  • How is my question a duplicate? If I knew that adding parentheses changes anything, I'd probably go in that direction. I did not know that. – mnj Dec 20 '22 at 17:18
  • Alright, after reading the question that mine is supposedly a duplicate of, I don't see any connection between them other than the fact that we're both using `#define`. Could someone explain what's the issue here? – mnj Dec 20 '22 at 17:21
  • FYI, in C++, the `operator<<` is overloaded for stream insertion. You may want to remove the C++ tag. – Thomas Matthews Dec 20 '22 at 18:23
  • @ThomasMatthews, I guess it's overloaded for Streams only, when my operands are numbers, the "normal" bit shift operation is executed. – mnj Dec 20 '22 at 18:47
  • Try to add `#define CONSOLE_BAUD 9600UL` -> `UL` and `#define UBRR_VALUE (F_CPU/(16UL * CONSOLE_BAUD) - 1UL)`. Shifting seems to be ok! – sunriax Dec 24 '22 at 11:43

0 Answers0