One last (maybe) update for those that are interested. Underlined pin names substitute for overlines on actual chips.
Using the 74x165 as an SPI device is possible, but imperfect. Wired as follows, 165 on the left, PIC (SPI master, frame master) on the right:
CP <- SCK : clockQ7
(output) -> SDI (input)CE
(clock enable) <- SDO (data output)PL
(parallel load) <- SS
: (chip select / frame pulse)
- You cannot define the 'inactive' state of SDO. The LSB you write must be 1 to keep CE high when not reading. Transition to high = the 165 stops shifting, so you will lose the first LSB from the 165.
- You cannot tell the PIC to send the frame pulse early enough, so the MSB must also be high in SDO. This delays the 165 from shifting for a clock, so you lose the next LSB.
You can get all the bits from up to three 165s, daisy chained. You need to set the SPI transaction width "one higher" than you are actually using; Set it to 16 bits for a single (8 bit) 165, or set it to 32 bits for two (16 bits) or three (24 bits) 165s.
The data you read in will be rotated and will contain repeated bits; e.g. reading from a single 165 with SPI set to 16 bits will give you a 16 bit value that needs to have bit 8 copied to bit 0, and then needs to be bitwise ANDed by 0xFF. The bit you copy into bit 0 will change for 16 and 32bit SPI modes, but it will always need copied over the LSB.Workaround 2:
Use your own pin for PL
, and tie SS
on the PIC low. Set your pin to be idle high. To read, first toggle your pin low and back to high for at least one clock cycle. Next, wait at least one full clock cycle before issuing the SPI transaction, and write 0x1 in the transaction.
Your data will not be shifted, but the LSB will be lost; the data you read will have the state of D6 in both bit 0 and bit 1.
In both of the above cases, since SDO will be initialized low by SPI, the 165 will be continually shifting its output until you write the first 0x1 and the first read performed will be garbage. You might also need to clear the buffer overflow bit.
Disclaimer: I haven't tried either of these workarounds yet, but I have successfully read from a single 165 by using all 4 SPI wires and writing 0x81. This gives only 6 of the inputs as the MSB is prematurely shifted out by the frame pulse going low immediately before SDO goes low, and the LSB is never shifted out since the SDO LSB being set to 1 stops shifting. With this in mind, both of the workarounds should actually work.
On the good news front, of course the 74x165 works flawlessly if you drive all the pins yourself and don't use SPI.
Here are two scope traces of a read with 0x3B is present on the 74x165 inputs. First, how it looks under software (non SPI) control. This is all correct.
Here is what the logic looks like when using SPI as I described. 0x3B is simply 0x77 shifted right by one. The LSB was lost. The MSB looks right, but is actually unusable as it's the unshifted LSB from the last transaction.