2023-04-17 01:20 PM - edited 2023-11-20 07:54 AM
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 << 8) | 0xDE; // Reg 0 settings
txIntanCalibrateData[3] = WriteCommandMask | (1 << 8) | 0x20; // Reg 1 settings
txIntanCalibrateData[4] = WriteCommandMask | (2 << 8) | 0x28; // Reg 2 settings
txIntanCalibrateData[5] = WriteCommandMask | (3 << 8) | 0x02; // Reg 3 settings
txIntanCalibrateData[6] = WriteCommandMask | (4 << 8) | 0x90; // Reg 4 settings
txIntanCalibrateData[7] = WriteCommandMask | (5 << 8) | 0x00; // Reg 5 settings
txIntanCalibrateData[8] = WriteCommandMask | (6 << 8) | 0x00; // Reg 6 settings
txIntanCalibrateData[9] = WriteCommandMask | (7 << 8) | 0x00; // Reg 7 settings
txIntanCalibrateData[10] = WriteCommandMask | (8 << 8) | 0x2C; // Reg 8 settings
txIntanCalibrateData[11] = WriteCommandMask | (9 << 8) | 0x11; // Reg 9 settings
txIntanCalibrateData[12] = WriteCommandMask | (10 << 8) | 0x08; // Reg 10 settings
txIntanCalibrateData[13] = WriteCommandMask | (11 << 8) | 0x15; // Reg 11 settings
txIntanCalibrateData[14] = WriteCommandMask | (12 << 8) | 0x36; // Reg 12 settings
txIntanCalibrateData[15] = WriteCommandMask | (13 << 8) | 0x00; // Reg 13 settings
txIntanCalibrateData[16] = WriteCommandMask | (14 << 8) | 0xFF; // Reg 14 settings
txIntanCalibrateData[17] = WriteCommandMask | (15 << 8) | 0xFF; // Reg 15 settings
txIntanCalibrateData[18] = WriteCommandMask | (16 << 8) | 0xFF; // Reg 16 settings
txIntanCalibrateData[19] = WriteCommandMask | (17 << 8) | 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);
}
}
2023-04-17 01:41 PM
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.
2023-04-17 01:50 PM
Do you mean there should no casting in transmit and receive line? Would the bitwise operations reverse order?
2023-04-17 02:09 PM
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?
2023-04-17 02:13 PM
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.
2023-04-17 02:16 PM
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?
2023-04-17 02:19 PM
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();
}
2023-04-17 02:27 PM
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.
2023-04-17 02:42 PM
Interestingly, I got 0 with the rx array. I will check the signal lines.
2023-04-19 07:52 AM
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]?