This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432P401R: SPI communication :

Part Number: MSP432P401R

Hi,

 As , I am working on SPI cimmunication between msp432p401r and dac161s055.I have two issues now and need your advice.

1) I used SPI master increment example from driver library to do communication between msp432 and dac161s055 and it worked very well in start. But, now SDO port is not responpding anymore and there is no signal on it and it is P 1.7 (SDO or SOMI). I have changed nothing in my code. What can be the possibility for this problem??

2) In dac161s055, there is 24 bit (3 byte) data co,,unication and for asserting communication , SCLK should turn on for 24 clock cycles but in my case (using already mentioned example) I am getting just 8 clock pulses and which is not sufficient for my requirement. Please tell me how can I increase the clock cycles of SCLK ??

Code is attached for below:

const eUSCI_SPI_MasterConfig spiMasterConfig =
{
        EUSCI_B_SPI_CLOCKSOURCE_SMCLK,             // SMCLK Clock Source
        24000000,                                   // SMCLK = 24MHZ
        1000000,                                    // SPICLK = 1 MHz
        EUSCI_B_SPI_MSB_FIRST,                     // MSB First
        EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,    // Phase
        EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // High polarity
        EUSCI_B_SPI_3PIN
};
/* Statics */
static volatile uint_fast16_t resultsBuffer[UINT8_MAX];
static volatile uint8_t resPos;
static volatile uint8_t RXData = 0;
static uint32_t TXData=0;

  /* Selecting P1.5 P1.6 and P1.7 in SPI mode */
     MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
               GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

   /* P 6.0 and P6.6 for CSB and LDACB */
     MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0);
     MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN0);
     MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN6);
     MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN6);

P:S: I am just new on embedded system side. So, may be my questions can be very basic.

Many thanks for your kind reply.

regards,

