I2C :: How to interface a SPI sensor

22 Jan 2012

Ok I understand !

I have tested the temperature reconstruction data. But the value is wasn't looking like a temperature value in my home. I sorted words as follow:

value[0] = packet[1];
value[1] = packet[2]; //LSW
value[2] = packet[3];
value[3] = packet[4]; //MSW

And the value is 23552 -> may be 23.552 °C would be better. the value do not have a " . " as a float.

22 Jan 2012

It is normal for ic's to send a float value as an int by multiplying the float by 100, 1000, ect depending on how many decimal places they want, I'm not sure we are getting the correct data yet, the top 32bits are supposed to be the utc time, maby they are 0 because you havnt set the clock though,

22 Jan 2012

According to the datasheet, the UTC information is the 4 times 8 bits (last 0 | 0 | 0 | 0) returned by the slave (at the end ) ? /media/uploads/gege089/mastr_slave.png

The clock is defined by the SPI class method "frequency"

device.frequency(5000);

The frequency is free (under 2 MHz)...

23 Jan 2012

the clock as in the time, not the frequency of the SPI, anyway ive figured out the construction of the data we got back is a bit more complicated then i thought (page 30 of the datasheet), bit 7 of the first byte and the second byte contain our temperature, this makes it 9bit 2's compliment value, im just working on how to reconstruct this for you as 9 bits is't very standard,

22 Jan 2012

ok so to reconstruct the bit of the data we need,

uint8_t temperature_value[2];

//first just set byte 0 of the 16bit value to the data in packet[2]
temperature_value[0] = packet[2];
//we need to establish if its positive or negative
if(packet[1] & 0x01){ //this will check whether bit7 of the first byte is 1 or 0
  //if the data is negative we need to pad with a 255(all bits set) byte
  temperature_value[1]= 255;
} else {
  //if our data is positive pad out the 16bit signed (2's compliment) value with a 0 byte
  temperature_value[1]= 0;
}

//finaly the datasheet says that the LSB is equal to 0.25 so to get the final value you multiply by 0.25

float final_value = *(reinterpret_cast<int16_t>(temperature_value));
final_value = final_value * 0.25;

using this method i get a value of 23.25 for the bytes in the previous post

22 Jan 2012

I don't really understand. Ok, I on the page 30 of the datashet. /media/uploads/gege089/lswmsw.png

there are two table which describes "LSW" and "MSW". It say 's complement for LSW *0.25.

First question : what is the link with the table of page 40 with # of bits = 32 ! where a data in packet is 8 bits and 4 packets is a 32 bit information (after reiterpret function). Now, temp is a 16 bit integer.

Second question : Where is the information which say "packet 1 contain the sign information (positive or negative value)" ?

Regards

22 Jan 2012

The table shows what each bit of the 32 bit value we got returned is, the MSW which was the first 2 bytes we got returned is explained in the top table,

byte 1 is explained in the first half bit 1 to 7; the last bit in this byte (bit 7) is the first bit in the 9 bit value for temperature, byte 2 is the last 8 bits of the 9 bit value, 9 bits is a bit odd and i had to use a 16bit int16_t to store it,

to figure out how the padding worked you'l need to look up 2's compliment on wiki, its the basis of how signed numbers work in computers so is useful to know,

it says 2'c compliment with LSB = 0.25, which means that the lowest significant BIT is 0.25 therefore we have to multiply by 0.25 to get the actual value.

23 Jan 2012

Nice, I have understood !

I publish a summary of the method, for anybody. /media/uploads/gege089/dataspi.pdf

Now to be sure I have understood, I will try to write a data inside the eeprom....

Sincerely ,

GM

23 Jan 2012

Glad you got it working guys, good work! Cheers to Chris for the reinterpret cast - I added those to my code after seeing it - and kudos to Gerald for giving back to the community :)

23 Jan 2012

reinterpret casts are very useful when dealing with spi, serial ect =) its quite powerful when used with byte aligned structs, you can recast a byte array to a struct and access the parts just like you would a struct, couldnt do that in this case as they didnt use standard bit size values,

just a few notes on the pdf, a Byte is 8bits, 2 bytes or 16bits is called a Word (there are exceptions with different processor architectures but that will just complicate the explanation), and the temperature value is 9bits in 2's compliment format,

anyway glad I could help =)

25 Jan 2012

Chris,

I am a looser. I tried to understand lonely the read/write memory function.

