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.
Features:
Requirements:
Check for required software:
which python3 which make which sdcc which git
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 https://github.com/piotrb5e3/AT89C2051_programmer.git
2. Open AT89C2051_programmer/AT89_prog/AT89_prog.ino file in Arduino IDE.
3. Build and upload the sketch from the Arduino IDE.
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
1. Clone a simple blink project.
cd ~ git clone https://github.com/piotrb5e3/hello-8051.git cd hello-8051/
2. Build the application.
make
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
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.
#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 #define INTERRUPTS_PER_SECOND 5208
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) { timer_counter--; 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).