Pretty much every time I tried to work with some sort of digital interface I run into some kind of trouble where a logic analyzer would have saved me hours of blind debugging and posting to various forums. Same thing happened when I decided to try the TMP121 temperature sensor from TI which has an SPI interface. It was the first time I worked with SPI on a pic32 and as expected nothing worked for the first try. The code for setting the SPI interface and reading from it seemed correct, I took it from the “32 bit peripheral lib user guide” from Microchip.
//configure SPI OpenSPI1(SPI_MODE16_ON | SPI_SMP_ON | SPI_CKE_ON | MASTER_ENABLE_ON | CLK_POL_ACTIVE_HIGH | SEC_PRESCAL_8_1 | PRI_PRESCAL_16_1, SPI_ENABLE); //start reading T1 mPORTEClearBits(BIT_0); // pull CS low to prepare for reading while(!DataRdySPI1()); T1 = ReadSPI1(); // read 16 bit word mPORTESetBits(BIT_0); // pull CS high
So what else could be wrong ? Well at this point it could be a faulty sensor or incorrect use of the SPI interface maybe I wasn’t generating the clock correctly or maybe some wiring issue. This is the point where you need to have a logic analyzer. While I don’t have a proper logic analyzer I do have a PicKit2 and it can emulate a 3 channel, modest logic analyzer. I hooked up one of channels to the SCK pin and I noticed I wasn’t getting any clock signal. But why isn’t the clock being generated ? The answer came from the Microchip forums, the guys there pointed out that in order to generate the clock signal you have to issue a dummy write. By issuing a dummy write you start generating the clock and you can do the reading. So I added a new line to the code and tried again:
//configure SPI OpenSPI1(SPI_MODE16_ON | SPI_SMP_ON | SPI_CKE_ON | MASTER_ENABLE_ON | CLK_POL_ACTIVE_HIGH | SEC_PRESCAL_8_1 | PRI_PRESCAL_16_1, SPI_ENABLE); //start reading T1 mPORTEClearBits(BIT_0); // pull CS low to prepare for reading SPI1BUF = 0x00; // this sends a 0x00 just to make the clock toggle in order to read while(!DataRdySPI1()); T1 = ReadSPI1(); // read 16 bit word mPORTESetBits(BIT_0); // pull CS high
This time I also connected a second channel from the logic analyzer to the SDI pin on the pic32 (data in) and it worked ðŸ™‚ , here is the capture:
As you can see on channel 2 there are 16 clock cycles corresponding to the 16 bit word sent by the TMP121 and on channel 3 connected to SDI(data in on pic32) is the actual binary temperature. If we analyze the data on Ch3, for every falling SCK edge we get 0001101010100000 we can discard the first bit cause its the sign bit (0 = positive , 1 = negative) and plug the rest of the bits in a calculator just to check the data.
Next we convert to decimal and we get a value ofÂ 6816.
6816 is not quite the number that we were looking for, but remember the data is represented in two’s complement so we have toÂ divide it by 256 to get the actual temperature in degrees C.
The result after division by 256 is 26.625 degrees C. This was the room temperature at the time of this test. From here on everything is simple, I know I’m getting the right data out of the sensor its just a matter of processing and using it. And here is a picture of the PCB I made for the TMP121 in SOT23-6 package. Probably one of the smallest PCB I made at home, 30×10 mm.
Now I’m seriously thinking about getting the Logic Sniffer from Dangerous Prototypes, it’s a must have.