Introduction to 8051 Programming With AT89C2051 (Guest Starring: Arduino)




Introduction: Introduction to 8051 Programming With AT89C2051 (Guest Starring: Arduino)

About: Passionate programmer by day, hardware hacker by night.

The 8051 (also known as MCS-51) is an MCU design from the 80's that remains popular today. Modern 8051-compatible microcontrollers are available from multiple vendors, in all shapes and sizes, and with a wide range of peripherals. In this instructable we will be looking at the AT89C2051 MCU from Atmel.

AT89C2051 is a small (2Kbyte Flash, 128byte RAM), cheap (~$1.40 per chip) microcontroller.

  • 2.7-6V operation
  • 15 I/O lines
  • 2 timers (16 bit)
  • Internal and external interrupts
  • UART
  • On-chip analog comparator
  • Up to 2MIPS with a 24MHz clock

Step 1: Requirements


  • Linux PC (required software: Arduino IDE, git, make, sdcc)
  • Arduino UNO
  • AT89C2051 chip (DIP20 package)
  • 20-pin ZIF socket
  • Optocoupler (preferably MOSFET-output)
  • Arduino prototyping shield
  • 12V power supply
  • 5V power supply
  • 16MHz crystal oscillator
  • 2x 30pF capacitor
  • 100nF capacitor
  • Diode (ex: 1N400X)
  • Resistors (1K, 3K3)
  • Protoboard
  • Jumpers
  • Copper wire

Check for required software:

which python3
which make
which sdcc
which git

Step 2: Building the Programmer

This section will be brief, as I built my programming shield some time ago. I've attached the schematic and pictures of the assembled board. The PDF of the schematic can be found in the repository.

You will have to program the programmer board:

1. Clone the repository.

git clone

2. Open AT89C2051_programmer/AT89_prog/AT89_prog.ino file in Arduino IDE.

3. Build and upload the sketch from the Arduino IDE.

Step 3: Installing Programmer Software

1. Create a python virtual environment.

python3 -m venv venv
. venv/bin/activate

2. Install at89overlord. at89overlord is an Open Source programmer for the AT89C2051 chip written by me.
It's source code can be found here.

pip install at89overlord

3. Verify installation.

at89overlord -h

Step 4: Programming the Chip

1. Clone a simple blink project.

cd ~
git clone
cd hello-8051/

2. Build the application.


3. Connect Arduino to the PC, connect the 12V supply, place the AT89C2051 chip in the ZIF socket.

4. Locate Arduino's serial port.

ls /dev/tty*

5. Upload built IntelHex file to the chip. If your Arduino's port is different from /dev/ttyACM0 you have to pass the correct value with the -p command line parameter.

at89overlord -f ./hello.ihx

Step 5: Assembly

Assemble the circuit according to schematic. A PDF version can be found in the repository.

You should see the green LED flash with a frequency of around 0.5Hz.

Step 6: Code Explanation

#include <mcs51/at89x051.h>
#include <stdint.h>

We start by including the AT89X051 header from sdcc. It contains macros for interacting with registers as if they were variables. We also include stdint.h which contains definitions of uint8_t and uint16_t integer types.

// Assuming oscillator is 16MHz

An interrupt occurs when the Timer0 overflows. It's configured as a single 8bit timer, so this happens every 2^8 processor cycles. One processor cycle takes 12 clock cycles, and thus we arrive at 16000000/12/2^8 = 5208.33333.

volatile uint8_t led_state = 0;
volatile uint16_t timer_counter = INTERRUPTS_PER_SECOND;

We declare the led state control and interrupt counter variables.

void Timer0_ISR(void) __interrupt (1) {
    if(timer_counter == 0) {
        led_state = !led_state;
        timer_counter = INTERRUPTS_PER_SECOND;

Every time the Timer0 overflows the counter is decreased. If it's equal to zero it's reset, and the led state is changed. This occurs around once per second, resulting in ~0.5Hz LED blinking frequency.

int main() {
    TMOD = 0x3;     // Timer mode - 8bits, no prescaler. freq = OSCFREQ/12/2^8
    TL0 = 0;        // Clear counter
    TH0 = 0;        // Clear register
    TR0 = 1;        // Set timer to run.
    ET0 = 1;        // Set interrupt.
    EA = 1;         // Set global interrupt.
    while(1) {
        if (led_state) {
            P1 = 0xFF;
        } else {
            P1 = 0x00;

We configure the timer module and await changes in the led state control variable.
TMOD is the timer mode control register. TL0 and TH0 are Timer0 control registers. ET0 is the enable-timer0 bit in the timer control register (TCON). TR0 and EA are bits in the interrupt enable register (IE).

Step 7: Additional Resources

Arduino Contest 2017

Participated in the
Arduino Contest 2017

1 Person Made This Project!


  • Big and Small Contest

    Big and Small Contest
  • Make It Bridge

    Make It Bridge
  • For the Home Contest

    For the Home Contest



8 months ago

I am trying to replicate this programmer, but i face an issue sourcing the TLP222A optocoupler (or any other optocoupler with a MOSFET as output device). So I am planning to use a pair of transistors to implement the same.

Are there opto-couplers with PNP transistor as output device?

One thing which I didn't understand is what purpose the diode "D1" does in the original schematic ? Is the diode "D1" for limiting the voltage seen at pin A0 of Arduino (to 5V + cut-in voltage of the diode) when the optocoupler is turned on?


Question 3 years ago on Step 6

Hi piotrb5e3,
I find myself into some trouble using the software, maybe you can helpme: I can read the AT89C2051, but I cannot write to it. I get an error message at the Verification step ("at89overlord.at89comm.AT89CommException: Verification error. Mismatch at byte 0x0"), any idea where the error may be?
I use Linux Mint, and the program is a simple blink using P1.3 as an output. Hardware is as suggested in the schematic, and ARDUINO UNO is loaded with the AT89_prog.ino.
Thanks in advance!


Answer 3 years ago

It sounds like a hardware issue.
I'd recheck the circuit:
- check supply voltage to AT89 (should be ~5V)
- check continuity from AT89 legs to Arduino pins
- check that the voltage on the RST pin is between 11.5V and 12.5V during programming


Reply 3 years ago

I tried with a different IR device, to enable the 12V to write. I also reviewed a couple resistors and one of them had a wrong value. No harm, just no current (or just too little) for the circuit to work.
So far, everything works as expected!!!! I could write and then read to check, and the result file is exactly what I flashed at the beginning!
Thanks piotrb5e3, for the project and the support!


5 years ago

I only knew assembly code back then. I forgot everything by now.


5 years ago

Every Microprocessor has its own instruction set. Once you learn that instruction set you can even program it via machine language. I used to do that back then. And there is so many thing you can do with such 8 bit controllers. Did the same with 6502 MPUs as well.


5 years ago

Thanks for sharing :)