Periodic interrupts with Energia and the MSP432 Launchpad

Correction on 25th July 2016: Base clock for timer was wrong in original – now fixed.

In a previous post I showed how a periodic interrupt could be generated with the MSP430 Launchpad.  This post shows how it can be done using Energia and the MSP432 (ARM Cortex M4F) Launchpad.  The example uses Timer A3 to generate a periodic (1 kHz) interrupt.  There appears to be some interplay between this and the built-in delay routine however the delayMicroseconds function seems to work fine.  A global counter variable is updated at each interrupt so software can use this to perform additional time delays etc.

Some use is made of lower level library functions that are included with the Energia environment.  This example was compiled with Energia 0101E0017.

/* Periodic interrupt example for the MSP432 development board and the energia development environment */
/* The function OnTimer is called every millisecond and flashes the green LED every second
   The main loop flashes the blue LED every second
   Timer A3 is used to generate the interrupt
*/
 
#include <msp432.h>;
#include <driverlib/timer_a.h>
#include <driverlib/interrupt.h>
 
/*
General notes: serial comms uses eusci_a
PWM uses Timer A0 (at least I think so)
The built-in delay function appears not to work if it expires at the same time as a timer interrupt
The delayMicroseconds appears not to be so affected (so far)
*/
volatile uint32_t millisecondCounter=0;
int count = 0;
volatile int state = HIGH;
volatile int flag = HIGH;
 
void setup()
{
  Serial.begin(9600);
 
  pinMode(BLUE_LED,OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  setupTimer(1000); // set timer period to 1000 micro seconds
}
 
void OnTimer()
{
 
  static int Count = 0;
  static int state = 0;
  Count++;
  if (Count > 1000)
  {
    Count = 0;
    digitalWrite(GREEN_LED,state);
    if (state)
      state = 0;
    else
      state = 1;
  }
}
void loop()
{
 
  digitalWrite(BLUE_LED,HIGH);
  delayMicroseconds(500000);
  digitalWrite(BLUE_LED,LOW);
  delayMicroseconds(500000);
  Serial.println(millisecondCounter);
}
 
void setupTimer(unsigned Period)
{
 
  // Configuration word
  // Bits 15-10: Unused
  // Bits 9-8: Clock source select: set to SMCLK (12MHz)
  // Bits 7-6: Input divider: set to 4
  // Bits 5-4: Mode control: Count up to TACCRO and reset
  // Bit 3: Unused
  // Bits 2: TACLR : set to initially clear timer system
  // Bit 1: Enable interrupts from TA0
  // Bit 0: Interrupt (pending) flag : set to zero (initially)
  TA3CTL=0b0000001010010110;
  TA3CCR0=Period*3; // Set TACCR0 = Period (3MHz clock)
  TA3CCTL0=BIT4; // Enable interrupts when TAR = TACCR0
// The following places the address of our interrupt service routine in the RAM based interrupt vector table
// The vector number is 14 + 16  = 30 which is represented by the symbol INT_TA3_0
  Interrupt_registerInterrupt(INT_TA3_0,timerA3ISR); 
 
  // according to the datasheet Table 6-12 timer A3 is on ISR 14
  NVIC_ISER0 = (1<<14); // enable this interrupt in the NVIC
 
}
 
void timerA3ISR(void)
{
  TA3CTL &= ~1;         // Acknowledge the interrupt
  TA3CCTL0 &= ~1;       // Acknowledge the interrupt
  NVIC_ICPR0 = (1<<14); // clear interrupt pending flag in NVIC
  millisecondCounter++;
  OnTimer();
}

 

Adding a DAC to the MSP432 Launchpad

The MSP432 Launchpad features quite a powerful low energy processor (the MSP432P401R).  This should make it ideal for a little DSP but for one problem: there is no DAC.  I decided that I should remedy this by adding an SPI DAC in the form of a TLV5618A. This 12-bit IC has two DAC outputs and can be driven at a speed sufficient for some pretty decent audio.  Wiring is as shown below:

wiring

Code was developed in Energia – an experience that left me wondering about the completeness and documentation of the MSP432 port to this environment.

 

#include <SPI.h>
#include <msp432.h>
#define SS_PIN 17
void setup()
{
  // put your setup code here, to run once:
  pinMode(SS_PIN,OUTPUT);
  pinMode(15,OUTPUT); // MOSI
  pinMode(7,OUTPUT); // SCK
  SPI.setModule(EUSCI_B0_MODULE);
  SPI.setDataMode(SPI_MODE1);
  SPI.setBitOrder(MSBFIRST);   //
  SPI.setClockDivider(SPI_CLOCK_DIV2); // DIV2 = 8MHz, DIV4 = 4MHz, DIV8 = 2MHz etc. (from measurement)
}
void writeDACA(int Value)
{
  Value=Value & 0xfff;
  Value = Value | 0xc000; // Write DAC A
  digitalWrite(SS_PIN,LOW);
  SPI.transfer( (Value >> 8) & 0xff);
  SPI.transfer( Value  & 0xff);
  digitalWrite(SS_PIN,HIGH);
}
int i=0;
void loop()
{
  // put your main code here, to run repeatedly:
  while(1)
  {
    writeDACA(i);
    i++;
    if (i > 0xfff)
      i = 0;
  }

}

This produces the following output waveform:

waveform

This is a little noisy but more to the point : SLOW!  The pair of SPI writes are taking more than 70 microseconds which makes me wonder about the efficiency of the underlying libraries.  I hope to remedy this in a later post (Edit: you can read about this here: https://ioprog.com/2016/07/02/speedier-dacs-with-the-msp432-launchpad/)