Tool/software:
Hello,
I’m trying to send data through SPI when the SD24B conversion is complete.
The device is running as a slave and is responsible for transmitting the data.
Any idea why the code isn’t working?
Could it be an interrupt issue?
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "msp430.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define Num_of_Results 260
/* Arrays to store SD24_B conversion results */
unsigned long Ch0results[Num_of_Results];
unsigned long Ch1results[Num_of_Results];
unsigned long Ch2results[Num_of_Results];
void initClockTo16MHz()
{
UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_0; // Set ACLK = XT1CLK
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation
UCSCTL2 = FLLD_0 + 487; // Set DCO Multiplier for 16MHz
// (N + 1) * FLLRef = Fdco
// (487 + 1) * 32768 = 16MHz
// Set FLL Div = fDCOCLK
__bic_SR_register(SCG0); // Enable the FLL control loop
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
// UG for optimization.
// 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
__delay_cycles(500000);//
UCSCTL6 &= ~(XT1OFF); // XT1 On
UCSCTL6 |= XCAP_3; // Internal load cap
// Loop until XT1 fault flag is cleared
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
UCSCTL6 &= ~(XT1DRIVE_3); // Xtal is now stable, reduce drive strength
}
uint16_t setVCoreUp(uint8_t level){
uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
//The code flow for increasing the Vcore has been altered to work around
//the erratum FLASH37.
//Please refer to the Errata sheet to know if a specific device is affected
//DO NOT ALTER THIS FUNCTION
//Open PMM registers for write access
PMMCTL0_H = 0xA5;
//Disable dedicated Interrupts
//Backup all registers
PMMRIE_backup = PMMRIE;
PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
SVSLPE | SVMHVLRIE | SVMHIE |
SVSMHDLYIE | SVMLVLRIE | SVMLIE |
SVSMLDLYIE
);
SVSMHCTL_backup = SVSMHCTL;
SVSMLCTL_backup = SVSMLCTL;
//Clear flags
PMMIFG = 0;
//Set SVM highside to new level and check if a VCore increase is possible
SVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);
//Wait until SVM highside is settled
while((PMMIFG & SVSMHDLYIFG) == 0)
{
;
}
//Clear flag
PMMIFG &= ~SVSMHDLYIFG;
//Check if a VCore increase is possible
if((PMMIFG & SVMHIFG) == SVMHIFG)
{
//-> Vcc is too low for a Vcore increase
//recover the previous settings
PMMIFG &= ~SVSMHDLYIFG;
SVSMHCTL = SVSMHCTL_backup;
//Wait until SVM highside is settled
while((PMMIFG & SVSMHDLYIFG) == 0)
{
;
}
//Clear all Flags
PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG |
SVSMLDLYIFG
);
//Restore PMM interrupt enable register
PMMRIE = PMMRIE_backup;
//Lock PMM registers for write access
PMMCTL0_H = 0x00;
//return: voltage not set
return false;
}
//Set also SVS highside to new level
//Vcc is high enough for a Vcore increase
SVSMHCTL |= (SVSHRVL0 * level);
//Wait until SVM highside is settled
while((PMMIFG & SVSMHDLYIFG) == 0)
{
;
}
//Clear flag
PMMIFG &= ~SVSMHDLYIFG;
//Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
//Set SVM, SVS low side to new level
SVSMLCTL = SVMLE | (SVSMLRRL0 * level) |
SVSLE | (SVSLRVL0 * level);
//Wait until SVM, SVS low side is settled
while((PMMIFG & SVSMLDLYIFG) == 0)
{
;
}
//Clear flag
PMMIFG &= ~SVSMLDLYIFG;
//SVS, SVM core and high side are now set to protect for the new core level
//Restore Low side settings
//Clear all other bits _except_ level settings
SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
SVSMLRRL1 + SVSMLRRL2
);
//Clear level settings in the backup register,keep all other bits
SVSMLCTL_backup &=
~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
//Restore low-side SVS monitor settings
SVSMLCTL |= SVSMLCTL_backup;
//Restore High side settings
//Clear all other bits except level settings
SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +
SVSMHRRL0 + SVSMHRRL1 +
SVSMHRRL2
);
//Clear level settings in the backup register,keep all other bits
SVSMHCTL_backup &=
~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
//Restore backup
SVSMHCTL |= SVSMHCTL_backup;
//Wait until high side, low side settled
while(((PMMIFG & SVSMLDLYIFG) == 0) &&
((PMMIFG & SVSMHDLYIFG) == 0))
{
;
}
//Clear all Flags
PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
);
//Restore PMM interrupt enable register
PMMRIE = PMMRIE_backup;
//Lock PMM registers for write access
PMMCTL0_H = 0x00;
return true;
}
bool increaseVCoreToLevel2()
{
uint8_t level = 2;
uint8_t actlevel;
bool status = true;
//Set Mask for Max. level
level &= PMMCOREV_3;
//Get actual VCore
actlevel = PMMCTL0 & PMMCOREV_3;
//step by step increase or decrease
while((level != actlevel) && (status == true))
{
if(level > actlevel)
{
status = setVCoreUp(++actlevel);
}
}
return (status);
}
void SPI_init(void)
{
// Setup P1.2 UCA0SOMI, P1.3 UCA0SIMO, P1.6 UCA0CLK
P1SEL |= BIT7;
P2SEL |= BIT0 | BIT1;
UCB0CTLW0 |= UCSWRST; // **Put state machine in reset**
UCB0CTLW0 |= UCSYNC | UCMSB ;
// 3-pin, 8-bit SPI slave,
// Clock polarity high, MSB
UCB0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
UCB0IE |= UCRXIE | UCTXIE; // Enable RX interrupt // Enable RX interrupt
}
void SD24_init(void)
{
SD24BCTL0 = SD24REFS | SD24SSEL_1 | SD24DIV4; // Select internal REF
// Select SMCLK as SD24_B clock source
SD24BCCTL0 = SD24ALGN | SD24SCS_4; // Left-aligned, group 0
SD24BCCTL1 = SD24ALGN | SD24SCS_4; // Left-aligned, group 0
SD24BCCTL2 = SD24ALGN | SD24SCS_4; // Left-aligned, group 0
SD24BINCTL0 = SD24GAIN_1;
SD24BINCTL1 = SD24GAIN_1;
SD24BINCTL2 = SD24GAIN_1;
SD24BIE = SD24IE2; // Enable channel 2 interrupt
__delay_cycles(0x3600); // Delay for 1.5V REF startup
//SD24BCTL1 |= SD24GRP0SC; // Set bit to start conversion
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
increaseVCoreToLevel2();
initClockTo16MHz();
SPI_init();
SD24_init();
_NOP();
_EINT();
while(1)
{
}
}
#pragma vector=SD24B_VECTOR
__interrupt void SD24BISR(void)
{
static unsigned int adc_index = 0;
switch (SD24BIV)
{
case SD24BIV_SD24OVIFG: // SD24MEM Overflow
break;
case SD24BIV_SD24TRGIFG: // SD24 Trigger IFG
break;
case SD24BIV_SD24IFG0: // SD24MEM0 IFG
break;
case SD24BIV_SD24IFG1: // SD24MEM1 IFG
break;
case SD24BIV_SD24IFG2: // SD24MEM2 IFG
Ch0results[adc_index] = SD24BMEMH0; // Save CH0 results (clears IFG)
Ch1results[adc_index] = SD24BMEMH1; // Save CH1 results (clears IFG)
Ch2results[adc_index] = SD24BMEMH2; // Save CH2 results (clears IFG)
adc_index++;
if (adc_index >= Num_of_Results)
{
adc_index = 0;
while (!(UCB0IFG & UCTXIFG)) ; // USCI_A0 TX buffer ready?
UCB0TXBUF = 'Y';
}
break;
}
}