Attiny13 microcontroller have many unique advantage- low price, small size, versatile functionalities. Although it has small memory size or flash memory, it can be used in sensor and automation circuits. Some of the functionalities it has includes timers, external and interrupt support, PWM, SPI, ADC etc. but it lacks USART/UART hardware support. I used the Atiny13 IC pinout explorer and 74HC595 IC pinout explorer, datasheet alternative free web tool, to know pins functions and capabilities instantly. But as soon as one begins working with it problems start to emerge. The main limitations of Attiny13 MCU is the flash memory size and the I/O pins. Limited flash memory means, many of the Arduino libraries cannot be used. Many of the short coming can be handled such as for USART, we can implement serial communication via software. Other short coming like the flash memory size and limited I/O pins can be addressed too. For memory one can use external EEPROM IC.
Here I wanted to show my experiment with the ATtiny13 and the 74HC595 shift register to expand its output capability and increase the number of controllable pins. Since the ATtiny13 provides only six I/O pins, it quickly reaches its limit when driving multiple devices. The 74HC595, a serial‑to‑parallel converter, can be controlled using just three signals: data, clock, and latch. By dedicating three of the ATtiny13’s pins to these signals, the microcontroller can drive eight outputs through the shift register. In other words, although we sacrifice three pins to control the 74HC595, we gain eight additional outputs — a net expansion that makes the tiny ATtiny13 far more versatile in practical applications.
Circuit Diagram
Shown below is the circuit diagram to connect 74HC595 with Attiny13 to increase output capability.
The circuit is a Serial-to-Parallel Output Expansion system. It allows the ATtiny13 (which has very few pins) to control 8 separate outputs (though only 4 are used here) using only 3 digital lines.
1. The Controller: ATtiny13 (U1)
The ATtiny13 acts as the "brain." It manages two distinct tasks:
Input Sensing: Pins PB3 (3) and PB4 (4) are connected to tactile buttons. These buttons are wired to Ground (GND). When a button is pressed, it completes the circuit, pulling the voltage on that pin to 0V.
Serial Communication: Pins PB0 (5), PB1 (6), and PB2 (7) are used as the control bus for the shift register.
2. The Expander: 74HC595 (U2)
This IC is an 8-bit shift register. It takes data in "serial" (one bit at a time) and outputs it in "parallel" (all 8 bits at once).
Control Interface (The Input Side)
DS (Pin 14 - Data): This receives the 1s and 0s from the ATtiny13.
SH_CP (Pin 11 - Shift Clock): Every time this pin pulses, the 74HC595 "shifts" the bit currently on the Data pin into its internal memory.
ST_CP (Pin 12 - Latch/Storage Clock): Once all bits are shifted in, a pulse on this pin "latches" the data, making it appear on the output pins (Q0–Q7) simultaneously.
Configuration Pins
VCC (16) & GND (8): Power supply (typically 5V).
OE (Pin 13 - Output Enable): Tied to GND. This ensures the outputs are always active.
MR (Pin 10 - Master Reset): Tied to VCC. This prevents the chip from clearing its memory unexpectedly.
3. The Load: LEDs (D1–D4)
The LEDs represent the devices being controlled.
Connection: They are connected to outputs Q1, Q2, Q3, and Q4 (Pins 1, 2, 3, and 4).
Current Limiting: Each LED has a 270Ω resistor (R1–R4) in series. This is critical to prevent the LEDs and the 74HC595 from drawing too much current and burning out.
Common Ground: The cathodes (short legs) of all LEDs are tied to the common Ground rail.
4. Signal Flow Summary
- Input: You press a button connected to PB3 or PB4.
- Processing: The ATtiny13 detects the Ground signal and decides which LED should be on.
- Transmission: The ATtiny13 sends a sequence of pulses (Data and Clock) to the 74HC595.
- Output: The 74HC595 "latches" that data, and the corresponding pin ($Q_1$–$Q_4$) goes High (5V), pushing current through the resistor and lighting the LED.
You can see that the Q0 (Pin 15) and Q5–Q7 are currently unused in this diagram, so one could use them to control 4 additional LEDs or components without needing any extra pins from the ATtiny13.
Program Code
#include <avr/io.h>
#include <util/delay.h>
// Pin definitions
#define DS PB0 // Data (Pin 14 on 595)
#define STCP PB1 // Latch (Pin 12 on 595)
#define SHCP PB2 // Clock (Pin 11 on 595)
// Helper to pulse the clock
void pulseClock() {
PORTB |= (1 << SHCP);
_delay_us(5);
PORTB &= ~(1 << SHCP);
}
// Helper to pulse the latch
void pulseLatch() {
PORTB |= (1 << STCP);
_delay_us(5);
PORTB &= ~(1 << STCP);
}
// Shift out 8-bit data (C90 compatible)
void shiftOut(unsigned char data) {
signed char i;
for (i = 7; i >= 0; i--) {
if (data & (1 << i))
PORTB |= (1 << DS);
else
PORTB &= ~(1 << DS);
pulseClock();
}
}
void sendData(unsigned char data) {
shiftOut(data);
pulseLatch();
}
int main(void) {
// Set PB0, PB1, PB2 as outputs
DDRB |= (1 << DS) | (1 << STCP) | (1 << SHCP);
// Set PB3, PB4 as inputs
DDRB &= ~((1 << PB3) | (1 << PB4));
// Enable internal pull-ups for the buttons
PORTB |= (1 << PB3) | (1 << PB4);
unsigned char input;
unsigned char ledData;
while (1) {
input = 0;
// Read buttons (Inverted logic: 0 when pressed)
if (!(PINB & (1 << PB3))) input |= (1 << 0);
if (!(PINB & (1 << PB4))) input |= (1 << 1);
// Logic adjusted for LEDs on Q1, Q2, Q3, Q4
switch (input) {
case 0: // No buttons pressed
ledData = 0b00000010; // Q1 (D1)
break;
case 1: // PB3 pressed
ledData = 0b00000100; // Q2 (D2)
break;
case 2: // PB4 pressed
ledData = 0b00001000; // Q3 (D3)
break;
case 3: // Both pressed
ledData = 0b00010000; // Q4 (D4)
break;
default:
ledData = 0x00;
break;
}
sendData(ledData);
_delay_ms(50); // Debounce delay
}
return 0;
}
switch statement assigns a specific bit pattern to the ledData variable, which is then passed to the shiftOut function. This function iterates through each bit of the byte, setting the Data Serial (DS) pin accordingly and pulsing the Shift Clock (SHCP) to move the bit into the register. Finally, a pulse to the Storage Clock (STCP) latches the completed byte to the 74HC595's output pins ($Q_0$–$Q_7$), updating the LEDs to reflect the current button state while a small delay provides basic software debouncing.
