0
\$\begingroup\$

I've got an accelerometer connected to a PIC24FJ family controller via SPI. I'm trying the simplest operation--reading an ID register whose contents never change--to confirm that I can make it work. While the problem could be due to one of many things, I'm working with the SPI peripheral for the first time and code generated by MCC.

What I'm wondering is, in an 8-bit transfer, does it generate 8 clocks to send the register request, followed by 8 more clocks to read the reply? Or do I have to get the reply byte separately? I've looked at both the datasheet for the processor as well as the Family datasheet, and neither seems to show this. There are plenty of pictures of waveforms for audio streams, and slave operation but I couldn't find something this simple. There is an illustration of an 8-bit transfer, but no suggestion as to what happens after the first 8 bits go out.

As for the peripheral, you put something to the transmit register, wait for a ready bit, and go pick up your results from the receive register. Since they don't explain what happens, that makes it magic. When I read the source code, I end up in the same place. Stuff the register, pick up results from the other register. I could look up other processors, but I couldn't be confident that the peripheral works the same way.

I haven't put a 'scope on it yet, because it's a BGA chip, and the PIC is a pretty find pitch. It may come to that anyway, but there's a chance someone could help if in fact there's something I don't understand about the transfer process.

. . .

Bonus question: What data do you clock out when you are just trying to read a byte from the chip? In this case, writing all zeroes would be a write request to a register you're not supposed to access. So there's got to be a better answer.

\$\endgroup\$
5
  • \$\begingroup\$ To answer your last question, in general, once you've clocked out the command, you can clock out anything while clocking in the result. The slave should ignore the input data, as long as it is clocking out data and chip select remains asserted. To abort a command, de-assert chip select and then re-assert it for the next command. \$\endgroup\$
    – DoxyLover
    Commented Aug 6, 2017 at 1:13
  • \$\begingroup\$ One obvious question for you is are you handling chip-select properly? \$\endgroup\$
    – DoxyLover
    Commented Aug 6, 2017 at 1:14
  • \$\begingroup\$ Thank DoxyLover for that--now the answer is more important because it explains why two successive reads (I tried) don't necessarily produce the data, if CS goes inactive in between the two. I may try a "16 bit transfer" just to try to fool it. \$\endgroup\$
    – gbarry
    Commented Aug 6, 2017 at 1:17
  • \$\begingroup\$ I don't know about CS--I assume the "magic" peripheral does it correctly. It's supposedly configured for 4-wire. I never had a problem bit-banging this. PIC peripherals...not so much :) Given infinite time, I can figure it out. I don't have that right now. \$\endgroup\$
    – gbarry
    Commented Aug 6, 2017 at 1:21
  • \$\begingroup\$ "what happens after the first 8 bits go out" - Nothing happens. You asked it to clock 8 bits, so it clocked 8 bits. Job done. If you want another 8 bits you have to ask for another 8 bits. Your PIC is (in this case) the master of the SPI bus, and your code is the master (hopefully) of the PIC. Nothing happens unless you tell it to. \$\endgroup\$
    – brhans
    Commented Aug 6, 2017 at 15:07

1 Answer 1

1
\$\begingroup\$

I've been using the SPI on 18F using MCC generated code so am familiar with your difficulty.

SPI is more like exchanging register values between master and slave; communication is always two ways. For every byte you send, you will also receive a byte.

Typical communication is like this:

  1. Master selects the slave by driving its Slave Select input low. You must add this code yourself. MCC does not generate this! Just define one PIC IO pin as output connect that to the slave device and drive it with your own code.

  2. Master sends a command byte to the slave serially through the MOSI pin (Master Out, Slave In), toggling SCK clock line for each of the 8 bits.

  3. Slave recognizes the received command byte and stores the requested data into its output buffer ready to be shifted out.

  4. Master sends another byte with just zeros. The slave ignores these zeros (but check your datasheet).

  5. While the master is clocking out the zero byte in step 4, it is also receiving the data byte that the slave is sending via the MISO pin (Master In, Slave Out).

  6. Raise SS (Slave Select) high to tell the Slave the transaction is complete.

For example, let's say your slave slave returns a 16-bit reply when sent a certain command byte. This means you would need to send 3 bytes: the command byte and two zero bytes. You would also get 3 bytes back.

The first byte you received would have been when you sent the command byte. This is generally ignored; the slave usually just sends back a zero byte since it did not get a command yet and doesn't know what the master wants. The second and third byte would be the 16-bit reply from the slave from the command it was sent.

This is a general description. Read your datasheet for specifics. But this is a very typical transaction that might help you understand how SPI works.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.