USART0 Communication Failure with Incorrect Baud Rate Configuration

The ATSAM3X8E microcontroller, part of the SAM3X series from Microchip (formerly Atmel), is a powerful ARM Cortex-M3-based device widely used in embedded systems. One of its key peripherals is the Universal Synchronous Asynchronous Receiver Transmitter (USART), which facilitates serial communication. In this case, the user attempted to initialize USART0 on the ATSAM3X8E microcontroller to enable serial communication via the TX and RX pins. However, the communication failed, and the serial monitor displayed incorrect data (0x00 in hex mode) despite the baud rate being set to 115200. The root cause of this issue lies in the incorrect calculation of the baud rate divisor value, which is critical for accurate serial communication.

The baud rate divisor, stored in the US_BRGR register, determines the frequency at which data is transmitted and received. The formula for calculating the baud rate divisor is:

[
\text{US_BRGR} = \frac{\text{MCK}}{\text{Baud Rate} \times 16}
]

Where:

  • MCK is the master clock frequency (84 MHz in this case).
  • Baud Rate is the desired communication speed (e.g., 115200).

The user initially calculated the divisor as follows:

[
\text{US_BRGR} = \frac{84,000,000}{115,200 \times 16} = 45.57
]

However, the US_BRGR register only accepts integer values, and the fractional part (0.57) was discarded, leading to an incorrect baud rate configuration. This resulted in a mismatch between the transmitter and receiver baud rates, causing communication failure.

Incorrect Baud Rate Divisor Calculation and Integer Truncation

The primary cause of the issue is the incorrect calculation of the baud rate divisor and the subsequent truncation of the fractional part. The US_BRGR register in the ATSAM3X8E microcontroller is a 16-bit register that only accepts integer values. When a floating-point value is assigned to this register, the fractional part is truncated, leading to an incorrect baud rate. For example, the calculated value of 45.57 was truncated to 45, which significantly deviates from the required value for a baud rate of 115200.

The correct baud rate divisor for 115200 baud with an 84 MHz master clock is:

[
\text{US_BRGR} = \frac{84,000,000}{115,200 \times 16} = 45.57
]

Since the fractional part cannot be used, the closest integer value (46) should be used instead. However, even this approximation introduces a small error in the baud rate, which can be calculated as follows:

[
\text{Actual Baud Rate} = \frac{\text{MCK}}{\text{US_BRGR} \times 16} = \frac{84,000,000}{46 \times 16} = 114,130.43
]

The percentage error in the baud rate is:

[
\text{Error Percentage} = \frac{115,200 – 114,130.43}{115,200} \times 100 = 0.93%
]

While this error is within the acceptable range for most applications, it highlights the importance of selecting an appropriate baud rate and master clock frequency to minimize errors.

Another potential cause of the issue is the incorrect configuration of the USART peripheral. The user’s code includes several steps to initialize the USART, such as enabling the clock, configuring the pins, and setting the mode and parity. However, any misconfiguration in these steps could also lead to communication failure. For example, if the clock source is not correctly set, the baud rate calculation will be incorrect. Similarly, if the pins are not properly configured for peripheral function, the USART will not be able to transmit or receive data.

Correcting Baud Rate Calculation and Verifying USART Configuration

To resolve the issue, the baud rate divisor must be calculated correctly, and the USART configuration must be verified. The following steps outline the troubleshooting process and the necessary fixes:

  1. Correct Baud Rate Calculation: The baud rate divisor should be calculated using integer arithmetic to avoid truncation errors. For example, to achieve a baud rate of 115200 with an 84 MHz master clock, the divisor should be calculated as follows:

[
\text{US_BRGR} = \frac{84,000,000}{115,200 \times 16} = 45.57 \approx 46
]

The code should be updated to use the correct integer value:

USART0->US_BRGR = 46; // Correct baud rate divisor for 115200 baud
  1. Selecting an Appropriate Baud Rate: To minimize baud rate errors, it is advisable to select a baud rate that results in an integer divisor. For example, a baud rate of 300 with an 84 MHz master clock results in an integer divisor:

[
\text{US_BRGR} = \frac{84,000,000}{300 \times 16} = 17,500
]

This ensures that the baud rate is exact, with no error. The updated code for a baud rate of 300 is:

USART0->US_BRGR = 17500; // Correct baud rate divisor for 300 baud
  1. Verifying USART Configuration: The USART configuration should be carefully reviewed to ensure that all settings are correct. This includes:
    • Enabling the clock for the USART peripheral.
    • Configuring the TX and RX pins for peripheral function.
    • Setting the correct mode, parity, and data length.
    • Enabling the transmitter and receiver.

The following code snippet demonstrates the correct initialization of USART0:

#include "asf.h"

Byte GetChar();
void PutChar(const uint8_t c);

int main() {
    SystemInit();
    WDT->WDT_MR |= WDT_MR_WDDIS; // Disable watchdog timer

    // Enable clock for USART0
    PMC->PMC_PCER0 = 1 << ID_USART0;

    // Disable Rx and Tx PIO lines
    PIOA->PIO_PDR |= PIO_PA10A_RXD0;
    PIOA->PIO_PDR |= PIO_PA11A_TXD0;

    // Set pins to use peripheral A
    PIOA->PIO_ABSR &= ~PIO_PA10A_RXD0;
    PIOA->PIO_ABSR &= ~PIO_PA11A_TXD0;

    // Enable pull-up on Rx and Tx pins
    PIOA->PIO_PUER |= PIO_PA10A_RXD0;
    PIOA->PIO_PUER |= PIO_PA11A_TXD0;

    // Disable PDC requests
    USART0->US_PTCR = US_PTCR_RXTDIS | US_PTCR_TXTDIS;

    // Reset receiver, transmitter, and status register
    USART0->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RSTSTA;

    // Disable all interrupts
    USART0->US_IDR = 0xFFFFFFFF;

    // Configure USART mode: normal, no parity, 8-bit data, internal clock
    USART0->US_MR = US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK |
                    US_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_PAR_NO;

    // Set baud rate to 115200
    USART0->US_BRGR = 46;

    // Enable receiver and transmitter
    USART0->US_CR = US_CR_RXEN | US_CR_TXEN;

    while (1) {
        PutChar('N'); // Transmit character 'N'
    }
}

Byte GetChar() {
    // Wait until receiver is ready
    while ((USART0->US_CSR & US_CSR_RXRDY) == 0);
    return USART0->US_RHR;
}

void PutChar(const uint8_t c) {
    // Wait until transmitter is ready
    while (!(USART0->US_CSR & US_CSR_TXRDY));
    // Send the character
    USART0->US_THR = c;
}
  1. Testing and Validation: After implementing the fixes, the system should be tested to verify that the USART communication is functioning correctly. This can be done by connecting the microcontroller to a serial terminal and checking that the transmitted data matches the expected output. If the issue persists, additional debugging steps, such as checking the clock configuration and signal integrity, may be necessary.

By following these steps, the issue with USART0 initialization on the ATSAM3X8E microcontroller can be resolved, ensuring reliable serial communication. Proper calculation of the baud rate divisor and careful configuration of the USART peripheral are critical to achieving accurate and stable communication.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *