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