DesignSpark Electrical Logolinkedin
  • Brought to you by
  • RS Components
  • Allied Electronics

March 13, 2017 10:49

Follow

Talk UART to any Microcontroller with C++ and IOT2020

In this blog I'll make the IOT2020 talk to the ARM microcontroller on a Texas Instruments CC1310 LaunchPad. It's part of a design I'm building where the IOT2020 talks to the Sigfox network. I've chosen UART because (excuse) i²c and SPI are intended as on-pcb communication mechanisms and (real reason) I couldn't get i²c slave mode working on the controller I was talking to.

I'll first handle the IOT2020 part, hard- and software.

IOT2020 Hardware

All signals are available from the Arduino headers. We need the serial transmit and receive lines and ground.

 

 The UART lines are on X11 and we'll tap GND from X13.

 

 

 

 

 

 

 

 

 

 

 

 

These signals will go to the microcontroller we talk to. The Tx from the IOT2020 will go to the Rx input at the other end. And the microntroller's Tx output will connect to the IOT2020's  Rx signal. Attention if you're using an Arduino or other device with 5V logic levels: you'll need a level shifters. For 3V3 devices a pair of plain wires will do.

IOT2020 Software

It's derived from the github example for C++ UART. UART0 on the IOT2020 is linked to the two pins I'm using, so I open that, set it's speed and push data to it:

#include  
using namespace std;
#include "mraa.hpp"


using namespace mraa;


int main(void) {
  mraa::Uart *uart;

  uart = new mraa::Uart(0);
  uart->setBaudRate(9600);
  uart->writeStr("Hello, world!\n");

  return 0;

 

I have success when the message "Hello, world'\n" arrives intact at the other side. Let's have a look at that.

CC1310 LaunchPad Hardware

The device I talk to also has a UART peripheral - most of the controllers have at least one serial communication channel. It's 3V3, so I don't have to worry about signal level compatibility.

 

There's one watchout though. The CC1310s only UART is routed to the USB port of the LaunchPad. The USB port is the connection for the debugger -  and also acts as a COM port. I can leave the debugger part intact but will disable the serial communication over the USB. This is easy. Just remove the 2 jumpers between the debug part and the radio part of the LaunchPad that are labeled RXD and TXD. This will leave the two signals coupled only to the TXD and RXD pin on the BoosterPack connector.

CC1310 LaunchPad Software

I'm running RTOS on the CC1310. All UART handling is done in a single task. This task isn't scheduled at regular times, but triggered by an interrupt when a character from the IOT2020 appears on the Rx line of the CC1310.

First I declare a semaphore that will wait for interrupts on the UART port, and the interrupt handler that will release the lock of that semaphore when traffic arrives (read a whole RTOS book if you don't understand this mechanism :-) ).

Semaphore_Handle SEM_uart_rx; // this binary semaphore handles uart receiving interrupts

void UART00_IRQHandler(UART_Handle handle, void *buffer, size_t num)
{
  Semaphore_post(SEM_uart_rx);
}

 

The initialisation and handling of the received data is done in an RTOS task:

/*
* ======== fnTaskUART ========
* Task for this function is created statically. See the project's .cfg file.
*/
Void fnTaskUART(UArg arg0, UArg arg1)
{
  char input;
  Error_Block eb;
  Semaphore_Params sem_params;

  UART_Params uartParams;
  UART_Handle uart;

  UART_init();

  UART_Params_init(&uartParams);
  uartParams.writeDataMode = UART_DATA_BINARY;
  uartParams.readDataMode = UART_DATA_BINARY;
  uartParams.readReturnMode = UART_RETURN_FULL;
  uartParams.readEcho = UART_ECHO_OFF;
  uartParams.baudRate = 9600;
  uartParams.readMode = UART_MODE_CALLBACK; // the uart uses a read interrupt
  uartParams.readCallback = &UART00_IRQHandler; // function called when the uart 
  // interrupt fires

  uart = UART_open(Board_UART0, &uartParams);
  if (uart == NULL) {
    while (1);
  }

  Semaphore_Params_init(&sem_params);
  sem_params.mode = Semaphore_Mode_BINARY;

  SEM_uart_rx = Semaphore_create(0, &sem_params, &eb);

  while (1) {
    UART_read(uart, &input, 1);
    Semaphore_pend(SEM_uart_rx, BIOS_WAIT_FOREVER); 
    // TODO:
  }
}

 

 

Connecting the Two Systems

Easy again. Tx to Rx, Rx to Tx. Gnd to Gnd.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I've used a protocol analyser and the debuggers of both IOT2020 and CC1310 to validate the traffic.

 

 

 

 

You can reuse this mechanism for many scenarios. Enjoy!

industrial automotive medical electronics

March 13, 2017 10:49

Follow

Comments

0 Votes
peteroakes

March 16, 2017 10:03

Very good post, I like it, and will be keeping a link for reference.