Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

12
This tutorial is downloaded from https://sites.google.com/site/enggprojectece Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling Compiled by: Sivaranjan Goswami, Pursuing M. Tech. (2013-15 batch) Dept. of ECE, Gauhati University, Guwahati, India Contact: [email protected] Note: It is a practical guide in which it is presumed that the reader has already learned about the hardware architecture, programming model, and assembly language programming of 8051 microcontroller. In case you are totally new to 8051 microcontroller I recommend you to read the 8051 Tutorial” available at: https://sites.google.com/site/enggprojectece/my-reading-list It has also been presumed that the reader has at least the beginner level knowledge of computer programming in C language (user defined functions, data types, header files, loops and the flow of a C program). In this tutorial first an introduction to Embedded C is given. A few examples are shown. Then the implementation of timer and interrupt are discussed. (All programs shown here are compiled and executed using Keil µVision 3) Pin Diagram of 8051 (please note the pins used for external interrupts – INT0 & INT1, Serial Port Transmitter – TxD, Serial Port Receiver – RxD, Counter input for Timer-0 – T0 and Counter input for Timer-1 – T1)

description

In this tutorial first an introduction to Embedded C is given. A few examples are shown. Then the implementation of timer and interrupt are discussed. For more tutorials visit: https://sites.google.com/site/enggprojectece

Transcript of Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

Page 1: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

Compiled by: Sivaranjan Goswami, Pursuing M. Tech. (2013-15 batch) Dept. of ECE, Gauhati University, Guwahati, India

Contact: [email protected]

Note: It is a practical guide in which it is presumed that the reader has already learned about the hardware architecture, programming model, and assembly language programming of 8051 microcontroller. In case you are totally new to 8051 microcontroller I recommend you to read the “8051 Tutorial” available at: https://sites.google.com/site/enggprojectece/my-reading-list

It has also been presumed that the reader has at least the beginner level knowledge of computer programming in C language (user defined functions, data types, header files, loops and the flow of a C program).

In this tutorial first an introduction to Embedded C is given. A few examples are shown. Then the implementation of timer and interrupt are discussed.

(All programs shown here are compiled and executed using Keil µVision 3)

Pin Diagram of 8051

(please note the pins used for external interrupts – INT0 & INT1, Serial Port Transmitter – TxD, Serial Port Receiver – RxD, Counter input for Timer-0 – T0 and Counter input for Timer-1 – T1)

Page 2: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

Embedded C

The syntax of embedded C is the same as the C language that we use for writing computer programs. The only difference is the libraries and hence the functions. Particularly for 8051 based microcontrollers, the header file <REGX51.H> has to be added. In this header file the addresses of all the special function registers (SFRs) and other memory locations are defined. Hence we can access an SFR by simply writing its name. We don’t need to use the registers of the programming model (A, B, R0, R1, R2, …, R7) because when the compiler compiles the compiles the C program, it actually converts the program into an equivalent assembly language program. In this process the compiler itself uses the registers in an optimized manner to represent the variables that we define in the C program.

Let’s see a simple program to blink an LED at a fixed interval.

#include <REGX51.H> sbit x=P0^0; //x is defined as a binary variable to represent bit-0 of

// port P0 void delay() //delay program { int i,j;

