The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Dependents:   hello SerialTestv11 SerialTestv12 Sierpinski ... more

Issue: SPI port#0 on FRDM-KL25Z reading erroneous data (Closed: Invalid)

On reading a MAX31855 14-bit data with two sequential back to back 8-bit writes, oscilloscope says that the data out from the MAX31855 is correct but the micro begins to read erroneous data shortly after reboot. Data appears correct just after reboot but eventually (within a minute) appears to be latching MSBits higher and higher.

  • spi_cs_ = 0; active low nCS

read_byte = spi_port_->write(0); temp_ |= read_byte << 8; read_byte = spi_port_->write(0); temp_ |= read_byte << 0;

  • spi_cs_ = 1; release nCS

fault_ |= temp_ & 0x00000001; if(!fault_) { if FAULT bit NOT set temperature_ = (double)(temp_ & 0xfffffffc); mask lower two bits Signed 14-bit data, SHR 2-bits with div by 4 for 0.25C resolution temperature_ = temperature_/16.0; * 9/(5 * 16) + 32;

6 comments:

11 Sep 2013

Hello Brendan Graham,

can you use please use the code formatting for code ( "<<code>> <</code>>"). I have been using SPI communication, I have not have any problems so far. Can you share more than just a part of communication. What are settings for SPI (freq, format)? What's the bus clock?

Regards,
0xc0170

11 Sep 2013

HI Brendan,

Can you please share more of your code? I'm particularly interested in the type of the "temp_" variable and on the location(s) where it is initialized. Also, as Martin mentioned, please format your code using "<<code>>" blocks.

Thanks,
Bogdan

11 Sep 2013

If the temp sensor is stimulated, the temp reported by the micro will creep upwards and latch at discrete levels to 31.75C, 63.75C,

Bus freq: Default for FRDM-KL25Z board. I have not bothered to check. SPI format: (8, 0) SPI frequency: Have confirmed erroneous operation at 500kcps, 1Mcps, 2Mcps, 5Mcps, have not tried other freq's

...

void fire(void) {
        *spi_cs_ = 0; // active low nCS
        
        read_byte = spi_port_->write(0);
        temp_ |= read_byte << 8;
        read_byte = spi_port_->write(0);
        temp_ |= read_byte << 0;
        
        *spi_cs_ = 1; // release nCS
                
        fault_ |= temp_ & 0x00000001;
        //if(!fault_) { // if FAULT bit NOT set
        temperature_ = (double)(temp_ & 0xfffffffc); // mask lower two bits
        // Signed 14-bit data, SHR 2-bits with div by 4 for 0.25C resolution
        temperature_ = temperature_/16.0; // * 9/(5 * 16) + 32; 
        //}
    }

private:
    Serial *ser_;
    SPI *spi_port_;
    DigitalOut *spi_cs_;
    int temp_;
    double temperature_;
    uint8_t read_byte;
    bool fault_;
};

int main(void) {  
    
    // Setup the SPI0 port for MAX31855 communications
    MAX31855.format(8, 0);           // 8-bit SPI, mode0
    MAX31855.frequency(5000000);    // 5MHz

...

11 Sep 2013

Where do you initialize your temp_ variable?

11 Sep 2013

Oops!!! Silly error on my part. How embarrassing. The temp_ var is initialized in the constructor, but even without initializing in the constructor the var would automatically be init to 0 as per c++.

The problem is I forgot to init temp_ at the beginning of the fire() method prior to the actual SPI reads so it just continues to accumulate forever! Thanks for your assistance. I hope this serves to jar the cobwebs in others brains free! ;-)

class TempSensor {
public:

    TempSensor(Serial *ser, 
               SPI *spi_port,
               DigitalOut *spi_cs) {
        ser_ = ser;
        spi_port_ = spi_port;
        spi_cs_ = spi_cs;
        
        *spi_cs_ = 1;
        fault_ = 0;
        temp_ = 0;
    } 
               
    void fire(void) {

        temp_ = 0; // Must zero out temp_ or will have an accumulator for all eternity!!! ;-)

        *spi_cs_ = 0; // active low nCS
        
        read_byte = spi_port_->write(0);
        temp_ |= read_byte << 8;
        read_byte = spi_port_->write(0);
        temp_ |= read_byte << 0;
        
        *spi_cs_ = 1; // release nCS
                
        fault_ |= temp_ & 0x00000001;
        //if(!fault_) { // if FAULT bit NOT set
        temperature_ = (double)(temp_ & 0xfffffffc); // mask lower two bits
        // Signed 14-bit data, SHR 2-bits with div by 4 for 0.25C resolution
        temperature_ = temperature_/16.0; // * 9/(5 * 16) + 32; 
        //}
    }
    
    void update(void) {
        output = temperature_; // shift right two bits for 14-bit data
        
        //if(fault_) {
            (*ser_).printf("FAULT Temp=%4.2f C\r\n", output);
            return;
        //} 
        
        //(*ser_).printf("Temp=%4.2f C\r\n", output);        
    }
    
    volatile double output;
    
private:
    Serial *ser_;
    SPI *spi_port_;
    DigitalOut *spi_cs_;
    int temp_;
    double temperature_;
    uint8_t read_byte;
    bool fault_;
};

11 Sep 2013

I'm glad your problem is fixed now. However, please note that "even without initializing in the constructor the var would automatically be init to 0 as per c++" is NOT generally true. More details here (for example):

http://stackoverflow.com/questions/2417065/does-the-default-constructor-initialize-built-in-types