Ok first I read the datasheet to the valuable page... Page SPI commands for read/write a word.

I choose readable memory. In I/O control : adress 0xF0.

Start I write a data a word of 16 bits = 2 bytes: 0xFF and 0x01

 cs=0;
    uint8_t packet[4];
    
    uint8_t returns[4];
    
    packet[0]=0xE8;packet[1]=0xF0;packet[2]=0xFF;packet[3]=0x01;
    for (int i=0;i<4;i++){
        returns[i] = device.write(packet[i]);
        wait(0.3);
    }
    wait(0.1);
    cs =1;

I think it goo d for this part.... The returns array is 0|0|0|0

Let's go to read the value in the memory.

      cs=0;
    
    store[0]=0xE7;store[1]=0xF0;
    for (int i=0;i<2;i++){
        device.write(packet[i]);
        wait(0.3);
    }
    wait(0.1);
       for (int i=0;i<3;i++){
        returned[i] = device.write(0x00);
        wait(0.3);
    }
    cs =1;

And the next code to print the value returned on my laptop screen:

//returns value 
    for (int j=0;j<3;j++){
        uint8_t dd = returned[j];
        pc.printf("value read is %d \r\n", dd);
    }
25 Jan 2012

Please don't write me a code. Some words would be a fine help to beginning ;)

25 Jan 2012

you should always check for the return code after a command to see whether it executed correctly, they are explained in the SPIRequestStatus section, you don't know how long it will take to get a response, I used waits because it was simple, the reply status will be none zero so you could use a while loop, and use a timer to break it if you don't get a response in specific period (time-out and retry) , the device will always send a reply status first and then the data, so it can be used to indicate the start of your data and put the next however many bytes you expected into an array

30 Jan 2012

hi

I don't know really why my chip do not answer any things. For the same code as last week, nothing appear:

#include "mbed.h"


int main() {
SPI spi(p11, p12, p13);//mosi on mosi, miso on miso, slc on sclc gnd on gnd and power supply with 2 V DC
DigitalOut cs(p14);//cs information
spi.format(8,0);
spi.frequency(100000); // 50kHz on sck
AnalogOut an(p18);
uint8_t packet[9];
Serial pc(USBTX, USBRX);
    while(1) {
  cs = 0;
  spi.write(0xE5); //command byte
  wait(2);
  uint8_t reply = spi.write(0x00); // itl send 0x00 before packet
  wait(1);
  for(uint8_t i = 0; i < 9; ++i) {
    packet[i] = spi.write(0x00);
    wait(1);
  }
  cs = 1; // must raise cs between commands but after the reply
  for (int i=0;i<9;i++){
  uint8_t toto = packet[i];
    printf("v = %d \r\n", toto);
  }
    }
}

eight 0 appear in my terminal !

Regards,

GG

30 Jan 2012

#include "mbed.h"

SPI spi(p11, p12, p13);//mosi on mosi, miso on miso, slc on sclc gnd on gnd and power supply with 2 V DC
DigitalOut cs(p14);//cs information

uint8_t packet[9];
Serial pc(USBTX, USBRX);

Timer timeout;
bool timed_out;

int main() {
    uint8_t status_byte = 0x00;
    timeout.start(); //start the timeout timer
    
    //continously loop through the four SPI modes trying to get a response
    while (1) {
        //try the 4 available modes to see if it will work
        for (int mode = 0; mode < 4; ++mode) {
            //initialise the current mode
            spi.format(8, mode);
            spi.frequency(100000); // 50kHz on sck

            cs = 0;

            printf("Testing Command in SPI Mode %d\r\n", mode);
            spi.write(0xE5); //send command byte

            timeout.reset(); //reset the timeout to wait for reply for 2 seconds
            timed_out = false;
            
            //wait for the status byte
            while (status_byte == 0x00) {
                status_byte = spi.write(0x00);
                
                //waited too long timeout
                if (timeout.read_ms() > 2000) {
                    timed_out = true;
                    break;
                }
            }

            if (!timed_out) {
                packet[0] = status_byte;
                //have the status (should check it really)

                //get the rest of the packet
                for (int i=1; i<9; i++) {
                    packet[i] = spi.write(0x00);
                }
                
                //output the packet
                for (int i=0; i<9; i++) {
                    printf("%02X ", packet[i]); //output the bytes in hex format on one line
                }
                printf("\r\n");
            } else {
                printf("Command timeout..\r\n");
            }

            cs = 1; // must raise cs between commands but after the reply
            wait(2);
        }
    }
}

