8051… this is historically one of the most important microcontroller the world has seen so far. To say it in one sentence..Its a piece of beauty.
What I present in this article is the first assembly language program that I ran on the 8051 microcontroller. If you have seen my “Blinking LED using Arduino”, we do a very similar thing here. However the difference is, blinking an LED using an Arduino board is just too easy and for the most part of it we are unaware of what is happens in the various registers. Although there is an easier way to program an 8051 using the C language, I intend to program it using the assembly language here simply because it gives me a better sense of control over the registers and also it is a fairly easy program to be implemented in assembly. Also programming in assembly makes you think a bit harder which can be fun if you want it to be.
Okay enough of the intro .. lets start.
The following components are required in this project:
- An 8051 board. I am using the 89V51RD2 starter kit. I got it from here: 8051 Starter Kit
- A programmer
- Programs like Keil and flashmagic to write the program and upload it to the microcontroller.
- Connecting wires.
First things first, the objective. Our aim here is to connect LEDs to one of the i/o ports and program the microcontroller such that the LEDs glow for 1 sec and turn off for the next second and they keep doing until the end of time (.. or as long as we supply power to the microcontroller)
Now.. the crystal that is used in my 8051 board oscillates at 11.0592MHz frequency. In other words there are 11.0592 million crystal pulses every second.
Next we look at the two timers (T0 & T1). Irrespective of which mode they are used in, the timers in the 8051 only keep incrementing and they increment by 1 every “machine cycle”. A machine cycle in 8051 requires 12 crystal pulses always. So although different instructions in the “Instruction set” require different number of machine cycles, a timer increments after every machine cycle.
So doing some math here a timer increments
11059200/12 = 921600 times every second
In other words it increases by 1 in 1.085 micro seconds. Here we will be using Timer 0 and will be using it in the 16 bit mode( Timer 0 and Timer 1 each are actually a combination of two 8 bit registers. Timer 0 -TH0 & TL0, Timer 1 – TH1 & TL1). Okay so 16 bits… which means it can count from 0 to (2^16) – 1 i.e from 0 to 65535, after which it will overflow, reset itself to 0 and start all over again. So lets check how much time does it take to do that:
65536 / 921600 = 0.07 sec
Well this is an odd value and it might be a bit tedious to work with such a number. So lets go the other way round. Lets check how many times does it increment in 0.05sec
0.05 * 921600 = 46080 increments.
Since it takes 1/20 th of a second to have 46080 increments, what we need to do is carry out 46080 increments of the timer 20 times to have a delay of 1 sec.
All right then now that we have an algorithm to measure time, now all we have to do is implement it in the timers.
This is done using two Special Function Registers ( SFRs), TCON and TMOD registers. Each one of them has eight bits and every bit has a particular function. The details of the TMOD timer are given below:
Next is the TCON register. In this register only two bits are useful for us at the moment and both of them can be accessed by specially assigned names.
TF0 – This bit sets when the timer 0 overflows.
TR0 – This bit must be set by us to enable the timer.
In our earlier derivation, we said that we need the timer to increment 46080 times to introduce a delay of 0.05s. So we need to determine the starting point for the timer which is (65535 – 46080) = 19455( which in hexadecimal is 4BFFh) i.e. this is the value with which the timer needs to be initialized.
Now that we have all the bits and pieces, here is the algorithm for blinking an led every two seconds(“on” for 1 sec and “off” for the next second)
- Set a flag bit ..say the bit at 20h and set the timer in mode1.
- Store 20 (14 hex) in R0. This is the initialization step.
- Initialize timer0 to 4BFF hex
- Start the timer ( Set TR0)
- Check the TF0 bit. Every time it overflows decrement R0 by 1.
- If R0 is not zero jump back to the initialization process. Else if it is zero depending upon the flag jump to instructions that turn on the led or turn off the led. Change the flag bit to the other state(if flag = 0 initially set it to 1 and vice verse)
- Jump back to the point of initialization.
Here is the final code that I came up with and it appears to be working all right:
I must confess though, that the time delay is not exactly 1 sec. There is an error of a few milliseconds but even then its a pretty good result. Now all that needs to be done is to convert this asm file to a hex file and upload it onto the microcontroller.
There you have it.. blinking LED using 8051. Here is the video Video