SPI Data From Slave Device Not Displaying correct data on LCD

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Greetings, I have been trying to get my PSoC5LP to communicate with a Freescale MPL115A Barometer via a SPI 4 wire bus. I have encountered a problem that I am having trouble resolving. I will list the details.

   

SETUP:

       

PROBLEM:

   

Data is being sent out from SPI master (PSoC5LP), MPL115A responds to data read and sends data back to SPI master.

   

Data displayed on LCD for MSB is 00, Data for LSB is 00 should be other than zero, like 0x7E, 0xC0  See images attached for DSO data capture and LCD readout. The blue trace is data from the SPIM, yellow trace is data from MPL115A.

   

At this point, I am not sure if I am reading the data from the MPL115 device, or is the problem with the way I am trying to display the data. I have attached the build bundle and my code is below:

   
   

/* ========================================
 *
 * Copyright ConCon Engineering LLC, 2015
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF ConCon Engineering LLC.
 *
 * Purpose of this design is to communicate to MPL115 Barometer and Temp sensors via SPI bus
 * Barometer and temp is used for gas sensor data correction
 * ========================================
*/
/*  MPL115 BreakOut ------------------CY8CKIT-050
                SDN ------------------P0[3]
                CSN ------------------P0[2]     CS_n
                SDO ------------------P0[1]     MISI
                SDI ------------------P0[0]     MOSI
                SCK ------------------P0[5]     SCLK
                GND ------------------System conn pin P6 - 7
                VDD ------------------System conn pin P6 - 3
*/
                
/* MPL115 Memory Map
   For reads must set bit 7 to 1. So a read will be 0x8X ie. Tadc_MSB 0x82           
  Address Name      Description                 Size (bits)
    0x00 Padc_MSB 10-bit Pressure output value    MSB 8
    0x01 Padc_LSB 10-bit Pressure output value    LSB 2
    0x02 Tadc_MSB 10-bit Temperature output value MSB 8
    0x03 Tadc_LSB 10-bit Temperature output value LSB 2
    0x04 a0MSB a0 coefficient MSB 8
    0x05 a0LSB a0 coefficient LSB 8
    0x06 b1MSB b1 coefficient MSB 8
    0x07 b1LSB b1 coefficient LSB 8
    0x08 b2MSB b2 coefficient MSB 8
    0x09 b2LSB b2 coefficient LSB 8
    0x0A c12MSB c12 coefficient MSB 8
    0x0B c12LSB c12 coefficient LSB 8
*/

   

#include <project.h>
#include <cylib.h>
#include <stdio.h>

   

//======================//
//          Macros            //
//======================//

   

#define Wait(x)                                //    Just for better reading
#define FALSE        0                        //    Boolean false
#define TRUE        !FALSE                    //    and true
#define forever        1                        //    I like that

   

//======================//
//     Global Variables    //
//======================//

   

uint8 BitStuff = 0x00u;

   


/* *******************
MPL115A1 Functions
**********************/

   

/*******************************************************************************
* Function Name: ControlReg and ControlReg1_Write
********************************************************************************
* Function enables hardware to display LED value of status register
* Parameters led
********************************************************************************/
void ControlReg1_Write (uint8 ledZ); // declaring the function
void ControlReg_Write (uint8);
/*****************************************************************************
/ SPI Master Read and write function (This function calls SPIM_WriteTxData
/ and SPIM_ReadRxData functions
******************************************************************************/

   

void CyDelay(uint32 milliseconds);

   

