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

NRF51 DK Interrupts using SPI

Hello,

I am working on a project with nRF51822, I want to connect two or more nRF51DK boards using SPI and send an interrupt from one board to another, Is there any code or any tutorial which will help me through this project. That would be really appreciated. I want to know the code for how to send interrupts from one development board to another.

Thank You.

  • Hi,

    I don't know which SDK you are using, so I will just post the generic way to find a suitable example.

    Under this link you can find all the documentation. Under the SDK of your choosing go to \examples\Hardware peripheral examples\Pin Change Interrupt Example. This will then give you a brief overview of what the example does and where to find it.

    I hope this is enough to help you

    Edit to add:

    I'm not sure if you need some SPI examples too, but you can find them at

    \examples\Hardware peripheral examples\SPI Master Example

    \examples\Hardware peripheral examples\SPI Slave Example

  • What is saying is correct. On Infocenter (that he linked to) you can find a description of the examples in SDK[version]\Hardware peripheral examples\SPI ...

    In the SDK, which you can find here, the examples for spi are located under SDK<version>\examples\peripheral\spi...

     

    I suggest that you download SDK15.0.0, if you are starting from scratch now. I also recommend that you start with the examples "spi" and "spis" from the path above.

     

    Best regards,

    Edvin

  • Hello,

    Thank You for all your help KevinL and Edvin. I executed spi and spis code in nRF51DK. I am using SDK version 12.3, I want to know how do I transfer a variable that I want using the spi as in what changes do I make in the spi and spis code for that and I want to transfer an unsigned integer variable instead of a string. If you could give me a gist of the code changes that would really help me a lot.

    Thank You.

  • Hello,

    You can transfer integers using the example application. You just need to change the m_tx_buf and length to match your data.

    m_tx_buf[0] = 123;

    m_length = 1;

    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));

     

    Have you tried this?

     

    Best regards,

    Edvin

  • Hello Edvin,

    I am trying to combine the radio transmitter and receiver code in SDK v12.3 with the spi and spis example.

    I want to transmit a packet from the transmitter over the radio and at the receiver send the RSSI value back to the transmitter using SPI. I have combined the two codes in the SDK i.e examples->peripheral->radio(transmitter and receiver) and examples->peripheral->(spi and spis) but it doesn't seem to work, I have been trying to figure the problem in my code but couldn't, if you can please check the code out and point me towards the right direction that would be great. 

    The transmitter and spis combined code is:

    /**
     * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    
    /** @file
    *
    * @defgroup nrf_dev_button_radio_tx_example_main main.c
    * @{
    * @ingroup nrf_dev_button_radio_tx_example
    *
    * @brief Radio Transceiver Example Application main file.
    *
    * This file contains the source code for a sample application using the NRF_RADIO peripheral.
    *
    */
    #include "sdk_config.h"
    #include "nrf_drv_spis.h"
    #include "app_error.h"
    #include <string.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include "radio_config.h"
    #include "nrf_gpio.h"
    #include "app_timer.h"
    #include "boards.h"
    #include "bsp.h"
    #include "nordic_common.h"
    #include "nrf_error.h"
    #define NRF_LOG_MODULE_NAME "APP"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    
    
    #define APP_TIMER_PRESCALER      0                           /**< Value of the RTC1 PRESCALER register. */
    #define APP_TIMER_OP_QUEUE_SIZE  2                           /**< Size of timer operation queues. */
    
    static uint32_t                   packet;                    /**< Packet to transmit. */
    
    
    #define SPIS_INSTANCE 1 /**< SPIS instance index. */
    static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(SPIS_INSTANCE);/**< SPIS instance. */
    
    #define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    static volatile bool spis_xfer_done; /**< Flag used to indicate that SPIS instance completed the transfer. */
    
    
    /**
     * @brief SPIS user event handler.
     *
     * @param event
     */
    void spis_event_handler(nrf_drv_spis_event_t event)
    {
        if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
        {
            spis_xfer_done = true;
            NRF_LOG_INFO(" Transfer completed. Received: %s\r\n",(uint32_t)m_rx_buf);
        }
    }
    
    
    /**@brief Function for sending packet.
     */
    void send_packet()
    {
        // send the packet:
        NRF_RADIO->EVENTS_READY = 0U;
        NRF_RADIO->TASKS_TXEN   = 1;
    
        while (NRF_RADIO->EVENTS_READY == 0U)
        {
            // wait
        }
        NRF_RADIO->EVENTS_END  = 0U;
        NRF_RADIO->TASKS_START = 1U;
    
        while (NRF_RADIO->EVENTS_END == 0U)
        {
            // wait
        }
    
        uint32_t err_code = bsp_indication_set(BSP_INDICATE_SENT_OK);
        NRF_LOG_INFO("The packet was sent\r\n");
        APP_ERROR_CHECK(err_code);
    
        NRF_RADIO->EVENTS_DISABLED = 0U;
        // Disable radio
        NRF_RADIO->TASKS_DISABLE = 1U;
    
        while (NRF_RADIO->EVENTS_DISABLED == 0U)
        {
            // wait
        }
    }
    
    
    /**@brief Function for handling bsp events.
     */
    void bsp_evt_handler(bsp_event_t evt)
    {
        uint32_t prep_packet = 0;
        switch (evt)
        {
            case BSP_EVENT_KEY_0:
                /* Fall through. */
            case BSP_EVENT_KEY_1:
                /* Fall through. */
            case BSP_EVENT_KEY_2:
                /* Fall through. */
            case BSP_EVENT_KEY_3:
                /* Fall through. */
            case BSP_EVENT_KEY_4:
                /* Fall through. */
            case BSP_EVENT_KEY_5:
                /* Fall through. */
            case BSP_EVENT_KEY_6:
                /* Fall through. */
            case BSP_EVENT_KEY_7:
                /* Get actual button state. */
                for (int i = 0; i < BUTTONS_NUMBER; i++)
                {
                    prep_packet |= (bsp_board_button_state_get(i) ? (1 << i) : 0);
                }
                break;
            default:
                /* No implementation needed. */
                break;
        }
        packet = prep_packet;
    }
    
    
    /**@brief Function for initialization oscillators.
     */
    void clock_initialization()
    {
        /* Start 16 MHz crystal oscillator */
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART    = 1;
    
        /* Wait for the external oscillator to start up */
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
        {
            // Do nothing.
        }
    
        /* Start low frequency crystal oscillator for app_timer(used by bsp)*/
        NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_LFCLKSTART    = 1;
    
        while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
        {
            // Do nothing.
        }
    }
    
    
    /**
     * @brief Function for application main entry.
     * @return 0. int return type required by ANSI/ISO standard.
     */
    int main(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    
        clock_initialization();
        APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS,
                            APP_TIMER_TICKS(100, APP_TIMER_PRESCALER),
                            bsp_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        // Set radio configuration parameters
        radio_configure();
    
        // Set payload pointer
        NRF_RADIO->PACKETPTR = (uint32_t)&packet;
    
        err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_OFF);
        NRF_LOG_INFO("Press Any Button\r\n");
        APP_ERROR_CHECK(err_code);
    		
    		// Enable the constant latency sub power mode to minimize the time it takes
        // for the SPIS peripheral to become active after the CSN line is asserted
        // (when the CPU is in sleep mode).
        NRF_POWER->TASKS_CONSTLAT = 1;
    
        //bsp_board_leds_init();
    
        //APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_INFO("SPIS example\r\n");
    
        nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
        spis_config.csn_pin               = APP_SPIS_CS_PIN;
        spis_config.miso_pin              = APP_SPIS_MISO_PIN;
        spis_config.mosi_pin              = APP_SPIS_MOSI_PIN;
        spis_config.sck_pin               = APP_SPIS_SCK_PIN;
    
        err_code = nrf_drv_spis_init(&spis, &spis_config, spis_event_handler);
    		APP_ERROR_CHECK(err_code);
        while (true)
        {
            if (packet != 0)
            {
                send_packet();
                NRF_LOG_INFO("The contents of the package was %u\r\n", (unsigned int)packet);
                packet = 0;
            }
            //NRF_LOG_FLUSH();
            __WFE();
    				
    				memset(m_rx_buf, 0, m_length);
            spis_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, m_tx_buf, m_length, m_rx_buf, m_length));
    
            while (!spis_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
        }
    }
    
    
    /**
     *@}
     **/
    

    The receiver and SPI combined code is:

    /**
     * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    
    /** @file
    *
    * @defgroup nrf_dev_radio_rx_example_main main.c
    * @{
    * @ingroup nrf_dev_radio_rx_example
    * @brief Radio Receiver example Application main file.
    *
    * This file contains the source code for a sample application using the NRF_RADIO peripheral.
    *
    */
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include "radio_config.h"
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "nordic_common.h"
    #include "nrf_error.h"
    #include "app_error.h"
     #define NRF_LOG_MODULE_NAME "APP"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_drv_spi.h"
    #include "app_util_platform.h"
    #include <string.h>
    #include "nrf_delay.h"
    
    #define APP_TIMER_PRESCALER      0                     /**< Value of the RTC1 PRESCALER register. */
    #define APP_TIMER_OP_QUEUE_SIZE  2                     /**< Size of timer operation queues. */
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    uint32_t rssi;
    #define TEST_STRING "Nordic"
    uint8_t       m_tx_buf[1] ;           /**< TX buffer. */
    uint8_t       m_rx_buf[sizeof(m_tx_buf) + 1];    /**< RX buffer. */
    uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    uint32_t                   packet;              /**< Packet to transmit. */
    
    
    /**@brief Function for initialization oscillators.
     */
    void clock_initialization()
    {
        /* Start 16 MHz crystal oscillator */
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART    = 1;
    
        /* Wait for the external oscillator to start up */
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
        {
            // Do nothing.
        }
    
        /* Start low frequency crystal oscillator for app_timer(used by bsp)*/
        NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_LFCLKSTART    = 1;
    
        while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
        {
            // Do nothing.
        }
    }
    
    
    /**@brief Function for reading packet.
     */
    uint32_t read_packet()
    {
    	
    		NRF_RADIO->SHORTS |= RADIO_SHORTS_ADDRESS_RSSISTART_Msk;
    	
    		NRF_RADIO->INTENSET = RADIO_INTENSET_READY_Msk | RADIO_INTENSET_END_Msk | RADIO_INTENSET_DISABLED_Msk;
    	
        uint32_t result = 0;
    
        NRF_RADIO->EVENTS_READY = 0U;
        // Enable radio and wait for ready
        NRF_RADIO->TASKS_RXEN = 1U;
    
        while (NRF_RADIO->EVENTS_READY == 0U)
        {
            // wait
        }
        NRF_RADIO->EVENTS_END = 0U;
        // Start listening and wait for address received event
        NRF_RADIO->TASKS_START = 1U;
    
        // Wait for end of packet or buttons state changed
        while (NRF_RADIO->EVENTS_END == 0U)
        {
            // wait
        }
    
        if (NRF_RADIO->CRCSTATUS == 1U)
        {
            result = packet;
    				rssi = NRF_RADIO->RSSISAMPLE;
    				
        }
        NRF_RADIO->EVENTS_DISABLED = 0U;
        // Disable radio
        NRF_RADIO->TASKS_DISABLE = 1U;
    
        while (NRF_RADIO->EVENTS_DISABLED == 0U)
        {
            // wait
        }
        return result;
    }
    
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.\r\n");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received: \r\n");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    
    /**
     * @brief Function for application main entry.
     * @return 0. int return type required by ANSI/ISO standard.
     */
    int main(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    	
    		nrf_gpio_range_cfg_output(21, 24);
    
        clock_initialization();
        APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
        err_code = bsp_init(BSP_INIT_LED, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), NULL);
        APP_ERROR_CHECK(err_code);
    
        // Set radio configuration parameters
        radio_configure();
        NRF_RADIO->PACKETPTR = (uint32_t)&packet;
    
        err_code = bsp_indication_set(BSP_INDICATE_USER_STATE_OFF);
        NRF_LOG_INFO("Wait for first packet\r\n");
        APP_ERROR_CHECK(err_code);
        NRF_LOG_FLUSH(); 
    
    		//bsp_board_leds_init();
    
        //APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    
        NRF_LOG_INFO("SPI example\r\n");
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin   = SPI_SS_PIN;
        spi_config.miso_pin = SPI_MISO_PIN;
        spi_config.mosi_pin = SPI_MOSI_PIN;
        spi_config.sck_pin  = SPI_SCK_PIN;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));
    
        while (true)
        {
            uint32_t received = read_packet();
    
            err_code = bsp_indication_set(BSP_INDICATE_RCV_OK);
            NRF_LOG_INFO("Packet was received\r\n");
            APP_ERROR_CHECK(err_code);
    
            NRF_LOG_INFO("The contents of the package is %u\r\n", (unsigned int)received);
    				NRF_LOG_INFO("The RSSI of the package is %u\r\n", (unsigned int)rssi);
    			
    				m_tx_buf[0] = rssi;
    				m_length = sizeof(m_tx_buf);
    			
    				if(rssi>40 && rssi<50)
    				{
    					nrf_gpio_pin_write(21, 0);
    					nrf_gpio_pin_write(22, 0);
    					nrf_gpio_pin_write(23, 0);
    					nrf_gpio_pin_write(24, 0);
    				}
    				
    				if(rssi>50 && rssi<60)
    				{
    					nrf_gpio_pin_write(21, 1);
    					nrf_gpio_pin_write(22, 0);
    					nrf_gpio_pin_write(23, 0);
    					nrf_gpio_pin_write(24, 0);
    				}
    				
    				if(rssi>60 && rssi<70)
    				{ 
    					nrf_gpio_pin_write(21, 1);
    					nrf_gpio_pin_write(22, 1);
    					nrf_gpio_pin_write(23, 0);
    					nrf_gpio_pin_write(24, 0);
    				}
    			
    				if(rssi>70 && rssi<80)
    				{
    					nrf_gpio_pin_write(21, 1);
    					nrf_gpio_pin_write(22, 1);
    					nrf_gpio_pin_write(23, 1);
    					nrf_gpio_pin_write(24, 0);
    				}
           // NRF_LOG_FLUSH();
    				
    				// Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(200);
        }
    }
    
    /**
     *@}
     **/
    

    radio.zip

    I have also attached the zip file of the code to make it easier for you.

    Thank You for all your help.

Related