Question

I am trying to do serial communication in ATMEGA32 and I have a question:

In asynchronous serial communication both UBRRH and UCSRC registers have same location. I don't know which conditions that location will act as UBRRH and for which conditions, it will act as UCSRC. I need different values for each register according to the work assigned to those registers

In the datasheet, they have mentioned the use of URSEL bit for selection betweem two registers but somehow I am not getting that.

Was it helpful?

Solution

The answer is: Yes, the URSEL bit. According to the datasheet:

When doing a write access of this I/O location, the high bit of the value written, the USART Register Select (URSEL) bit, controls which one of the two registers that will be written. If URSEL is zero during a write operation, the UBRRH value will be updated. If URSEL is one, the UCSRC setting will be updated.

This means, when you write to UCSRC, regardless of what value you want to put there, also set the URSEL bit (make sure that URSEL is 1):

UCSRC = (1<<URSEL)| ... whatever else ...

When you write to UBRRH, make sure that URSEL bit must is zero. Here are some different ways of doing that:

UBRRH = (0<<URSEL)| ... whatever else ...  // just showing that URSEL isn't set
UBRRH = ...some value...                   // simple not setting URSEL
UBRRH = (someValue)&(~(1<<URSEL)           // Ensuring that URSEL isn't set

URSEL bit is just a high bit. So whatever value you write to UCSRC, set (turn on, make 1) the high bit (bit 7). And when writing to UBRRH, make sure that bit 7 is cleared. Another way of thinking about it, every value you write to UBRRH must be under 128. And every value that you want to write to UCSRC, add 128 to it: this will turn on bit 7. This is just as a way of explanation, the code above is clearer.


How is this done? I don't know, I am not a uC designer. What seems likely is that the same IO location location is mapped to two different registers in the processor. Say you have a register named foo, and when you write a value to it the uC checks if the high bit is set. If it is it writes the value to internal memory location 1 and if it isn't it writes the value to internal memory location 2.


If you are using the URSEL bit correctly, then the values are being written correctly. Your testing not showing the correct values because you are not reading them propertly. Page 162 of the datasheet:

Doing a read access to the UBRRH or the UCSRC Register is a more complex operation. How- ever, in most applications, it is rarely necessary to read any of these registers.

The read access is controlled by a timed sequence. Reading the I/O location once returns the UBRRH Register contents. If the register location was read in previous system clock cycle, reading the register in the current clock cycle will return the UCSRC contents. Note that the timed sequence for reading the UCSRC is an atomic operation. Interrupts must therefore be controlled (for example by disabling interrupts globally) during the read operation.

So when your read UBRRH / UCSRC for the first time you get UBRRH. If you immediately read again you read UCSRC. But as the documentation suggests, there is no real reason to read these registers. It seems that you do not trust the datasheet, but this is a mistake: the datasheet is the best source of information about such matters: without datasheets we would be nowhere.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top