HELP: 74hc595 library randomly shifting bits SOLVED

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As the title shows, I have been trying to create a library for the popular shift register, which compiled successfully in Atmel Studio 6. However, in practise, whichever byte I set in the shiftWrite function is meaningless, as the leds are all on, all of the time. If anyone has any ideas for this phenomenon, I would greatly appreciate any replies, and questions surrounding the hardware are welcomed. The library is as follows:

#ifndef shift
#define shift

#include <avr/io.h>
#include <util/delay.h>

//define variables for ease of  use
#define shiftPort	PORTB
#define shiftDDR	DDRB
#define shiftDS		PB0
#define shiftClock	PB1
#define storeClock	PB2

void shiftInit(){
	shiftDDR |= (1<<shiftClock)|(1<<storeClock)|(1<<shiftDS);//Make output lines
}
//Define macros for DS line
#define shiftHigh() (shiftPort |= 1<<shiftDS)
#define shiftLow() (shiftPort &= ~(1<<shiftDS))
 
void shiftPulse(){//Pulse the shiftClock line
	shiftPort |= 1<<shiftClock;//High
	shiftPort &= ~(1<<shiftClock);//Low
}

void shiftLatch(){//Pulse the storeClock line
	shiftPort |= 1<<storeClock;//High
	_delay_loop_1(1);
	shiftPort &= ~(1<<storeClock);//Low
	_delay_loop_1(1);
}

void shiftWrite(uint8_t data){//The main function to send byte: argument is the byte for you to send
	for(uint8_t i=0;i<8;i++){
		if(data & 0b10000000){
			shiftHigh();//MSB is high
		}else{
			shiftLow();//MSB is low
		}//else
		shiftPulse();//Pulse the Clock line
		data = data<<1;//Move next bit to MSB place
	}//For
	shiftLatch();//Move all 8 bits to output latch at once
}//shiftWrite

void wait(){//Function to delay 500ms
	for(uint8_t i=0;i<30;i++){
		_delay_loop_2(0);
	}//For
}//Wait

#endif

 

Last Edited: Thu. Dec 18, 2014 - 05:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try putting a delay to keep clock high, depending on speed of processor I've found this is a factor.

 

void shiftPulse(){//Pulse the shiftClock line
	shiftPort |= 1<<shiftClock;//High
        delay_loop_1(1);
	shiftPort &= ~(1<<shiftClock)//Low
}

Happy Trails,

Mike

JaxCoder.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Mike,

Unfortunately the circuit is still not working. One thing I neglected to mention is that I just have LEDs on Qa and Qh. I sure do wish I had a scope to check the delays needed on things like this!

Ben

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The code looks like it should be OK so I would recheck the connections?

 

Yeah a scope or logic analyzer is really helpful.  I have a Saleae LA that I use all the time and it is a life saver.

Happy Trails,

Mike

JaxCoder.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just have LEDs on Qa and Qh.

And what values are the LEDs series resistors?

 

Do you have a diagram of your setup?  It may have nothing to do with code.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For some reason, everything  changes when I apply or release pressure on the connections, LEDs or resistors (all of them), the lights flicker, and change state (sometimes briefly, sometimes permanently) is this a result of a breadboarded circuit? And its not really possible for me to get a scope or logic analyser, the curse of being a fourteen year old with no money!

Thanks again for your help

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you slow you clock down to a couple of kHz, you can use you PC's sound card as a scope. Mr Google will show how - just ask him: soundcard oscilloscope.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks I might give that a go... And it might be useful to add that the LEDs always seem too turn on in a certain order, Qa then Qh. It might just be a coincidence but it seems a little strange... 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

YOu could always just use the SPI port of the AVR and avoid the fuss.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How would I go about doing this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also I would appreciate it if you could tell me whether this code is correct, for utilising the library (I have defined it as "shift.h" because I am using the Arduino IDE to program my arduino UNO, which does not allow for global libraries)

#include <avr/io.h>
#include <util/delay.h>
#include "shift.h"

int main(){

    shiftInit();
    shiftWrite(0b11111110);
    wait();
    while(1){
  
    }
}

Last Edited: Thu. Dec 18, 2014 - 05:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BenTaylor wrote:

How would I go about doing this?

Connect the SCK on teh '328 to the SHCP input on the  '595.  MOSI on the '328 to the DS input on the '595.  Connect the /SS pin to the STCP inout, BUT BE CAREFUL. You must keep this pin low while the SPI is shifting out, THEN pulse it HIGH, which is not what is normally done in SPI, but since you control the /SS pin this is not a big deal.

 

Now what happens is that SPI shifts out data 8 bits at a time and provides a synchronous clock so you do not have to do all the work.  Pretty much all you have to do is control the /SS line the way you need it to operate.

 

Take a look at page 162 in the datasheet.  There are some code examples as well.  Just remember that you will need to pulse the /SS pin high at the end of transmission rather than bring it LOW at the beginning of transmission, then HIGH.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
is this a result of a breadboarded circuit?
Sure smells like it.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should be able to find a lot of prior 74HC595 discussions on these forums.  One of mine is here:

https://www.avrfreaks.net/comment...

 

That is for 9 bits, but see the loop below.  I don't need to wait for clock toggle; I do "useful stuff" (prepare the next bit) which should take a us or so.

	SPI_SCK = 0;						//	drive the clock low.
	SPI_XFER = 0;						//	drive the latch low.


  	for (looper = 0; looper < SPI_OUTPUTS; looper++)
  		{
		SPI_MOSI = (work & 256) ? 1 : 0;// present the bit to the data line
		SPI_SCK = 1;					// raise the clock to present the bit to the line
		work <<= 1;						// prepare next bit & take some time
		SPI_SCK = 0;					// drop the clock for the next go-round
  		}

	SPI_XFER = 1;						// drive the latch RCLK/XFER high, latching data.
	SPI_MOSI = (work & 256) ? 1 : 0;	// present the 9th bit to the data line; take time
	SPI_XFER = 0;						//	drive the latch low.

As this is CodeVision style, treat it like pseudocode. ;)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry everyone! I forgot to call shiftInit()! Thank you all for your suggestions and help,

Ben

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And to anyone who wants to use my library remember to put 0bxxxxxxxx, not just xxxxxxxx in the function like I did!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So Ben,

 

If it is SOLVED, please edit your thread title with SOLVED at the end.

 

And I guess you could also edit your sample to include your shiftInit() call to help others who want to use your "library".

 

Cheers,

 

Ross

 

Ross McKenzie ValuSoft Melbourne Australia