int main()
{
/************************
    Local variables
*************************/
//uint8 MyData;
uint16 Tadc_MSB = 0x00; //Store MSB of SPI Rx data
uint16 Tadc_LSB = 0x00;
uint8 GoBit = 0x00;  //Press SW3 to force main to loop once else it waits
    
     CyGlobalIntEnable; /* Always enable global interrupts. */
//********************************************************************
//      This section of code is just for debug, remove when not needed  
//********************************************************************
    uint8 ledZ = 0x01; //code debug
    ControlReg1_Write(ledZ);
    CyDelay(250);
    ledZ = 0x00;
    ControlReg1_Write(ledZ);
    CyDelay(250);
    ledZ = 0x01;
    ControlReg1_Write(ledZ);
    CyDelay(250);
    ledZ = 0x00;
    ControlReg1_Write(ledZ);
    CyDelay(250);
 //*******************************************************************
    
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
// Start the LCD and Display
LCD_Start ();
LCD_Position(0u,0u);
LCD_PrintString("SPI Master");
LCD_Position(1u,0u);
LCD_PrintString("Test Code");
CyDelay(2000);
ledZ = 0x01;
ControlReg1_Write(ledZ);
CyDelay(1000);

   

//Start the SPI master component
// while(!(SPIS_ReadTxStatus() & SPIS_STS_SPI_DONE)); // SPIS_STS_SPI_DONE from function
SPIM_Start();

   


    //while(forever) //This loops forever, part of design template
   do //start of do while loop
    {
         while(SPIM_GetTxBufferSize()) Wait();            //    Wait until all bytes transmitted
            SPIM_WriteTxData(0x24u);  // MPL115A Start Conversion
            SPIM_WriteTxData(BitStuff); //MPL115 expects 1 byte all zeros
            CyDelay(5);
            
        /* Must write address to MPL115, then read Rx data buffer */
        while(SPIM_GetTxBufferSize()) Wait();            //    Wait until all bytes transmitted
            SPIM_WriteTxData(0x84u);  // MPL115A MSB of Temp data
            SPIM_WriteTxData(BitStuff);
        
        while(SPIM_GetRxBufferSize())
            Tadc_MSB = SPIM_ReadRxData(); // Read the temp MSB data in Rx buffer
            
            
        while(SPIM_GetTxBufferSize()) Wait();            //    Wait until all bytes transmitted
            SPIM_WriteTxData(0x86u);  // MPL115A LSB of Temp data
            SPIM_WriteTxData(BitStuff);
            
        while(SPIM_GetRxBufferSize())       
            Tadc_LSB = SPIM_ReadRxData(); // Read the temp LSB data in Rx buffer
            
        
        LCD_Position(1u,0u);
        LCD_PrintString("Tadc_LSB  ");
        LCD_PrintHexUint16(Tadc_LSB);
                
        LCD_Position(0u,0u);
        LCD_PrintString("Tadc_MSB  ");
        LCD_PrintHexUint16(Tadc_MSB);
        
        
        ledZ = 0x02;
        ControlReg1_Write(ledZ);
        CyDelay (1000);
        ledZ = 0x03;
        ControlReg1_Write(ledZ);
        CyDelay (1000);
        
        GoBit = StatusReg_Read(); //Read sw3 (GoBit) If true repeat loop
    } while (GoBit);
    
}

   

 

   

// [] END OF FILE */

   

Appreciate any help you can provide. At this stage I am in the learning process, so I am sure the problem will be a bonehead thing on my part.

0 Likes
21 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Your SPI-logic does not follow exactly what you want to have.

   

Keep in mind: For every bit (byte) the master sends a bit (byte) is returned immediately. Whether the returned data contain valid information or not the slave's datasheet will tell. Your master's buffer for keeping the returned results is only 4 bytes deep, you may increase that at need.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Thanks, I changed the RX buffer from 4 to 8, the MSB now reads correctly (0x7E), but LSB is still 00.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

And did you already change something in the logic?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Okay I am really trying to get a handle on this so, don't think I am being lazy. I think there is something that I am just not getting, because I am just not getting where my problem lies.

   

I decided to sit down with a printout of my code and write down the steps 1 at a time to see if something stuck out at me.

   

This is how I think it is suppose to work.

   

SPI write/read sequence:

   

    1. Get Tx buffer size (according to Cypress SPI video we need to make sure buffer is empty).

   

Link to SPI video:  https://www.youtube.com/watch?v=oWLriIreYRU

   

