Friday, September 28, 2018

Arduino Due - UART

Introduction

One of the most important functions in embedded electronics is the abitlity to communicate with other processors or integrated circuits and one of the primary ways that the Arduino Due can accomplish this is with the UART/USART Controllers. For those not familiar with this method of communications I recommend the Serial Communication[4] article at Sparkfun.com.

My definition of Serial Communication via UART/USART in a nut shell; I think of UART communications as being basically SPI where both parties agree on a clock rate, so the clock line is not necessary and two devices are connected together directly so you don't need a chip select line. Both protocols use a shift register to perform the actual transfer of data but the UART/USART has some additional lines that SPI doesn't.

Electrical Warning

The Arduino Due is powered by 3.3V and it's I/O lines ARE NOT 5V tolerant. Each pin can source a current of 3 mA or 15 mA, depending on the pin, or sink a current of 6 mA or 9 mA, depending on the pin with a total of 130mA DC Output Current on all I/O lines.

I'm not going to go into a lot of the definition or mechanics of the UART Controller and how it works because of it's simplicity but instead provide an example download and a bit of code here in the article to explain the basic functionality of the Controller.

We start as always with the initialization of the PIO Controller and in this example there are two lines that need to be configured; the receive and transmit lines. Both use the Peripheral A functionality and both use pull ups.


void InitPIO()
{	
	//Enable clock for the UART
	PMC->PMC_PCER0 = 1 << ID_UART;
	
	// Disable RX and TX PIO lines
	PIOA->PIO_PDR |= PIO_PA8A_URXD;
	PIOA->PIO_PDR |= PIO_PA9A_UTXD;
	//Set pins to use peripheral A
	PIOA->PIO_ABSR &= ~PIO_PA8A_URXD;
	PIOA->PIO_ABSR &= ~PIO_PA9A_UTXD;
	// Enable the pull up on the Rx and Tx pins
	PIOA->PIO_PUER |= PIO_PA8A_URXD;
	PIOA->PIO_PUER |= PIO_PA9A_UTXD;
}

    

Configuring the UART is pretty simple we just need to set it to use no parity, not sure why this is not the default then set the compare value in the Baud Rate Generator Register for the baud rate we desire using the formula; MCK / (CD ^ 16) therefore to set the baud rate to 115200 we calculate 84000000 / (45 * 16) = 116666.67 which gives us an error rate of +/- 1.25%.


void InitUART(void)
{
	// Reset receiver & transmitter, on reset both are disabled
	UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX;
	// Set the baud rate to 115200
	UART->UART_BRGR = 45;
	// No Parity
	UART->UART_MR = UART_MR_PAR_NO;
	//Configure receive interrupt
	UART->UART_IER = UART_IER_RXRDY;
	NVIC_EnableIRQ((IRQn_Type) ID_UART);
	// Enable receiver and transmitter
	UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
}

    

This method is being called from an interrupt handler so we already know that there is data there but just for safty we check to be sure the character is ready to be read and then we retreive the value from the Receiver Holding Register.


byte GetChar()
{
	//Wait until receiver ready
	while(!(UART->UART_SR & UART_SR_RXRDY)){}
	
	return UART->UART_RHR;
}

    

When transmitting a character we, in a manner similar to the Receive first check that the transmitter buffer is empty and ready to accept our character.


void PutChar(const uint8_t c)
{
	// Check if the transmitter is ready
	while(!(UART->UART_SR & UART_SR_TXRDY)){}
	// Send the character
	UART->UART_THR = c;
}

    

Summary

This module turned out to be a lot easier than I had anticipated, for one thing using the code from CODETRON I was able to cut and paste and it worked the first time. I just modified it to do what I wanted, but it was a very simple process.

References

[1]MicroChip.com, SAM3X/SAM3A Series Complete, data sheet, http://www.atmel.com/devices/sam3x8e.aspx
[2]Gaynomad, Due pinout diagram, http://forum.arduino.cc/index.php/topic,132130.0.html
[3]Arduino Due, schematics, eagle files, and more, https://www.sparkfun.com/products/11589
[4]Sparkfun.com, Serial Communication https://learn.sparkfun.com/tutorials/serial-communication/all
Top ^