Wish i had a way of testing it, that's how I would try and receive an SPI packet, it will test the four SPI modes then start again at 0, if you get nothing, check your wiring carefully (no guarantee theres no serious bugs)

30 Jan 2012

OKay ! Thanks. I note the to wait is important to obtain a statue response which signify something.

I obtain for the 3 modes the 80 0 0 0 0 0 0 0.

The main important here is the status byte 80. As an hexadecimal 80 = 10000000. According to the datasheet, this statue response signify - header : 1 - transponder disable - device is ready and listen - memory is no busy - and the command had been executed

<<edit>> it mine "no connected....." I have checked all the connections pin....

Sincerely,

GM

30 Jan 2012

Not sure I understand that post? what didn't work?

30 Jan 2012

For each mode, the answer is 80 00 00 00 00 00 00 00 00. If I disconnect the devicne the answer is 80 FF FF FF FF FF FF FF

30 Jan 2012

80 is the status bytes in Hex ? => page 39 of the datasheet, there is an explanation of the status bytes.

30 Jan 2012

oh, I probably don't reset the status to 0x00 at the start of each loop, told you there would be bugs =), im surprised it compiled to be honest

31 Jan 2012

Well, I compiled your code with a reset status byte.

I rediscovered an issue with the pin connections. I'll post this afternoon the results. It is a very strange issue with my PCB. Straps connection are moving and the hexadecimal transmitted are changing....

31 Jan 2012

The result change each time I move straps....

Testing Command in SPI Mode 2
Command timeout..
Testing Command in SPI Mode 3
Command timeout..
Testing Command in SPI Mode 0
Command timeout..
Testing Command in SPI Mode 1
Command timeout..
Testing Command in SPI Mode 2
Command timeout..
Testing Command in SPI Mode 3
Command timeout..
Testing Command in SPI Mode 0
Command timeout..
Testing Command in SPI Mode 1
80 00 00 00 00 00 00 00 00 
Testing Command in SPI Mode 2
Command timeout..
Testing Command in SPI Mode 3
Testing Command in SPI Mode 0
Command timeout..
Testing Command in SPI Mode 1
80 00 00 00 00 00 00 00 00 
Testing Command in SPI Mode 2
Command timeout..
Testing Command in SPI Mode 3
Command timeout..
Testing Command in SPI Mode 0
Command timeout..
Testing Command in SPI Mode 1
80 00 00 00 00 00 00 00 00 
Testing Command in SPI Mode 2

31 Jan 2012

well we can assume you have a faulty cable or badly soldered connector, (I have no idea how you've connected things up), at least we know that mode 1 works and you can take out that bit of the test =),

if you take out the mode test, and decrease the waits & timout, you can poke things and see what causes the connection issue

31 Jan 2012

Hey guys, I noticed the same thing while trying to interface a NTSC lcd controller - the SPI would shout back 'roughly' what was going out on MOSI whenever I touched the wires - even on the insulated portion. I think it had to do with my not knowing the pinout of the controller, so I was trying to input to an output or vis versa probably... Check your connections and send us a diagram of your hookup if possible :)!

31 Jan 2012

I thanks for your answer. I checked the pin conenction. For me, it is okay ! The application is bellow : /media/uploads/gege089/capture_du_2012-01-31_23-00-06.png

And my pcb is : /media/uploads/gege089/capture_du_2012-01-31_23-03-24.png

So,

1NC
2GNDp1
3SCLp14
4ScLKp13
5AUX +NC
6MOSIp11
7MISOp12

<<edit>>

VBAP has been connected on 3.3 VDC

05 Feb 2012

I waked up this morning with a very good idea !

Quote:

So, a relatively high value pull-up or pull-down value, say 10k, should be placed on the MISO at least. It also makes sense to pull the other master generated signals into a default state when the master outputs are tri-stated, such as when the uC master is in reset.

:( I have no pull-up resistor in my device. That may be my issue ?

05 Feb 2012

The pullup and pull down resistors are internal to the mbed - it just means that if a signal is too high or too low for the mbed's logic range, then it can enable a pathway that goes input->resistor->(GND for pull down/Vdd for pullup)->internal logic gates. I think the SPI class defines MISO to be pullup by default, so as long as your device is providing over 1v and under 3.3v for logic 1 you should be good... What does the data sheet say the serial output voltage is?