9
\$\begingroup\$

I have a project based on a pic 18f4550. To write to a '595 shift register, is there a distinct advantage to using spi over regular io pins? I heard that spi is faster, but I am not sure how. Does it use a different, faster clock than the rest of the chip, or is it simply more efficient? I can bit-bang out a byte through regular io pins in a pretty small number of instructions. Does spi use less processing power? I will be shifting out fairly often during fairly intense calculations, so I want as many cycles as possible dedicated to my process and not shifting out.

My main reason for not wanting to use spi is that my current layout would make it a bit more difficult to access the required pins because I am already using a few of them for other things and would have to shuffle things around. I wanted to find out what benefits there are before I start ripping things up and moving them around.

\$\endgroup\$
1
  • 5
    \$\begingroup\$ You can do SPI by bit-banging. \$\endgroup\$
    – starblue
    Commented Dec 7, 2011 at 7:46

4 Answers 4

17
\$\begingroup\$

Assuming you are comparing an spi peripheral or synchronous serial "engine" in the micro to generating the same sequence via "bit-banging", then yes, it tends to be somewhat faster, but more importantly the processor can hand off an entire byte to the peripheral to send and then do other things while it is transmitted. In the bit-banging case, the processor tends to be tied up during the transmission (though as the micro tends to be the master and most peripherals are fully static, you can probably tolerate pausing mid-byte to service an interrupt or to even poll things - interface-clocked serial ADC and sample-interval tasks being notable examples of exceptions).

On more capable MCU's it may even be possible to program a DMA controller to execute a multi-byte transfer from memory through the SPI engine without further attention from the processor, especially if only data in one direction is important.

But many micro-controller projects end up highly optimized to their task; if you can spare the cycles and tolerate the speed reduction, then complicating your software in order to be able to use whatever GPIOs make the physical layout cleaner is not by any means an uncommon choice.

\$\endgroup\$
5
  • \$\begingroup\$ Yes this ^. As Chris mentions, the biggest advantage of using hardware peripherals is that you can hand off a data byte from a stream to the peripheral and be notified through interrupt if it is finished shifting it out and ready for another byte. This frees up your CPU usage for other things while the byte is being shifted out - which can be a life time in machine cycles given the baud rate of these serial protocols. \$\endgroup\$
    – Jon L
    Commented Dec 7, 2011 at 7:42
  • 3
    \$\begingroup\$ Not a lifetime for SPI. If you're talking about speed, then you might well be running the SPI at 10MHz, which is only 10 PIC instructions at full speed. That's hardly an age. Just about enough time to get your next byte ready. It's barely enough time to service an interrupt. \$\endgroup\$ Commented Dec 7, 2011 at 11:43
  • 2
    \$\begingroup\$ It might be fair to say a lot depends on the intended/required baud rate, which hasn't been stated. However, as I pointed out, if the micro is the master it may be free to be late in sending the next byte, provided the application can tolerate the irregularity/reduction in throughput. \$\endgroup\$ Commented Dec 7, 2011 at 17:01
  • 1
    \$\begingroup\$ @Rocketmagnet, I stand corrected. SPI is a lot faster than I thought - I guess I lumped it in with slower serial protocols such as UART (where 9600 baud is ~ 10 kHz). \$\endgroup\$
    – Jon L
    Commented Dec 7, 2011 at 20:42
  • 1
    \$\begingroup\$ Also note that SPI master is relatively easy to bit bang. SPI slave may be somewhat harder as the chip select & clock transistions need to be specifically timed and handled upon (like an external interrupt pin). I use SPI master bit bang style often in my projects, especially if I don't need high performance but want a clean board (also nice for home etching). Also note that it's common practice to do the opposite: shift data into shift registers (HC595 etc) using SPI and a GPIO (latch pin). \$\endgroup\$
    – Hans
    Commented Dec 8, 2011 at 17:06
10
\$\begingroup\$

Advantages to bit-banging:

  • Absolute control over protocol.
  • If the time to execute instructions on the microcontroller is faster than the SPI's baudrate, it can be faster, but this is unlikely. It would take a very very low speed SPI baudrate with a relatively high speed microcontroller.
  • Can have a smaller latency than a SPI interrupt.
  • Choice of pins.

