-1
\$\begingroup\$

I'm trying to daisy-chain two shift register using a STM32F407 discovery kit, but I can't seem to get it right. I use the following function to send a byte to the shift register:

void selector_SendByte(uint8_t byte)
{
  // Define timeout (ms)
  uint16_t clock_timeout = 10000;
  uint16_t latch_timeout = 1000;

  for (int8_t i = 7; i >= 0; --i)
  {
    uint8_t bit = byte & (0x1 << i);    // Read bit
    HAL_GPIO_WritePin(SL_SD_GPIO_Port, SL_SD_Pin, bit);
        
    // Toggle clock
    HAL_GPIO_WritePin(SL_SP_GPIO_Port, SL_SP_Pin, 1);
        
    while (clock_timeout--);

    HAL_GPIO_WritePin(SL_SP_GPIO_Port, SL_SP_Pin, 0);
    }

  // Toggle latch
  HAL_GPIO_WritePin(SL_SS_GPIO_Port, SL_SS_Pin, 1);
    
  while (latch_timeout--);

  HAL_GPIO_WritePin(SL_SS_GPIO_Port, SL_SS_Pin, 0);
}

Where SL_SD is the data, SL_SP is SRCLK, and SL_SS is RCLK.

I defined the following outputs:

#define Q0 0b0000000000000001
#define Q1 0b0000000000000010
#define Q2 0b0000000000000100
#define Q3 0b0000000000001000
#define Q4 0b0000000000010000
#define Q5 0b0000000000100000
#define Q6 0b0000000001000000
#define Q7 0b0000000010000000
// shift register 2
#define Q8  (Q0 << 8)
#define Q9  (Q1 << 8)
#define Q10 (Q2 << 8)
#define Q11 (Q3 << 8)
#define Q12 (Q4 << 8)
#define Q13 (Q5 << 8)
#define Q14 (Q6 << 8)
#define Q15 (Q7 << 8)

When calling selector_SendByte(Q0) and then selector_SendByte(Q8) it doesn't do what I want.

I connected a pull-up resistor of 10 kΩ to each output, and connected LEDs with 440 Ω resistors to each output. For the first shift register I can turn on the LEDs correctly, but the second shift register is not doing what I expected.

Any help on what I am missing?

\$\endgroup\$
3
  • \$\begingroup\$ With that function, you will never be able to send any shift register 2 defines as they will all be 0 as bytes. What you can already do is send one byte and then next byte and data will propagate. But there are many ways to solve this. Pick what you want to do. Send 16 bits and then latch, or send two bytes and then latch, or send two bytes and latch both of them. \$\endgroup\$
    – Justme
    Commented Jan 10, 2023 at 11:42
  • 1
    \$\begingroup\$ doesn't do what I want is not a useful description. What behaviour do you observe, and what do you require? \$\endgroup\$
    – greybeard
    Commented Apr 12, 2023 at 7:47
  • \$\begingroup\$ // Define timeout (ms) I don't think one trip through one of the tight delay loops will take 1 ms. Bug: as clock_timeout is used for every bit in turn, but set to a value purposefully just once, every delay but the first will count down from the maximal value clock_timeout can take on. I don't see a reason to have more than 1 μs between edges, and there is no explicit delay between HAL_GPIO_WritePin(SL_SP_GPIO_Port, SL_SP_Pin, 0) and HAL_GPIO_WritePin(SL_SS_GPIO_Port, SL_SS_Pin, 1);. \$\endgroup\$
    – greybeard
    Commented May 14, 2023 at 4:38

2 Answers 2

0
\$\begingroup\$

That function is written for an 8-bit (not cascaded) shift register.

You have to send 16 bits before toggling the latch. Change the byte and bit variables to a 16-bit (or larger) data type, rename byte (because it is no longer a byte), and change the loop count.

\$\endgroup\$
0
\$\begingroup\$

what I am missing?

You call void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)passing an undocumented value as PinState:

PinState: specifies the value to be written to the selected bit. This parameter can be one of the GPIO_PinState enum values:

  • GPIO_PIN_RESET: to clear the port pin
  • GPIO_PIN_SET: to set the port pin

from

/** @brief  GPIO Bit SET and Bit RESET enumeration */
typedef enum {
  GPIO_PIN_RESET = 0,
  GPIO_PIN_SET
}GPIO_PinState;

Prudent:
uint8_t bit = byte & (1 << i) ? GPIO_PIN_SET : GPIO_PIN_RESET; or
uint8_t bit = (byte >> i) & 1 ? GPIO_PIN_SET : GPIO_PIN_RESET;
know-it-all:
uint8_t bit = (byte >> i) & 1;

For shift-out of more than 8 bits, see CL.'s answer.

\$\endgroup\$
1
  • \$\begingroup\$ Actually the HAL code works with the given inputs. It simply checks if parameter == GPIO_PIN_RESET (which is 0) to set pin low, and in all other non-zero cases it is set high. So this isn't the problem here. Good suggestion how it should be done though. \$\endgroup\$
    – Justme
    Commented Sep 15, 2023 at 4:57

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.