Hi all,
I've been working on a project involving the use of four 74HC595's to control four 8x8 LED matrices in order to form a 16x16 matrix. I was able to create a successful prototype using a single 8x8 matrix but I'm getting a lot of strange things happening when I moved to the cascading shift registers.
My code is below. I'm using the following array to contain the image that is to displayed, unsigned long drawing[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // LED control array
where the first eight bits of the long int contain the information for the first LED matrix, the second eight bits for the second LED matrix, and so on. For the purpose of this post and for my own debugging I have been hard coding values into drawing[0] in order to try and figure out what is going on.
Here's where it get strange, consider the code segment: unsigned long drawing[8] = {32768, 0, 0, 0, 0, 0, 0, 0};
As one would expect this lights a single LED on the matrix in the location it should be. However, if I do this: unsigned long drawing[8] = {1<<15, 0, 0, 0, 0, 0, 0, 0};
the same LED lights up in addition to all the LEDs in the next two shift registers. (1<<15 == 32768). It's as if I wrote a 0xFFFF8000 into the shift registers. And if I shift one any more than fifteen, nothing at all is displayed.
In addition, I've discovered that if I use any number, as long as it does not contain a bit shift operator, it will be displayed correctly. I believe that this means I've got the cascading aspect of it down.
I have tried several different methods of rectifying the problem and have quadruple checked that everything is connected correctly; I just cannot seem to figure out what is going on. I'm hoping that one of you has some insights as to what may be happening and how I can solve this problem. If anymore clarification is needed please let me know, and thanks in advance for your help!
Entire Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#define DIMENSION 16 //length and width of Matrix
#define DIVISOR (int)(1024/DIMENSION) //Poteniometer increment value
// Variables
int latchPin = 8;
int clockPin = 12;
int dataPin = 11;
int rowPot = 1; //Right side potentiometer
int colPot = 5; //Left side pot
int currentRow = 0;
int cRow = 0, cCol = 0; //Cursor row and col
int soft_prescaler = 0;
unsigned long drawing[8] = {1<<8, 0, 0, 0, 0, 0, 0, 0}; // LED control array
void setup()
{
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
DDRD = B11111111; //Sets digital pins 0-7 as outputs
// Calculation for timer 2
// 16 MHz / 8 = 2 MHz (prescaler 8)
// 2 MHz / 256 = 7812 Hz
// soft_prescaler = 15 ==> 520.8 updates per second
// 520.8 / 8 rows ==> 65.1 Hz for the complete display
TCCR2A = 0; // normal operation
TCCR2B = (1<<CS21); // prescaler 8
TIMSK2 = (1<<TOIE2); // enable overflow interrupt
// Sets initial cursor row and column
//cRow = analogRead(rowPot) / DIVISOR;
//cCol = analogRead(colPot) / DIVISOR;
//drawing[0] = (unsigned long)(1<<16);
}
/**
* ISR TIMER2_OVF_vect
* This is the timer interrupt service routine.
* It gets called at 7812 times per second.
*/
ISR(TIMER2_OVF_vect)
{
soft_prescaler++;
if (soft_prescaler == 15)
{
//Turn off currentRow
//PORTD = (0<<currentRow);
currentRow = (currentRow+1) % 8;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, (drawing[currentRow])>>24);
shiftOut(dataPin, clockPin, LSBFIRST, (drawing[currentRow])>>16);
shiftOut(dataPin, clockPin, LSBFIRST, (drawing[currentRow])>>8);
shiftOut(dataPin, clockPin, LSBFIRST, (drawing[currentRow])>>0);
digitalWrite(latchPin, HIGH);
PORTD = (1<<currentRow);
soft_prescaler = 0;
}
}
void loop()
{}