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.

CCS/MSP432P401R: SPI Protocol ARDUCAM ov5642

Part Number: MSP432P401R

Tool/software: Code Composer Studio

Hello everybody, 

I'm trying to interface ARDUCAM ov5642 with MSP432, through SPI protocol. I try to send a byte to a test register but the code always be stuck in the line while (!(UCB0IFG & UCRXIFG));. 

I'd like to know if somebody can help me.

CODE:

void spiWrite(uint8_t addr, uint8_t value)
{
    ASSERT_CS();

    while (!(UCB0IFG & UCTXIFG))
        ;        // wait for TX flag
    UCB0TXBUF = addr;               // send register address

    while (UCB0STAT & UCBUSY);

    UCB0RXBUF;

    while (!(UCB0IFG & UCTXIFG))
        ;     // wait for TX flag
    UCB0TXBUF = value;              // send register value to write
    while (!(UCB0IFG & UCRXIFG))
        ;
    UCB0RXBUF;

    DEASSERT_CS();
}

int spiRead(uint8_t addr, uint8_t *data, int len)
{

    int i = 0;

    ASSERT_CS();

    for (i = 0; i < len; i++)
    {
        while (!(UCB0IFG & UCTXIFG))
            ;     // wait for TX flag
        if (i >= 1)
            UCB0TXBUF = 0x00;    // send dummy byte if greater than 1
        else
            UCB0TXBUF = addr;  // send address if this is the first send
        while (!(UCB0IFG & UCRXIFG))
            ;     // wait for RX flag
        if (i >= 1)
            data[i - 1] = UCB0RXBUF; // store data if the address has already been sent
        else
            UCB0RXBUF; // don't care about first byte sent from Arducam
    }

    DEASSERT_CS();

    return len;
}

  • Hello Guilherme,

    Can you refer the following example (in SimpleLink MSP432P4 SDK) to see how to configure the SPI in master mode:  ./examples/nortos/MSP_EXP432P401R/driverlib/spi_3wire_incrementing_data-master/

    Thanks,

    Sai

  • My guess is that your SPI input clock (UCSSEL) isn't running and/or UCB0 is still in reset (UCSWRST). I'm pretty sure that is the symptom this code would see.

    Can you show your SPI initialization code? (And are you sure it's being called?)

  • Hello Bruce, it follows part of my code. The function spiInit() initialize the SPI module in MSP432. Is there anything wrong?

    CODE:

    #define EUSCI_SPI_MODULE                EUSCI_B0_BASE
    #define EUSCI_SPI_PORT                  GPIO_PORT_P1
    #define EUSCI_SPI_SCL_PIN               GPIO_PIN5
    #define EUSCI_SPI_SCL_PIN_FUNCTION      GPIO_PRIMARY_MODULE_FUNCTION
    #define EUSCI_SPI_MOSI_PIN              GPIO_PIN6
    #define EUSCI_SPI_MOSI_PIN_FUNCTION     GPIO_PRIMARY_MODULE_FUNCTION
    #define EUSCI_SPI_MISO_PIN              GPIO_PIN7
    #define EUSCI_SPI_MISO_PIN_FUNCTION     GPIO_PRIMARY_MODULE_FUNCTION
    #define EUSCI_SPI_STATUS_SLAVE_NACK     1
    #define EUSCI_SPI_CS_PIN                GPIO_PIN2
    #define EUSCI_SPI_CS_PORT               GPIO_PORT_P5
    
    /* SPI Master Configuration Parameter */
    volatile eUSCI_SPI_MasterConfig spiConfig = {
            EUSCI_B_SPI_CLOCKSOURCE_SMCLK,                 // SMCLK Clock Source
            0,                                          
            4000000,                                       // SPICLK = 4Mhz
            EUSCI_B_SPI_MSB_FIRST,                         // MSB First
            EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW |
            EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,    // Phase
            EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW,      // High polarity
            EUSCI_B_SPI_3PIN                               // 3Wire SPI Mode
            };
    
    void spiInit(void)
    {
        /* I2C Clock Soruce Speed */
        spiConfigg.clockSourceFrequency = MAP_CS_getSMCLK();         //running at 48MHz
    
        /* Selecting P1.5(SCK) P1.6(MOSI) and P1.7(MISO) in SPI mode */
        GPIO_setAsPeripheralModuleFunctionInputPin(
                EUSCI_SPI_PORT,
                EUSCI_SPI_SCL_PIN | EUSCI_SPI_MISO_PIN | EUSCI_SPI_MOSI_PIN,
                GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* CS setup. */
        GPIO_setOutputLowOnPin(EUSCI_SPI_CS_PORT, EUSCI_SPI_CS_PIN);
        GPIO_setAsOutputPin(EUSCI_SPI_CS_PORT, EUSCI_SPI_CS_PIN);
    
        /* Configuring SPI in 3wire master mode */
        SPI_initMaster(EUSCI_SPI_MODULE,
                       (const eUSCI_SPI_MasterConfig *) &spiConfig);
    
        /* Enable SPI module */
        SPI_enableModule(EUSCI_SPI_MODULE);
    }
    
    
    

  • Hello Sai,

    I used that code for reference too but didn't receive any bit from the Camera. Could you double check my code? Is it ok?

    CODE:

    void bspSpiWrite(const uint8_t *buf, size_t length)
    {
        ASSERT_CS();
      while (length--)
      {
          MAP_SPI_transmitData(EUSCI_B0_BASE, *buf++);
          while(MAP_SPI_isBusy(EUSCI_B0_BASE));
      }
      DEASSERT_CS();
    }
    
    void bspSpiRead(uint8_t *buf, size_t length)
    {
        ASSERT_CS();
      while (length--)
      {
          MAP_SPI_transmitData(EUSCI_B0_BASE, 0x00);
          while(MAP_SPI_isBusy(EUSCI_B0_BASE));
          *buf++ = MAP_SPI_receiveData(EUSCI_B0_BASE);
      }
    
      DEASSERT_CS();
    }
    

  • Hello Sai, 

    I started to receive some data, but it wasn't what I expected. Probably I'm doing something wrong when I configured the SPI module, phase/polarity/bit_direction. I attached the code that I used.

    PS: Here are some links that contain information about ov5642 SPI configuration.

    ARDUCAM - ov5642: https://arducam.com/downloads/shields/ArduCAM_Mini_5MP_Plus_OV5642_Camera_Module_Hardware_Application_Note.pdf

    ARDUCAM spi timing:  https://www.arducam.com/knowledge-base/understanding-spi-bus-timing-arducam-mini-camera/

    CODE:

    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #include <stdbool.h>
    
    
    //![Simple SPI Config]
    /* SPI Master Configuration Parameter */
    const eUSCI_SPI_MasterConfig spiMasterConfig =
    {
            EUSCI_B_SPI_CLOCKSOURCE_SMCLK,             // SMCLK Clock Source
            24000000,                                   // SMCLK = DCO = 24MHZ
            4000000,                                    // SPICLK = 4Mhz
            EUSCI_B_SPI_MSB_FIRST,                     // MSB First
            EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,    // Phase
            EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW, // High polarity
            EUSCI_B_SPI_3PIN                           // 3Wire SPI Mode
    };
    //![Simple SPI Config]
    
    
    int main(void)
    {
        /* Halting WDT  */
        WDT_A_holdTimer();
        PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_Interrupt_disableMaster();
    
        /* Set 2 flash wait states for Flash bank 0 and 1*/
        FlashCtl_setWaitState( FLASH_BANK0, 2);
        FlashCtl_setWaitState( FLASH_BANK1, 2);
    
        CS_setDCOCenteredFrequency(CS_24MHZ);                    //48MHZ
        CS_initClockSignal( CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    
    
        //![Simple SPI Example]
        /* Selecting P1.5 P1.6 and P1.7 in SPI mode */
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,
                GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
    
        GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN12);
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN12);
    
        /* Configuring SPI in 3wire master mode */
        SPI_initMaster(EUSCI_B2_BASE, &spiMasterConfig);
    
        /* Enable SPI module */
        SPI_enableModule(EUSCI_B2_BASE);
    
        /* Enabling interrupts */
        SPI_enableInterrupt(EUSCI_B2_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT);
        Interrupt_enableInterrupt(INT_EUSCIB2);
        Interrupt_enableSleepOnIsrExit();
        //![Simple SPI Example]
        TXData = 0x01;
    
        /* Polling to see if the TX buffer is ready */
        while (!(SPI_getInterruptStatus(EUSCI_B2_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT)));
    
        /* Transmitting data to slave */
    
    
        uint16_t i;
        write_reg(0x07, 0x80);
    
        for(i=0;i<10000;i++);
    
        write_reg(0x07, 0x00);
    
        for(i=0;i<10000;i++);
    
        while(1){
    
            test();
    
        }
    
        PCM_gotoLPM0();
        __no_operation();
    }
    
    
    void test(){
    
        uint32_t i = 0;
        uint8_t value;
    
        spiLow();
    
        SPI_transmitData(EUSCI_B2_BASE, 0x00 | 0x80);
        SPI_transmitData(EUSCI_B2_BASE, 0x55);
    
        for (i = 0; i < 1000; i++);
    
        SPI_transmitData(EUSCI_B2_BASE, 0x00);
        value=SPI_receiveData(EUSCI_B2_BASE);
    
        spiHigh();
    }
    
    void write_reg(uint8_t add, uint8_t value){
        uint32_t i=0;
        spiLow();
        for(i=0;i<100;i++);
    
        SPI_transmitData(EUSCI_B2_BASE, add|0x80);
        SPI_transmitData(EUSCI_B2_BASE, value);
    
        spiHigh();
    
    }
    
    void read_reg(uint8_t add, uint8_t *value){
    
        spiLow();
    
        SPI_transmitData(EUSCI_B2_BASE, add);
        *value=SPI_receiveData(EUSCI_B2_BASE);
    
        spiHigh();
    
    }
    
    void spiLow(){
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN2);
        uint32_t i=0;
        for(i=0;i<100;i++);
    }
    
    void spiHigh(){
        GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN2);
    }
    

  • >    GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN12);

    >    GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN12);

    spiHigh() seems to think /CS is P5.2, not P5.12. (P5 only has 8 bits, so I think P5.12 ends up being P6.4.) /CS should be configured initially High, not Low.

     >  SPI_enableInterrupt(EUSCI_B2_BASE, EUSCI_B_SPI_RECEIVE_INTERRUPT);

     >   Interrupt_enableInterrupt(INT_EUSCIB2);

    Remove these lines. You don't have an ISR so you shouldn't be enabling the interrupt. Not having an ISR isn't hurting you yet, since you've disabled interrupts globally, but it will eventually.

    More immediately: Enabling the RECEIVE_INTERRUPT will cause receiveData() to read the Rx data (probably) before it's ready.

        SPI_transmitData(EUSCI_B2_BASE, 0x55);

    Be sure to drain the RXIFG (by calling receiveData and throwing the data away) after a sequence of transmitData calls. (Your original code did this and it's still a good idea.)
     
    >    Interrupt_enableSleepOnIsrExit();
    Remove this line. Your program is not written to use this feature, and it will get you in trouble eventually. 
  • Hi Sai,

    >      while(MAP_SPI_isBusy(EUSCI_B0_BASE));

    It looks as though the code in EUSCI_B_SPI_isBusy  is still wrong in SDK 3.20.00.06. It should be testing UCBUSY, not UCBBUSY:

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/724511/2715379

    [Edit: Also EUSCI_A_SPI_isBusy]

     

  • Hello Bruce,

    We are working on updating this issue for the upcoming 3.30.xx.xx release.

    Thanks,

    Sai

**Attention** This is a public forum