2018-07-26 01:11 AM
We want to use the L9663 PSI5 Transceiver to interface a sensor. A STM32 Discovery board is being used as the SPI master, in mode 1 (CPOL = 0, CPHA = 1). The SPI clock speed is set to 10MHz.
The module configuration is:
/* 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_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 11;
We are sending 32 bit frames to the device formatted as specified on the datasheet (Frame definition section, pages 84-85) .
However, the IC is not responding to any SPI commands, and the MISO line stays always high. We have verified that the SPI module of the STM32 board functions properly, by interfacing a MCP2515 SPI CAN controller successfully. i.e. getting an SPI response and activity on the MISO line.
We have also verified that the number of clock cycles for each SPI transaction is correct (32 clock cycles as specified on the datasheet, page 87).
The transceiver has been supplied with one of the configurations described in the documentation (page 15), with the following values (all within the operational range):
VB = 12V - Including a 75nF capacitor between the pin and GND
VDD = 5V - Including a 75nF capacitor between the pin and GND
VASSUP = 0V (Charge pump off)
VAS = 7.6V (Using an external regulated voltage)
Included a 75nF capacitor across the pins VINTD and DGND.
Since we are using the exposed pad TQFP32 package, the pad is soldered to a GND plane. All the grounds have been kept electrically shorted, as specified on the datasheet (page 11). The TM pin is also connected to GND.
We have also confirmed that the device is switched on, by measuring the output voltage on the VINTD pin, which is 3.3V when the device is enabled, consuming around 19mA when powered up.
The question:
Could someone please describe why the device is not communicating back on the MISO line?
2018-08-08 09:45 AM
@ST Community Please move to an appropriate forum and flag for staff engagement.
2018-08-28 06:09 AM
Hello,
the reported behavior on MISO could be due to incomplete power up sequence of L9663; please ensure Figure 6 of DS (Doc ID028693 Rev 3, Mar 17) is followed (a part from the necessary change because of different VAS configuration). You may have a look also to paragraph 2.1 and 2.6 .
Regards,
Pasquale
2018-08-29 02:54 AM
Thank you @Community member for directing attention to this post.
Thank you @Pasquale D'Argenio for your answer. We have followed the power up sequence, as specified on figure 6, and now we have some activity on the MISO line.
However, we are sending frames as specified on the following figure of the datasheet (page 85), but the MISO response is always of incorrect SPI operation.
See figure 27 attached.
As an example, if we wanted to write 0x0443 to the register CHCNT with address 0x02, we are sending the frame:
0x02 0x80 0x88 0x68 (as per formatting rules).
Could you please clarify if this frame formatting is correct, or which format should we follow in order to write the device's registers successfully?
We very much appreciate your help.
2018-09-20 01:30 PM
Hi @ljuarez
Were you able to figure out the issue?
I'm having the same problem, SPI fault register is always set, initially I suspected crc but after after verifying that is correct, still no luck. Any insight/experience?
Thank you!
2018-10-04 09:38 AM
2019-02-06 09:01 PM
Thank you for posting the L9663 SPI CRC Algorithm. It was impossible to work out from the Data Sheet, which only states:
5.2.4 Communication frames
CRC on MOSI is calculated over bits 31:5. CRC on MISO is:
a) CRC from the sensor
b) CRC calculated over bits 26:3
depending on GCR1[1].
CRC generation is based on the same calculation scheme used for PSI5 sensor data
(generator polynomial g(x)=1+x+x3, initialization value "111") with MSB passed first.
Register Address out on MISO is checked internally with the register decoded address; a
CRC error is generated in case of mismatch (last two bits are inverted)
There are a lot of problems with the above. As shown in your posting the CRC on MOSI is calculated over bits 31:2 and not 31:5. The calculation is over 31:5 with three zero-bits appended. It won't work otherwise. This may be obvious to people familiar with the specific details of CRC calculation in this chip, but I had to see your post to get it working.
The CRC on MISO is validated by performing the CRC over bits 26:3 WITH THREE ZEROS APPENDED in place of the received CRC bits, meaning over bits 26:0. The resulting calculated CRC is then compared with the one received. Alternately, the CRC can be run over bits 26:0 as received, and the expected result is ZERO if there are no errors.
The CRC on MOSI can't be be the "CRC from the sensor" when reading or writing the internal registers. This section can only apply to the "Sensor Data Reading" frames, but it doesn't say that.
It would help if an example of the calculation was given rather than just referring to the polynomial and to PSI5. Especially since PSI5 checks starting at the LSB and this starts at the MSB. That excludes the use of common code.
The condition that causes the "Last two bits inverted" on MISO is not explained. What does "Register Address out on MISO is checked internally with the register decoded address" mean?
It seems to mean that if you try to read Register 60 (which doesn't exist) then it returns the "last two bits inverted". Reading Register 49 (110000) which also doesn't exist doesn't give this error though.
There's a minor bug on Pages 62 and 63 of the current Rev 3 L9663 Manual. It has the same address for two different registers. The second one should be "010100":
CH1_CR3 (PROG): Address: 010011
CH1_CR4 (PROG): Address: 010011
Tom
2019-02-15 01:51 AM
hello,
Thanks for the observations about the datasheet. Regarding your questions:
Mahshid
2019-02-17 04:45 PM
Thank you for the clarification.
The reason this is so confusing is that there are three different ways to calculate CRCs in software. There's the "Augmented Method" where the data has to have zero bits appended. That version derives directly from the basic theory of CRC generation, so it is the version given in educational material showing the derivation.
It is possible to rearrange the "software shift register" so that the "appending" can be skipped. This gives the "Direct Method". As it is more efficient, that's the way most people do it, and how most sample code is written.
So the "Direct Method" can be implemented on 31:5 or the "Augmented Method" can be implemented on "31:5 plus three zeros". Searching for code examples turns up a lot of "Direct" examples, without any explanation that they're different to the other method, which is the one assumed in the L9663 Manual.
The next problem is that ST's routine requires an "Initializer" of "7". Using "Direct Method" code with "7" gives the wrong result. For "Direct", the value "2" has to be used instead.
I said there were three methods. The most common is the "Table Driven" one that operates 8 bits at a time on large amounts of data. That's the most common example code out there, but you can't use one of them on 27 BITS of data.
The image you've included in your reply seems to be of a software tool that calculates the CRC and other parameters. Is that available for developers?
Tom
2019-05-29 07:58 AM
Hello,
Is it possible to have the routine chosen for the CRC calculation in a programming language which everybody is able to understand (like c for exemple).
I made this routine, and I think this is working.
#include<stdio.h>
int main() {
char data_packet[30]={0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};// (MOSI{31:5}+000)
char CRC[3]={1,1,1}; //MSB first
char CRCnext[3];
for(int i=0; i<=29 ; i=i+1){
CRCnext[2]= CRC[1];
CRCnext[1]= CRC[0]^CRC[2];
CRCnext[0] = CRC[2]^data_packet[i];
CRC[0] = CRCnext[0];
CRC[1] = CRCnext[1];
CRC[2] = CRCnext[2];
}
printf("CRC[2:0]=%d%d%d",CRC[2],CRC[1],CRC[0]);
}
thank you ST for the waste of time