Hasan

  • 1) What command(s) are you sending? It's not clear to me how the FIFO reads back if you send a powerdown (PD) command.
    2) Each SPI byte is an exchange: You transmit a (Tx) byte and get a (Rx) byte back. Writing to the Tx buffer causes SCLK to run (8 bits). To get three bytes back, you need to send three bytes -- a command (1B) and some (possibly dummy) data (2B). [Ref Data Sheet (SNAS503B) section 1.4.1 and table on pp. 19-20.]

    [Edit: Added words about SCLK.]

  • hi Bruce,

    I am just sending this dummy data to check either SPI is working fine or not.

    /* Enabling interrupts */
    SPI_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT);
    Interrupt_enableInterrupt(INT_EUSCIB0);
    Interrupt_enableSleepOnIsrExit();

    TXData = 0x00FFFF;

    /* Polling to see if the TX buffer is ready */
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    /* Transmitting data to slave */
    SPI_transmitData(EUSCI_B0_BASE, TXData);
    /* Going to sleep *
  • I encourage you to read over the data sheet "SERIAL INTERFACE" section (pp. 14-15).
    1) In particular a "valid transfer" requires 24 bits (3 bytes). It's hard to know what SDO looks like if you stop in the middle.
    2) I don't see 0xFF in the command table (pp. 19-20), so I don't know what it does. A better bet might be NOP (0x00).
    3) I don't see where you pull CSB low. It will ignore you until you do that.
    4) You're enabling the (RX) interrupt, but I don't see an ISR for it.

    Unsolicited:
    > Interrupt_enableSleepOnIsrExit();
    This puts your program into a specific mode which I suspect you don't want. I recommend you remove this line unless/until you Know you need it.
  • Good morning,
    here is the interrupt hnadler for above mentioned intreuupt. I just took the given template for SPI master configuration.

    /* Enabling interrupts */
    SPI_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT);
    Interrupt_enableInterrupt(INT_EUSCIB0);
    //Interrupt_enableSleepOnIsrExit();
    SPI_enableInterrupt(EUSCI_B1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT );
    Interrupt_enableInterrupt(INT_EUSCIB1);
    //![Simple SPI Example]
    TXData = 0x1101;

    /* Polling to see if the TX buffer is ready */
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    /* Transmitting data to slave */
    SPI_transmitData(EUSCI_B0_BASE, TXData)

    void EUSCIB0_IRQHandler(void)
    {
    uint32_t status = SPI_getEnabledInterruptStatus(EUSCI_B0_BASE);
    uint32_t jj;

    SPI_clearInterruptFlag(EUSCI_B0_BASE, status);

    if(status & EUSCI_B_SPI_RECEIVE_INTERRUPT)
    {
    /* USCI_B0 TX buffer ready? */
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    RXData = SPI_receiveData(EUSCI_B0_BASE);

    /* Send the next data packet */
    SPI_transmitData(EUSCI_B0_BASE, ++TXData);

    /* Delay between transmissions for slave to process information */
    for(jj=50;jj<50;jj++);
    }

    }
  • Your ISR looks OK as far as it goes, but it responds to every Rx interrupt by sending another byte. In SPI, every Tx includes an Rx. Thus this logic will produce a steady Tx stream out to the DAC. I think that was the intent in the original Example, but you just want to send 3 bytes, not an infinite number.

    My suggestion: Get rid of the interrupt (and ISR) and just duplicate your transmit code two (more) times.
    ---------------
    I think the real problem you're observing is caused by not pulling CSB low before (and high after) you transmit the 3 bytes. I think the DAC is ignoring you.
  • Hi Bruce,

    where should i duplicate my transmit code two more times ? in main code or in ISR part ??

    I am not understanding how can I pull down CSB low and high during that data transmitting time . My idea is that may be I can have an TXIE which will be set when TXBUF will be empty and after the transmission of one byte , TXIE will be set again. In three itterations , it will be possible to send 3 bytes data and then SPI process should be stopped. When CSB pulls up(low to high) , data should be updated in DAC register while keeping LDACB pin low. what is your kind suggestion on this idea sir ??

    I am very grateful to you for your advice Sir.

    My skills are poor in c langauge too and may be this is the main reason that I am not able to understand this process completely :(
  • I encourage you to read over the data sheet "SERIAL INTERFACE" section (pp. 14-15).

    -------------------------

    [Untested, but it looks right:]

    GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0); // CSB low to select device
    
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
    SPI_transmitData(EUSCI_B0_BASE, TXData1);  // First byte
    
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
    SPI_transmitData(EUSCI_B0_BASE, TXData2);  // Second byte
    
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
    SPI_transmitData(EUSCI_B0_BASE, TXData3);  // Third byte
    
    while (EUSCI_B0->STATW & EUSCI_B_STATW_SPI_BUSY) /*EMPTY*/;  // Wait for SPI to finish
    GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN0); // CSB high to de-select device

    -------------------------

  • Hi bruce,

    Just help me to understand it in much more clear way. I have read (P14-15).

    Where should I use this code ? how much I am understanding is that I can use this code in main body code and I should replace ISR now. Just correct me please
    My code sequence is mentioned below with CSB and LDAC bit.

    SPI_enableModule(EUSCI_B0_BASE);
    /* P 6.0 and P6.6 for CSB and LDACB */
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0);
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN0);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN6);
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN6);

    /* Enabling interrupts */
    SPI_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT);
    Interrupt_enableInterrupt(INT_EUSCIB0);
    Interrupt_enableSleepOnIsrExit();
    //![Simple SPI Example]
    TXData = 0x01;

    /* Polling to see if the TX buffer is ready */
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    /* Transmitting data to slave */
    SPI_transmitData(EUSCI_B0_BASE, TXData);

    PCM_gotoLPM0();
    __no_operation();
    void EUSCIB0_IRQHandler(void)
    {
    uint32_t status = SPI_getEnabledInterruptStatus(EUSCI_B0_BASE);
    uint32_t jj;

    SPI_clearInterruptFlag(EUSCI_B0_BASE, status);

    if(status & EUSCI_B_SPI_RECEIVE_INTERRUPT)
    {
    /* USCI_B0 TX buffer ready? */
    while (!(SPI_getInterruptStatus(EUSCI_B0_BASE, EUSCI_B_SPI_TRANSMIT_INTERRUPT)));

    RXData = SPI_receiveData(EUSCI_B0_BASE);

    /* Send the next data packet */
    SPI_transmitData(EUSCI_B0_BASE, ++TXData);

    /* Delay between transmissions for slave to process information */
    for(jj=50;jj<50;jj++);
    }

    }
  • I suggest you get rid of the ISR (and the interrupt enables). It will complicate your program and, with a 1MHz SPI clock, will slow you down.

    Your transmit code in main sends one byte, without setting CSB. My suggested replacement for this code sends 3 bytes, just by repeating the sequence. It also brackets this transaction by setting (and un-setting) CSB (P6.0 per your comments). Since CSB is active low, it sets the pin to 0, then to 1.

    I changed the TXData name(s) to indicate that you will (in general) be sending 3 different bytes. The particular choice of bytes can be selected from the command Table (pp. 19-20).
  • Good morning Bruce,

    I also want to send these three bytes for infinite time because I have analog input from ADC and i will get analog output from DAC. But, I need three itteration every time in 24 CLK cycles and I think this is only possible if I would have interrupt enable and handler for it.

  • You get 24=(3*8) SCLKs by writing to the TXBUF three times.

    I suggest you not think of the DAC output as infinite/continuous since it will lead you astray:
    1) The output to the DAC is groups of 3, framed by CSB transitions. At minimum you'll need more bookkeeping in the SPI ISR.
    2) There's no reason to write to the DAC until/unless the data changes.

    Knowing that the data is coming from an ADC gives some perspective. I suggest that (due to (2)) the pacing in your program will come from the ADC, not the DAC -- the ADC will "push" rather than the DAC "pull"ing. One simple approach: Write the 3 bytes (with CSB framing) to the DAC inline, each time you receive a new sample from the ADC. A more complex approach: Have an ADC arrival turn on the TXIE, then have the SPI ISR turn the TXIE off after 3 bytes.

    The DAC claims to be capable of 20MHz, so you should be able to manage (24/2)=12MHz. This is a small change that will give a large relative advantage to the "simple" approach above.

**Attention** This is a public forum