After setup, for every transaction, you need these calls:
spiSelect(&SPID1); // START SPI
spiSend(&SPID1,3,txbuf); // send SPI data txbuf[]
spiReceive(&SPID1,3,rxbuf); // receive SPI data from MCP3208
spiUnselect(&SPID1);
I think spiSend()
and spiReceive()
can be merged in one call of spiExchange
. But the chip select input must see a high pulse between transactions. The data sheet shows DIN is "don't care" after the first transaction.
The spiSend()
, spiReceive()
and spiExchange()
function calls setup the transaction (using DMA), suspends the current thread so other threads can do useful work in the meantime, and when the transaction is finished, it resumes the original thread.
There are several option to schedule the transactions:
- Making a thread with a tight loop with
spiX..()
is a bit too aggressive, perhaps with the spi bitrate set to the slowest possible. I would not recommend.
- Creating a thread with chThdSleepMilliseconds() in the loop is fine, but has a 1 millisecond timing granularity (as configured in firmware: chconfig.h). This is what I'd recommend
- Calling
spiX..()
at k-rate (from the dsp thread), I would not recommend as that makes the time during the transaction unavailable for audio processing... It is possible to do SPI without the spiX..()
calls, by manipulating the memory-mapped IO registers defined in stm32fxxx.h, within k-rate and poll for the result at the next k-rate interval. But such an implementation is very unportable.
The capacitor between pin 2 and 3, I think you're referring to pin 14 and 15. Pin numbering start at a "mark", often a dot, then go around counter-clock-wise. As a starting point I'd suggest a 100nF capacitor across every GND/VDD pair of pins of every chip, close to each pin pair. In this case, pin 15 is the voltage reference input, I'd give it a 100nF capacitor too on each chip. The mcp3208 datasheet has a chapter on Layout Considerations, they recommend a 1uF capacitor "placed as close as possible to the device pin". Such layout considerations are not supercritical to get it to work, but certainly useful to reach best possible performance. But I would not be surprised if it also works fine without any respect for the layout recommendations.