cancel
Showing results for 
Search instead for 
Did you mean: 

WHY MISO ECHO BACK WHAT MOSI SENT, EVEN THE MISO PIN IS ALREADY DISABLED.

WM_IR
Senior

I make a code that is just send SPI data, and the MISO should not return anything. Here is my code:

int main(void)

{

char user_data[] = "Hello World!";

GPIO_ButtonInit();

SPI2_GPIOInits();

SPI2_Inits();

SPI_SSOEConfig(SPI2,ENABLE);

  while(1)

  {

while(GPIO_ReadFromInputPin(GPIOC,GPIO_PIN_NO_13));

delay();

SPI_PeripheralControl(SPI2,ENABLE);

uint8_t dataLen = strlen(user_data);

SPI_SendData(SPI2,&dataLen,1);

SPI_SendData(SPI2,(uint8_t*)user_data,strlen(user_data));

while(SPI_GetFlagStatus(SPI2,SPI_BUSY_FLAG));

SPI_PeripheralControl(SPI2,DISABLE);

  }

return 0;

}

So, there should be no any SPI receivedata from MISO, but when I look the data at the logic analyzer, the MISO sent back the data from MOSI. It is like echoing, Or Is it because of the SPI nature?

this code I sent "Hello world!" the string length is 12.

First, I send the length of the string to the slave, Then, I send the Hello world! sentence to the slave.

the thing is, every data transmit from the MOSI, there will be a data sent back from MISO which is the sentence of the Hello world!

example in my picture, when I send the length 12, the MISO will exchange the " ! ". which is the last letter of hello world!

Then, when letter H is being sent, the MISO will reply back the length of the string data which is sent previously. Why is this happening? anyone can help me?

0693W00000ANsncQAD.png

11 REPLIES 11
Javier1
Principal

CAN YOU TELL US WHAT HARDWARE ARE YOU USING?

MAYBE A NUCLEO BOARD?

we dont need to firmware by ourselves, lets talk

Yes, Im using nucleo board stm32F302R8 as my master, and slave is arduino UNO

i love your oscilloscope, you have any analog channels available?

you should measure analog AND digital MISO and MOSI at the same time, maybe you see some noise false triggering your gpios----

we dont need to firmware by ourselves, lets talk

for SPI analysis I did not use oscilloscope, im using USB logic analyzer. By using the USB logic analyzer, it already measured the MOSI and MISO at the same time. Thus, the result as I attached from the above

> slave is arduino UNO

MISO means Master-In-Slave-Out, so it's the slave (i.e. the Arduino) which drives the MISO line, not the STM32.

JW

> picoscope?

It's a Saleae logic analyzer. It does have (limited) analog capabilities and a decent software. Overall, a decent product IMO if you can justify the cost.

If you feel a post has answered your question, please click "Accept as Solution".
TDK
Guru

> the MISO should not return anything.

"nothing" is not an option. It's a digital line, it can be either 0 or 1. But whatever it's doing is defined by the Arduino code and not the STM32.

If you feel a post has answered your question, please click "Accept as Solution".
WM_IR
Senior

Actually, im following stm32 course from udemy, so the arduino code is provided from the instructor. Here is my arduino code, in the void loop, the slave will receive the data at the line:

 for(i = 0 ; i < dataLen ; i++ )

 {

  dataBuff[i] = SPI_SlaveReceive();

 }

So, inside of the SPI_SlaveReceive() function is:

uint8_t SPI_SlaveReceive(void)

{

 /* Wait for reception complete */

 while(!(SPSR & (1<<SPIF)));

 /* Return Data Register */

 return SPDR;

}

so in the code, return SPDR only store in dataBuff[i] array. It did not transmit any data from the slave. Below, I attached the full arduino code:

#include <SPI.h>

#include<stdint.h>

#define SPI_SCK 13

#define SPI_MISO 12

#define SPI_MOSI 11

#define SPI_SS 10

char dataBuff[500];

//Initialize SPI slave.

void SPI_SlaveInit(void) 

 #if 0 

 // Initialize SPI pins.

 pinMode(SPI_SCK, INPUT);

 pinMode(SPI_MOSI, INPUT);

 pinMode(SPI_MISO, OUTPUT);

 pinMode(SPI_SS, INPUT);

  

 // Enable SPI as slave.

 SPCR = (1 << SPE);

 #endif 

 

  // Initialize SPI pins.

 pinMode(SCK, INPUT);

 pinMode(MOSI, INPUT);

 pinMode(MISO, OUTPUT);

 pinMode(SS, INPUT);

 //make SPI as slave

  

 // Enable SPI as slave.

 SPCR = (1 << SPE);

}

//This function returns SPDR Contents 

uint8_t SPI_SlaveReceive(void)

{

 /* Wait for reception complete */

 while(!(SPSR & (1<<SPIF)));

 /* Return Data Register */

 return SPDR;

}

//sends one byte of data 

void SPI_SlaveTransmit(char data)

{

 /* Start transmission */

 SPDR = data;

  

 /* Wait for transmission complete */

 while(!(SPSR & (1<<SPIF)));

}

  

// The setup() function runs right after reset.

void setup() 

{

 // Initialize serial communication 

 Serial.begin(9600);

  

 // Initialize SPI Slave.

 SPI_SlaveInit();

  

 Serial.println("Slave Initialized");

}

 uint16_t dataLen = 0;

 uint32_t i = 0;

  

// The loop function runs continuously after setup().

void loop() 

{

 Serial.println("Slave waiting for ss to go low");

 while(digitalRead(SS) );

 i = 0;

 dataLen = SPI_SlaveReceive();

 for(i = 0 ; i < dataLen ; i++ )

 {

  dataBuff[i] = SPI_SlaveReceive();

 }

 dataBuff[i] = '\0';

  

 Serial.println("Rcvd:");

 Serial.println(dataBuff);

 Serial.print("Length:");

 Serial.println(dataLen);

  

}

OR IS IT MY SPI_SendData() function is wrong?

void SPI_SendData(SPI_RegDef_t *pSPIx, uint8_t *pTxBuffer, uint32_t Len)

{   

  while(Len > 0)

  {

  

   while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG) == FLAG_RESET);

   if(pSPIx->CR1 & (1 << SPI_CR1_CRCL))

   {

   //16 bit data frame format

   //1. Load the data into Data Register(DR)

   pSPIx->DR = *((uint16_t*)pTxBuffer);

   Len--;

   Len--;

   (uint16_t*)pTxBuffer++;

   }

   else

   {

   //8 bit data frame format

   //1. Load the data into Data Register(DR)

   *((volatile uint8_t *)&pSPIx->DR) = *pTxBuffer;

  

   Len--;

   pTxBuffer++;

   }

  }

}

  

  

In AVR (ATMega8 or whichever you have in the Arduino), SPI is a true 8-bit shift register, so if it is set to slave, with no writing to it, this is exactly how it behaves, i.e. MISO copies MOSI with an 8-bit delay. Read the AVR datasheet SPI chapter.

JW