Write Tx Data (0x24),(0x00) - MPL115 data sheet says a dummy byte of zeros must be sent after a write

   

MPL115 will send 2 bytes of garbage (According to Bob M. Description of writes. For every bit (byte) the master sends a bit (byte) is returned immediately.)                    2 bytes of data in RX buffer

   

    2. Get Tx Buffer size

   

write Tx Data (0x84), (0x00)

   

MPL115 returns 2 bytes 1 byte 00, 1 byte raw data (4 bytes of data in Rx Buffer).

   

     3. Get Rx Buffer Size (ensure buffer not empty) Then read Read RX data buffer MSB. ( This part displays correctly).

   

     4. Get Tx Buffer size; write Tx Data (0x86),(0x00)

   

MPL115 returns 2 bytes, 1 byte of 00, 1 byte raw data (should be LSB) (6 bytes of data in Rx Buffer).

   

     5. Get Rx Buffer size; Read Rx data buffer. Should be LSB but is 0x0000.

   

My only thought was to clear the RX data buffer after step 1, since the returned data is garbage. I inserted the function SPIM_ClearRxBuffer(); after the first write 0x24, 0x00;

   

What resulted was MSB read 0000 and LSB read C000 which is correct for LSB. So I am not sure what is exactly happening.

   

Thanks

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

2. Get Tx Buffer size

   

write Tx Data (0x84), (0x00)

   

I cannot follow where you get the 0x84-address from. Also, we need the exact device name, I could only find an MPL115A2 with an I2C interface.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

I thought I posted the link in my first message. I am using the MPL115A1.

   

http://www.freescale.com/products/sensors/pressure-sensors/barometric-pressure-15-to-115-kpa/50-to-1...

   

This is from datasheet:

   

Table 5. Example SPI Read Commands
Command Binary HEX(1)
1. The command byte needs to be paired with a 0x00 as part of the SPI exchange to complete the passing of stated
command.
Read Pressure MSB 1000000X 0x80
Read Pressure LSB 1000001X 0x82
Read Temperature MSB 1000010X 0x84
Read Temperature LSB 1000011X 0x86
Read Coefficient data byte 1 1000100X 0x88
X = don’t care

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I just found it in your code snippet as comment: MPL115A1. Now I got a datasheet. Still need actual workspace bundle.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

I sent my workspace bundle in the first post.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

So no changes at all or no help wanted?

   

 

   

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Your right, my bad. And yes I do want help. Thank you.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

OK:

   

When you count the bytes (1 up for each write and 1 down for each read) that will be kept in the receive buffer you'll see that there will be some leftovers. And keep in mind: it is a FIFO buffer!

   

When you look at the datasheet of MPL115A1

   

 at page 10 there is an interesting list. Watch the CS-line!!! For the SPIM component, the SS-line will go up again when the tx-buffer is empty, so I would suggest at first to use a pin for SS (CS) and handle it manually as shown in the example.

   

The SPIM-write functions are blocking, so when there is no room in the buffer the function will wait (Interrupts must be enabled as you did). Nonetheless I would suggest you to increase both buffers to something like 10 or 20 (there is plenty of SRam in your PSoC5).

   

So you can reduce/remove your wait-functions line by line to get a short tough routine for reading pressure.

   

BTW: What are you measuring? Height of a plane or copter?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Thanks, I will try to implement the suggestions you made. The barometer is used because I have some gas sensors onboard that vary with barometric pressure, the barometric data will be used to make corrections to the gas sensor data input. Thanks for your assistance, it is greatly appreciated.

0 Likes
Anonymous
Not applicable

Just a thought ... Have you looked at the SPI signals on a logic analyzer?  I have had trouble with the Cypress SPI component's handling of the chip select signal.  I expected the chip select to stay active for an entire transfer.  Instead, it toggled on every byte.  That confused the slave device I was using.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hello, I had to take a few days off this problem to put out some other fires, but back on it now. I have discovered a few things and made some changes.

   

