2
\$\begingroup\$

I am working on a project using two daisy-chained AD5207 digital potentiometer ICs controlled by the SPI interface of an STM32 micro. I'm following the directions given on P.9 of the AD5207 datasheet, but I am a little confused about how to properly format the serial data, since the AD5207 wants 10 bits of serial information, whereas the SPI hardware port will write bits in multiples of 8, meaning there will be extra unused bits at the beginning or end.

I can think of two ways this could be handled. One is treating each 10-bit packet as a 16-bit write, with 6 blank bits at the beginning or end, and doing two 16-bit writes in a row. Another would be offsetting the two 10-bit packets within 3 8-bit writes, with 4 blank bits at the beginning or end. Please advise which method is correct.

Here is the example code for each scenario. Which is correct?

static void ad5207_write_spi_dual(uint8_t pot, uint8_t val1, uint8_t val2) {
  // pot selects pot channel a or b, val1 controls IC 1, val2 controls IC 2

  #if 1

  // 4 8-bit writes, leading 0's
  uint8_t spi_block[4] = { 0, 0, 0, 0 };

  spi_block[0] = pot;
  spi_block[1] = val2;
  spi_block[2] = pot;
  spi_block[3] = val1;

  #elif 0

  // 4 8-bit writes, trailing 0's
  uint8_t spi_block[4] = {0, 0, 0, 0};

  spi_block[0] = (pot << 6) | (val2 >> 2);
  spi_block[1] = (val2 << 6) & 255; 
  spi_block[2] = (pot << 6) | (val1 >> 2);
  spi_block[3] = (val1 << 6) & 255;

  #elif 0

  // 3 8-bit writes, leading 0's

  uint8_t spi_block[3] = {0, 0, 0};

  spi_block[0] = (pot << 2) | (val2 >> 6);
  spi_block[1] = pot | ((val2 << 2) & 255);
  spi_block[2] = val1;

  #else

  // 3 8 bit writes, trailing 0's
  uint8_t spi_block[3] = { 0, 0, 0 };

  spi_block[0] = (pot << 6) | (val2 >> 2);
  spi_block[1] = (pot << 4) | ((val2 << 6) & 255) | (val1 >> 4);
  spi_block[2] = (val1 << 4) & 255;

  #endif

  HAL_GPIO_WritePin(SPI1_SEL_GPIO_Port, SPI1_SEL_Pin, GPIO_PIN_RESET);

  delay(1);

  HAL_SPI_Transmit(&hspi1, (uint8_t*) spi_block, sizeof(spi_block), 5);

  delay(1);
  HAL_GPIO_WritePin(SPI1_SEL_GPIO_Port, SPI1_SEL_Pin, GPIO_PIN_SET);

  delay(1);
}

Here is the serial data word format defined by the datasheet, and the daisy chain instructions given on P.9 for reference:

enter image description here

The serial-data-output (SDO) pin contains an open drain n-channel FET. This output requires a pull-up resistor in order to transfer data to the next package’s SDI pin. The pull-up resistor termination voltage may be larger than the VDD supply of the AD5207 SDO output device, e.g., the AD5207 could operate at VDD = 3.3 V and the pull-up for interface to the next device could be set at 5 V. This allows for daisy chaining several RDACs from a single processor serial-data line. The clock period may need to be increased when using a pull-up resistor to the SDI pin of the following devices in series. Capacitive loading at the daisy chain node SDO–SDI between devices may add time delay to subsequent devices. User should be aware of this potential problem in order to successfully achieve data transfer. See Figure 3. When configuring devices for daisy-chaining, the CS should be kept low until all the bits of every package are clocked into their respective serial registers, ensuring that the address bit and data bits are in the proper decoding location. This requires 20 bits of address and data complying with the data word in Table I if two AD5207 RDACs are daisy chained.

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

SDO is delayed by 10 bits (clock cycles) compared to SDI. When /CS is let high, last 10 bits seen on SDI are interpreted as a serial data according to the table I.

It means, the first chip in the chain will be configured by the last 10 bits clocked out. That is last octet + 2 LSBs from previous octet. Next chip in the chain will be configured by bits on position 11 to 20 counted from the last bit clocked out. That is 6 MSBs from last-but-one octet and 4 LSBs from the previous octet. You can pad this by as many bits as you want, the only significant are last 20 bits clocked out before raising the /CS.

So from practical purposes, you probably want to clock 3 octets in format xxxxAADD DDDDDDAA DDDDDDDD (shown from MSB to LSB in order in which they are sent on SPI).

\$\endgroup\$
1
  • \$\begingroup\$ So the method of 3 8-bit writes with leading zeros is correct? Thanks! \$\endgroup\$ Commented Feb 15, 2023 at 17:11
1
\$\begingroup\$

The AD5207 doesn't care about your silly little bytes. You have to send 10 bits for the second potentiometer, then another 10 bits for the first potentiometer, then set /CS to high.

All the potentiometers form one big shift register. Bits that you send earlier will get shifted farther, so if you send too many, it's the bits that are sent first that fall off the end. Therefore that's where the padding bits must be.

\$\endgroup\$
1
  • \$\begingroup\$ "The AD5207 doesn't care about your silly little bytes" epic comment 😹 🤟 \$\endgroup\$ Commented Feb 15, 2023 at 17:10

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.