Program AT89S52 with Arduino

We are going to use an Arduino Uno as an ISP to program the AT89S52 microcontroller. AT89 series from Atmel are compatible with Intel’s popular 8051 microcontroller.

In order to use Arduino as an ISP, we have to burn the ArduinoISP sketch to Arduino itself. Launch Arduino IDE and open the ArduinoISP sketch from:

File -> Examples -> 11.ArduinoISP -> ArduinoISP

We will be using pins 10-13 of the Arduino, instead of the ICSP header, so we need to define that into the ArduinoISP sketch before we build/upload it. Go to line 81 and uncomment the following:

#define USE_OLD_STYLE_WIRING

Save, Compile and Upload ArduinoISP to Arduino.

Next, we connect the Arduino Uno with the AT89S52 as follows.

Programming the AT89S52 microcontroller with Arduino Uno as an ISP
Programming the AT89S52 microcontroller with Arduino Uno as an ISP

This is a list of the components I used in the above circuit:

  • XTAL 11.0592MHz
  • 2x 22pF capacitors for the crystal
  • 10uF capacitor
  • 220Ω resistor for the LED
  • 10KΩ resistor
  • red LED

I decided to use Keil uVision to build a basic program (blinky) for the AT89S52. You can use the open-source SDCC (C compiler for 8051/AT89SXX) as an alternative. For uVision to support the AT89 targets, I had to install the C51 Development Tools before anything.

We can now start a new Keil uVision project targeting the AT89S52. Select Project -> New uVision Project. On the following dialog select the “AT89S52” target from the “Legacy Device Database” (which was added when we installed the C51 development tools).

AT89S52 target for Keil uVision project
AT89S52 target for Keil uVision project

Press “Yes” on the prompt asking to copy the STARTUP.A51 file into the project.

From the project tree on the left, select the “Source Group 1” item, right click on it and choose “Add new item”. Then select “C File” option and give it a name, e.g. blinky.c. Paste the following code into the newly created tab, which basically turns on and off the connected LED with an approximate delay of 1 second.

#include <REGX52.h>

// This gives ~1s delay for a 11.0592MHz xtal, using timer0
void delay()
{
int i;
for(i=0; i<1000; i++) {
TMOD = 0x01; // Timer0 mode1
TH0 = 0xFC; //initial value for 1ms
TL0 = 0x66;
TR0 = 1; // timer start
while(TF0==0); // check overflow condition
TR0 = 0; // Stop Timer
TF0 = 0; // Clear flag
}
}

void main()
{
P1_2 = 0x00; // all pins of PORT2 declared as output
while(1) {
P1_2 = 1; // pin P1_2 high
delay();
P1_2 = 0; // pin P1_2 low
delay();
}
}

Before we build our program, make sure that you have selected the correct crystal frequency (11.0592MHz in our case) in the project’s target options (Target tab), as well as to also generate the hex file (“Create HEX File” checkbox) in the Output tab.

After you build the above source code, you should end up with a hex file. You can get mine here. We are gonna feed that hex file to AVRDUDE utility that will program our AT89S52 microcontroller through the ArduinoISP. Get the latest avrdude, or use the one supplied with Arduino IDE.

Since AVRDUDE does not support AT89S52 target by default, we will have to add the following lines at the end of our avrdude.conf file:

part
    id               = "89s52";
    desc             = "AT89S52";
    stk500_devcode   = 0xE1;
    signature        = 0x1e 0x52 0x06;
    chip_erase_delay = 500000;
    reset            = dedicated;
    pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                       "x x x x  x x x x    x x x x  x x x x";

    chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                       "x x x x  x x x x    x x x x  x x x x";

    memory "flash"
        size            = 8192 ;             # bytes
        read            = "0 0 1 0 0 0 0 0  x x x a12 a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
        write           = "0 1 0 0 0 0 0 0 x x x a12 a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
        ;
    memory "signature"
        size            = 3;
        read            = "0 0 1 0 1 0 0 0  0 0 0 0 0 0 a1 a0",
                          "0 0 0 0 0 0 0 0  o o o o o o  o  o";
        ;
  ;
part parent "89s52"
    id = "89s51";
    desc = "AT89S51";
    signature = 0x1e 0x51 0x06;
    memory "flash"
        size            = 4096 ;             # bytes
        read            = "0 0 1 0 0 0 0 0  x x x x a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
        write           = "0 1 0 0 0 0 0 0 x x x x a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
      ;
    ;

You can get my avrdude configuration file here.

Having all the pieces together, we can finally burn our program onto AT89S52.

>avrdude.exe -c avrisp -p at89s52 -C my-avrdude.conf -P com3 -b 19200 -U flash:w:blinky.hex:i

avrdude.exe: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.03s
avrdude.exe: Device signature = 0x1e5206 (probably 89s52)
avrdude.exe: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude.exe: erasing chip
avrdude.exe: reading input file "blinky.hex"
avrdude.exe: writing flash (2108 bytes):
Writing | ################################################## | 100% 1.80s
avrdude.exe: 2108 bytes of flash written
avrdude.exe: verifying flash memory against blinky.hex:
avrdude.exe: load data flash data from input file blinky.hex:
avrdude.exe: input file blinky.hex contains 2108 bytes
avrdude.exe: reading on-chip flash data:
Reading | ################################################## | 100% 0.80s
avrdude.exe: verifying …
avrdude.exe: 2108 bytes of flash verified
avrdude.exe: safemode: Fuses OK (E:FF, H:FF, L:FF)
avrdude.exe done. Thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *