0 evaluări0% au considerat acest document util (0 voturi)
94 vizualizări28 pagini
The 8051 microcontroller has two independent 16 bit up counting timers named timer 0 and timer 1. A timer can be generalized as a multi-bit counter which increments / decrements itself on receiving a clock signal. The maximum time delay possible using a single 8051 timer is ( 216) x (1uS) = 65536uS.
The 8051 microcontroller has two independent 16 bit up counting timers named timer 0 and timer 1. A timer can be generalized as a multi-bit counter which increments / decrements itself on receiving a clock signal. The maximum time delay possible using a single 8051 timer is ( 216) x (1uS) = 65536uS.
The 8051 microcontroller has two independent 16 bit up counting timers named timer 0 and timer 1. A timer can be generalized as a multi-bit counter which increments / decrements itself on receiving a clock signal. The maximum time delay possible using a single 8051 timer is ( 216) x (1uS) = 65536uS.
The 8051 microcontroller has two independent 16 bit up counting timers named Timer 0 and Timer 1 and this article is about generating time delays using the 8051 timers. Generating delay using pure software loops have been already discussed here but such delays are poor in accuracy and cannot be used in sensitive applications. Delay using timer is the most accurate and surely the best method. A timer can be generalized as a multi-bit counter which increments/decrements itself on receiving a clock signal and produces an interrupt signal up on roll over. When the counter is running on the processors clock , it is called a Timer, which counts a predefined number of processor clock pulses and generates a programmable delay. When the counter is running on an external clock source (may be a periodic or aperiodic external signal) it is called a Counter itself and it can be used for counting external events. In 8051, the oscillator output is divided by 12 using a divide by 12 network and then fed to the Timer as the clock signal. That means for an 8051 running at 12MHz, the timer clock input will be 1MHz. That means the the timer advances once in every 1uS and the maximum time delay possible using a single 8051 timer is ( 2^16) x (1S) = 65536S. Delays longer than this can be implemented by writing up a basic delay program using timer and then looping it for a required number of time. We will see all these in detail in next sections of this article. Designing a delay program using 8051 timers. While designing delay programs in 8051, calculating the initial value that has to be loaded inot TH and TL registers forms a very important thing. Let us see how it is done. Assume the processor is clocked by a 12MHz crystal. That means, the timer clock input will be 12MHz/12 = 1MHz That means, the time taken for the timer to make one increment = 1/1MHz = 1uS For a time delay of X uS the timer has to make X increments. 2^16 = 65536 is the maximim number of counts possible for a 16 bit timer. Let TH be the value value that has to be loaded to TH registed and TL be the value that has to be loaded to TL register. Then, THTL = Hexadecimal equivalent of (65536-X) where (65536-X) is considered in decimal. Example. Let the required delay be 1000uS (ie; 1mS). That means X = 1000 65536 X = 65536 1000 = 64536. 64536 is considered in decimal and converting it t0 hexadecimal gives FC18 That means THTL = FC18 Therefore TH=FC and TL=18 Program for generating 1mS delay using 8051 timer. The program shown below can be used for generating 1mS delay and it is written as a subroutine so that you can call it anywhere in the program. Also you can put this in a loop for creating longer time delays (multiples of 1mS). Here Timer 0 of 8051 is used and it is operating in MODE1 (16 bit timer). DELAY: MOV TMOD,#00000001B // Sets Timer 0 to MODE1 (16 bit timer). Timer 1 is not used MOV TH0,#0FCH // Loads TH0 register with FCH MOV TL0,#018H // LOads TL0 register with 18H SETB TR0 // Starts the Timer 0 HERE: JNB TF0,HERE // Loops here until TF0 is set (ie;until roll over) CLR TR0 // Stops Timer 0 CLR TF0 // Clears TF0 flag RET The above delay routine can be looped twice in order to get a 2mS delay and it is shown in the program below. MAIN: MOV R6,#2D LOOP: ACALL DELAY DJNZ R6,LOOP SJMP MAIN
DELAY: MOV TMOD,#00000001B MOV TH0,#0FCH MOV TL0,#018H SETB TR0 HERE: JNB TF0,HERE CLR TR0 CLR TF0 RET Few points to remember while using timers. Once timer flag (TF) is set, the programmer must clear it before it can be set again. The timer does not stop after the timer flag is set. The programmer must clear the TR bit in order to stop the timer. Once the timer overflows, the programmer must reload the initial start values to the TH and TL registers to begin counting up from. We can configure the desired timer to create an interrupt when the TF flag is set. If interrupt is not used, then we have to check the timer flag (TF) is set using some conditional branching instruction. Maximum delay possible using a single 8051 timer is 65536S and minimum is 1S provided that you are using a 12MHz crystal for clocking the microcontroller. Square wave generation using 8051 timer. Square waves of any frequency (limited by the controller specifications) can be generated using the 8051 timer. The technique is very simple. Write up a delay subroutine with delay equal to half the time period of the square wave. Make any port pin high and call the delay subroutine. After the delay subroutine is finished, make the corresponding port pin low and call the delay subroutine gain. After the subroutine is finished , repeat the cycle again. The result will be a square wave of the desired frequency at the selected port pin. The circuit diagram is shown below and it can be used for any square wave, but the program has to be accordingly. Programs for different square waves are shown below the circuit diagram.
Square wave generation using 8051 timer 1KHz Square wave using 8051 timer. MOV P1,#00000000B MOV TMOD,#00000001B MAIN: SETB P1.0 ACALL DELAY CLR P1.0 ACALL DELAY SJMP MAIN DELAY: MOV TH0,#0FEH MOV TL0,#00CH SETB TR0 HERE: JNB TF0,HERE CLR TR0 CLR TF0 SETB P1.0 RET END 2 KHz Square wave using 8051 timer. MOV P1,#00000000B MOV TMOD,#00000001B MAIN: SETB P1.0 ACALL DELAY CLR P1.0 ACALL DELAY SJMP MAIN DELAY: MOV TH0,#0FCH MOV TL0,#018H SETB TR0 HERE:JNB TF0,HERE CLR TR0 CLR TF0 SETB P1.0 RET END 10 KHz square wave using 8051 timer. MOV P1,#00000000B MOV TMOD,#00000001B MAIN: SETB P1.0 ACALL DELAY CLR P1.0 ACALL DELAY SJMP MAIN DELAY: MOV TH0,#0FFH MOV TL0,#0CEH SETB TR0 HERE:JNB TF0,HERE CLR TR0 CLR TF0 SETB P1.0 RET END Object counter using 8051 microcontroller. This article is about a simple object counter/visitor counter using 8051 microcontroller . AT89S51 belonging to the 8051 family is the microcontroller used here. This circuit can count the number of objects passing across a line , number of persons passing through a gate/door and so on. The can be simply divided into two sections i.e. the sensor section and the display section. Sensor. The sensor part consists of a ultra bright led (with focus), and LDR, opamp LM324 and the associated passive components. The LED is placed on one side of the door and the LDR is placed on the other side so that the light from the LED falls directly on the LDR.As you know, the resistance of the LDR has an inverse relationship with the intensity of the light falling on it. The preset resistor R14 is so adjusted that the voltage across the LDR is below 1.5V when it is illuminated. This voltage (labelled A in the circuit diagram) is connected to the inverting input of the opamp which is wired as a comparator with reference voltage 1.5V (set using R15 and R16).Capacitor C1 is meant for bypassing noise or anything like that which may cause false triggering.Resistor R13 is meant to control the current through the LED. When the light is falling on the LDR the voltage across it will be less than the reference voltage and so the output of the opamp remains high. When the light beam is interrupted, the voltage across the LDR goes above the reference voltage and so the opamp output goes low and it indicates a pass. Display section. The output of the opamp is fed to the INTO (interrupt 0) pin of the microcontroller. The microcontroller is programmed to count the number of negative edge pulses received at the INT0 pin and displays it on the three digit seven segment display. Circuit diagram. Object counter using 8051
Program. ORG 000H SJMP INIT ORG 003H // starting address of interrupt service routine (ISR) ACALL ISR // calls interrupt service routine RETI
INIT: MOV P0,#00000000B MOV P3,#11111111B MOV P1,#00000000B MOV R6,#00000000B MOV DPTR,#LUT SETB IP.0 // sets highest priority for the interrupt INT0 SETB TCON.0 // interrupt generated by a falling edge signal at INT0 pin SETB IE.0 //enables the external interrupt SETB IE.7 //enables the global interrupt control
MAIN: MOV A,R6 MOV B,#100D DIV AB ACALL DISPLAY SETB P1.0 ACALL DELAY ACALL DELAY MOV A,B MOV B,#10D DIV AB ACALL DISPLAY CLR P1.0 SETB P1.1 ACALL DELAY ACALL DELAY MOV A,B ACALL DISPLAY CLR P1.1 SETB P1.2 ACALL DELAY ACALL DELAY CLR P1.2 SJMP MAIN
ISR: INC R6 //interrupt service routine RET
DISPLAY: MOVC A,@A+DPTR // display sub routine CPL A MOV P0,A RET
DELAY: MOV R3,#255D // 1mS delay LABEL: DJNZ R3,LABEL RET LUT: DB 3FH DB 06H DB 5BH DB 4FH DB 66H DB 6DH DB 7DH DB 07H DB 7FH DB 6FH END About the program. The program is written so that, it keeps displaying the current value in register R6 on the three digit seven segment display. When ever there is a valid negative going pulse (interrupt) at the INT0 pin, the program branches to the interrupt service routine (sub routine ISR). Subroutine ISR increments the value in register R6, then jumps back to the MAIN loop and the display gets updated by the new value. Notes. Entire circuit can be powered from a 5V DC supply. LDR must be placed in an enclosure so that the light from LED alone falls on it.
This article is about interfacing a hex key pad to 8051 microcontroller. A clear knowledge on interfacing hex key pad to 8051 is very essential while designing embedded system projects which requires character or numeric input or both. For example projects like digital code lock, numeric calculator etc. Before going to the interfacing in detail, lets have a look at the hex keypad. Hex keypad. Hex key pad is essentially a collection of 16 keys arranged in the form of a 44 matrix. Hex key pad usually have keys representing numerics 0 to 9 and characters A to F. The simplified diagram of a typical hex key pad is shown in the figure below.
Hex keypad The hex keypad has 8 communication lines namely R1, R2, R3, R4, C1, C2, C3 and C4. R1 to R4 represents the four rows and C1 to C4 represents the four columns. When a particular key is pressed the corresponding row and column to which the terminals of the key are connected gets shorted. For example if key 1 is pressed row R1 and column C1 gets shorted and so on. The program identifies which key is pressed by a method known as column scanning. In this method a particular row is kept low (other rows are kept high) and the columns are checked for low. If a particular column is found low then that means that the key connected between that column and the corresponding row (the row that is kept low) is been pressed. For example if row R1 is initially kept low and column C1 is found low during scanning, that means key 1 is pressed. Interfacing hex keypad to 8051. The circuit diagram for demonstrating interfacing hex keypad to 8051 is shown below.Like previous 8051 projects, AT89S51 is the microcontroller used here. The circuit will display the character/numeric pressed on a seven segment LED display. The circuit is very simple and it uses only two ports of the microcontroller, one for the hex keypad and the other for the seven segment LED display.
Interfacing hex keypad to 8051 The hex keypad is interfaced to port 1 and seven segment LED display is interfaced to port 0 of the microcontroller. Resistors R1 to R8 limits the current through the corresponding segments of the LED display. Capacitors C1, C2 and crystal X1 completes the clock circuitry for the microcontroller. Capacitor C3, resistor R9 and push button switch S1 forms a debouncing reset mechanism. Program. ORG 00H MOV DPTR,#LUT // moves starting address of LUT to DPTR MOV A,#11111111B // loads A with all 1's MOV P0,#00000000B // initializes P0 as output port
BACK:MOV P1,#11111111B // loads P1 with all 1's CLR P1.0 // makes row 1 low JB P1.4,NEXT1 // checks whether column 1 is low and jumps to NEXT1 if not low MOV A,#0D // loads a with 0D if column is low (that means key 1 is pressed) ACALL DISPLAY // calls DISPLAY subroutine NEXT1:JB P1.5,NEXT2 // checks whether column 2 is low and so on... MOV A,#1D ACALL DISPLAY NEXT2:JB P1.6,NEXT3 MOV A,#2D ACALL DISPLAY NEXT3:JB P1.7,NEXT4 MOV A,#3D ACALL DISPLAY NEXT4:SETB P1.0 CLR P1.1 JB P1.4,NEXT5 MOV A,#4D ACALL DISPLAY NEXT5:JB P1.5,NEXT6 MOV A,#5D ACALL DISPLAY NEXT6:JB P1.6,NEXT7 MOV A,#6D ACALL DISPLAY NEXT7:JB P1.7,NEXT8 MOV A,#7D ACALL DISPLAY NEXT8:SETB P1.1 CLR P1.2 JB P1.4,NEXT9 MOV A,#8D ACALL DISPLAY NEXT9:JB P1.5,NEXT10 MOV A,#9D ACALL DISPLAY NEXT10:JB P1.6,NEXT11 MOV A,#10D ACALL DISPLAY NEXT11:JB P1.7,NEXT12 MOV A,#11D ACALL DISPLAY NEXT12:SETB P1.2 CLR P1.3 JB P1.4,NEXT13 MOV A,#12D ACALL DISPLAY NEXT13:JB P1.5,NEXT14 MOV A,#13D ACALL DISPLAY NEXT14:JB P1.6,NEXT15 MOV A,#14D ACALL DISPLAY NEXT15:JB P1.7,BACK MOV A,#15D ACALL DISPLAY LJMP BACK
DISPLAY:MOVC A,@A+DPTR // gets digit drive pattern for the current key from LUT MOV P0,A // puts corresponding digit drive pattern into P0 RET
LUT: DB 01100000B // Look up table starts here DB 11011010B DB 11110010B DB 11101110B DB 01100110B DB 10110110B DB 10111110B DB 00111110B DB 11100000B DB 11111110B DB 11110110B DB 10011100B DB 10011110B DB 11111100B DB 10001110B DB 01111010B END About the program. Firstly the program initializes port 0 as an output port by writing all 0s to it and port 1 as an input port by writing all 1s to it. Then the program makes row 1 low by clearing P1.0 and scans the columns one by one for low using JB instruction.If column C1 is found low, that means 1 is pressed and accumulator is loaded by zero and DISPLAY subroutine is called. The display subroutine adds the content in A with the starting address of LUT stored in DPTR and loads A with the data to which the resultant address points (using instruction MOVC A,@A+DPTR). The present data in A will be the digit drive pattern for the current key press and this pattern is put to Port 0 for display. This way the program scans for each key one by one and puts it on the display if it is found to be pressed. Notes. The 5V DC power supply must be well regulated and filtered. Column scanning is not the only method to identify the key press. You can use row scanning also. In row scanning a particular column is kept low (other columns are kept high) and the rows are tested for low using a suitable branching instruction. If a particular row is observed low then that means that the key connected between that row and the corresponding column (the column that is kept low) is been pressed. For example if column C1 is initially kept low and row R1 is observed low during scanning, that means key 1 is pressed. A membrane type hex keypad was used during the testing. Push button switch type and dome switch type will also work. I havent checked other types. The display used was a common cathode seven segment LED display with type number ELK5613A. This is just for information and any general purpose common cathode 7 segment LED display will work here.
A Note about 7 segment LED display. This article is about how to interface a seven segment LED display to an 8051 microcontroller. 7 segment LED display is very popular and it can display digits from 0 to 9 and quite a few characters like A, b, C, ., H, E, e, F, n, o,t,u,y, etc. Knowledge about how to interface a seven segment display to a micro controller is very essential in designing embedded systems. A seven segment display consists of seven LEDs arranged in the form of a squarish 8 slightly inclined to the right and a single LED as the dot character. Different characters can be displayed by selectively glowing the required LED segments. Seven segment displays are of two types,common cathode and common anode. In common cathode type , the cathode of all LEDs are tied together to a single terminal which is usually labeled as com and the anode of all LEDs are left alone as individual pins labeled as a, b, c, d, e, f, g & h (or dot) . In common anode type, the anode of all LEDs are tied together as a single terminal and cathodes are left alone as individual pins. The pin out scheme and picture of a typical 7 segment LED display is shown in the image below.
7 segment LED display Digit drive pattern. Digit drive pattern of a seven segment LED display is simply the different logic combinations of its terminalsa to h in order to display different digits and characters. The common digit drive patterns (0 to 9) of a seven segment display are shown in the table below. Digit a b c d e f g 0 1 1 1 1 1 1 0 1 0 1 1 0 0 0 0 2 1 1 0 1 1 0 1 3 1 1 1 1 0 0 1 4 0 1 1 0 0 1 1 5 1 0 1 1 0 1 1 6 1 0 1 1 1 1 1 7 1 1 1 0 0 0 0 8 1 1 1 1 1 1 1 9 1 1 1 1 0 1 1 Interfacing seven segment display to 8051.
Interfacing 7 segment display to 8051 The circuit diagram shown above is of an AT89S51 microcontroller based 0 to 9 counter which has a 7 segment LED display interfaced to it in order to display the count. This simple circuit illustrates two things. How to setup simple 0 to 9 up counter using 8051 and more importantly how to interface a seven segment LED display to 8051 in order to display a particular result. The common cathode seven segment display D1 is connected to the Port 1 of the microcontroller (AT89S51) as shown in the circuit diagram. R3 to R10 are current limiting resistors. S3 is the reset switch and R2,C3 forms a debouncing circuitry. C1, C2 and X1 are related to the clock circuit. The software part of the project has to do the following tasks. Form a 0 to 9 counter with a predetermined delay (around 1/2 second here). Convert the current count into digit drive pattern. Put the current digit drive pattern into a port for displaying. All the above said tasks are accomplished by the program given below. Program. ORG 000H //initial starting address START: MOV A,#00001001B // initial value of accumulator MOV B,A MOV R0,#0AH //Register R0 initialized as counter which counts from 10 to 0 LABEL: MOV A,B INC A MOV B,A MOVC A,@A+PC // adds the byte in A to the program counters address MOV P1,A ACALL DELAY // calls the delay of the timer DEC R0//Counter R0 decremented by 1 MOV A,R0 // R0 moved to accumulator to check if it is zero in next instruction. JZ START //Checks accumulator for zero and jumps to START. Done to check if counting has been finished. SJMP LABEL DB 3FH // digit drive pattern for 0 DB 06H // digit drive pattern for 1 DB 5BH // digit drive pattern for 2 DB 4FH // digit drive pattern for 3 DB 66H // digit drive pattern for 4 DB 6DH // digit drive pattern for 5 DB 7DH // digit drive pattern for 6 DB 07H // digit drive pattern for 7 DB 7FH // digit drive pattern for 8 DB 6FH // digit drive pattern for 9 DELAY: MOV R4,#05H // subroutine for delay WAIT1: MOV R3,#00H WAIT2: MOV R2,#00H WAIT3: DJNZ R2,WAIT3 DJNZ R3,WAIT2 DJNZ R4,WAIT1 RET END About the program. Instruction MOVC A,@A+PC is the instruction that produces the required digit drive pattern for the display. Execution of this instruction will add the value in the accumulator A with the content of the program counter(address of the next instruction) and will move the data present in the resultant address to A. After this the program resumes from the line after MOVC A,@A+PC. In the program, initial value in A is 00001001B. Execution of MOVC A,@A+PC will add oooo1001B to the content in PC ( address of next instruction). The result will be the address of label DB 3FH (line15) and the data present in this address ie 3FH (digit drive pattern for 0) gets moved into the accumulator. Moving this pattern in the accumulator to Port 1 will display 0 which is the first count. At the next count, value in A will advance to 00001010 and after the execution of MOVC A,@+PC ,the value in A will be 06H which is the digit drive pattern for 1 and this will display 1 which is the next count and this cycle gets repeated for subsequent counts. The reason why accumulator is loaded with 00001001B (9 in decimal) initially is that the instructions from line 9 to line 15 consumes 9 bytes in total. The lines 15 to 24 in the program which starts with label DB can be called as a Look Up Table (LUT). label DB is known as Define Byte which defines a byte. This table defines the digit drive patterns for 7 segment display as bytes (in hex format). MOVC operator fetches the byte from this table based on the result of adding PC and contents in the accumulator. Register B is used as a temporary storage of the initial value of the accumulator and the subsequent increments made to accumulator to fetch each digit drive pattern one by one from the look up table(LUT). Note:- In line 6, Accumulator is incremented by 1 each time (each loop iteration) to select the next digit drive pattern. Since MOVC operator uses the value in A to fetch the digit drive pattern from LUT, value in ACC has to be incremented/manipulated accordingly. The digit drive patterns are arranged consecutively in LUT. Register R0 is used as a counter which counts from 10 down to 0. This ensures that digits from o to 9 are continuously displayed in the 7 segment LED. You may note lines 4, 11, 12, and 13 in the above program. Line 4 initializes R0 to 10 (OAh). When the program counter reaches line 11 for the first time, 7 segment LED has already displayed 0. So we can reduce one count and that is why we have written DEC Ro. We need to continuously check if R0 has reached full count (that is 0). In order to do that lines 12 and 13 are used. We move R0 to accumulator and then use the Jump if Zero (JZ) instruction to check if accumulator has reached zero. If Acc=0, then we makes the program to jump to START (initial state) and hence we restart the 7 segment LED to display from 0 to 9 again. If Acc not equal to zero, we continue the program to display the next digit (check line 14). Multiplexing 7 segment display to 8051. Suppose you need a three digit display connected to the 8051. Each 7 segment display have 8 pins and so a total amount of 24 pins are to the connected to the microcontroller and there will be only 8 pins left with the microcontroller for other input output applications. Also the maximum number of displays that can be connected to the 8051 is limited to 4 because 8051 has only 4 ports. More over three 3 displays will be ON always and this consumes a considerable amount of power. All these problems associated with the straight forward method can be solved by multiplexing . In multiplexing all displays are connected in parallel to one port and only one display is allowed to turn ON at a time, for a short period. This cycle is repeated for at a fast rate and due to the persistence of vision of human eye, all digits seems to glow. The main advantages of this method are Fewer number of port pins are required . Consumes less power. More number of display units can be interfaced (maximum 24). The circuit diagram for multiplexing 2 seven segment displays to the 8051 is shown below.
Multiplexing 7 segement display to 8051 When assembled and powered on, the circuit will display the number 16 and let us see how it is done. Initially the first display is activated by making P3.0 high and then digit drive pattern for 1 is loaded to the Port 1. This will make the first display to show 1. In the mean time P3.1 will be low and so do the second display will be OFF. This condition is maintained for around 1ms and then P3.0 is made low. Now both displays will be OFF. Then the second display is activated by making P3.1 high and then the digit drive pattern for 6 is loaded to the port 1. This will make the second display to show 6. In the mean time P3.0 will be low and so the second display will be OFF. This condition is maintained for another 1ms and then port 3.1 is made low. This cycle is repeated and due to the persistence of vision you will feel it as 16. Transistor Q1 drives the first display (D1) and transistor Q2 drives the second display (D2). R11 and R12 are the base current limiting resistors of Q1 and Q2. The purpose of other components are explained in the first circuit. Program. ORG 000H // initial starting address MOV P1,#00000000B // clears port 1 MOV R6,#1H // stores "1" MOV R7,#6H // stores "6" MOV P3,#00000000B // clears port 3 MOV DPTR,#LABEL1 // loads the adress of line 29 to DPTR MAIN: MOV A,R6 // "1" is moved to accumulator SETB P3.0 // activates 1st display ACALL DISPLAY // calls the display sub routine for getting the pattern for "1" MOV P1,A // moves the pattern for "1" into port 1 ACALL DELAY // calls the 1ms delay CLR P3.0 // deactivates the 1st display MOV A,R7 // "2" is moved to accumulator SETB P3.1 // activates 2nd display ACALL DISPLAY // calls the display sub routine for getting the pattern for "2" MOV P1,A // moves the pattern for "2" into port 1 ACALL DELAY // calls the 1ms delay CLR P3.1 // deactivates the 2nd display SJMP MAIN // jumps back to main and cycle is repeated DELAY: MOV R3,#02H DEL1: MOV R2,#0FAH DEL2: DJNZ R2,DEL2 DJNZ R3,DEL1 RET DISPLAY: MOVC A,@A+DPTR // adds the byte in A to the address in DPTR and loads A with data present in the resultant address RET LABEL1:DB 3FH DB 06H DB 5BH DB 4FH DB 66H DB 6DH DB 7DH DB 07H DB 7FH DB 6FH END
Interrupt sources In an 8051 micro controller there are 2 external interrupts, 2 timer interrupts, and 1 serial interrupt. External interrupts are external interrupt 0(INT0) and external interrupt 1 (INT1). Timer interrupts are Timer 0 interrupt and Timer 1 interrupt. A serial interrupt is given for serial communication with the micro controller (transmit and receive) . All these four interrupts, when evoked serves or executes a particular set of predefined activities known asInterrupt Service Routines. Its way of functioning is similar to the subroutines we write while developing a complete program. In the case of 8051, the interrupt service routines(ISR) of each interrupt must begin from a corresponding address in the program memory. This address from which an ISR begins is called the vector address of the interrupt. Interrupt Source Vector address Interrupt priority External Interrupt 0 INT0 0003H 1 Timer 0 Interrupt 000BH 2 External Interrupt 1 INT1 0013H 3 Timer 1 Interrupt 001BH 4 Serial Interrupt 0023H 5 Interrupt Priority All the 5 interrupts of 8051 has got different priorities. Interrupts are serviced according to its priority order. From the table above, you can see that INT0 has the highest priority of 1 and Timer 0 comes next with priority value 2. The order of priority works like this consider a case where two interrupts are raised at the same time one from INT0 and another from Timer 1 interrupt. Now which one would be served first? In such a case, processor would serve the interrupt according to its priority. In our case INT0 is of high priority (priority order 1)and Timer 1 interrupt is of low priority (priority order 4). So processor will execute ISR of INTO first and then later,after finishing ISR of INT0, processor will begin executing ISR of Timer 1 interrupt.
From the figure above, you may note that INTO is an alternate function P3.2 and INT1 is an alternate function of P3.3. A signal received at these pins will evoke the interrupts accordingly. But not all signals will evoke the interrupt! The signal received at pins should be either a low level one or it should be a falling edge signal to evoke the corresponding interrupt. However to serve the interrupt upon receiving the signal at pins, the man who programs 8051 should preprocess a few bits 3 SFRs namely TCON, IE and IP. Lets examine them. TCON
TCON is a bit addressable SFR. Out of the 8 bits, only the lower 4 bits are concerned with external interrupts. The upper 4 bits deals with interrupts from Timers. The lower four bits are TCON.0 (IT0), TCON.1 (IE0), TCON.2 (IT1) and TCON.3 (IE1). You can refer the figure given below for a better understanding. Out of these 4 bits, bits 0 and 1 that means TCON.0 and TCON.1 are concerned with external interrupt 0 (INT0), where as bits 2 and 3 TCON.2 and TCON.3 are concerned with external interrupt 1 (INT1). Out of these bits only TCON.0 and TCON.2 are directly manipulated by the programmer while dealing with an external interrupt. Bits TCON.1 (IE0) and TCON.3 (IE1) are manipulated by the processor itself. An external signal received at INTO would set the bit TCON.1 (also known as IE0) and will be cleared by the processor itself, after it branches to the corresponding ISR located at 0003H. Similarly TCON.3 is set when an interrupt signal is received at INT1 and would be cleared by processor after branching. The other 2 bits TCON.0 and TCON.2 are used for selecting type of signal received. TCON.0 (or IT0) is set to 0 if the interrupt at INT0 is to be evoked by a low level signal. If TCON.0 is set to high, then the interrupt at INT0 would be evoked by a falling edge signal (high to low transition). Same is the case with TCON.1 if set to 0 then low level signal would raise an interrupt at INT1 and if set to high, then a falling edge signal would do the job. IE (Interrupt Enable)
There are 3 bits associated with external interrupts in IE they are bits 0,2 and 7. The main purpose of this SFR is to enable/disable different interrupts based on whether its corresponding bits are set or not. Refer the figure below. IE.7 is known as global interrupt bit which when set to 0 disables all kinds of interrupts in 8051. Only if this bit is set to 1, any kind of interrupt would be enabled in 8051. If this bit is set to 1, programmer can then individually enable or disable all other interrupts INT0, INT1, Timer interrupts (0 and 1) and serial interrupt. IE.0 If set to 1 it enables INT0 and if set to 0 INT0 would be disabled. So in order to enable external interrupt 0 (INT0) IE.7 and IE.0 should be set to 1. IE.2 Similar to IE.0 IE.1 enables/disables external interrupt 1 (INT1). Interrupt Priority (IP)
Basic function of this SFR is to set interrupt priority (IP). By default INT0 is of priority value 1 (which is the highest) and INT1 is of priority value 3 (which is lower than INT0). The programmer can alter this priority, if he wants! If IP.0 is set to 0 and then IP.2 is set to 0 then the priority order changes. INT1 will change to high priority and INT0 will change to lower priority compared to INT1. How to write an ISR (Interrupt Service Routine) An ISR is just like any other subroutine we write inside a program, except for the difference that an ISR must always end with a RETI instruction and not with a RET instruction (as in the case of subroutines). An ISR when evoked, executes a certain lines of code that does some kind of operations. It can be anything as defined by the programmer. The only condition is that the first line of ISR must begin from the corresponding vector address. Vector address of INT0 is 0003H and that of INT1 is 0013H. Note: In some cases the ISR will be too long that it wont be practical to write all codes staring from 0003H or the other vector address. In such cases, ISR can be placed at any other location in program memory and programmer must provide an unconditional jump to the starting address of ISR from the corresponding vector address. Example:- The ISR of INT0 has been written from location 2000H. Now programmer must place an instruction LJMP 2000H at the vector address of INT0 0003H. Note:- Whenever an evoked interrupt is acknowledged and the processor branches to its corresponding vector address, it automatically disables the interrupt in IE register. This disabled interrupt would only be re-enabled upon executing the RETI instruction placed inside the ISR. That is the single reason, a programmer must use RETI inside an ISR instead of RET instruction. Placing RET will also do the job of returning from interrupt routine to main program (the calling program) but the RET instruction will not re-enable the disabled interrupt in IE register. So if an RET is used, the interrupt would be permanently disabled after its first serving of ISR (unless it is enabled again by the programmer at some other part of the same program). So in order to write an ISR for INT0, you have to keep in mind the following things:- 1) Place the ISR for INT0 beginning from its vector address 0003H. If the ISR is too long, place an unconditional jump from 0003H to the starting address of ISR (which is placed at some other location of program memory). The ISR must end with a RETI instruction. 2) Select the triggering signal type of interrupt by setting/clearing TCON.0 bit. TCON.0=1 means interrupt would be triggered by a falling edge signal. TCON.0 =0 means interrupt would be triggered by a low level signal. 3)Set IE.0 =1 to enable the external interrupt 0 (INT0) 4)Set IE.7=1 to enable the global interrupt control bit. 5) Optionally, programmer can alter the priority of INT0 by setting/clearing IP.0 (Note: This step is optional.) Now when it comes to external interrupt 1 INT1 the processes are all same, except for the change in bits that are to be programmed. 1) Place the ISR in vector address of INT1 0013H. Or if the ISR is long, place an LJMP at 0013H to the corresponding starting address of ISR for INT1. 2)Triggering signal type is selected by setting/clearing TCON.2. TCON.2 = 0 triggered by low level signal. TCON.2 = 1 triggered by falling edge signal. 3)Set IE.2 = 1 to enable INT1 4) Set IE.7 =1 to enable global interrupt control bit. 5) Interrupt priority can be altered by changing value of IP.2 (optional). Refer the diagram of IP register given above. How to generate Software Interrupts in 8051? Software interrupts are nothing but an interrupt generated by a program inside the controller. To generate an external interrupt, we need a signal input either at INT0 or INT1 pin of the 8051 micro controller. We have seen that, when an interrupt signal is received at the INTo pin, the TCON.1 bit would automatically get set and that is how the processor knows an interrupt signal has been received at INT0 pin. When TCON.1 is set, processor would immediately acknowledge the interrupt and branch to the corresponding ISR of INT0. While branching to the ISR, processor would also clear the TCON.1 bit. The same happens in the case of INT1 and the associated bit is TCON.3. Now in order to generate a software interrupt, the programmer can manipulate these bits TCON.1 and TCON.3 manually inside a program. An instruction like SETB TCON.1 will activate the interrupt for INT0 (without any external signal at the INT0 pin) inside the controller. Now the processor will acknowledge the interrupt and branch to the corresponding location of ISR for INT0 (vector address 0003H). After branching to ISR, the processor would clear the bit TCON.1. An instruction like SETB TCON.3 would activate the interrupt for INT1 and processor would branch to ISR of INT1 located at vector address 0013H. While branching it would automatically clear the bit TCON.3, so that the programmer can activate the interrupt again inside a loop or some other part of the program. Example Program:- Previously,we have developed a circuit to toggle two LEDs with a single push button switch in 8051. It has been developed for educational purpose. 1) To learn how to interface LEDs to 8051 2) How to use push button switch to manipulate output status of LEDs 3) How to use interrupt and develop an ISR for 8051.
You can see the circuit and article here This article is all about how to interface push button switches to an 8051 microcontroller. Push button switches are widely used in embedded system projects and the knowledge about interfacing them to 8051 is very essential in designing such projects. A typical push button switch has two active terminals that are normally open and these two terminals get internally shorted when the push button is depressed. Images of a typical pushbutton switch is shown below.
Pushbutton switch Circuit diagram.
Interfacng 8051 and pushbutton The circuit diagram for interfacing push button switch to 8051 is shown above. AT89S51 is the microcontroller used here. The circuit is so designed that when push button S1 is depressed the LED D1 goes ON and remains ON until push button switch S2 is depressed and this cycle can be repeated. Resistor R3, capacitor C3 and push button S3 forms the reset circuitry for the microcontroller. Capacitor C1, C2 and crystal X1 belongs to the clock circuitry. R1 and R2 are pull up resistors for the push buttons. R4 is the current limiting resistor for LED. Program. MOV P0,#83H // Initializing push button switches and initializing LED in OFF state. READSW: MOV A,P0 // Moving the port value to Accumulator. RRC A // Checking the vale of Port 0 to know if switch 1 is ON or not JC NXT // If switch 1 is OFF then jump to NXT to check if switch 2 is ON CLR P0.7 // Turn ON LED because Switch 1 is ON SJMP READSW // Read switch status again. NXT: RRC A // Checking the value of Port 0 to know if switch 2 is ON or not JC READSW // Jumping to READSW to check status of switch 1 again (provided switch 2 is OFF) SETB P0.7 // Turning OFF LED because Switch 2 is ON SJMP READSW // Jumping to READSW to read status of switch 1 again. END
The Logic The first instruction MOV P0 #83H - is to turn LED off (Hex 83 in binary = 10000011) and to initialize switches 1 and 2. Switch 1 is connected to port 0.0 and switch 2 is connected to port 0.1. Also note that LED is connected to port 0.7. Note:- Po.0 = 1 means switch 1 is OFF and Po.1 = 1 means switch 2 is OFF. P0.0 = o means switch 1 is ON and p0.1 = o means switch 2 is ON. LED turns ON when P0.7 = 0 and turns OFF when P0.7 = 1 The program has two labels READSW and NXT. Its all about reading switch values that is P0.0 and P0.1. We are using RRC instruction to read switch values. The values of port 0 is moved to accumulator. Since port 0 and 1 are used to interface switches 1 and 2, we can get the values of both port bits in LSBs 0 and 1 of accumulator by using MOV A,P0 instruction. RRC means rotate right through carry. You can learn more about this instruction here 8051 programming tutorial 1 . What RRC do is simple it will move value of port 0.0 to the carry bit. Now we can check the carry bit using instruction JC which means jump if carry is set . If carry is SET then it means port0.0 =1 and this means switch 1 is OFF. If switch 1 is OFF then we have to check status of switch 2 and that is why we jump to label NXT. In the mean time if switch 1 is pressed then value of port 0.0 will be equal to zero. This will get moved to accumulator and hence an RRC will result in carry bit = o. If carry bit = 0 then result of executing JC instruction is negative and it will not jump. The next instruction will get executed that is CLR P0.7. This clears port 0.7 to zero and hence LED will turn ON. Once turned On- LED will be kept On until switch 2 is pressed. The status of switch 2 is checked in NXT label. When NXT is executed, we are using RRC for the second time consecutively. This means, the carry bit now holds the value of P0.1 which is status of switch 2. If carry bit = 1 then switch 2 is OFF. This means LED should not be turned OFF. If carry bit = 0 then LED should be turned OFF (The instruction SETB P0.7 turns LED OFF)
Toggling 2 LED with a pushbutton using interrupt. This circuit demonstrates how to toggle two LEDs with a single push button using the external interrupts. Interrupt is an asynchronous signal (either hardware or software) which indicates the processor to make a change in current execution. When the processor receives a valid interrupt signal it saves the current state and then goes to execute a set of predefined steps called interrupt service routine (ISR). After executing ISR, the processor goes back to the point where it deviated and continues from there. To learn more about interrupts check this link. External interrupt handling in 8051. Circuit diagram.
Toggling LED using 8051 with interrupt In the circuit shown above D1, D2 (the LEDs to be toggled) are connected to P1.0 and P1.1 respectively. R2 and R4 limits the current through the LEDs. The push button switch S2 is connected to the INT0 pin where R1 is a pull up resistor and C4 is the debouncing capacitor. C3, R3 and S3 forms the reset circuitry. Capacitors C2, C2 and crystal X1 are related to the clock circuitry. When powered ON LED D1 will be OFF and and LED D2 will be ON. Whenever push button switch S2 is pressed it creates an interrupt and the software makes the status of P1.o and P1.1 to toggle which gets reflected in the LEDs. Program. ORG 000H // starting address SJMP LABEL //jumps to the LABEL ORG 003H // starting address for the ISR(INT0) ACALL ISR // calls the ISR (interrupt service routine) RETI // returns from the interrupt LABEL: MOV A,#10000000B // sets the initial stage of the LEDs (D1 OFF & D2 ON) MAIN: // main function that sets the interrupt parameters SETB IP.0 // sets highest priority for the interrupt INT0 SETB TCON.0 // interrupt generated by a falling edge signal at INT0 (pin12) SETB IE.0 // enables the external interrupt SETB IE.7 // enables the global interrupt control SJMP MAIN // jumps back to the MAIN subroutine ISR: // interrupt service routine CPL A // complements the current value in accumulator A MOV P1,A // moves the current accumulator value to port 1 RET // jumps to RETI END If you come across any doubts/errors while implementing this circuit, please feel free to ask in our comments section.