cancel
Showing results for 
Search instead for 
Did you mean: 

SPI Transmitting and Receiving Data Not Matching

AE104
Senior

Hello,

I control an ADC with SPI interface of the STM32F44 microcontroller. The ADC datasheet is in the link, https://intantech.com/files/Intan_RHD2000_series_datasheet.pdf . I set up global variables as read, write, and calibrate masks. The I call them with certain sequence based on the datasheet suggestions. But based on the transmitting values, the receiving value are not matching? For example, how the rx..[2]=2 is possible? Do you have any suggestion about the problem?

// Intan READ WRITE CONVERT CALIBRATE masks
uint16_t ReadCommandMask = 0b1100000000000000;
uint16_t WriteCommandMask = 0b1000000000000000;
uint16_t ConvertCommandMask = 0b0000000000000001;
uint16_t CalibrateCommandMask = 0b0101010100000000;
 
//INTAN Register Settings
	  		  txIntanCalibrateData[0] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[1] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[2] = WriteCommandMask | (0 << 😎 | 0xDE; // Reg 0 settings
	  		  txIntanCalibrateData[3] = WriteCommandMask | (1 << 😎 | 0x20; // Reg 1 settings
	  		  txIntanCalibrateData[4] = WriteCommandMask | (2 << 😎 | 0x28; // Reg 2 settings
	  		  txIntanCalibrateData[5] = WriteCommandMask | (3 << 😎 | 0x02; // Reg 3 settings
	  		  txIntanCalibrateData[6] = WriteCommandMask | (4 << 😎 | 0x90; // Reg 4 settings
	  		  txIntanCalibrateData[7] = WriteCommandMask | (5 << 😎 | 0x00; // Reg 5 settings
	  		  txIntanCalibrateData[8] = WriteCommandMask | (6 << 😎 | 0x00; // Reg 6 settings
	  		  txIntanCalibrateData[9] = WriteCommandMask | (7 << 😎 | 0x00; // Reg 7 settings
	  		  txIntanCalibrateData[10] = WriteCommandMask | (8 << 😎 | 0x2C; // Reg 8 settings
	  		  txIntanCalibrateData[11] = WriteCommandMask | (9 << 😎 | 0x11; // Reg 9 settings
	  		  txIntanCalibrateData[12] = WriteCommandMask | (10 << 😎 | 0x08; // Reg 10 settings
	  		  txIntanCalibrateData[13] = WriteCommandMask | (11 << 😎 | 0x15; // Reg 11 settings
	  		  txIntanCalibrateData[14] = WriteCommandMask | (12 << 😎 | 0x36; // Reg 12 settings
	  		  txIntanCalibrateData[15] = WriteCommandMask | (13 << 😎 | 0x00; // Reg 13 settings
	  		  txIntanCalibrateData[16] = WriteCommandMask | (14 << 😎 | 0xFF; // Reg 14 settings
	  		  txIntanCalibrateData[17] = WriteCommandMask | (15 << 😎 | 0xFF; // Reg 15 settings
	  		  txIntanCalibrateData[18] = WriteCommandMask | (16 << 😎 | 0xFF; // Reg 16 settings
	  		  txIntanCalibrateData[19] = WriteCommandMask | (17 << 😎 | 0xFF; // Reg 17 settings
	  		  txIntanCalibrateData[20] = CalibrateCommandMask; // Calibrate
	  		  txIntanCalibrateData[21] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[22] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[23] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[24] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[25] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[26] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[27] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[28] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
	  		  txIntanCalibrateData[29] = ReadCommandMask | (63 << 8); // Reg 63, used as a dummy read
 
for (int i = 0; i < 30; i++) {
	  			  HAL_GPIO_WritePin(INTAN_SPI2_CS_GPIO_Port, INTAN_SPI2_CS_Pin, GPIO_PIN_RESET);
	  			  hal_status = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) &txIntanCalibrateData[i], (uint8_t*) &rxIntanCalibrateData[i], 1, 100);
	  			  HAL_GPIO_WritePin(INTAN_SPI2_CS_GPIO_Port, INTAN_SPI2_CS_Pin, GPIO_PIN_SET);
	  			  HAL_Delay(100);
	  			  if (hal_status != HAL_OK) {
	  			  	 printf("HAL SPI TransmitReceive error: %d\r\n", (int) hal_status);
	  			  }
	  		  }


_legacyfs_online_stmicro_images_0693W00000biGAhQAM.png

9 REPLIES 9

Why do you send a byte when you want to send words?

Also watch the endian byte order, the chip looks to want the MSB from the high order byte FIRST.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Do you mean there should no casting in transmit and receive line? Would the bitwise operations reverse order?

You cast the buffer, which is fine to get the address, but you send a single byte

hal_status = HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) &txIntanCalibrateData[i], (uint8_t*) &rxIntanCalibrateData[i], 1, 100); // The ONE here is a BYTE count

You'll need to swap the high/low bytes as the ARM CM4 here is Little Endian, and the RHD2000 diagrams a 16-bit word clocked Big Endian form. As I recall you can configure the SPI bit order, the default I think is MSB first, but you need to address the BYTE order, which is currently wrong.

Perhaps put a scope on the signals so you can visually confirm?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

It might be a configuration thing, I don't see any of that code. Assuming 8-bit MSB first..

But if it's not doing what you expect, get out a scope or logic analyzer, and look critically at the signals, and if they match the documented expectations.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I see, so I will need to update to 2, instead 1.

I modified the addressing the values like that

txIntanCalibrateData[0] = 0xbf00; txIntanCalibrateData[1] = 0xbf00;  txIntanCalibrateData[2] = 0x80DE;...

Is there any other configuration?

Do you mean monitoring MOSI and MISO lines?

Here is the SPI configuration:

hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }

Ok, so that looks fine, would need to check the HAL_SPI_Transmit_Receive() to double check the usage of the length count

>>Do you mean monitoring MOSI and MISO lines?

Yes, and perhaps contextually the SCLK and NCS to give you the full context in the time domain.

You're interested in confirming the signals vs the clock phase, and what's going out vs what you see received. Perhaps start doing one word instead of two dozen, and perhaps find a WHO-AM-I or STATUS/COUNT type registers you can sanity check against.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Interestingly, I got 0 with the rx array. I will check the signal lines.

AE104
Senior

Sorry, I fixed the problem about getting values 0. The values in my first thread are expected based on the support team suggestion of the chip company. Such as txIntanCalibrateData[2], is 32990, or in binary, 1000 0000 1101 1110. This is a WRITE to register 0, with 8 data bits 1101 1110. You can then see rxIntanCalibrateData[4] (2 commands later), you get 65502, or in binary, 1111 1111 1101 1110. I just wonder why I see the expected values 2 commands later? Ideally, it should not be monitored at rxIntanCalibrateData[2]?