This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

New with SPI on nrfd52 DK

I am new with nrf52 DK . I was trying to work with SPI code example given in the nordic example folder but its not working . I am trying to transfer the accellero/ gyro data through spi to nrf52.

Parents
  • Normally when SPI is not working the problem is one of the following : 

    1 : You have configured the pins incorrectly. nRF52 datasheet specifies the GPIO settings required to ensure proper SPI functionality prior to enabling the SPI functionality on the pins.

    2 : MOSI/MISO pins are swapped.

    3 : Incorrect SPI mode / frequency. You will find the mode and max frequency in the accelerometer datasheet.

    4 : You have forgotten to lower the CS pin prior to sending requests to the accelerometer.

    But without any more details / code example of what you are doing it will be very difficult to help you pinpoint the problem.

  • Hi, I am using Master SPI example in the nrf52 DK board and connecting my accelero output to controller through SPI. So I was expecting some output in the m_rux_buf string after the accelerometer starts sending information but  this string always remains empty. I have checked MOSI pin of controller on oscilloscope,its working fine but what I have to do when want to receive info from the accelerometer (controller (MISO)is getting data from sensor )

  • I'm assuming since you mention that you have connected something, that you are using custom code. If so we need to see this code to be able to help you with your problem.

    Pasting the exact same information twice does not help much...

    But anyways I'll give you a short example. Here is the SPI initialization. This is used for mode 0,0 and max nRF SPI frequency. You have to change this to fit the pins you are using.

    NRF_P0->DIR |= (1 << 27) + (1 << 28) + (1 << 30);
    NRF_P0->OUT |= (1<< 30);
    NRF_P0->PIN_CNF[29] |= 0;
    NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos);
    NRF_SPIM0->PSEL.SCK = (28 << SPIM_PSEL_SCK_PIN_Pos) + (SPIM_PSEL_SCK_CONNECT_Connected << SPIM_PSEL_SCK_CONNECT_Pos);
    NRF_SPIM0->PSEL.MOSI = (27 << SPIM_PSEL_MOSI_PIN_Pos) + (SPIM_PSEL_MOSI_CONNECT_Connected << SPIM_PSEL_MOSI_CONNECT_Pos);
    NRF_SPIM0->PSEL.MISO = (29 << SPIM_PSEL_MISO_PIN_Pos) + (SPIM_PSEL_MISO_CONNECT_Connected << SPIM_PSEL_MISO_CONNECT_Pos);
    NRF_SPIM0->FREQUENCY = 0x80000000;
    NRF_SPIM0->CONFIG = (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos) + (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos) +\
    (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos);
    NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos);
    NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
    (NRF_SPIM0->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) |
    (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
    NRF_PPI->CH[2].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
    NRF_PPI->CH[2].TEP = (uint32_t)&NRF_SPIM0->TASKS_STOP;
    NRF_PPI->CHENSET = 1U << 2;

    Pay special attention to the last 6 lines which is a correction to an errata on the SPI causing error in reception. If you are using the SDK I'm sure this is already handled there.

    Next method is the actual transmit/receive method.

    uint8_t spim0_readback_write(uint8_t data) {
        /* Private variables */
        uint8_t rx_byte = 0;

        /* Setting up RX and TX buffers */
        NRF_SPIM0->TXD.PTR = (uint32_t) &data;
        NRF_SPIM0->TXD.MAXCNT = 1;
        NRF_SPIM0->RXD.PTR = (uint32_t) &rx_byte;
        NRF_SPIM0->RXD.MAXCNT = 1;

        /* Start TX/RX sequence */
        NRF_SPIM0->TASKS_START = 1;

        /* Waiting for END event signaling that both RX and TX is finished */
        while(!NRF_SPIM0->EVENTS_END);
        NRF_SPIM0->EVENTS_END = 0;

        /* Return received data */
        return rx_byte;
    }

    Next you will need two methods, or calls / macros. One for driving the CS pin low and one for driving it high.

    Then to talk to the accelerometer you have to first look in the datasheet to get the commands, and instructions on how to read information from it. Then just call spim0_readback_write to send/receive bytes.

    For instance, a normal SPI routine to receive data from an external device could be something like this:

    NRF_P0->OUT &= ~(1<<CS_PIN) // Lowering CS to select the device

    spim0_readback_write(COMMAND_TO_USE); // Sending the command to the accelerometer. For instance this could be command to read X axis data. 

    Then to obtain the for instance two byte register in the accelerometer you can do:

    uint16_t x_axis_data = 0;

    x_axis_data = spim0_readback_write(0) << 8; // Fetching the first part of the register, MSB and shifting up 

    x_axis_data |= spim0_readback_write(0);

    Notice on the two readouts I'm using just 0 in the data, this is because the data here does not really matter since we are only transmitting something to get something back.

    Once you are done you have to remember to drive the CS pin high again

    NRF_P0->OUT |= (1<<CS_PIN);

    Hope this helps you a little bit.

Reply
  • I'm assuming since you mention that you have connected something, that you are using custom code. If so we need to see this code to be able to help you with your problem.

    Pasting the exact same information twice does not help much...

    But anyways I'll give you a short example. Here is the SPI initialization. This is used for mode 0,0 and max nRF SPI frequency. You have to change this to fit the pins you are using.

    NRF_P0->DIR |= (1 << 27) + (1 << 28) + (1 << 30);
    NRF_P0->OUT |= (1<< 30);
    NRF_P0->PIN_CNF[29] |= 0;
    NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos);
    NRF_SPIM0->PSEL.SCK = (28 << SPIM_PSEL_SCK_PIN_Pos) + (SPIM_PSEL_SCK_CONNECT_Connected << SPIM_PSEL_SCK_CONNECT_Pos);
    NRF_SPIM0->PSEL.MOSI = (27 << SPIM_PSEL_MOSI_PIN_Pos) + (SPIM_PSEL_MOSI_CONNECT_Connected << SPIM_PSEL_MOSI_CONNECT_Pos);
    NRF_SPIM0->PSEL.MISO = (29 << SPIM_PSEL_MISO_PIN_Pos) + (SPIM_PSEL_MISO_CONNECT_Connected << SPIM_PSEL_MISO_CONNECT_Pos);
    NRF_SPIM0->FREQUENCY = 0x80000000;
    NRF_SPIM0->CONFIG = (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos) + (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos) +\
    (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos);
    NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos);
    NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
    (NRF_SPIM0->PSEL.SCK << GPIOTE_CONFIG_PSEL_Pos) |
    (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
    NRF_PPI->CH[2].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
    NRF_PPI->CH[2].TEP = (uint32_t)&NRF_SPIM0->TASKS_STOP;
    NRF_PPI->CHENSET = 1U << 2;

    Pay special attention to the last 6 lines which is a correction to an errata on the SPI causing error in reception. If you are using the SDK I'm sure this is already handled there.

    Next method is the actual transmit/receive method.

    uint8_t spim0_readback_write(uint8_t data) {
        /* Private variables */
        uint8_t rx_byte = 0;

        /* Setting up RX and TX buffers */
        NRF_SPIM0->TXD.PTR = (uint32_t) &data;
        NRF_SPIM0->TXD.MAXCNT = 1;
        NRF_SPIM0->RXD.PTR = (uint32_t) &rx_byte;
        NRF_SPIM0->RXD.MAXCNT = 1;

        /* Start TX/RX sequence */
        NRF_SPIM0->TASKS_START = 1;

        /* Waiting for END event signaling that both RX and TX is finished */
        while(!NRF_SPIM0->EVENTS_END);
        NRF_SPIM0->EVENTS_END = 0;

        /* Return received data */
        return rx_byte;
    }

    Next you will need two methods, or calls / macros. One for driving the CS pin low and one for driving it high.

    Then to talk to the accelerometer you have to first look in the datasheet to get the commands, and instructions on how to read information from it. Then just call spim0_readback_write to send/receive bytes.

    For instance, a normal SPI routine to receive data from an external device could be something like this:

    NRF_P0->OUT &= ~(1<<CS_PIN) // Lowering CS to select the device

    spim0_readback_write(COMMAND_TO_USE); // Sending the command to the accelerometer. For instance this could be command to read X axis data. 

    Then to obtain the for instance two byte register in the accelerometer you can do:

    uint16_t x_axis_data = 0;

    x_axis_data = spim0_readback_write(0) << 8; // Fetching the first part of the register, MSB and shifting up 

    x_axis_data |= spim0_readback_write(0);

    Notice on the two readouts I'm using just 0 in the data, this is because the data here does not really matter since we are only transmitting something to get something back.

    Once you are done you have to remember to drive the CS pin high again

    NRF_P0->OUT |= (1<<CS_PIN);

    Hope this helps you a little bit.

Children
No Data
Related