AnsweredAssumed Answered

Missing byte in SPI RX using KEAZ128, MC33664TL and MC33771

Question asked by joaofracarolli on Apr 14, 2016
Latest reply on Nov 19, 2017 by grace baldonasa

Hello,

I’m using the Kinetis KEAZ128 with the MC33664TL transceiver to communicate with a MC33771 battery cell controller.

 

The transceiver uses 2 SPI: one as a Master device (microcontroller to transceiver) and the other as a Slave device (transceiver to microcontroller). It transforms the information received via SPI into a format using a differential transformer pulse format, as stated in the datasheet:

img1.png

The diagram below shows the communication between the devices:

img2.png

If a bit “1” is sent through SPI, it is translated into a positive phase sine pulse. If the bit is “0”, the pulse has negative phase:

img3.png

These pulses are sent to the MC33771 via a twisted line pair. The messages from the MC33771 uses the same TPL to get to the transceiver, where they are converted to the SPI format and sent to the microcontroller.

 

The following picture was taken using an oscilloscope measuring the SPI0 (slave) pins. Here, we can see the the data being transmitted and received from the MC33771. Because the command and the response share the same line, the command from SPI1 (master) is echoed to SPI0 (slave). The command and response frames have 40 bits each.

 

img4.png

I’m sending the command READ to the MC33771, asking to read a register called SYS_CFG2. This command is composed by the frame 00 01 04 11 E8, in hexadecimal.

According to the MC33771 datasheet, when sending this frame, it is expected to receive a response composed by the frame 24 30 04 11 8F. Looking closely, that is exactly what the device is sending to the microcontroller:

scope_5.png

In my code, I’m using the processor expert generated functions to send and receive for both SPIs. The received frame is stored in a global variable called “response”, which is an array of 5 bytes (40 bits). I am using the onBlockReceived() interrupt to set a flag when 5 bytes are received by the microcontroller. I also defined a (primitive) timeout checking to avoid blocking my program when 5 bytes are not received. The chip_select() function is used to drive the CS pin to low state. I'll need more than one CS pin, so I use the "bank" parameter to choose which CS I will use.

 

int mc33771_command(uint8 *cmd, int bank){

            LDD_TError spierr;

       clear_buffer();

       block_sent_flag = 0;

       block_rcvd_flag = 0;             

       chip_select(bank);

             // Sending the command

       spierr = SPIMaster_SendBlock(spi_tx, cmd, FRAMESIZE);

            while(!SPIMaster_GetBlockSentStatus(spi_tx)){

          SPIMaster_Main(spi_tx);

       }

           // Monitoring the RX line ...

      spierr = SPISlave_ReceiveBlock(spi_rx, response, RESPSIZE);

        chip_select(CLEAR);       

           return get_spi_response(5000);

   }

 

int get_spi_response(uint16 timeout){

       uint16 timer = 0;

      // Waiting for reception to complete or the timeout

       while((!block_rcvd_flag) && (timer < timeout) ){

        Delay_Waitus(10);

        timer += 10;

    }

       // Checking if a timeout occurred

       if(timer >= timeout){

       SPISlave_CancelBlockReception(spi_rx);

       SPIMaster_CancelBlockTransmission(spi_tx);

             return SPI_TIMEOUT;

       }

       return SPI_OK;

}

 

The problem is, when I debug my program using Code Warrior, I see that the response variable is always missing the last byte, and the 4th byte has a strange behaviour. Sometimes it has the expected value, and sometimes it assumes the value expected for the 5th byte. The change in the value of the 4th bytes seems to occur randomly.

 

img6.png

This behavior is not exclusive to the KEAZ128 controller. I used the KL25Z and had the same issue.

Does anyone have any idea what’s happening?

 

Thanks! (Sorry for this very long text )

Outcomes