Forums

How to get a signal from 74595

Started by kingca 7 months ago11 replieslatest reply 7 months ago59 views
Schematic > https://i.stack.imgur.com/1JQkW.jpg
I used the code as shift_register_write_byte(0xFF); I want to use the shift_register_write_byte function to generate an LED output based on an 8bit data variable. But I did not receive a signal. How can I get a signal? Thank you!


/*---------------------------------------------------------------------------------------------------------------------------------*/
void shift_register_reset(void){
GPIOA->BSRR=GPIO_PIN_9;
Delay_us(5);
GPIOA->BRR=GPIO_PIN_9;
Delay_us(5);
GPIOA->BSRR=GPIO_PIN_9;}

void shift_register_clk_pulse(void){
GPIOA->BSRR=GPIO_PIN_8;
Delay_us(5);
GPIOA->BRR=GPIO_PIN_8;
}

void shift_register_load_pulse(void){
GPIOA->BSRR=GPIO_PIN_10;
Delay_us(5);
GPIOA->BRR=GPIO_PIN_10;
}

void shift_register_write_byte(uint8_t data){
shift_register_reset();
for(int i=0;i<8;i++){

if(((data>>i) &0x01) == 0 ){
GPIOA->BSRR = GPIO_PIN_15;
HAL_Delay(5);
shift_register_clk_pulse();
}
else if(((data>>i)& 0x01) == 1){
GPIOA->BSRR = GPIO_PIN_15;
HAL_Delay(5);
GPIOA->BRR = GPIO_PIN_15;
shift_register_clk_pulse();
}
}
HAL_Delay(5);
shift_register_clk_pulse();
HAL_Delay(5);
shift_register_load_pulse();}
[ - ]
Reply by DilbertoJanuary 11, 2020

Hi, kingca!

   What µController are you using? What IDE are you using? What tools ( compiler, etc. ) are you using?

Are your system working and just this function not, or is your system just dead?

   Bear in your mind that, when asking about embedded programmable electronics that have software, it's much difficult answering without this information.


Cheers!

[ - ]
Reply by CustomSargeJanuary 11, 2020

Hi, Regardless your code, look at the datasheet, this is a 3 stage register - S/R, Latch, 3S Buffer:

1> present serial data at pin 14, clocked into/through by pin 11

2> data from serial register is clocked through (latched) in parallel by pin 12

3> data from parallel register is asserted (enabled) by pin 13

As a 3 stage, it's Real flexible: you can clock in new data, transfer it to the parallel (output) register then assert it when you want. OR you can assert the parallel data, then clock in new serially and assert the new with 1 clock of pin 12. This used to be 2 chips: the serial register (74164) feeding a latch w/3S buffer (74374). Last time I built discrete, it's what I did.

Using your o'scope (you DO have one?!), step through the code and verify (@595 p#):

> serial clear is high (@10)

> {serial data present (@14), then clock high & low (@11)} done 8 times

> transfer clock high & low once (@12)

> enable output (assert data) by low (@13)

Good Hunting  <<<)))


[ - ]
Reply by hodgecJanuary 11, 2020

As Dilberto stated we need a little more information.  Also, I suggest you rename your GPIO_PINS_XX to match the name of the signals on the 74595 as that would help us follow you code better. 

Questions:

1) What is the state of OE ( Output Enable ) pin?

2) Do you have SRCLK and RCLK tied together?

Keep in mind that both clocks are positive edge triggered.  I'm assuming BSRR is set and BRR is clear, but I have no way of knowing that.

[ - ]
Reply by TheCaptainJanuary 11, 2020

If you don't have a scope, the first thing I would do is reduce your clock rate and put an LED on the S/R output.  If you do, then test the o/p for a data stream when the S/R is being loaded.  There is no need to reset the thing each time, the bits will just fall out.

[ - ]
Reply by doctekJanuary 11, 2020

kingca -

All that has been said about the control of the HW is correct, but you should also have a look at your SW as well. The way your if - else if test is written in shift_register_write_byte will cause your data to be shifted right twice each time through the loop. This is not what you want!

[ - ]
Reply by DilbertoJanuary 11, 2020

I don't think so. The 'shift' is inside the if clause and is not been assigned to the 'data' variable.

[ - ]
Reply by doctekJanuary 11, 2020

Quite correct! So data never changes. Putting the statement 

data = data >> 1;

after the else if clause will make it work.


[ - ]
Reply by DilbertoJanuary 12, 2020

In reality, the data variable doesn't need to change, because the shift is

         data>>i

and not

         data>>1

I dislike this type of construction, due to its unneeded complexity, and I must confess that at a first glance I had the same impression as you and only after looking carefully at the code I realized the pitfall.

Cheers.

[ - ]
Reply by doctekJanuary 12, 2020

Right again! The construction completely confused me as I missed the "i". The original code works, but I would certainly not have written it that way.

Sorry for the confusion, but it certainly illustrates the point.

[ - ]
Reply by DilbertoJanuary 12, 2020

Me too. And I forgot to mention the code is also very inefficient, because every time the loop executes, the number of shifts increases, instead of doing just one, as in the code that was in your brain. :-)

If the core is an ARM, the problem is not so big, because of the barrel shifter but, for other processors, it really would take a much longer time than it would need.

Edited: As the number of shifts is in a variable, I suspect that even an ARM core will have to iterate by the number of shifts instead of using the barrel shifter.

As you said, this illustrates the point that, no matter how good a language is, it's impossible to prevent the programmer from writing inefficient code.

[ - ]
Reply by DilbertoJanuary 11, 2020

I guess you're using some flavor of STM32 µController and Atollic Studio or STM32CubeIDE and a GCC C or C++ compiler. Maybe I'm completely wrong, however.

As advice to improve the readability of your code, use the following macros

static __inline void pio_set( GPIO_TypeDef * GpioPortParam, uint16_t u16PinParam )
{
  GpioPortParam->BSRR = u16PinParam ;
}
static __inline void pio_clear( GPIO_TypeDef * GpioPortParam, uint16_t u16PinParam )
{
  GpioPortParam->BRR = u16PinParam ;
}