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...
You seem to be waiting on an SPI1 flag when you're using SPI2?