I tried to streamline the code as suggested by Bob, which has helped me figure out what is going on. I also added some hardware in the PSoC to count the amount of times the SPIM generates a chip select as that seemed to be in question. As it turns out there are 2 chip selects generated for the whole transaction.

   

I also take the Rx buffer and output the entire contents as raw data to the display, to see if I have the right data in the buffer.

   

The results displayed in the buffer is as follows: [00][00][00][7D][00][C0], note the 7D and C0 is real data, the rest is just empty bytes sent by the slave. The first 2 bytes are a result of the start conversion command sent by the SPIM, so after the start cmd. I added a clear Rx buffer so I end up with [00][7D][00][C0]. The slave device always sends a byte of zero's then the actual data. So my problem is, how do I extract the data only 7DC0? My original problem was when I read the data my output was 7D00, so not sure how to handle this. I hope I was able to explain well enough. Below is my code and I am attaching my build file. Thanks

   

/* ========================================
 *
 * Copyright ConCon Engineering LLC, 2015
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF ConCon Engineering LLC.
 *
 * Purpose of this design is to communicate to MPL115 Barometer and Temp sensors via SPI bus
 * Barometer and temp is used for gas sensor data correction
 * ========================================
*/
/*  MPL115 BreakOut ------------------CY8CKIT-050
                SDN ------------------P0[3]
                CSN ------------------P0[2]     CS_n
                SDO ------------------P0[1]     MISI
                SDI ------------------P0[0]     MOSI
                SCK ------------------P0[5]     SCLK
                GND ------------------System conn pin P6 - 7
                VDD ------------------System conn pin P6 - 3
*/
                
/* MPL115 Memory Map
   For reads must set bit 7 to 1. So a read will be 0x8X ie. Tadc_MSB 0x82           
  Address Name      Description                 Size (bits)
    0x00 Padc_MSB 10-bit Pressure output value    MSB 8
    0x01 Padc_LSB 10-bit Pressure output value    LSB 2
    0x02 Tadc_MSB 10-bit Temperature output value MSB 8
    0x03 Tadc_LSB 10-bit Temperature output value LSB 2
    0x04 a0MSB a0 coefficient MSB 8
    0x05 a0LSB a0 coefficient LSB 8
    0x06 b1MSB b1 coefficient MSB 8
    0x07 b1LSB b1 coefficient LSB 8
    0x08 b2MSB b2 coefficient MSB 8
    0x09 b2LSB b2 coefficient LSB 8
    0x0A c12MSB c12 coefficient MSB 8
    0x0B c12LSB c12 coefficient LSB 8
*/

   

#include <project.h>
#include <cylib.h>
#include <stdio.h>

   

//======================//
//          Macros            //
//======================//

   

#define Wait(x)                                //    Just for better reading
#define FALSE        0                        //    Boolean false
#define TRUE        !FALSE                    //    and true
#define forever        1                        //    I like that

   

//======================//
//     Global Variables    //
//======================//

   

uint8 BitStuff = 0x00u;

   


/* *******************
MPL115A1 Functions
**********************/

   

/*******************************************************************************
* Function Name: ControlReg and ControlReg1_Write
********************************************************************************
* Function enables hardware to display LED value of status register
* Parameters led
********************************************************************************/
void ControlReg1_Write (uint8); // declaring the function
void ChipSelect_Write (uint8);
uint8 ssCountReg_Read (void);
/*****************************************************************************
/ SPI Master Read and write function (This function calls SPIM_WriteTxData
/ and SPIM_ReadRxData functions
******************************************************************************/

   

void CyDelay(uint32 milliseconds);

   

