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

nRF51822 Radio Transmitter & Receiver with SPI.

Hello,

I am working on a project which requires radio transmitter and receiver to work in sync with the SPI. So the setup is as follows the Transmitter transmits a signal to the receiver and the receiver sends the RSSI(Received Signal Strength Indicator) to the transmitter using SPI. I have merged the two codes for the radio transmitter-receiver and the spi, spis code from the SDK 12.3. When I run the two codes in two different development kits, they are transmitting and receiving the rssi but when I connect the two Development kits with the (using male to male wires)SPI connection i.e SCK - SCK, MISO- MISO, MOSI- MOSI, SS-SS pins of the two development kit, It no longer transmits and receives any signal. I know that it is receiving the signal because it glows the leds. Also, the log is not working for this code and I have no idea why I have also included the following code in the sdk_config file:- 

#ifdef NRF_LOG_ENABLED
#define NRF_LOG_ENABLED 1
#endif

The transmitter code :-

/**
 * Copyright (c) 2015 - 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.
 * 
 */

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "radio_config.h"
#include "app_timer.h"
#include "bsp.h"
#include "nrf_gpio.h"
#include "sdk_config.h"
#include "nrf_drv_spis.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "app_error.h"
#include "nordic_common.h"
#include "nrf_error.h"
#include <string.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 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 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);
    }
}

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;

    APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));

    while (1)
    {
				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_2);
    }
}

The receiver code:-

/**
 * Copyright (c) 2015 - 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.
 * 
 */


#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "radio_config.h"
#include "nrf_drv_spi.h"
#include "bsp.h"
#include "app_timer.h"
#include "nordic_common.h"
#include "nrf_error.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.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. */
uint32_t rssi;

#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. */

#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. */


/**@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;
}

/**
 * @brief SPI user event handler.
 * @param event
 */
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));
    }
}

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);
    
    //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));

		NRF_LOG_FLUSH();
		
    while (1)
    {
				
				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);
			
				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);
				}
       
				
        // 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();
					spi_xfer_done = true;
        }

        //NRF_LOG_FLUSH();

        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(200);
    }
}

I would really appreciate if you could help me run this code properly.

Thank You.

Parents
  • Hello,

    When you use SPI, you must connect MISO on one device to MOSI on the other and vice versa.

    BR,

    Edvin

  • I tried connecting that but this code is still not working. if you find anything else wrong please let me know.

    Thank You.

  • Hello,

    I don't understand exactly what you mean. Let me ask a few questions from your original text:

     

    When I run the two codes in two different development kits, they are transmitting and receiving the rssi but when I connect the two Development kits with the (using male to male wires)SPI connection i.e SCK - SCK, MISO- MISO, MOSI- MOSI, SS-SS pins of the two development kit, It no longer transmits and receives any signal

     "When I run the two codes in two different development kits, they are transmitting and receiving the rssi"

    Is this over SPI or BLE, or both?

    "but when I connect the two Development kits with the SPI connetcion (...) it no longer transmits and receives any signal"

    Not transmitting and receiving signal over SPI, BLE or both?

    BR,

    Edvin

  • So, My code transmits using radio, transmitter, and receiver and then it is using SPI to transmit the received RSSI from the radio to send it to the master again. I have basically combined the two codes from the SDK i.e SDK->examples->peripheral->radio(transmitter ad receiver) and SDK->examples->peripheral->spi &spis. I hope you understand my code or what i am trying to do with this.

    Thank You.

  • I will repeat my question:

     "When I run the two codes in two different development kits, they are transmitting and receiving the rssi"

    Is this over SPI or BLE, or both?

    "but when I connect the two Development kits with the SPI connetcion (...) it no longer transmits and receives any signal"

    Not transmitting and receiving signal over SPI, BLE or both?

    So you don't get any messages at all through the SPI, right? 

    If you turn off everything regarding radio, can you then send (and receive) any SPI messages?

  • "When I run the two codes in two different development kits, they are transmitting and receiving the rssi"

    This is over the radio, so they are transmitting and receiving over the radio.

    "but when I connect the two Development kits with the SPI connetcion (...) it no longer transmits and receives any signal"

    This is over the radio and SPI both none of them are receiving any signal.

    "So you don't get any messages at all through the SPI, right?" 

    Yes, I am not getting any messages over the SPI at all.

    "If you turn off everything regarding radio, can you then send (and receive) any SPI messages?"

    How do I turn off everything regarding the radio in this code? When I run the SDK examples spi and spis, they seem to be working properly.

Reply
  • "When I run the two codes in two different development kits, they are transmitting and receiving the rssi"

    This is over the radio, so they are transmitting and receiving over the radio.

    "but when I connect the two Development kits with the SPI connetcion (...) it no longer transmits and receives any signal"

    This is over the radio and SPI both none of them are receiving any signal.

    "So you don't get any messages at all through the SPI, right?" 

    Yes, I am not getting any messages over the SPI at all.

    "If you turn off everything regarding radio, can you then send (and receive) any SPI messages?"

    How do I turn off everything regarding the radio in this code? When I run the SDK examples spi and spis, they seem to be working properly.

Children
  • Ok. If you don't get any radio messages as well when you enable the SPI, it sounds like the application stops. It might be an APP_ERROR_CHECK(err_code); that receives an err_code != 0. 

    Can you try the following:

    Define DEBUG in your preprocessor defines, and turn off optimization on your project. Then set a breakpoint on line 76 in app_error.c.

    Then debug your project. Does any of the boards stop on this line? If so, try to add error_info to watch. Can you see what .line_num, .err_code and .p_file_name that it refers to?

    What function returned the err_code passed into APP_ERROR_CHECK(err_code) that is referred to?

    Best regards,

    Edvin

Related