Electronic – STM32L1 SPI to nRF24L01 Not Working

nrf24l01spistm32stm32l

I am currently trying to get spi communication up and running between a stm32l-discovery board (uses STM32L152RCT6 mcu) and a nRF24L01 module. I have the module connected to the discovery board via the following pins (apart from the 3v and gnd):

// CS  = PB12 (SPI_NSS)
// SCK = PB13 (SPI_SCK)
// MI  = PB14 (SPI_MISO)
// MO  = PB15 (SPI_MOSI)
// CE  = PD2

My uart gives the following output:

nrf radio example
set 1500us timeout: (LOW)

It is currently stuck there because the spi registers don't seem to update and I'm not sure if I configured something wrong. My biggest problem though is that I'm not sure how I can debug this further? I'm still very new to stm32.

Here is my current code:

#include "stm32l1xx_conf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/* Memory Map */
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
#define DYNPD 0x1C
#define FEATURE 0x1D

/* Bit Mnemonics */
#define MASK_RX_DR 6
#define MASK_TX_DS 5
#define MASK_MAX_RT 4
#define EN_CRC 3
#define CRCO 2
#define PWR_UP 1
#define PRIM_RX 0
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
#define AW 0
#define ARD 4
#define ARC 0
#define PLL_LOCK 4
#define RF_DR 3
#define RF_PWR 6
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
#define RX_P_NO 1
#define TX_FULL 0
#define PLOS_CNT 4
#define ARC_CNT 0
#define TX_REUSE 6
#define FIFO_FULL 5
#define TX_EMPTY 4
#define RX_FULL 1
#define RX_EMPTY 0
#define DPL_P5 5
#define DPL_P4 4
#define DPL_P3 3
#define DPL_P2 2
#define DPL_P1 1
#define DPL_P0 0
#define EN_DPL 2
#define EN_ACK_PAY 1
#define EN_DYN_ACK 0

/* Instruction Mnemonics */
#define R_REGISTER 0x00
#define W_REGISTER 0x20
#define REGISTER_MASK 0x1F
#define ACTIVATE 0x50
#define R_RX_PL_WID 0x60
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define W_ACK_PAYLOAD 0xA8
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF

/* Non-P omissions */
#define LNA_HCURR 0

/* P model memory Map */
#define RPD 0x09

/* P model bit Mnemonics */
#define RF_DR_LOW 5
#define RF_DR_HIGH 3
#define RF_PWR_LOW 1
#define RF_PWR_HIGH 2

#define SPI_CS_HIGH GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET);
#define SPI_CS_LOW GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET);

#define NRF_CE_HIGH GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_SET);
#define NRF_CE_LOW GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_RESET);

void usart_write(uint8_t ch)
{
      USART_SendData(USART1, (uint8_t) ch);
      while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
      {
      }
}


void usart_print( char *msg )
{
    int len = strlen( msg );

    for ( int c = 0; c < len; c++ )
        usart_write( (uint8_t)*msg++ );
}

void delay( int a )
{
    volatile int i, j;

    for ( i = 0; i < a; i++ )
    {
        j++;
    }
} 

uint16_t spi_transfer( uint16_t data )
{
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    usart_print( "(senddata)" );
    SPI_I2S_SendData( SPI2, data );
    usart_print( "(wait)" );
    // wait for transfer to finish
    while (SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_RXNE ) == RESET);
    usart_print( "(recvdata)" );
    return SPI_I2S_ReceiveData(SPI2);
}

void spi_send( uint16_t data )
{
    // wait for transfer to finish
    while ( SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_TXE ) == RESET );

    SPI_I2S_SendData( SPI2, data );
}

uint16_t spi_read(void)
{
    // wait for transfer to finish  
    while ( SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_RXNE ) == RESET );

    return SPI_I2S_ReceiveData(SPI2);
}

uint16_t write_register_data(uint8_t reg, const uint8_t* buff, uint8_t len )
{
    uint16_t status;

    SPI_CS_LOW;
    status = spi_transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
    while ( len-- )
    {
        spi_transfer(*buff++);
    }   
    SPI_CS_HIGH;

    return status;
}

uint16_t read_register_data(uint8_t reg, uint8_t* buff, uint8_t len )
{
    uint16_t status;

    SPI_CS_LOW;
    status = spi_transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
    while ( len-- )
    {
        *buff++ = spi_transfer(0xff);
    }   
    SPI_CS_HIGH;

    return status;
}

