Question

So I am reading up on programming an Atmel 328p and I want to be able to program serial input and output but I saw something I didn't completely get:

  • UBRR0H is called UBRRnH in this assembly code:

    USART_Init:
        ; Set baud rate
        out UBRRnH, r17
        out UBRRnL, r16
        ; Enable receiver and transmitter
        ldi r16, (1<<RXENn)|(1<<TXENn)
        out UCSRnB,r16
        ; Set frame format: 8data, 2stop bit
        ldi r16, (1<<USBSn)|(3<<UCSZn0)
        out UCSRnC,r16
        ret
    
  • While it stays as the name UBRR0H in this C code:

    #define FOSC 1843200 // Clock Speed
    #define BAUD 9600
    #define MYUBRR FOSC/16/BAUD-1
    void main( void ) {
        ...
        USART_Init(MYUBRR)
        ...
    }
    
    void USART_Init( unsigned int ubrr) {
        /*Set baud rate */
        UBRR0H = (unsigned char)(ubrr>>8);
        UBRR0L = (unsigned char)ubrr;
        Enable receiver and transmitter */
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);
        /* Set frame format: 8data, 2stop bit */
        UCSR0C = (1<<USBS0)|(3<<UCSZ00);
    }
    

This code does the completely same according to Atmel who makes the CPU, so why can it be called two different things?

Thanks :)

Était-ce utile?

La solution

According to Atmel documentation UBRRnL and UBRRnH are USART Baud Rate Registers.

The UBRRnH contains the four most significant bits, and the UBRRnL contains the eight least significant bits of the USART baud rate.

USART Baud Rate Registers

As I see if your device has multiple USARTs for example USART0 and USART1 you can choose the one you need by modifying UBRRnL and UBRRnH (and maybe other registers too). Change the n (in UBRRnL and UBRRnH) to the required USART id number and assign it to UBRRnL and UBRRnH.

For example in Assembly:

.equ USART = 1 
.if USART == 0 
    .equ UBRRnH = UBRR0H 
    .equ UBRRnL = UBRR0L 
 .else 
    .equ UBRRnH = UBRR1H 
    .equ UBRRnL = UBRR1L 
 .endif

So when Assembly code is generated from the C source, the compiler might compile the UBRR0Hs and UBRR0Ls to UBRRnL and UBRRnL and define them as UBRR0H and UBRR0L, as Robert Harvey stated.

Autres conseils

In Nut/OS, I see this #define:

#define     UBRRnH   UBRR0H

It's entirely possible that they are equivalent.

In the datasheet (using the The ATmega164P/324P/644P datasheet), Atmel explains the use of 'n' in the naming. It is because the MCU has 2 USARTs, USART0 and USART1 so it is upon you to replace 'n' with '0' or '1' depending on the USART you are using.
Use of #define can solve this,

#define UBRRnH UBRR0H
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top