Here is my Python code so far:
from Adafruit_BBIO.SPI import SPI
spi = SPI(0,0)
My question is how do I read register 0x00? The device I am working with shoudl have 0x17 in that register. It is it's deviceID.
The docs for that device read:
"A read operation, defined as data going from the ADNS-
3080 to the micro-controller, is always initiated by the
micro-controller and consists of two bytes. The first byte
contains the address, is sent by the micro-controller over
MOSI, and has a “0” as its MSB to indicate data direction.
The second byte contains the data and is driven by the
ADNS-3080 over MISO. The sensor outputs MISO bits on
falling edges of SCLK and samples MOSI bits on every
rising edge of SCLK."
So, I figured I should be able to do this:
spi.writebytes([0x00])
val = spi.readbytes(1)
And then val should be 0x17, but that's not what I get. What should my code look like?
How do I read a register via spi?
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- tdicola
- Posts: 1074
- Joined: Thu Oct 17, 2013 9:11 pm
Re: How do I read a register via spi?
Oh it sounds like you want to use the xfer2 (transfer) function from the library. The BBIO SPI support is actually a fork of the python spidev module and you can see a little summary of the functions it exposes here: http://tightdev.net/SpiDev_Doc.pdf With SPI there are basically 3 types of actions you can perform:
- Read, just reading bytes from the MISO pin
- Write, just writing bytes out the MOSI pin
- Transfer, both reading from MISO and writing to MOSI at the same time
Because you're trying to read and write in the same SPI 'call' (i.e. in the same transaction where the device's CS/chip select pin is enabled) you want to use the transfer function. If you used a write and then read it actually turns into to two separate SPI transactions where the CS pin is enabled and disabled between them. For some devices you don't want that behavior and instead need the CS pin to stay enabled during the write and read, that's where the transfer function comes in handy.
One thing to note is that there are actually two transfer functions, xfer and xfer2. The linked PDF mentions the difference is with how the CS pin acts. With xfer it disables and enables the CS pin after sending/receiving each byte, whereas with xfer2 it just keeps the CS pin enabled the entire time bytes are read and written. Most devices expect behavior like xfer2, but check the datasheet and its SPI / timing diagrams to see if they show the CS pin being disabled after every byte.
So ultimately you want to switch your code to look something like:
- Read, just reading bytes from the MISO pin
- Write, just writing bytes out the MOSI pin
- Transfer, both reading from MISO and writing to MOSI at the same time
Because you're trying to read and write in the same SPI 'call' (i.e. in the same transaction where the device's CS/chip select pin is enabled) you want to use the transfer function. If you used a write and then read it actually turns into to two separate SPI transactions where the CS pin is enabled and disabled between them. For some devices you don't want that behavior and instead need the CS pin to stay enabled during the write and read, that's where the transfer function comes in handy.
One thing to note is that there are actually two transfer functions, xfer and xfer2. The linked PDF mentions the difference is with how the CS pin acts. With xfer it disables and enables the CS pin after sending/receiving each byte, whereas with xfer2 it just keeps the CS pin enabled the entire time bytes are read and written. Most devices expect behavior like xfer2, but check the datasheet and its SPI / timing diagrams to see if they show the CS pin being disabled after every byte.
So ultimately you want to switch your code to look something like:
Code: Select all
from Adafruit_BBIO.SPI import SPI
spi = SPI(0,0)
// Transfer 0x00, 0x00. The first 0x00 is the register to read and the second
// 0x00 is a dummy byte that pads out the length of the transfer to 2 bytes in length.
result = spi.xfer2([0x00, 0x00])
// The result of the transfer will be an array of 2 bytes where the first byte is what
// was read while the first byte was written and the second byte is what was read
// while the second byte was written. We care about the second byte since that's
// where the chip's response after it sees the first byte will be.
val = result[1]
-
- Posts: 2
- Joined: Fri Feb 15, 2013 7:35 pm
Re: How do I read a register via spi?
Thanks for this excellent information. That leaped a hurdle for me. Tonight I am miles ahead of where I was last night.
- tdicola
- Posts: 1074
- Joined: Thu Oct 17, 2013 9:11 pm
Re: How do I read a register via spi?
No problem, glad I could help and good luck with the project!
- hari_cet
- Posts: 2
- Joined: Sun Sep 20, 2015 9:45 am
Re: How do I read a register via spi?
Hello
How to read a 16 bit register using xfer2 command
I have a register with 16 bit address.
the command i used is
value=spi.xfer2([0x43,0x31]) as theaddress of my register is 0x43C1.
The output value is 32 bit
Help in sorting out the problem is highly appreciated
thanks
How to read a 16 bit register using xfer2 command
I have a register with 16 bit address.
the command i used is
value=spi.xfer2([0x43,0x31]) as theaddress of my register is 0x43C1.
The output value is 32 bit
Help in sorting out the problem is highly appreciated
thanks
- tdicola
- Posts: 1074
- Joined: Thu Oct 17, 2013 9:11 pm
Re: How do I read a register via spi?
Ah, yeah Python can be a little tricky since it doesn't have explicit 16 bit number types. If you're sending a 16-bit address (0x43C1) and then expect to read 16-bits you actually want to add two zero bytes to the xfer2 command. That will twiddle the SPI clock lines, etc. to read the 16-bit response after sending the 16-bit address. So do something like:
Then the response should be 4 bytes long and the last 2 are your 16-bit response. You can grab these and assemble them into an unsigned 16-bit value by doing (assuming the high order byte comes first and low order byte comes second, i.e. big endian byte order):
The '& 0xFF' is the trick to help ensure python interprets the value as an 8-bit unsigned type instead of some arbitrarily long signed value. It's basically chopping off all other data beyond the 8 bits we care about and ignoring any negative value sign extension, etc. You can do this to turn any Python number into an unsigned value of a specific length, so a 16-bit unsigned value would be & 0xFFFF. Hope that helps, thanks!
Code: Select all
value=spi.xfer2([0x43,0x31,0x00,0x00])
Code: Select all
low_byte = value[2] & 0xFF
high_byte = value[3] & 0xFF
result = high_byte << 8 & low_byte
- hari_cet
- Posts: 2
- Joined: Sun Sep 20, 2015 9:45 am
Re: How do I read a register via spi?
Thank you very much.
Please be positive and constructive with your questions and comments.