I'm using SPI for interfacing between STM32F103 and MRF24J40. I write a value to MRF24J40 register and then read back to confirm it works functionally but I only receive 0x00 from MISO pin. Here are my SPI Initialize and MRF24J40 interface
SPI Config:
SPI_InitTypeDef SPI_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
SPI_Init(SPI2, &SPI_InitStruct);
SPI_Cmd(SPI2, ENABLE);
GPIOB->BSRR = GPIO_Pin_12; //Disable SPI slave
GPIO Config:
GPIO_InitTypeDef GPIO_InitStruct;
//Clock providing for SPI peripheral
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//GPIO config for SCK and MOSI pin
GPIO_InitStruct.GPIO_Pin = (GPIO_Pin_13 | GPIO_Pin_15);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//GPIO config for MISO pin
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//GPIO config for NSS pin
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
SPI Transfer:
uint8_t SPI_ByteTransfer(uint8_t data) {
while(!((SPI2->SR) & SPI_I2S_FLAG_TXE)); //Wait for data transmitted
SPI_I2S_SendData(SPI2, data & 0xFF); //Send data to TX buffer
while(!((SPI2->SR) & SPI_I2S_FLAG_RXNE)); //Wait for data received
data = SPI_I2S_ReceiveData(SPI2);
return data;
}
MRF24J40 Write and Read register functions:
void MRF24J40_WriteShortAddrReg(uint8_t addr, uint8_t data) {
addr = (addr << 1) | 0x01; //MSB = 0 for short, LSB = 1 for writing
GPIOB->BRR = GPIO_Pin_12; //Enable SPI slave
SPI_ByteTransfer(addr);
SPI_ByteTransfer(data);
while(SPI2->SR & SPI_I2S_FLAG_BSY); //Wait for bus free
GPIOB->BSRR = GPIO_Pin_12; //Disable SPI slave
}
uint8_t MRF24J40_ReadShortAddrReg(uint8_t addr) {
uint8_t data;
addr <<= 1; //MSB = 0 for short, LSB = 0 for reading
GPIOB->BRR = GPIO_Pin_12; //Enable SPI slave
data = SPI_ByteTransfer(addr);
while(SPI2->SR & SPI_I2S_FLAG_BSY); //Wait for bus free
GPIOB->BSRR = GPIO_Pin_12; //Disable SPI slave
return data;
}
Best Answer
As SPI is a synchronous interface, data is received from the slave at the same time as data is transmitted by the master.
In your receive function data is received from the slave while sending the address byte. The slave does not know what register you want to access when it shifts out the first byte as the transmit of the address byte is still undergoing.
Try to add a dummy write (e.g. 0x00) after sending the address byte to enable the slave to shift out the requested data: