SparkFun Forums 

Where electronics enthusiasts find answers.

Your source for all things Atmel.
By Jpantoga
#16419
Hey everybody!
My name's Joseph, and I am about to enter my junior year of High School. I recently purchased a tri-color LED matrix controller to help me learn programming with an AVR microcontroller. Because I do not have a full understanding of using the backpack via SPI at the moment, I would like to first try programming the onboard ATmega8 myself in order to display a set pattern on the LEDs to verify that I have learned the architecture of the board. However, before I set out to program, I would first like to understand how to use the 74HC595 first. Do any of you have code snippets or links or suggestions on helping me understand the shift register and how to use it with an AVR? Any help would be greatly appreciated.

PS I will be programming in C
User avatar
By bigglez
#17922
Jpantoga wrote:Hey everybody!
I recently purchased a tri-color LED matrix controller to help me learn programming with an AVR microcontroller. Because I do not have a full understanding of using the backpack via SPI at the moment, I would like to first try programming the onboard ATmega8 myself in order to display a set pattern on the LEDs to verify that I have learned the architecture of the board. However, before I set out to program, I would first like to understand how to use the 74HC595 first.
Joseph,

I'm not familiar with the matrix controller (not sure if it's a chip or a module or a commercial product that you have...)

To get started with the AVR you will need to buy (or borrow) development tools. At a minimum you'll need the AVR ATAVRISP Kit or the STK500 ATSTK500 kit. There are non-Atmel alternatives including building your own parallel port adapter. Next you'll need a PC running Atmel AVR Studio.

For the actual hardware you'll need a prototype 'block board' or equivalent to connect several parts together, and a regulated power supply.

Perhaps you have these? Or, access to them through your school?

For the 74HC595 start with the DIP version and a datasheet. Alternatively, look for the Texas Instruments Power Logic version, which can drive much greater current to the load (if you want to connect multiple LEDs or small lamps to the outputs). TI part number:
TPIC6C596D

So far all of these items can be found at Digikey.

The '595 (and TI '596) devices are shift registers (SRs), that require serial data and a clock to shift the data through the 8 shift registers. More than one device can be cascaded, by carrying the QH (DOUT) signal to the SER (SER IN) of the next stage.

Data in the SRs is loaded to separate latches upon another clock signal, RCLK, and provided the outputs (OE) are enabled the data will appear at the outputs.

To know if the device is doing anything you could attach eight LEDs (with current limit resistors) to the outputs, such that a low output turns on the LED. Next you need to feed serial data, SRCLK, and RCLK to the IC, from your AVR. The SRCLR and OE lines can be tied off as they are not needed in a simple experiment, and they should not be left to float either.

For a quick test of the design you could set the SER data, clock the SRCLK once, reset the SER data, wait a quarter second and clock the SRCLK with similar quarter second pauses for seven more times. Nothing will be seen unless the RCLK is also clocked after each SRCLK, so that fresh data from the SR is transfered to the outputs. This will give a single flash passing from one LED to the next.

At this point you will be well on the way to creating your own patterns.

Instead of descrete LEDs you could try a seven segment LED display, eight if you count the decimal point. For this to make any sense you will need to send bit patterns to the LED that create numbers (and limited alphabet) symbols. The AVR can be programmed with a LUT (Look Up Table) to translate data (a byte) in to a pattern (different byte) for display.

Good Luck, Let us know what you invent!

Peter
By mrmeval
#37152
Two places to look http://www.arduino.cc/ and http://www.freeduino.org/

This is the article:
http://www.arduino.cc/en/Tutorial/ShiftOut

But this was meant to drive LED and you can clock data in while the previous data is lighting the LEDs

http://www.arduino.cc/en/Tutorial/LEDDriver

Why the author of the 2nd article didn't use the shiftout function is a mystery as it gets rid of a lot of code.

This for the 2nd link and is only for testing and you'll need to look at the way it's wired carefully. It counts out a number from 0 to 65535 and uses two hef4794 led drivers which have been daisy chained.

I should be able to use 8 ICs, this would drive 64 LEDs but the delays in getting data out to the chips would be long and construction difficult.

I'm curious if a matrix that used only two of these ICs world work but Dallas semiconductor has one IC that can do drive a large number of LEDs easily.

/* Shift Out Data
* --------------
*
* Shows a byte, stored in "dato" on a set of 8 LEDs
*
* (copyleft) 2005 K3, Malmo University
* @author: David Cuartielles, Marcus Hannerstig
* @hardware: David Cuartielles, Marcos Yarza
* @project: made for SMEE - Experiential Vehicles
* Modified pretty radically by mrmeval
*/


int data = 9;
int strob = 8;
int clock = 10;
int oe = 11;
int count = 0;
int dato = 0;
int ack = 13;
void setup()
{
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(strob, OUTPUT);
pinMode(oe, OUTPUT);
pinMode(ack, OUTPUT);
}


void loop()
{
digitalWrite(ack, HIGH);
for (dato = 0; dato < 65536; dato++) {
shiftOut(data, clock, LSBFIRST, (dato >> 8));
shiftOut(data, clock, LSBFIRST, dato);
digitalWrite(oe, LOW);
digitalWrite(strob, HIGH);
digitalWrite(oe, HIGH);
digitalWrite(strob, LOW);
delay(10); // waits for a moment
digitalWrite(ack, LOW);
}
}

Jpantoga wrote:Hey everybody!
My name's Joseph, and I am about to enter my junior year of High School. I recently purchased a tri-color LED matrix controller to help me learn programming with an AVR microcontroller. Because I do not have a full understanding of using the backpack via SPI at the moment, I would like to first try programming the onboard ATmega8 myself in order to display a set pattern on the LEDs to verify that I have learned the architecture of the board. However, before I set out to program, I would first like to understand how to use the 74HC595 first. Do any of you have code snippets or links or suggestions on helping me understand the shift register and how to use it with an AVR? Any help would be greatly appreciated.

PS I will be programming in C
By mrmeval
#38891
http://mrmeval.is-a-geek.net/~jcaldwel/images/4794.pdf

This is pretty crappy as I'm unfamiliar with GEDA and hand drew the chip and connections.

I do not know why but the LED example from the arduino site seems to have the bits backwards. It all works though.

Here is some revised code.
/* Dual hef4794 knightrider toy

hacked and completely redone based on info from

http://www.arduino.cc/en/Tutorial/LEDDriver

* (copyleft) 2005 K3, Malmo University
* @author: David Cuartielles, Marcus Hannerstig
* @hardware: David Cuartielles, Marcos Yarza
* @project: made for SMEE - Experiential Vehicles
*/
*/

int data = 9;
int strob = 8;
int clock = 10;
int oe = 11;
int count = 0;
int dato = 0;
int ack = 5;

void setup()
{
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(strob, OUTPUT);
pinMode(oe, OUTPUT);
pinMode(ack, OUTPUT);
digitalWrite(oe, LOW);
}

void loop()
{
digitalWrite(ack, HIGH);
dato = 1;
for (int i = 0 ; i < 16 ; i++){
shiftOut(data, clock, LSBFIRST, dato>>8);
shiftOut(data, clock, LSBFIRST, dato);
dato = dato<<1;
digitalWrite(oe, LOW);
digitalWrite(strob, HIGH);
digitalWrite(oe, HIGH);
digitalWrite(strob, LOW);
delay(50); // waits for a moment
digitalWrite(ack, LOW);
}
dato = 32768;
for (int i = 16 ; i > 0 ; i--){
shiftOut(data, clock, LSBFIRST, dato>>8);
shiftOut(data, clock, LSBFIRST, dato);
dato = unsigned (dato)>>1;
digitalWrite(oe, LOW);
digitalWrite(strob, HIGH);
digitalWrite(oe, HIGH);
digitalWrite(strob, LOW);
delay(50); // waits for a moment
digitalWrite(ack, LOW);
}

}
/* serially control single bits, useful as single bit I/O, someone else will have to modify to directly accept a 16 bit value.
*/

int data = 9;
int strob = 8;
int clock = 10;
int oe = 11;
int count = 0;
int ack = 13;
int incomingByte;


void setup()
{
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(strob, OUTPUT);
pinMode(oe, OUTPUT);
pinMode(ack, OUTPUT);
digitalWrite(oe, LOW);
Serial.begin(9600);
}

void write16(int x) {
shiftOut(data, clock, LSBFIRST, x>>8);
shiftOut(data, clock, LSBFIRST, x);
digitalWrite(oe, LOW);
digitalWrite(strob, HIGH);
digitalWrite(oe, HIGH);
digitalWrite(strob, LOW);
}

void loop()
{
digitalWrite(ack, HIGH);

if (Serial.available() > 0) {
incomingByte = Serial.read();
Serial.println(incomingByte);
switch (incomingByte) {
case 49:
write16 (1);
break;

case 50:
write16 (2);
break;

case 52:
write16 (4);
break;

case 56:
write16 (8);
break;

case 97:
write16 (16);
break;

case 98:
write16 (32);
break;

case 99:
write16 (64);
break;

case 100:
write16 (128);
break;

case 101:
write16 (256);
break;

case 102:
write16 (512);
break;

case 103:
write16 (1024);
break;

case 104:
write16 (2048);
break;

case 105:
write16 (4096);
break;

case 106:
write16 (8192);
break;

case 107:
write16 (16384);
break;

case 108:
write16 (32768);
break;

case 48:
write16 (0);
break;

case 126:
write16 (65535);
break;

default:
write16 (0);
break;
}
delay(50);
}
}


/*Since I can't seem to read two bytes in a row, I encode thuse
a=16 b=32 c=64 d=128 e=256 f=512 g=1024 h=2048 i=4096 j=8192 k=16384 l=32768
zero sets them all to 0, tilda sets them all on.
ascii codes
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
107 k
108 l
*/