int main()
{
/************************
    Local variables
*************************/
//uint8 MyData;
uint8 Tadc_MSB = 0x55; //Store MSB of SPI Rx data
uint8 Tadc_LSB = 0x55;
uint8 GoBit = 0x00;  //Press SW3 to force main to loop once else it waits
uint8 i = 0u;  
//uint8 ssCountBits = 0x00; //Count how many times SS is asserted
    
     CyGlobalIntEnable; /* Always enable global interrupts. */

   

    
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
// Start the LCD and Display
LCD_Start ();
//LCD_Position(0u,0u);
//LCD_PrintString("SPI Master");
//LCD_Position(1u,0u);
//LCD_PrintString("Test Code");

   


//Start the SPI master component
SPIM_Start();

   

    //while(forever) //This loops forever, part of design template
   do //start of do while loop
    {
         while(SPIM_GetTxBufferSize()) Wait();            //    Wait until all bytes transmitted
            SPIM_WriteTxData(0x24u);  // MPL115A Start Conversion
            SPIM_WriteTxData(BitStuff); //MPL115 expects 1 byte all zeros
            CyDelay(5);
            SPIM_ClearRxBuffer(); //Clear some bogus bytes sent by MPL115
            
            SPIM_WriteTxData(0x84u);  // MPL115A MSB of Temp data
            SPIM_WriteTxData(BitStuff);
     //   while(SPIM_GetRxBufferSize())
     //       Tadc_MSB = SPIM_ReadRxData(); // Read the temp MSB data in Rx buffer
            
            SPIM_WriteTxData(0x86u);  // MPL115A LSB of Temp data
            SPIM_WriteTxData(BitStuff);        
            
     //   while(SPIM_GetRxBufferSize())       
     //       Tadc_LSB = SPIM_ReadRxData(); // Read the temp LSB data in Rx buffer
            
    while(!(SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)) // SPIM_STS_SPI_DONE from function       
    
    //ssCountBits = ssCountReg_Read();
    ControlReg1_Write (ssCountReg_Read()); //Just for debug display number of chip selects
    
        LCD_Position(0u,0u);
        for (i=0u; i<8u; i++)
        {
        LCD_PrintHexUint8(SPIM_ReadRxData());
        }
        LCD_Position(1u,0u);
        LCD_PrintHexUint8(ssCountReg_Read()); //Displays number of chip selects
        
       // LCD_PrintString("Tadc_MSB  ");
      //  LCD_PrintHexUint16(Tadc_MSB);
        
       // LCD_Position(1u,0u);
      //  LCD_PrintString("Tadc_LSB  ");
     //   LCD_PrintHexUint16(Tadc_LSB);
   
        
        GoBit = StatusReg_Read(); //Read sw3 (GoBit) If true repeat loop
    } while (GoBit);
    
}

   

 

   

// [] END OF FILE */

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

No need to post code-snippets here, always better to use a workspace archive as you did.

   

The conversion is relatively simple, all odd data contain information, so

   

uint16 MyResult;

   

SPIM_ReadRxData(); //Throw away

   

MyResult = (uint16)SPIM_ReadRxData(); //MSB

   

SPIM_ReadRxData(); //Throw away

   

MyResult = (MyResult << 😎 | SPIM_ReadRxData(); //LSB

   

SPIM_ClearRxBuffer(); //Clear

   

 

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Thank you very much Bob, I will give that a try and let you know:)

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Gee, this seems like this should be so simple. I added you code and am just getting 0000. I feel sorta bad for bugging you, as this is so simple looking and I feel a bit like a dumb dumb.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Since I do not have an MPL115A1 I cannot debug. So why don't you debug the results of the SPIM_ReadRxData() calls which you said to be 00,MSB,00,LSB ?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Okay Bob, Thanks. I will get this thing figured out. Your help is very appreciated.

0 Likes
Anonymous
Not applicable

It is confirmed, I'm a bonehead. Somewhere in the process, my chip select wire got pulled loose and was disconnected (like my brain). Reconnected the CSn and display is 7FC0, so it is working after all. I have been putting in some late hours, I think it is affecting the quality of my work :~<

   

Thanks for all the help Bob.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

No "sorries"! We all have been in situations like yours before, and if not we are really newbees!  😉

   

 

   

Bob

0 Likes