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.
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.