Here is my code for using a single 595 to drive the columns, and hooking up the rows to the Arduino pins themselves. Here I demonstrate a clear delay in each row update, as well as another delay before the image changes. I hope this clears up your confusion, and I apologize for not have a 2 595 setup handy (though I have 2 595s so if this doesn't help you, I'd be more than happy to set it up...), but it should be easy to adapt for a second 595. This supports a variable amount of width and height.
// Pin connected to ST_CP of 74HC595
const int latchPin = 8;
// Pin connected to SH_CP of 74HC595
const int clockPin = 12;
// Pin connected to DS of 74HC595
const int dataPin = 11;
// The pin of the first row of your display
const int row1Pin = 2; // WARNING: All future rows are assumed to be row1Pin + n
// The amount of rows your display has
const int HEIGHT = 3;
// The amount of columns your display has
const int WIDTH = 2;
// The reset pin of 74HC595 (not required as it isn't used, but this pin is pulled low)
const int resetPin = 9;
// Variable used to keep track of currently lit up row
int currentRow = 0;
// Array of rows
int rows[] = {0b11,
0b01,
0b11};
unsigned long lastChange = 0;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(resetPin, OUTPUT);
digitalWrite(resetPin, LOW);
}
/* I don't think this works, but it might with a much higher delay.
void reset() {
pinMode(resetPin, INPUT);
delayMicroseconds(1);
pinMode(resetPin, OUTPUT);
digitalWrite(resetPin, LOW);
}
*/
// enableRow changes the currently enabled row for future calls, it also changes
// the pinMode on the previous row to "INPUT", disabling all lights on that row.
void enableRow(int row) {
if (currentRow != 0) {
pinMode(currentRow, INPUT);
}
currentRow = row;
}
// This is a quick function to test one single LED on your dotmatrix display.
void lightOne(int pos) {
enableRow(row1Pin + int(pos / (WIDTH+1)));
shiftOut(dataPin, clockPin, MSBFIRST, 1 + pos % (WIDTH+1));
}
// This function draws the display stored in "rows".
void displayRows() {
for (int i = 0; i < HEIGHT; i++) {
digitalWrite(latchPin, LOW);
enableRow(row1Pin+i);
// shift out the bits:
shiftOut(dataPin, clockPin, MSBFIRST, rows[HEIGHT-i-1]);
reset();
digitalWrite(latchPin, HIGH);
pinMode(currentRow, OUTPUT); // set the current row's pin as OUTPUT
digitalWrite(currentRow, LOW); // output LOW on currentRow to complete light's circuit and display
delay(3); // time in ms to hold each row lit
}
}
void loop() {
displayRows();
if (lastChange+1000 /* 1000ms between changes */ < millis()) {
for (int i = 0; i < HEIGHT; i++) {
rows[i] = random(4);
}
lastChange = millis();
}
}