Part Number: MSP432P401R
This is my first project with MSP432, and I'm using a custom board.
External 2-channel ADC is connected to eUSCI_B0, and also external 1-channel DAC connected to eUSCI_B1. I'm using external 32MHz HFXT for MCLK and SMCLK.
I should take ADC samples from both channels, do some processing and write the result to DAC. The code below is simplified version - just ADC read and write value of one channel to DAC(no processing still).
The sampling is controlled by timers, TIMER_A0 - interrupt in 32kHz - setting ConversionStart signal for ADC, and running TIMER_A1 to enter CCR0 isr in ~9us (max conversion time of the ADC).
The rest is just ADC result read (4 bytes via SPI) and DAC write (3 bytes via SPI).
This 2 actions last for 80us! I can not reach even sampling frequency speed, not to mention any processing.
I tried even just a bit set/reset in TIMER_A1 routine (no SPI at all) and that single instruction lasts for 4us!
I would appreciate any help.
Here is the code with SPI:
#include "msp.h" #include <driverlib.h> #include <stdio.h> #include <arm_math.h> #include "arm_const_structs.h" #define LFXT_FREQUENCY 32768 #define HFXT_FREQUENCY 32000000 #define SMCLK_FREQUENCY HFXT_FREQUENCY #define SPI_CLK_FREQUENCY SMCLK_FREQUENCY/2 const eUSCI_SPI_MasterConfig spiMasterConfig = { EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source SMCLK_FREQUENCY, // SMCLK = HFXT = 32MHz SPI_CLK_FREQUENCY, // SPICLK = SMCLK/2 = 16MHz EUSCI_B_SPI_MSB_FIRST, // MSB First EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT, EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // Low clock polarity EUSCI_B_SPI_3PIN // 3-wire SPI mode }; uint16_t X, Y; uint8_t ConvOver = 0; void InitADC (void); void ReadADCResults (void); void InitDAC (void); void uWriteDAC (uint16_t value); void TimerA0_IRQHandler(void); void TimerA1_IRQHandler(void); void main(void) { /* Halting WDT and disabling master interrupts */ MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); /* Set the core voltage level to VCORE1 */ MAP_PCM_setCoreVoltageLevel(PCM_VCORE1); MAP_FlashCtl_setWaitState(FLASH_BANK0, 2); MAP_FlashCtl_setWaitState(FLASH_BANK1, 2); /* Initializes Clock System */ MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN3 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION); MAP_CS_setExternalClockSourceFrequency(LFXT_FREQUENCY,HFXT_FREQUENCY); MAP_CS_startHFXT(false); MAP_CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_HSMCLK, CS_HFXTCLK_SELECT,CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT,CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); /* Initialize Peripherals */ InitADC(); InitDAC(); /* Initialize TimerA0 and map interrupt */ TIMER_A0->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG; TIMER_A0->CCTL[0] = TIMER_A_CCTLN_CCIE; // TACCR0 interrupt enabled TIMER_A0->CCR[0] = 1000 - 1; TIMER_A0->CTL = TIMER_A_CTL_SSEL__SMCLK | // SMCLK, UP mode TIMER_A_CTL_MC__UP; MAP_Interrupt_enableInterrupt(INT_TA0_0); /* Initialize TimerA1 and map interrupt */ TIMER_A1->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG; TIMER_A1->CCTL[0] = TIMER_A_CCTLN_CCIE; // TACCR1 interrupt enabled TIMER_A1->CCR[0] = 0; TIMER_A1->CTL = TIMER_A_CTL_SSEL__SMCLK | // SMCLK, UP mode TIMER_A_CTL_MC__UP; MAP_Interrupt_enableInterrupt(INT_TA1_0); /* General Interrupt Enable */ MAP_Interrupt_enableMaster(); while(1) { while(!ConvOver); ConvOver = 0; ReadADCResults(); // Will be written to X, Y
P2->OUT &= ~BIT1; // CONVST = 0
uWriteDAC(X); } } void InitADC (void) { // * Port init for ADC SPI communication // P1.5 - SCLK - SPI output GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1,GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION); // P1.7 - SDATA - SOMI - SPI input GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION); // P2.1 - CONVST - GPIO output GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1); GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1); // * Initialize USCI_B0 for SPI master operation SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig); SPI_enableModule(EUSCI_B0_BASE); SPI_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_SPI_RECEIVE_INTERRUPT); } void ReadADCResults (void) { X = 0; Y = 0; Interrupt_disableMaster(); SPI_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_SPI_RECEIVE_INTERRUPT); while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B0_BASE, 0xFF); while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); Y = SPI_receiveData(EUSCI_B0_BASE); Y = Y<<8; while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B0_BASE, 0xFF); while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); Y += SPI_receiveData(EUSCI_B0_BASE); while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B0_BASE, 0xFF); while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); X = SPI_receiveData(EUSCI_B0_BASE); X = X<<8; while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B0_BASE, 0xFF); while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); X += SPI_receiveData(EUSCI_B0_BASE); Interrupt_enableMaster(); } void InitDAC (void) { // * Port init for DAC SPI communication // P6.3 - SCLK - SPI output GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION); // P6.4 - DATA - SIMO - SPI output GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION); // P5.7 - SYNC - GPIO output GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN7); GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN7); // * Initialize USCI_B1 for SPI master operation SPI_initMaster(EUSCI_B1_BASE, &spiMasterConfig); SPI_enableModule(EUSCI_B1_BASE); SPI_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_SPI_RECEIVE_INTERRUPT); } void uWriteDAC (uint16_t value) { Interrupt_disableMaster(); GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN7); while (!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B1_BASE, (value>>10)&0x3F); while (!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B1_BASE, value>>2); while (!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG)); SPI_transmitData(EUSCI_B1_BASE, value<<6); while (!(EUSCI_B1->IFG & EUSCI_B_IFG_TXIFG)); GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN7); Interrupt_enableMaster(); } /* ISR for TimerA0 */ void TimerA0_IRQHandler(void) { TIMER_A0->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG; // Start conversion here P2->OUT |= BIT1; // CONVST = 1 TA1CCR0 = 280; // Set TimerA1 to max conversion time } /* ISR for TimerA1 */ void TimerA1_IRQHandler(void) { TIMER_A1->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG; ConvOver = 1; // Set Conversion Over Flag TA1CCR0 = 0; // Halt TimerA1 }