for(i=0;i<1000;i++) for(j=0;j<1000;j++); } void main() { x=0; //This will define P0^0 as an output port. while(1) { x=!x; delay(); } }

In the program we can see that the delay is achieved by running two nested empty loops to achieve some fixed delay. It is assumed that the LED is connected to the bit 0 of port P0 (P0.0).

It is totally inconvenient to know the exact duration of the delay as we don’t know what assembly code is generated by the compiler to implement this C code. It may vary from compiler to compiler. Even if we know, it requires lots of calculations. Another drawback is that the achieved delay must be an integral multiple of the time required to execute one empty for-loop used in the program.

The Super-Loop (while(1) – with no break statement)

If you are familiar with computer programming using C language you must know that the main() function of a computer program must end with a return statement. But it is not same for embedded C. A computer program, after its execution, must return the control to the operating system. But a simple embedded system doesn’t have an operating system. The single program that we write controls the embedded system entirely. So we must write the body of the main program (excluding the variable declarations and initializations) inside a super-loop (or infinite loop) as shown in the above example

Page 3: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

so that the program keeps on running until it is reset or turned off by a user. If the chip is the main() function will start from the beginning and do all the variable declarations and initializations again.

If the embedded system you want to design is intended to perform a single task and then stop until it is restarted (or reset) an empty super-loop should be written at the end.

while(1);

It is equivalent to assembly (8051) mnemonics:

loop: jmp loop; or jmp $;

This is required because if some values are stored in the program memory after the last line of the program, the microcontroller will treat them as some opcodes and attempt to execute them. It can cause some really unexpected run-time error as we are not aware of what values are stored and their equivalent instructions.

Event Counter using Embedded C

Let us now look at another program. Here the aim is to count the number of times an event occurs. Whenever the event occurs, the pin P0.0 is reset. It remains reset as the event is occurring and it is set again as the event has occurred. In other words a negative wire is connected from an external source to the pin P0.0 of the microcontroller. The aim of the program is to keep track of the number of times the wire feeds a logic zero to the microcontroller. Here the program goes:

#include <REGX51.H> sbit b=P0^0; void main() { int x=0; P1=0x00; while(1) { if(b==0) { x++; while(b==0); //Wait until b is set again } P1=x; //send result to port 1 } } As we can see the entire processor remains busy in keeping track of whether the selected bit is set or reset. We cannot risk including some additional task into the program because it may lead to miss some event when it is busy in executing additional tasks.

Page 4: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

Timer and Interrupt

We have discussed how delay and counter can be implemented in a conventional embedded C program and also discussed their limitations. Now we will see how we can implement the same things using timer and interrupt. First we will discuss the timers and interrupts of 8051 microcontroller and their operation and control. Then we will see their implementation in a program.

Interrupt and Timer are two very important tools which are provided by any microcontroller. They can help us to make our programs more efficient and smarter. Like many other microcontrollers in 8051 also we can manage and use them by adjusting the values of some pre-defined Special Function Registers (SFRs). In the theory and lab classes of 8051 microcontrollers, these topics are covered in details and students are also taught to write Assembly Language Programs to control timer and interrupt.

If you are not familiar with timers and interrupts, please refer to the 8051 tutorial available in the page mentioned at the beginning of this tutorial. Here we will cover only the SFRs involved with timer and interrupt along with the functions of their bits.

Timers of 8051 Microcontroller:

The 8051 comes equipped with two timers, both of which may be controlled, set, read, and configured individually. The 8051 timers have three general functions:

(1) Keeping time and/or calculating the amount of time between events,

(2) Counting the events themselves

(3) Generating baud rates for the serial port. (beyond the scope of this tutorial – you may go through serial port of 8051 for further details)

There are two 16-bit timers (Timer0 and Timer1) in 8051. Both the timer counts up. (In some microcontrollers we can program the timer registers to move up or down, some varieties of 8051 also includes this feature, but in general the timers of 8051 only counts up hence we consider the general case only)

How long a Timer does take to Count?

First, it’s worth mentioning that when a timer is in interval timer mode (as opposed to event counter mode) and correctly configured, it will increment by 1 every machine cycle. A machine cycle in 8051 contains 12 clock pulses. The crystal oscillator usually used in 8051 is of frequency 11.059 MHz (11059000 Hz).

Thus time required by the counter to count is:

1,10,59,000/12 = 9,21,583 times per second. (Or once in every 1.085 µs).

Page 5: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

SFRs associated with the Timers of 8051 microcontroller:

TCON and TMOD registers are used for controlling the two timers. TH0 and TL0 jointly store the current 16-bit (2 bytes) value of Timer 0. Similarly, TH1 and TL1 store the current value of Timer 1. If we initialize the Timer register with some value then it will start counting up from that value. In this way we can make the timer to reach its maximum value at the required instant of time. After reaching this maximum value the timer will overflow, that is, it will start from zero (0000h).

TMOD Register

Bit Name Description Timer 7 GATE1 When this bit is set the timer will only run when INT1 (P3.3) is high.

When this bit is clear the timer will run regardless of the state of INT1.

1

6 C/T1 When this bit is set the timer will count events on T1 (P3.5). When this bit is clear the timer will be incremented every machine cycle.

1

5 T1M1 Mode select for Timer 1 1 4 T1M0 1 3 GATE0 When this bit is set the timer will only run when INT0 (P3.2) is high.

When this bit is clear the timer will run regardless of the state of INT0.

0

2 C/T2 When this bit is set the timer will count events on T0 (P3.4). When this bit is clear the timer will be incremented every machine cycle.

0

1 T0M1 Mode select for Timer 0 0 0 T0M0 0

Modes of Timer 0 and Timer 1

TxM1 TxM0 Timer Mode Description of Mode 0 0 Mode 0 13 - bit timer (0000h to 1FFFh) 0 1 Mode 1 16 - bit timer (0000h to FFFFh) 1 0 Mode 2 8 - bit (00h to FFh) auto reload 1 1 Mode 3 Split Timer Mode

*x can be either 0 or 1.

(Read the concepts of auto-reload and split timer from the 8051 Tutorial mentioned above or some book)

Page 6: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

TCON Register:

As you may notice, we’ve only defined 4 of the 8 bits. That’s because the other 4 bits of the SFR don’t have anything to do with timers – they have to do with Interrupts and they will be discussed in the chapter that addresses interrupts.

Generation of Baud Rate for Serial Port:

Timer-1 can be used for generating baud rate for serial communication. To explain the operation a brief discussion of the serial port of 8051 microcontroller is given. The serial communication of 8051 microcontroller is done through pins P3.0 (serial input port) and P3.1 (serial output port). The serial communication is controlled by the SFR SCON. The various bits of the SCON SFR and their descriptions are given in the following table:

Table: Bits of SCON Register

Bit Name Bit Address Description 0 SM0 9Fh Serial port mode bit 0 1 SM1 9Eh Serial port mode bit 1 2 SM2 9Dh Multiprocessor communication enable 3 REN 9Ch Receive Enable. This bit must be set to receive characters. 4 TB8 9Bh Transmit Bit 8. The 9th bit to transmit in mode 2 and mode 3 5 RB8 9Ah Receive Bit 8. The 9th bit to receive in mode 2 and mode 3 6 TI 99h Transmit Flag. Set when a byte has been completely transmitted 7 RI 98h Receive Flag. Set when a byte has been completely received

Interrupts of 8051 Microcontroller:

Program flow is always sequential, being altered only by those instructions which expressly cause program flow to deviate in some way. However, interrupts give us a mechanism to "put on hold" the normal program flow, execute a subroutine, and then resume normal program flow as if we had never left it. This subroutine, called an interrupt handler, is only executed when a certain event (interrupt) occurs. The event may be one of the timers "overflowing," receiving a character via the serial port, transmitting a character via the serial port, or one of two "external events." The 8051 may be configured so that when any of these events occur the main program is temporarily suspended and control passed to a special section of code which presumably would execute some function related to the event that occurred. Once complete, control would be returned to the original program. The main program never even knows it was interrupted.

Page 7: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

We can configure the 8051 so that any of the following events will cause an interrupt:

Timer 0 Overflow. Timer 1 Overflow. Reception/Transmission of Serial Character. External Event 0. External Event 1.

We need to be able to distinguish between various interrupts and executing different code depending on what interrupt was triggered. This is accomplished by jumping to a fixed address (known as interrupt vector) when a given interrupt occurs. These addresses are stored in a inbuilt table inside the microcontroller called interrupt vector table.

The Interrupt Vector Table of 8051 Microcontroller (In order of polling sequence)

The SFRs used for setting and controlling interrupts in 8051 are:

1. Interrupt Enable (IE) SFR: Address 0A8h 2. Interrupt Priority (IP) SFR: Address 0B8h 3. Lower 4 bits of the TCON SFR for external interrupt control

IE SFR

Bit Name Bit Address Description 7 EA AFh Global Interrupt Enable/Disable 6 - AEh Undefined 5 - ADh Undefined 4 ES Ach Enable Serial Interrupt 3 ET1 ABh Enable Timer 1 Interrupt 2 EX1 AAh Enable External 1 Interrupt 1 ET0 A9h Enable Timer 0 Interrupt 0 EX0 A8h Enable External 0 Interrupt

Interrupt Priority

When more than one interrupts are enabled, it is necessary to set priority of interrupts. The priority of an interrupt can be high or low. A high priority interrupt can interrupt the service routine of a low priority interrupt.

Page 8: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

For example, you may have enabled Timer 1 Interrupt which is automatically called every time Timer 1 overflows. Additionally, you may have enabled the Serial Interrupt which is called every time a character is received via the serial port. However, you may consider that receiving a character is much more important than the timer interrupt. In this case, if Timer 1 Interrupt is already executing you may wish that the serial interrupt itself interrupts the Timer 1 Interrupt. When the serial interrupt is complete, control passes back to Timer 1 Interrupt and finally back to the main program. You may accomplish this by assigning a high priority to the Serial Interrupt and a low priority to the Timer 1 Interrupt.

IP SFR

Lower 4 bits of TCON for External Interrupt

It has already been said that the lower 4 bits of TCON are used for interrupt handling in 8051. The following figure shows the use of these four bits.

So use of these bits can give more sophisticated control over external interrupt which may of use for certain applications. However, we don’t use these bits in our examples.

Page 9: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

8051 Embedded C Example 1

Aim: To write a program to blink an LED after every 0.5 second using timer. Assume that a 12 MHz crystal is used generate clock pulses the 8051 microcontroller.

Calculation of Timer Value:

Clock frequency = 12 MHz = 12,000,000 Hz

Time required for 1 clock pulse = 1/12,000,0000 sec

1 machine cycle = 12 clock pulses

Hence, time required for 1 machine cycle = 12 x 1/12,000,000 sec = 10 – 6 sec

In other words,

Machine cycles in 10 – 6 sec = 1

Machine cycles 0.5 sec = 0.5 x 106 = 500,000

A 16-bit timer can count from 0000h to FFFFh, i.e., 0 to 65,535.

Let us start the timer from (65,535 – 50,000) = 15,535 = 3CAFh so that it overflows after 50,000 steps.

We need to run the timer 10 times to make it 500,000.

Calculation of SFR Values:

Let us use timer 0 as 16-bit timer. Here we are using the timers to keep time. As the timer will be used as 16-bit mode (Mode 1) we need to specify this to TMOD register

TMOD = 0000 0001 b = 1

Here goes the program:

#include <REGX51.H> sbit x=P0^0; //set x as the bit 0 of P0 where the LED is connected void main() { int count=0; x=0; TMOD=1; TH0=0x3c; TL0=0xaf; //separately initialize TH0 & TL0 TR0=1; while(1) { while(!TF0); //wait until TF bit is set TF0=0; count++;//when timer overflows we increment the counter TH0=0x3c; TL0=0xaf; //Initialize every time so that we get 0.5 sec TR0=1; //Start the timer again

Page 10: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

if(count==10) { count=0; x=!x; } } }

