cancel
Showing results for 
Search instead for 
Did you mean: 

cant read a register with SPI

MSimo.1
Associate II

Hey There,

Ive got a Semtech SX1261 Board (LoRa- tranceiver) and iam trying to read its registers with my STM32L432KC (with SPI)

Ive got working arduino code to read all its registers, but its giving me different results when i try the same thing with my STM controller..

I tried to reduce the problem to the bare minimum ( read a single 1 byte register) buts its giving me wrong results... I read the datasheet and configured my SPI Interface in the .ioc file (CPOL, CPHA, max freq and the used pins)

I don't know what else I could try now .. so iam asking you guys.

Any help/tips would be super nice!

Firstoff the arduino code :

void loop()
{  uint16_t add = 0x8E1; // The Register i want to read
  uint8_t addr_l, addr_h;
 
  addr_h = add >> 8;
  addr_l = add & 0x00FF;
 
  Serial.print("MSB: ");
  Serial.print(addr_h);
  Serial.print("   LSB: ");
  Serial.print(addr_l);
  Serial.print("   addr: ");
  Serial.println(add);
  
  checkBusy();
  
  digitalWrite(NSS, LOW);
  SPI.transfer(RADIO_READ_REGISTER);  //0x1D
  SPI.transfer(addr_h);               //MSB
  SPI.transfer(addr_l);               //LSB
  SPI.transfer(0xFF);
 
  uint8_t data = SPI.transfer(0xFF); 
  
  digitalWrite(NSS, HIGH);
 
  checkBusy();
    Serial.println(data);
  delay(5000);
}
 
Output : 
MSB: 8   LSB: 225   addr: 2273 (decimal)
57  (decimal)

now my STM Code :

while(1) {
            uint16_t add = 0x8E1; // address i want to read ; result should be 57 in DEC
	    uint8_t addr_l, addr_h;
 
	    addr_h = add >> 8;
	    addr_l = add & 0x00FF;
 
	    checkBusy();
 
	    HAL_GPIO_WritePin(SX1261_NSS_GPIO_Port, SX1261_NSS_Pin, GPIO_PIN_RESET);
 
	    uint8_t rrg = RADIO_READ_REGISTER; //0x1D
	    uint8_t term = 0xFF;
	    
	    HAL_SPI_Transmit(&hspi1, &rrg,1, HAL_MAX_DELAY);
	    HAL_SPI_Transmit(&hspi1, &addr_h,1, HAL_MAX_DELAY);
	    HAL_SPI_Transmit(&hspi1, &addr_l,1, HAL_MAX_DELAY);
	    HAL_SPI_Transmit(&hspi1, &term,1, HAL_MAX_DELAY);
 
 
	    uint8_t spirxbuff=0;//[4] ={0};
	    //HAL_SPI_Receive(&hspi1, &spirxbuff, 1, HAL_MAX_DELAY);
	    HAL_SPI_TransmitReceive(&hspi1, &term, &spirxbuff, 1, HAL_MAX_DELAY);
 
	    HAL_GPIO_WritePin(SX1261_NSS_GPIO_Port, SX1261_NSS_Pin, GPIO_PIN_SET);
 
	    checkBusy();
		char s1[100] ;
		sprintf(s1,"MSB: %i LSB: %i addr = %i ; %x \r\n",addr_h, addr_l, add,spirxbuff);
		tx_com((uint8_t*)s1, strlen(s1));
 
	  HAL_Delay(3000);
}

the output is :

MSB: 8 LSB: 225 addr = 2273 ; 8 

the problem is that the value of the read register is wrong (8 instead of 57)

this is my SPI_Init funcion:

static void MX_SPI1_Init(void)
{
 
  /* USER CODE BEGIN SPI1_Init 0 */
 
 
 
  /* USER CODE END SPI1_Init 0 */
 
  /* USER CODE BEGIN SPI1_Init 1 */
 
  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_4BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */
	__HAL_SPI_ENABLE(&hspi1);
  /* USER CODE END SPI1_Init 2 */
 
}

thank you very much!

17 REPLIES 17

Yes, my probe is a 10:1.

My result (from the register read) were always 0x00 when i had it at 8 Bit. This was the reason i changed it to 16 bit. I know its nonsence, but i was happy to get any data (wich is wrong, but ar least there is something..)

Picture 1 and 3 are zoomed out. you can see the 5 Transmits iam doing in my code. thats th reason NSS is pulled high 5 Times (after each transmission)

Iam still wondering about the voltage levels in Picture 1 and 3 . The blue spikes are much smaller after i switched it back to 16Bit DataLength ..? no clue

