Lighting a grid of LEDs by using multiplexing consists of providing current to them row by row (or columns by column). In this way the LEDs are not lit 100 % of the time. For 8 rows the current to a 'ON' LED is flowing only 1/8 = 12.5 % of the time.
Below is an example schema. The rows and columns are controlled by shift registers to reduce the number of needed GPIO pins.
A simplified version of this circuit (no transistors but higher valued resistors) was implemented on a breadboard to control a 8×8 LED matrix.
The shift registers were fed by an Arduino Nano. The code is shown below.
int latchPin = 8;
int clockPin = 12;
int dataPin = 11;
void setup() {
// put your setup code here, to run once:
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(latchPin, LOW);
digitalWrite(clockPin, LOW);
digitalWrite(dataPin, LOW);
Serial.begin(9600);
Serial.println("reset");
}
unsigned char col[] = { // 8x8 smiley
0b01111110,
0b10000001,
0b10100101,
0b10000001,
0b10100101,
0b10011001,
0b10000001,
0b01111110,
};
int row = 0;
void loop() {
digitalWrite(latchPin, LOW);
digitalWrite(clockPin, LOW);
// Switching between MSBFIRST and LSBFIRST mirrors or flips the pattern
shiftOut(dataPin, clockPin, MSBFIRST, 1<<row);
// invert data: no transitor, writing lights led
shiftOut(dataPin, clockPin, MSBFIRST, ~col[row]);
digitalWrite(latchPin, HIGH);
row++;
if (row>7) row=0;
delay(1);
}