jboyton:
Multi-byte SPI works like this:
- CS is asserted
- The address + R/W bit are sent
- N bytes are read or written (the address auto-increments)
- CS is deasserted
You can't do multi-byte access in reverse order. Only the first address you send matters. If you start at address 6 the next byte you read will be address 7, which is one of the alarm registers.
I don't understand your code: x << 8 will always be zero if x is uint8_t.
OK, I finally have it figured out and it's working!
// read 7 bytes of raw clock data to buffer
void DS3234::_read_time (void)
{
uint8_t x;
*_SS_PORT &= ~_SS_BIT;
_spi_transfer (0x00);
for (x = 0; x < 7; x++) {
*(_buffer + x) = _spi_transfer (x);
}
*_SS_PORT |= _SS_BIT;
}
First of all (now it's so obvious) I have to read up from 0 to 6, not down from 6 to 0. What I need to do is send one byte of 0x00 which means "read register 0" then the next 7 reads actually get register 0 through 6 all during the CS low period.
Two mistakes I made before were:
(1) Reading backwards from 6 to 0
(2) Sending TWO bytes per read (i.e. register address x, read register x) when I should have just read all 7 in one shot.
Lastly, there's nothing wrong with "x << 8" if x is uint8_t because the DESTINATION needs to be of the proper size i.e.:
uint16_t result = (uint8_t data << 8);
I don't know if the compiler "promotes" data to 16 bits to make it work or if it copies the 8 bit value "data" to "result" and then shifts it, but in any case it works.......