Picture 2 and 4 are zoomed in. You can see the transmission before and after the trigger pulse .. the first one is from HAL_SPI_Transmit(&hspi1, &addr_l,1, HAL_MAX_DELAY); and the second one from HAL_SPI_Transmit(&hspi1, &term,1, HAL_MAX_DELAY);

         uint16_t addr = 0x919; // ADDRESS to read
	  uint8_t term = 0xFF;
	  uint8_t rrg = RADIO_READ_REGISTER;
	  uint8_t addr_l, addr_h;
	  uint8_t spiRXbuff;
 
	  addr_h = addr >> 8;
	  addr_l = addr & 0x00FF;
 
	  checkBusy();
 
	  HAL_SPI_Transmit(&hspi1, &term,1, HAL_MAX_DELAY); // Dummy read
	  HAL_SPI_Transmit(&hspi1, &term,1, HAL_MAX_DELAY);
 
	  HAL_GPIO_WritePin(SX1261_NSS_GPIO_Port, SX1261_NSS_Pin, GPIO_PIN_RESET);
 
	  HAL_SPI_Transmit(&hspi1, &rrg,1, HAL_MAX_DELAY);
	  HAL_SPI_Transmit(&hspi1, &addr_h,1, HAL_MAX_DELAY);
	  HAL_SPI_Transmit(&hspi1, &addr_l,1, HAL_MAX_DELAY);
 
	  HAL_GPIO_WritePin(TRIGGER_GPIO_Port, TRIGGER_Pin, GPIO_PIN_SET);
	  HAL_GPIO_WritePin(TRIGGER_GPIO_Port, TRIGGER_Pin, GPIO_PIN_RESET);
 
	  HAL_SPI_Transmit(&hspi1, &term,1, HAL_MAX_DELAY);
 
	  HAL_SPI_TransmitReceive(&hspi1, &term, &spiRXbuff, 1, HAL_MAX_DELAY);
 
	  HAL_GPIO_WritePin(SX1261_NSS_GPIO_Port, SX1261_NSS_Pin, GPIO_PIN_SET);

Thank you. I Read the Datasheet very carefully.

It clearly says that CPOL = 0 ; CPHA = 0 ; Motorola Data Format ,MSB First , max 10Mhz.

MSimo.1
Associate II

So what could i try next ?

i could connect the Chip to an arduino , connect the SPI lines to the Oscilloscope and compare the Signals bit by bit?

Could it be possible that am calling the HAL_SPI_Transmit() functions right? Maybe i got the pointers wrong ? could i be sending an adress instead of proper Data?

How can this be so complicated ..

RMcCa
Senior II

Not sure what the problem is exactly but it doesn't look like the nss line is being handled properly. Is it toggleing​ during the transmission?

MSimo.1
Associate II

alright, looks like i found the problem : 0693W000003PUiZQAW.pngis that a typical "breadboard" problem ? my project looks like that:0693W000003PUioQAG.jpgHow should i handle my NSS ? Can it be controlled by the HAL driver?

I tried to lower the Frequency and a PullDown at my NSS GPIO..

0693W000003PUkpQAG.pngshould i change something here ?

the GPIOs have a optoion called Max output frequency .. are that configurable low passes ? should i use that ?

Or Should i just solder my circuit onto a perfboard and get rid of this breadboard?

Thank you guys!

That’s literally the same thing I circled in my response two days ago.
Control the CS pin manually as a GPIO output.
If you feel a post has answered your question, please click "Accept as Solution".
MSimo.1
Associate II

thats why i looked at it further .. thank you!

so what can i do about it ?

Iam controlling it manually, but can i optimize my GPIO settings somehow to get rid of the toggeling?

what is NSSP used for ? I cant find anything about that ..

TFranke
Associate II

Well, there are a dozen options that come into my mind which all may have an impact, more or less.

(1) A breadboard is not necessarily worse than a PCB. Depends on the layout. On your breadboard you should feed VCC and GND to the + and - lines at the edge of the board. Connect all your parts / Mini-PCBs there and decouple your supply properly, e.g. by adding 10 .. 100uF capacitors between VCC and GND. BTW I hope that the backside of the pin headers of your LoRa-PCB do not hit the + contact line of your breadboard else they all would be shortened...

(2) I would feed at least the SPI signals individually from the STM32 to the SX1261. Currently you have put them together in a wiring harness which increases coupling between signals.

(3) Adjust your oscilloscope settings. Even when you're using 10:1 probes (which is good for high-speed signals) the scope software can be told which probe is connected so that voltages are scaled right. And connect the GND lines of your probes to the common GND as described above.

(4) As already suggested by TDK go back to 8 bit transaction and show a single SPI transaction. On your current screenshots one can only see the time distance between transactions, but one can only imagine how the signal looks like for a single byte.

It would be best to have the SCK and MOSI signal on screen to see the timing relationship. Make sure that your signal looks like in chapter 8.2.1 of the SX2161 datasheet (e.g. MOSI shall change state at the falling edge of SCK, SCK freq. <= 16 MHz with 50% dutycycle, else slower).

(5) Resistors on SPI lines are not needed, the STM32 has push-pull-drivers (assuming that the same VCC is used for the SX1261 and the STM32). Don't use the "max output frequency" option if not needed as this shortens the signals edge time (by a stronger driver) and in consequence generates a higher overshoot.

(6) The overshoots in your screenshots may be measurement artifacts due to poor GND connection of your probes. Make these as short as possible.

(7) The NOP command used during reads is defined as 0x00, not 0xFF, in the SX1261 datasheet. No clue if that matters when doing a read transaction.

(8) The Arduino is quite slow, due to CPU speed and hardware abstraction layers. Maybe that "helps" that your code is running there. The SX1261 as most Semtech chips incorporates various modes to save power, some of them are switched automatically but this takes time. For instance you have to wait at least 150us after the falling edge of NSS before you start the SPI clock on SCK. Either by waiting long enough, or by checking the BUSY signal of the chip.

If nothing helps, provide the high-res. scope screenshots for further analysis.

Best regards,

Tobias