Disadvantages to bit-banging:

  • Requires a lot more code to handle -Baudrate timing -Reliable sampling of received bits -Process frame boundaries *Each code segment above consumes time that could be spend running other code.

Advantages of SPI:

  • Register configurate handles baudrate timing, received bit sampling, and processing frame countaries
  • Most microcontrollers with SPI have a dedicated interrupt vector for each SPI peripheral (Double check your micro!)
  • Once configured, only need to check if the SPI TX/RX buffer is empty/full and write/read a byte.
  • If DMA is available, the SPI can transmit large buffers of contiguous data without any software interference.

Disadvantages of SPI:

  • An extra peripheral to learn and configure (Is that really a disadvantage?)
  • Requires extra pins or pin multiplexing
  • Extra cost (tends to be negligible with current microcontrollers)
  • I have had noise issues with SPI, but those were on prototype boardsat relatively high speeds (10MHz)
  • Highly restricted pin choice

To me, the advantages of bit-banging are minor compared to the advantages of SPI. The disadvantages of bit-banging are much greater than the SPI's. The main three reasons I can see for choosing bit-banging is for

  1. Custom low-speed protocol
  2. If the communication is low-speed and the rest of the application has low computation requirements
  3. Or if the communication is low speed and pin choice is a major problem
\$\endgroup\$
9
\$\begingroup\$

On the PIC, a conventional bit-bang SPI-style implementation takes about five cycles per bit; with a little work on 18Fxx parts, one can cut that to about four (at the cost of about three cycles per byte of extra overhead). That time is in addition to any time required to fetch data (typically three cycles per byte). So figure about 40-43 cycles per byte. Using the hardware SPI, the speed improves to two cycles per bit plus a couple extra cycles per byte (some other can handle back-to-back transfers, but the PICs I've seen cannot), and while the SPI is sending a byte the processor can fetch the next, allowing an overall time of about 18 cycles/byte--a speed gain of about 2.5x.

\$\endgroup\$
3
  • \$\begingroup\$ Hi. Do you have any tutorial on high-speed bitbanging in PIC assembly? I'm trying to optimize my PIC program, after some head-scraching, I've reached the speed of 5 cycles/bit (set data to HIGH, test bit and set data to LOW, otherwise skip it, set clock to LOW, set clock to HIGH). But it would be interesting to see how someone else might've done it differently. I'm also curious about the 4 cycles/bit solution on the PICF18. \$\endgroup\$ Commented Nov 18, 2022 at 21:24
  • 1
    \$\begingroup\$ On most PICs, I would generally use the five-cycle approach you describe. There are two ways of improving it to four in some situations: (1) either compute a byte whose bits indicate that a bit differs from the previous one, and then use either "btfsc flipBits,_ / btf DATA_PIN," or "btrsc flipBits, / xorwf DATA_PORT,f" [with W holding the proper bit mask]. Alternatively, one might be able to shave off a cycle by using either IORWF or ANDWF to simultaneously preset the data pin to a known state and set the clock to idle. \$\endgroup\$
    – supercat
    Commented Nov 18, 2022 at 21:41
  • \$\begingroup\$ Success. Now I've reached 4 cycles/bit. My new procedure: at initialization, load a bitmask to W, load the byte to common RAM, select the port's bank. To transmit a bit, ANDWF the port register and W, so both clocks and data are set to LOW simultaneously. Then test bit, and either skip it or set data to HIGH, finally set clock to HIGH. Thanks for the tip, it's now as fast as it can be. \$\endgroup\$ Commented Nov 19, 2022 at 23:12
0
\$\begingroup\$

For bit banging(BB) you forgot to mention :

  1. Ties up the processor for the period of the communication. (SPI loads registers then hands back for you to do something else)
  2. Background Interrupts can seriously interfere with the BB code, making it only useful in single threaded designs, remember you BB code has to give 100% attention to dealing with the protocol.
\$\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.