Part Number:MSP432P401R
Tool/software: Code Composer Studio
Hi,
I am using MSP432 evaluation board. I have written a code to read ADC and SPI values. I want to record data with higher frequency (1kHz) but there is a limitation here and even I change
ACLK_FREQUENCY
still the data collection is not going to be 1KHz. Do you have any suggestions or any example code available for recording at high frequency?
/*
* This project is about reading two 14 bit data streams using
* the Synchronous Peripheral Interface (SPI), and from four ADC
* channels every 1 seconds.
*
* Comments assume the reader is familiar with Double_14_bit_spi_example
* and ADC14-TimerA-Sample-Clock.
*
* When the timer triggers an interrupt, the SPIs and ADC are read (from),
* and the LED is toggled. The timer should trigger every 1 seconds.
*/
#include "msp.h"
#include <driverlib.h>
#include <stdio.h>
#define ACLK_FREQUENCY 32768 /* Hertz */
/* The time between timer interrupts in seconds is equal to
*
* (TIMER_OVERFLOWS + TOGGLE_FREQUENCY / ACLK_FREQUENCY) * 2
*
* TIMER_OVERFLOWS must be a positive integer.
*/
#define TOGGLE_FREQUENCY ACLK_FREQUENCY
#define TIMER_OVERFLOWS 0
/* Define result variables big enough to contain 14 bit results. */
uint32_t adc0Result = 0;
uint32_t adc1Result = 0;
uint32_t adc2Result = 0;
uint32_t adc3Result = 0;
uint32_t adc4Result = 0;
uint32_t adc5Result = 0;
uint32_t spi0Result = 0;
uint32_t spi1Result = 0;
uint32_t spi2Result = 0;
uint8_t timerOverflows = 0;
uint8_t index;
/* Sets up the ADC. */
void setup_ADC(void)
{
/* Enable ADC interrupt in NVIC module. */
NVIC->ISER[0] = 1 << ((ADC14_IRQn) & 31);
// Sampling time, S&H=4, ADC14 on
//ADC14->CTL0 = ADC14_CTL0_SHT0_0 | ADC14_CTL0_SHP | ADC14_CTL0_ON;
ADC14->CTL0 = ADC14_CTL0_SHT0__192 | ADC14_CTL0_MSC | ADC14_CTL0_SHP | ADC14_CTL0_ON | ADC14_CTL0_CONSEQ_1;
/* This setting sets the input pin (P5.5 to 5.0). */
ADC14->MCTL[0] |= ADC14_MCTLN_INCH_0;
ADC14->MCTL[1] |= ADC14_MCTLN_INCH_1;
ADC14->MCTL[2] |= ADC14_MCTLN_INCH_2;
ADC14->MCTL[3] |= ADC14_MCTLN_INCH_3;
ADC14->MCTL[4] |= ADC14_MCTLN_INCH_4;
ADC14->MCTL[5] |= ADC14_MCTLN_INCH_5;
/* Mark the final input as the end of the reading sequence. */
ADC14->MCTL[5] |= ADC14_MCTLN_EOS;
/* Enable interrupt in ADC */
ADC14->IER0 |= ADC14_IER0_IE0;
}
/* Sets up the timer. */
void setup_timer(void)
{
/* Enable interrupt from the timer in NVIC module. */
NVIC->ISER[0] = 1 << ((TA0_0_IRQn) & 31);
/* Clear timer interrupt trigger (if any).
* Note: the CC stands for capture (or) control. */
TIMER_A0->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG;
/* Enable interrupt functionality. */
TIMER_A0->CCTL[0] = TIMER_A_CCTLN_CCIE;
/* Set the time at which the timer triggers an interrupt. */
TIMER_A0->CCR[0] = TOGGLE_FREQUENCY;
/* Watch the ACLK (Auxiliary clock). */
TIMER_A0->CTL |= TIMER_A_CTL_TASSEL_1;
/* Define mode of the timer. This is continuous mode, where the
* Timer counts up to 0xFFFFF, then sets itself to zero. */
TIMER_A0->CTL |= TIMER_A_CTL_MC_2;
}
/* Configures the SPIs for use with thermocouples, ready to read. */
void setup_SP_interfaces(void)
{
/* Define ports to use for SPI. In this example, for interface B0,
* P1.5 transmits the clock signal (UCB0CLK), P1.6 sends data to the
* datagenerator/thermocouple to tell the generator that we are ready
* to receive data, and P1.7 stores the data in the reading
* buffer for us.
*
* The equivalent ports for interface B1 are P6.3, P6.4, and P6.5.
*
* These ports are hard-coded, and can be found in the data sheet.
*/
P1->SEL0 |= BIT5 | BIT6 | BIT7;
P6->SEL0 |= BIT3 | BIT4 | BIT5;
P10->SEL0 |= BIT1 | BIT2 | BIT3;
/* Reset the EUSCIs (serial communications interfaces), and prevent
* them from operating while we configure them. */
EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SWRST;
EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_SWRST;
EUSCI_B3->CTLW0 |= EUSCI_B_CTLW0_SWRST;
/* The serial communication interfaces require a master and a slave.
* The master tells the slave when the master is ready to receive
* data from the slave. In addition, the master is in charge of
* keeping communication time correct by sending its clock ticks to
* the slave. This microcontroller is the master. */
EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_MST;
EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_MST;
EUSCI_B3->CTLW0 |= EUSCI_B_CTLW0_MST;
/* Use the auxilliary clock for determining ticks. This choice seems
* largely superficial. */
EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SSEL__ACLK;
EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_SSEL__ACLK;
EUSCI_B3->CTLW0 |= EUSCI_B_CTLW0_SSEL__ACLK;
/* No idea. */
EUSCI_B0->BRW = 0x01; // /2,fBitClock = fBRCLK/(UCBRx+1).
EUSCI_B1->BRW = 0x01;
EUSCI_B3->BRW = 0x01;
/* We will read the data in two 8-Bit blocks, so we must configure
* the interface to not operate in 7-Bit mode. */
// EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_7BIT;
/* Enable MSB-first, which controls the direction of the receive
* and transmit shift register. Not sure what this does. */
EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_MSB;
EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_MSB;
EUSCI_B3->CTLW0 |= EUSCI_B_CTLW0_MSB;
/* Also not sure what these instructions do. */
EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_SYNC | EUSCI_B_CTLW0_CKPL;
EUSCI_B1->CTLW0 |= EUSCI_B_CTLW0_SYNC | EUSCI_B_CTLW0_CKPL;
EUSCI_B3->CTLW0 |= EUSCI_B_CTLW0_SYNC | EUSCI_B_CTLW0_CKPL;
/* Register the interfaces with the interrupt handler. */
NVIC->ISER[0] = 1 << ((EUSCIB0_IRQn) & 31);
NVIC->ISER[0] = 1 << ((EUSCIB1_IRQn) & 31);
NVIC->ISER[0] = 1 << ((EUSCIB2_IRQn) & 31);
/* Now we switch on the interfaces; they will not yet transmit data,
* but it is ready to do so. */
EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;
EUSCI_B1->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;
EUSCI_B3->CTLW0 &= ~EUSCI_B_CTLW0_SWRST;
/* Allow the interfaces to raise interrupts once data has been
* received, but not transmitted. */
EUSCI_B0->IE |= EUSCI_B_IE_RXIE;
EUSCI_B0->IE &= ~EUSCI_B_IE_TXIE;
EUSCI_B1->IE |= EUSCI_B_IE_RXIE;
EUSCI_B1->IE &= ~EUSCI_B_IE_TXIE;
EUSCI_B3->IE |= EUSCI_B_IE_RXIE;
EUSCI_B3->IE &= ~EUSCI_B_IE_TXIE;
/* Clear the interrupt flag, if any. */
EUSCI_B0->IFG = 0;
EUSCI_B1->IFG = 0;
EUSCI_B3->IFG = 0;
}
void main(void)
{
/* Disable watchdog. */
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;
/* Enable interrupt handler. */
__enable_irq();
/* When an interrupt is triggered while sleeping, this bit makes
* the microcontroller wake up. */
SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
/* Setup other stuff. */
setup_ADC();
setup_SP_interfaces();
setup_timer();
/* Use the LED as an output, and turn it on. */
P1->DIR |= BIT0;
P1->OUT = BIT0;
/* Wait for the timer to interrupt. */
while(1);
}
/* This function is called when the data interface 0 interrupts. */
void EUSCIB0_IRQHandler(void){return;}
/* This function is called when the data interface 1 interrupts. */
void EUSCIB1_IRQHandler(void){return;}
/* This function is called when the ADC interrupts. */
void ADC14_IRQHandler(void){return;}
/* This function is run when timer A0 interrupts. */
void TA0_0_IRQHandler(void)
{
/* Clear timer interrupt bit. */
TIMER_A0->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG;
/* Leave if we haven't hit the required number of overflows. */
if(timerOverflows < TIMER_OVERFLOWS)
{
timerOverflows++;
return;
}
timerOverflows = 0;
/* Blink LED (if it's on, turn it off. If it's off, turn it on). */
// printf("Timer has interrupted.\n");
P1->OUT ^= BIT0;
/* Perform a SPI read operation. */
EUSCI_B0->TXBUF = 1;
EUSCI_B1->TXBUF = 1;
EUSCI_B3->TXBUF = 1;
for(index=0; index<4; index++)
{
/* Set the input bit low. This causes the thermocouples to begin
* reading (if this has executed for the first time), or to
* continue reading. */
EUSCI_B0->TXBUF = 0;
EUSCI_B1->TXBUF = 0;
EUSCI_B3->TXBUF = 0;
while(EUSCI_B0->IFG == 0);
spi0Result |= EUSCI_B0->RXBUF;
if(index <= 2){spi0Result <<= 8;}
while(EUSCI_B1->IFG == 0);
spi1Result |= EUSCI_B1->RXBUF;
if(index <= 2){spi1Result <<= 8;}
while(EUSCI_B3->IFG == 0);
spi2Result |= EUSCI_B3->RXBUF;
if(index <= 2){spi2Result <<= 8;}
/* Clear the interrupt flags. */
EUSCI_B0->IFG = 0;
EUSCI_B1->IFG = 0;
EUSCI_B3->IFG = 0;
}
/* Measure with, and read from ADC. */
ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;
while (!(ADC14->IFGR0 | BIT0));
while (!(ADC14->IFGR0 | BIT1));
while (!(ADC14->IFGR0 | BIT2));
while (!(ADC14->IFGR0 | BIT3));
while (!(ADC14->IFGR0 | BIT4));
while (!(ADC14->IFGR0 | BIT5));
adc0Result = ADC14->MEM[0];
adc1Result = ADC14->MEM[1];
adc2Result = ADC14->MEM[2];
adc3Result = ADC14->MEM[3];
adc4Result = ADC14->MEM[4];
adc5Result = ADC14->MEM[5];
/* Print measurements.*/
/*printf("SPI0 Result: %u\nSPI1 Result: %u\nADC Measurement: %u\n",
spi0Result, spi1Result, adc0Result);*/
printf("\n%u, %u, %u, %u, %u, %u, %u, %u, %u", spi0Result, spi1Result, spi2Result, adc0Result, adc1Result, adc2Result, adc3Result, adc4Result, adc5Result);
/* Shift result data back to its original position. */
spi0Result = 0;
spi1Result = 0;
spi2Result = 0;
spi0Result >>= 24;
spi1Result >>= 24;
spi2Result >>= 24;
/* Set the next interrupt time. */
TIMER_A0->CCR[0] += TOGGLE_FREQUENCY;
}
Thanks,
Bezak