2018-10-09 09:55 AM
I am new in SPI protocol and trying to perform an application with LORA-Ra02 module via SPI protocol. I can send data through MOSI by considering DataFrame, CPOL, CPHA, rw bit of the frame but I cannot receive any data through MISO. I performed this application with both STM32 and Arduino to compare the differences. I want to share some picture and code to be understood better.
This is the picture of trying with Stm32f103, no incoming data :
This is the picture of trying with arduio, Datas must be like in this picture actually :
This is the information about SPI protocol of LORA Ra-02 module :
This is the codes I wrote :
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_spi.h"
#define SPIx_RCC RCC_APB2Periph_SPI1
#define SPIx SPI1
#define SPI_GPIO_RCC RCC_APB2Periph_GPIOA
#define SPI_GPIO GPIOA
#define SPI_PIN_MOSI GPIO_Pin_7
#define SPI_PIN_MISO GPIO_Pin_6
#define SPI_PIN_SCK GPIO_Pin_5
#define SPI_PIN_SS GPIO_Pin_4
void SPIx_Init(void);
uint8_t SPIx_Transfer(uint8_t data);
void SPIx_EnableSlave(void);
void SPIx_DisableSlave(void);
uint8_t receivedByte;
void delay(unsigned long int time){
unsigned long c;
for(c=1; c<=time; ++c); // some delay
}
int main()
{
// Initialization struct
SPI_InitTypeDef SPI_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
// Step 1: Initialize SPI
RCC_APB2PeriphClockCmd(SPIx_RCC, ENABLE);
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
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_NSSInternalSoft_Set;
SPI_Init(SPIx, &SPI_InitStruct);
SPI_Cmd(SPIx, ENABLE);
// Step 2: Initialize GPIO
RCC_APB2PeriphClockCmd(SPI_GPIO_RCC, ENABLE);
// GPIO pins for MOSI, MISO, and SCK
GPIO_InitStruct.GPIO_Pin = SPI_PIN_MOSI | SPI_PIN_MISO | SPI_PIN_SCK;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SPI_GPIO, &GPIO_InitStruct);
// GPIO pin for SS
GPIO_InitStruct.GPIO_Pin = SPI_PIN_SS;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SPI_GPIO, &GPIO_InitStruct);
// Disable SPI slave device
SPIx_DisableSlave();
receivedByte = SPIx_Transfer(0x22);
while(1)
{
}
}
uint8_t SPIx_Transfer(uint8_t data)
{
uint8_t receivedOne;
SPIx_EnableSlave();
delay(1000);
// Write data to be transmitted to the SPI data register
SPIx->DR = data;
// Wait until transmit complete
while (!(SPIx->SR & (SPI_I2S_FLAG_TXE)));
delay(1000);
// Wait until receive complete
while (!(SPIx->SR & (SPI_I2S_FLAG_RXNE)));
// Wait until SPI is not busy anymore
while (SPIx->SR & (SPI_I2S_FLAG_BSY));
// Return received data from SPI data register
receivedOne = SPIx->DR;
SPIx_DisableSlave();
return receivedOne;
}
void SPIx_EnableSlave()
{
// Set slave SS pin low
SPI_GPIO->BRR = SPI_PIN_SS;
}
void SPIx_DisableSlave()
{
// Set slave SS pin high
SPI_GPIO->BSRR = SPI_PIN_SS;
}
What seems to be my problem ?
Thanks in advance !
2018-10-12 07:11 AM
An off-the-wall question: In this line,
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
...what's the "SPI_NSSInternalSoft_Set" intended to do?
2018-10-12 09:50 AM
it's all about slave select pin management. It affects SSM and SSI bit in the SPI->CR1 register. That pair of bit is used to select either software select or hardware select.
From the datasheet :
SSI: This bit has an effect only when the SSM bit is set. The value of this bit is forced onto the
NSS pin and the IO value of the NSS pin is ignored.
SSM: When the SSM bit is set, the NSS pin input is replaced with the value from the SSI bit.
This time I tried RFID-RC522 card to communicate again there is no incoming data on the MISO line. It seems I am doing something wrong in the code
2018-10-12 10:21 AM
I don't know about the F10x family, but on the L4 you need to set an additional member in the GPIO_InitStruct. In my case (on the L4), using SPI1 it is:
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
The GPIO_Mode (that you DO configure) tells the GPIO init function to map these pins to alternate functions. The "Alternalte" settings tells the GPIO init function *WHICH* alternate function to map to these pins (each pin has multiple alternate functions available. If that structure member exists and you are not setting it, you get either zero or some random value - either of which means it won't work.
2018-10-13 12:44 AM
There is no such configuration in F10x family. If so, My former I2C examle should haven't worked. Also I found some code about spi in f10x family, They did gpio configuration like me.
2018-10-13 11:37 AM
The question in my mind with regard to spi communication is
While sending data through MOSI, sck is generated by master in this line:
SPIx->DR = data;
After that, We are waiting for some events to happen like this :
while (!(SPIx->SR & (SPI_I2S_FLAG_TXE)));
// Wait until receive complete
while (!(SPIx->SR & (SPI_I2S_FLAG_RXNE)));
// Wait until SPI is not busy anymore
while (SPIx->SR & (SPI_I2S_FLAG_BSY));
// Return received data from SPI data register
In fact, since communication is full-duplex, While sending data to slave , at the same time we are receiving dummy data and RXNE is set. Without waiting actual received data, We are proceeding to disable slave and end communication.
This might be the idea about my issue
2018-10-13 06:17 PM
this code works...
you can see the fastTX doesnt wait unless its busy...
but receive has to wait for the data to leave the pin before it can receive...
void SPI_t::fastTransfer(unsigned short data) {
// Clear_SPI1_nSS_Out();
char RxSPI;
while (!(hspi1.Instance->SR & SPI_FLAG_TXE))
; // wait for the last transfer to complete
*((__IO uint8_t *)&hspi1.Instance->DR) = data;
// clear receive buffer and dump data
while ((hspi1.Instance->SR & SPI_FLAG_RXNE))
RxSPI = hspi1.Instance->DR;
// Set_SPI1_nSS_Out();
}
unsigned char SPI_t::transfer_receive(unsigned short data) {
char RxSPI;
// Clear_SPI1_nSS_Out();
while (!(hspi1.Instance->SR & SPI_FLAG_TXE))
; // wait for the last transfer to complete
*((__IO uint8_t *)&hspi1.Instance->DR) = data; // force the SPI to transceive 8 bit
while (!(hspi1.Instance->SR & SPI_FLAG_TXE))
; // wait for this Tx fifo to clear
while ((hspi1.Instance->SR & SPI_FLAG_BSY))
; // wait for the data to leave the pin
// read out all Rx bytes only keep the last one.
while ((hspi1.Instance->SR & SPI_FLAG_RXNE))
RxSPI = hspi1.Instance->DR;
// Set_SPI1_nSS_Out();
return RxSPI;
}
2018-10-14 09:41 AM
I see, this is already what I did as it is seen above. The point I need to understand is
let's say I will send 8 bit data to slave and will receive 8 bit info. How to handle these 16 bit ? Outgoing and incoming data in one body of 16 bit or separately ?
This seems about DataFrame, I think this is the point I make the miskate. I suppose like this :
I will configure dataframe as 8 bit because I will send 8 bit and receive 8 bit. I can send data of 8 bit without problem but no incoming data. I was supposing something like slave device trigger master's SCK and incoming data will be received but in vain.
Even if datas are 8 bit, they must be considered together that is in one body of 16 bit
As you see in my code my dataframe and parameter of transfer function is 8 bit.
Probably Arduino example made me confused