Page 11: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

8051 Embedded C Example 2

Aim: Write a program to read port 0 when an external interrupt occurs. After 2 second of reading, display double of the value in port 1. Steps:

1. When external interrupt occurs, read the present value of port 0 and disable the interrupt. 2. Start timer to calculate 2 second elapse (calculation of time shown below). 3. Multiply the value with 2. 4. When 2 seconds are over, display the result at port 1 and enable the interrupt.

Calculation of time: Let the clock frequency be 12 MHz. The number of machine cycles required for 2 sec is: 2106 With reference to example 1, if we set timer to be elapse at 50,000 machine cycles, then number of times the timer needs to overflow is:

2,000,00050,000

= 40

So here maximum value of counter will be 40. Let us use timer interrupt to increment counter.

Interrupt Table

The interrupt number is required to write the interrupt service routine in embedded C. Program: #include <REGX51.H> int counter; bit flag; sbit ext_int=P3^2; void timer0_isr (void) interrupt 1 //timer 0: serial no. 1 in table { TH0=0x3c; TL0=0xaf; //initialize timer for next overflow TR0=1; //start timer counter++; } void extern0_isr (void) interrupt 0 //external 0: serial no. 0 in table { ext_int=1;

Page 12: Introduction to Embedded C for 8051 and Implementation of Timer and Interrupt Handling

This tutorial is downloaded from https://sites.google.com/site/enggprojectece

flag=1; } void main() { int x,y; flag=0; P0=0xff; //define P0 as input port P1=0x00; //define P1 as output port P3=0xff; //define P3 as input port (to receicve interrupt) while(1) { IE=0x81;

//Global enable(bit 7) on and external interrupt (bit 0) on. while(!flag); //flag will be set by external interrupt flag=0; IE=0x82; //enable general and timer0 interrupt counter =0; TMOD=1; TH0=0x3c; TL0=0xaf; //initialize timers TR0=1; //run timer x=P0; y=2*x; while(counter<40); counter=0; P1=y; } }