cancel
Showing results for 
Search instead for 
Did you mean: 

SPI receive, wrong LSB

NBlac
Associate III

I'm trying to communicate between the nucleoh743 (master mode) and a TDC GP22 slave chip but came across this issue:

I am expecting to read 0x27 but i always get 0x26. All the other bits from this 1 byte are correct so i was wondering if there something else that is wrong other than the slave device. Here is a pic from the logic analyzer. (CPOL=0, CPHA=1). The SPI init code was produced by cubemx.

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);  // CS
		         HAL_Delay(1);
       HAL_SPI_Transmit(&hspi1, &tx, 1, 1);   // transmit 0xB5 from uint8_t tx
			 HAL_Delay(1);
       HAL_SPI_Receive(&hspi1, &rx, 1, 1);  // store in uint8_t rx
			 HAL_Delay(1);
       HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);  // CS
/* SPI1 init function */
static void MX_SPI1_Init(void)
{
 
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
}

thanks

11 REPLIES 11

If SCK GPIO speed (as set in OSPEEDR) is set to LOW, set it to any of the higher settings.

JW

NBlac
Associate III

I set the SCK GPIO speed to "very high":

GPIOA->OSPEEDR = 0xC00;  // pin A5->0b11
// GPIOA->OSPEEDR |= (0x03 << 5*2);

but with the same results unfortunately.

I haven't had a look at the attached picture before, but now I looked and there's 0x26 transmitted indeed (CPHA=1 means "shift output on first edge, sample input on second edge", so the small arrows on rising edges of CK indicate change in output, input is sampled at falling edges).

Why do you expect 0x27?

(Btw. while lowest speed of SPI_CK is problematic if there's significant loading on the line because of the SPI receiver is clocked off the real waveform on the pin even in master mode; don't go for the other end unless you need to push things to edge (highest SPI speeds), as that tends to cause reflections/ringings (thus other sort of problems, false "multiple" clocks.)

JW

NBlac
Associate III

I write to register 1 the value 0x27444000. And when i do the test by sending the opcode 0xB5, i should receive the highest 8 bits from that value (0x27).

I lowered the speed of the gpio with the same results. I don't think there is anything wrong with the slave chip since it reads all 7 bits correctly even if i change them. I've added an excerpt from the datasheet regarding the test in the original post. Am i missing something?

thanks

T J
Lead

I use the following code to be sure the Receive Fifos are empty:

char writeLis3DEByte(char address, char writeByte) {
    address &= 0x3F;     // 6bit address
    //address += 0x80;    // Write == 0
    address += 0x40;     // Auto Increment
    HAL_GPIO_WritePin(LIS3DE_nSS_GPIO_Port, LIS3DE_nSS_Pin, GPIO_PIN_RESET);
    
    transfer(address);
    char dummyByte = 0;
    char RxSPI = transfer_receive(writeByte);
    
    //putc1(RxSPI);
    HAL_GPIO_WritePin(LIS3DE_nSS_GPIO_Port, LIS3DE_nSS_Pin, GPIO_PIN_SET);
    return RxSPI;
   
}
 
void transfer(unsigned short data) {   // send only 
    char RxSPI;
   
    while (!(hspi1.Instance->SR  & SPI_FLAG_TXE)) ;
    *((__IO uint8_t *)&hspi1.Instance->DR) =  data;
            RxSPI = hspi1.Instance->DR;// + readSPI_SR;    // read Rx byte and discard, only clearing the buffer
}
 
char transfer_receive(unsigned short data) {   // send and receive byte
 
    char RxSPI;                                                     
    while(!(hspi1.Instance->SR  & SPI_FLAG_TXE))    // make sure the last byte is gone.
         ;
    while ((hspi1.Instance->SR  & SPI_FLAG_RXNE))  
     RxSPI = hspi1.Instance->DR;      //empty and dump all fifo bytes
 
    *((__IO uint8_t *)&hspi1.Instance->DR) = data;  // force the SPI to transceive 8 bit
    while(!(hspi1.Instance->SR  & SPI_FLAG_TXE))    // wait to transmitter double buffer to shift into transmitter
         ;                   
    while ((hspi1.Instance->SR  & SPI_FLAG_BSY)) ;  // wait for data to shift out of the processor pins
    while((hspi1.Instance->SR  & SPI_FLAG_RXNE))   // load all the bytes received, only keep the last one
        RxSPI = hspi1.Instance->DR;     // we only want the last byte
 
    return RxSPI;
}

Well, I don't know what's the reason but you can see yourself on the LA trace that the response is 0x26 and that's what you see SPI receiving, so you really can't blame the STM32 for it.

Is the LSB always 0? Can you read something else, known, from the chip? Can't the problem be when writing (take traces with the LA)?

jw

NBlac
Associate III

I read the datasheet a bit more carefully (...) and i think i have made some mistakes with the SPI timings for the slave chip. I will try and fix them and i'll come back.

NBlac
Associate III

Ok, although the timings weren't configured properly i figured i would send the received byte to a terminal via uart to double check. When the logic analyzer is connected to the SPI pins the terminal shows 0x26 and when i disconnect it it shows the correct 0x27... All other SPI transmitted bytes are correctly shown in the software and transmitted. I'm glad it is actually working but do you guys have any idea what is going on? I am using a cheap saleae knock-off...

phase
Associate II

LA wire have some capacitance and may distort of the fronts. Take oscilloscope and test rising front and falling edge.

Or try to set SPI speed low as posible.

BR