uint16_t write_register_value(uint8_t reg, uint8_t value)
{
    uint16_t status;

    usart_print( "(LOW)");
    SPI_CS_LOW;
    status = spi_transfer(W_REGISTER | ( REGISTER_MASK & reg ) );
    spi_transfer( value );
    usart_print( "(HIGH)");
    SPI_CS_HIGH;

    return status;
}

uint16_t read_register_value(uint8_t reg)
{
    uint16_t status;

    SPI_CS_LOW;
    status = spi_transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
    spi_transfer( 0xff );
    SPI_CS_HIGH;

    return status;
}


int main(void) {
        GPIO_InitTypeDef gpio_init;
        USART_InitTypeDef usart_init;
        USART_ClockInitTypeDef usart_clk_init;
        SPI_InitTypeDef spi_init;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOD, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

        // spi
        // CS  = PB12 (SPI_NSS)
        // SCK = PB13 (SPI_SCK)
        // MI  = PB14 (SPI_MISO)
        // MO  = PB15 (SPI_MOSI)
        // CE  = PD2

        gpio_init.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
        gpio_init.GPIO_Mode = GPIO_Mode_AF;
        gpio_init.GPIO_Speed = GPIO_Speed_40MHz;
        gpio_init.GPIO_OType = GPIO_OType_PP;
        gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOB, &gpio_init);

        gpio_init.GPIO_Pin = GPIO_Pin_12;
        gpio_init.GPIO_Mode = GPIO_Mode_OUT;
        gpio_init.GPIO_Speed = GPIO_Speed_40MHz;
        gpio_init.GPIO_OType = GPIO_OType_PP;
        gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOB, &gpio_init);


        GPIO_PinAFConfig( GPIOB, GPIO_PinSource13, GPIO_AF_SPI2 );
        GPIO_PinAFConfig( GPIOB, GPIO_PinSource14, GPIO_AF_SPI2 );
        GPIO_PinAFConfig( GPIOB, GPIO_PinSource15, GPIO_AF_SPI2 );

        gpio_init.GPIO_Pin = GPIO_Pin_2;
        gpio_init.GPIO_Mode = GPIO_Mode_OUT;
        gpio_init.GPIO_Speed = GPIO_Speed_40MHz;
        gpio_init.GPIO_OType = GPIO_OType_PP;
        gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOD, &gpio_init);

        SPI_StructInit(&spi_init);
        spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        spi_init.SPI_Mode = SPI_Mode_Master;
        spi_init.SPI_DataSize = SPI_DataSize_8b;
        spi_init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
        spi_init.SPI_NSS = SPI_NSS_Soft;
        spi_init.SPI_CPOL = SPI_CPOL_Low;
        spi_init.SPI_CPHA = SPI_CPHA_1Edge;
        spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_Init(SPI2, &spi_init);

        SPI_Cmd(SPI2, ENABLE);

        SPI_CS_HIGH;
        NRF_CE_LOW;


        // uart
        // PA9 = Tx, PA10 = Rx
        gpio_init.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
        gpio_init.GPIO_Mode = GPIO_Mode_AF;
        gpio_init.GPIO_Speed = GPIO_Speed_40MHz;
        gpio_init.GPIO_OType = GPIO_OType_PP;
        gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOA, &gpio_init);

        GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

        USART_ClockStructInit(&usart_clk_init);
        USART_ClockInit(USART1, &usart_clk_init);

        usart_init.USART_BaudRate =            9600;
        usart_init.USART_WordLength =          USART_WordLength_8b;
        usart_init.USART_StopBits =            USART_StopBits_1;
        usart_init.USART_Parity =              USART_Parity_No ;
        usart_init.USART_Mode =                USART_Mode_Rx | USART_Mode_Tx;
        usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_Init(USART1, &usart_init);
        USART_Cmd(USART1,ENABLE);

        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
        usart_print( "nrf radio test\r\n" );

        delay(50000);

        usart_print( "set 1500us timeout: " );
        uint16_t status = write_register_value(SETUP_RETR,(4 << ARD) | (15 << ARC));
        usart_write( status ); usart_print( "\r\n" );

        usart_print( "begin\r\n" );

        while (1) {   
        }


        return 0;
}

Best Answer

Just one little thing I've noticed in the first line of your "spi_transfer" function...

 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

You seem to be waiting on an SPI1 flag when you're using SPI2?

Related Topic