NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » SPI Programming
February 10, 2010 by Mujda |
I am using a MAX6675 (googling this gets the datasheet) to take a K-type thermocouple input which then converts it to a SPI format which you should be able to interface directly with the ATmega168. I'm not having much luck though. I've taken the standard thermometer code and hardware from the Nerdkits kit, and simply added the MAX6675 on a breakout board (it's surface mount). There are very few connections to make, simply: 1) Gnd (checked) 2) Vcc (checked) 3) 2xThermocouple inputs - currently unconnected, but chip should communicate this on the SPI interface 4) SS (Slave Select), SCK (SPI clock), SO/MISO (Data) Basically, I'm not getting the SPIF (SPI Interupt Flag) set, which means it's not receiving any data. In 'Main' x remains zero, so neither MSB or LSB were received. When checking the hardware with a digital oscilloscope, it looks like SS is permanently high, and I can't seem to detect a clock signal on SCK. Can anyone help me? Thanks, Mujda See code below: I've not deleted any of the previous code, just added:
|
---|---|
February 10, 2010 by N3Roaster |
It looks like you want the MCU to be in master mode. In order to receive data over SPI in master mode, you must also send data. I know that might not make much sense if the device you're trying to communicate with doesn't even have a MOSI pin to connect to, but that's how it is. If you aren't trying to send data, you won't generate a clock signal and you won't get any data back on MISO. You might also have some trouble with the loops while waiting. The clock rate requested is pretty slow (that chip supports much faster), so it's entirely possible that you're running through those loops faster than you're transmitting/receiving the data, in which case you'll also miss detecting the data. I'm also not seeing where you're getting the data from SPDR. It looks as though your function should always return 0, 1, or 2, but I assume that's just for debugging purposes. |
February 10, 2010 by Mujda |
Thanks N3Roaster, I had assumed that as the MCU was receiving I shouldn't write anything to SPDR. I've adjusted the code to write a byte to SPDR before looking to receive a byte on the SPI. I've also included 'flag' which should be 0,1 or 2 depending on how many SPIF are received and increased the waiting loops to 1000. Is it correct to say that SCK will stop functioning after every byte received, so because I am receiving a 2 byte number, I need to write a byte to SPDR between receieved bytes? First run I set the function to 'return flag;', which was 2 (this is good news :-) ) Then I changed it to 'return data;', which is contantly zero. Frustratingly, my digital scope has stopped working. My digital multimeter gives SCK - Low SS - High MISO - Wandering between 1 & 2 volts (could mean a data flow?) My code is below:
|
February 10, 2010 by pbfy0 |
I don't think that code is quite right, you don't need to add to |
February 11, 2010 by N3Roaster |
No, that part of the code is fine. Since two bytes are being read, the MSB is read first and is shifted to the high byte of data, so what's expected is data to have the top 8 bits set to whatever was read and the lower 8 bits clear. Since the lower byte is all 0, adding SPDR to data just sets the bits in the lower byte. There's no way the addition can carry into the upper byte, so that should be fine. One thing that does concern me a bit is that SS is being pulled low after writing a byte to SPDR. That would typically be done first. Having 0 as the measurement is unexpected, however, as with the TC disconnected, bit D2 should be high. The result should show 4 or 5 if I'm reading the datasheet correctly. One thing that I am noticing that will interfere is that you haven't set CPOL or CPHA. Compare the timing diagrams on page 168 of the ATmega168 datasheet with the timing diagram for the MAX6675. You'll note that you want to sample on the falling edge, not the rising edge of the clock signal. The little blip where the clock signal stops while you load your next byte to write shouldn't matter. It's very short and you aren't setting SS high during that. |
February 11, 2010 by Mujda |
I've swapped the lines of code so now SS is pulled low before enabling SCK. Looking at the timing diagrams I see why I need to do this. I've also set CPOL=0 (which is what is was before, but now I understand why) and CPHA=1 to enable sampling on the falling edge. And, I'm still getting data=0....but I think we're much closer now to the solution. I'll try to get the scope working again (power supply issues) and see what the hardware is actually producing. Here's the modified code:
|
February 12, 2010 by Mujda |
Got the digital oscilloscope working, so have some diagnostic info. The SCK is working, but not quite how I'd expect. - I'm getting a sawtooth waveform, not a square waveform. - I'm getting 2 +ve pulses, then a small delay of about a cycle, then 8 +ve pulses. This is a little odd. I was expecting to get 8 pulses, then a short delay, then 8 pulses (MSB then LSB). SCK seems to produce this output even when all the external SPI connections are disconnected. Any tboughts? |
February 14, 2010 by N3Roaster |
The SCK thing is definitely weird. I just hooked a scope up to a project with a working SPI component and I'm definitely getting square waves. Eight square peaks per byte of communication with a little delay between each group of 8 on SCK. MOSI and MISO are also square, but only on 1 bits (and consecutive 1 bits result in a wider square). In my case I'm using the NK crystal and setting the clock divider to 8 for an expected clock rate of 1.8432MHz. Observed at the scope on SCK, it looks like it takes about 4µs for eight clock cycles and about 2µs delay between each group of 8 which is, checking the math, about exactly what's expected. |
February 15, 2010 by mrobbins (NerdKits Staff) |
Hi Mujda, The MOSI (Master Out, Slave In) pin should also be an output when you're using the ATmega168 as an SPI master. The "sawtooth" you're seeing might be the capacitance of the pin / wire being charged up very slowly by the pull-up-resistor only -- although you do seem to be setting SCK to be an output. Any chance you could post a photo of the scope watching the SCK pin (labeled with voltage and time)? Mike |
February 19, 2010 by Mujda |
Ok, I think the sawtooth SCK trace I was see was simply due to the limits of my scope (Velleman digit HP10) which has 10MS/s. It states its max measurement frequency to be 2MHz, although a square wave of this frequency will have much higher components, so it chops off the corners. Anyway, I've done the obvious and lowered the clock frequency to the lowest possible (f/128), and now I'm getting something looking like a square wave (approx 9microseconds/cycle = 0.11MHz = 14.2/128). I'm getting 15 pulses, but I think the scope may simply be missing the first one when it triggers. I have also been getting the number 32764 out, which from looking at the datasheet, is sensible. With MSB recieved first,
This looks like what you should get, for an opencircuit thermocouple. Unfortunately, connecting a thermocouple doesn't change the outputted number. I think some connections might be loose somewhere, so I'll tidy it all up. I'll also change the code to ensure MOSI is set an an output. I'll then take a shot of the traces I'm getting and post them, see if it'll help. Thanks. |
February 29, 2012 by RogerFL |
Old thread here but I'm trying to do the same project now so I'll hijack it. :) I wonder if it is necessary to "synchronize" using the SS. If you only have one slave, I thought you could just connect that pin to ground and forget about it. No? Did you ever get it working? Want to share the final code? |
Please log in to post a reply.
Did you know that two resistors can be used to make a voltage divider? Learn more...
|