You are on page 1of 26

Embedded Systems

Basics of Embedded Systems :


An embedded system is a computer system designed for specific control functions within a larger system, often with real-time computing constraints. It is embedded as part of a complete device often including hardware and mechanical parts. By contrast, a general-purpose computer, such as a personal computer (PC), is designed to be flexible and to meet a wide range of end-user needs. Embedded systems control many devices in common use today. Embedded systems contain processing cores that are typically either microcontrollers or digital signal processors (DSP). The key characteristic, however, is being dedicated to handle a particular task. Since the embedded system is dedicated to specific tasks, design engineers can optimize it to reduce the size and cost of the product and increase the reliability and performance. Some embedded systems are mass-produced, benefiting from economies of scale. Embedded systems range from portable devices such as digital watches and MP3 players, to large stationary installations like traffic lights, factory controllers, or the systems controlling nuclear power plants. Complexity varies from low, with a single microcontroller chip, to very high with multiple units, peripherals and networks mounted inside a large chassis or enclosure.

Characteristics of Embedded Systems:


1. These are designed to do some specific task, rather than be a general-purpose computer for multiple tasks. Some have real time performance constraints that must be met, such as safety and usability; others may have low or no performance requirements, allowing the system hardware to be simplified to reduce costs. 2. They are not always standalone devices. Many of themconsist of small, computerized parts within a larger device that serves a more general purpose. Eg: the Gibson Robot Guitar features an embedded system for tuning the strings, but the overall purpose of the Robot Guitar is, of course, to play music. Similarly, an embedded system in an automobile provides a specific function as a subsystem of the car itself. 3. The program instructions written for embedded systems are referred to as firmware, and are stored in read-only memory or Flash memory chips. They run with limited computer hardware resources: little memory, small or nonexistent keyboard or screen.

Microprocessor Vs. Microcontroller:


Microprocessor is an IC which has only the CPU inside them i.e. only the processing powers such as Intels Pentium 1,2,3,4, core 2 duo, i3, i5 etc. These microprocessors dont have RAM, ROM, and other peripheral on the chip. A system designer has to add them externally to make them functional. Application of microprocessor includes Desktop PCs, Laptops, notepads etc. But this is not the case with Microcontrollers. Microcontroller has a CPU, in addition with a fixed amount of RAM, ROM and other peripherals all embedded on a single chip. At times it is also termed as a mini computer or a computer on a single chip. Today different manufacturers produce microcontrollers with a wide range of features available in different versions. Some manufacturers are ATMEL, Microchip, TI, Freescale, Philips, Motorola etc. Microcontrollers are designed to perform specific tasks. Specific means applications where the relationship of input and output is defined. Depending on the input, some processing needs to be done and output is delivered. For example, keyboards, mouse, washing machine, digicam, pendrive, remote, microwave, cars, bikes, telephone, mobiles, watches, etc. Since the applications are very specific, they need small resources like RAM, ROM, I/O ports etc and hence can be embedded on a single chip. This in turn reduces the size and the cost. Microprocessor find applications where tasks are unspecific like developing software, games, websites, photo editing, creating documents etc. In such cases the relationship between input and output is not defined. They need high amount of resources like RAM, ROM, I/O ports etc. The clock speed of the Microprocessor is quite high as compared to the microcontroller. Whereas the microcontrollers operate from a few MHz to 30 to 50 MHz, todays microprocessor operate above 1GHz as they perform complex tasks. Comparing microcontroller and microprocessor in terms of cost is not justified. Undoubtedly a microcontroller is far cheaper than a microprocessor. However microcontroller cannot be used in place of microprocessor and using a microprocessor is not advised in place of a microcontroller as it makes the application quite costly. Microprocessor cannot be used stand alone. They need other peripherals like RAM, ROM, buffer, I/O ports etc and hence a system designed around a microprocessor is quite costly.

Microcontroller:
A microcontroller (sometimes abbreviated C, uC or MCU) is a small computer on a single integrated circuit containing a processor core, memory, and programmable input/output peripherals. Program memory in the form of NOR flash or OTP ROM is also often included on chip, as well as a typically small amount of RAM. Microcontrollers are designed for embedded applications, in contrast to the microprocessors used in personal computers or other general purpose applications. Microcontrollers are used in automatically controlled products and devices, such as automobile engine control systems, implantable medical devices, remote controls, office machines, appliances, power tools, toys and other embedded systems. By reducing the size and cost compared to a design that uses a separate microprocessor, memory, and input/output devices, microcontrollers make it economical to digitally control even more devices and processes. Mixed signal microcontrollers are common, integrating analog components needed to control non-digital electronic systems. Some microcontrollers may use four-bit words and operate at clock rate frequencies as low as 4 kHz, for low power consumption (milliwatts or microwatts). They will generally have the ability to retain functionality while waiting for an event such as a button press or other interrupt; power consumption while sleeping (CPU clock and most peripherals off) may be just nanowatts, making many of them well suited for long lasting battery applications. Other microcontrollers may serve performance-critical roles, where they may need to act more like a digital signal processor (DSP), with higher clock speeds and power consumption.

Various Microcontrollers till date:


ARM core processors (many vendors) includes ARM9, ARM Cortex-A8, Sitara ARM Microprocessor Atmel AVR (8-bit), AVR32 (32-bit), and AT91SAM (32-bit) Cypress Semiconductor's M8C Core used in their PSoC (Programmable System-on-Chip) Freescale ColdFire (32-bit) and S08 (8-bit) Freescale 68HC11 (8-bit) Intel 8051 Infineon: 8, 16, 32 Bit microcontrollers MIPS Microchip Technology PIC, (8-bit PIC16, PIC18, 16-bit dsPIC33 / PIC24), (32-bit PIC32) NXP Semiconductors LPC1000, LPC2000, LPC3000, LPC4000 (32-bit), LPC900, LPC700 (8-bit) Parallax Propeller PowerPC ISE Rabbit 2000 (8-bit) Renesas RX, V850, Hitachi H8, Hitachi SuperH (32-bit), M16C (16-bit), RL78, R8C, 78K0/78K0R (8-bit) Silicon Laboratories Pipelined 8-bit 8051 Microcontrollers and mixed-signal ARM-based 32-bit microcontrollers STMicroelectronics STM8 (8-bit), ST10 (16-bit) and STM32 (32-bit) Texas Instruments TI MSP430 (16-bit) Toshiba TLCS-870 (8-bit/16-bit). Many others exist, some of which are used in very narrow range of applications or are more like applications processors than microcontrollers. The microcontroller market is extremely fragmented, with numerous vendors, technologies, and markets. Note that many vendors sell or have sold multiple architectures. CLASSIFICATION OF MICROCONTROLLERS:

RISC Vs CISC ARCHITECTURE:


The simplest way to examine the advantages and disadvantages of RISC architecture is by contrasting it with it's predecessor: CISC (Complex Instruction Set Computers) architecture. Multiplying Two Numbers in Memory On the right is a diagram representing the storage scheme for a generic computer. The main memory is divided into locations numbered from (row) 1: (column) 1 to (row) 6: (column) 4. The execution unit is responsible for carrying out all computations. However, the execution unit can only operate on data that has been loaded into one of the six registers (A, B, C, D, E, or F). Let's say we want to find the product of two numbers - one stored in location 2:3 and another stored in location 5:2 - and then store the product back in the location 2:3. The CISC Approach The primary goal of CISC architecture is to complete a task in as few lines of assembly as possible. This is achieved by building processor hardware that is capable of understanding and executing a series of operations. For this particular task, a CISC processor would come prepared with a specific instruction (we'll call it "MULT"). When executed, this instruction loads the two values into separate registers, multiplies the operands in the execution unit, and then stores the product in the appropriate register. Thus, the entire task of multiplying two numbers can be completed with one instruction: MULT 2:3, 5:2 MULT is what is known as a "complex instruction." It operates directly on the computer's memory banks and does not require the programmer to explicitly call any loading or storing functions. It closely resembles a command in a higher level language. For instance, if we let "a" represent the value of 2:3 and "b" represent the value of 5:2, then this command is identical to the C statement "a = a * b." One of the primary advantages of this system is that the compiler has to do very little work to translate a high-level language statement into assembly. Because the length of the code is relatively short, very little RAM is required to store instructions. The emphasis is put on building complex instructions directly into the hardware. The RISC Approach RISC processors only use simple instructions that can be executed within one clock cycle. Thus, the "MULT" command described above could be divided into three separate commands: "LOAD," which moves data from the memory bank to a register, "PROD," which finds the product of two operands located within the registers, and "STORE," which moves data from a register to the memory banks. In order to perform the exact series of steps described in the CISC approach, a programmer would need to code four lines of assembly: LOAD A, 2:3 LOAD B, 5:2 PROD A, B STORE 2:3, A At first, this may seem like a much less efficient way of completing the operation. Because there are more lines of code, more RAM is needed to store the assembly level instructions. The compiler must also perform more work to convert a high-level language statement into code of this form. CISC Emphasis on hardware Includes multi-clock complex instructions RISC Emphasis on software Single-clock, reduced instruction only

However, the RISC strategy also brings Memory-to-memory: Register to register: some very important advantages. Because "LOAD" and "STORE" "LOAD" and "STORE" incorporated in instructions are independent instructions each instruction requires only one clock cycle to execute, the entire program will Small code sizes, Low cycles per second, execute in approximately the same amount high cycles per second large code sizes of time as the multi-cycle "MULT" command. These RISC "reduced Transistors used for storing Spends more transistors instructions" require less transistors of on memory registers complex instructions hardware space than the complex instructions, leaving more room for general purpose registers. Because all of the instructions execute in a uniform amount of time (i.e. one clock), pipelining is possible. Separating the "LOAD" and "STORE" instructions actually reduces the amount of work that the computer must perform. After a CISC-style "MULT" command is executed, the processor automatically erases the registers. If one of the operands needs to be used for another computation, the processor must re-load the data from the memory bank into a register. In RISC, the operand will remain in the register until another value is loaded in its place. The Performance Equation The following equation is commonly used for expressing a computer's performance ability:

The CISC approach attempts to minimize the number of instructions per program, sacrificing the number of cycles per instruction. RISC does the opposite, reducing the cycles per instruction at the cost of the number of instructions per program. RISC Roadblocks Despite the advantages of RISC based processing, RISC chips took over a decade to gain a foothold in the commercial world. This was largely due to a lack of software support. Although Apple's Power Macintosh line featured RISC-based chips and Windows NT was RISC compatible, Windows 3.1 and Windows 95 were designed with CISC processors in mind. Many companies were unwilling to take a chance with the emerging RISC technology. Without commercial interest, processor developers were unable to manufacture RISC chips in large enough volumes to make their price competitive. Another major setback was the presence of Intel. Although their CISC chips were becoming increasingly unwieldy and difficult to develop, Intel had the resources to plow through development and produce powerful processors. Although RISC chips might surpass Intel's efforts in specific areas, the differences were not great enough to persuade buyers to change technologies. The Overall RISC Advantage Today, the Intel x86 is arguable the only chip which retains CISC architecture. This is primarily due to advancements in other areas of computer technology. The price of RAM has decreased dramatically. In 1977, 1MB of DRAM cost about $5,000. By 1994, the same amount of memory cost only $6 (when adjusted for inflation). Compiler technology has also become more sophisticated, so that the RISC use of RAM and emphasis on software has become ideal.

Types Of RAM & ROM:


Types of RAM The RAM family includes two important memory devices: static RAM (SRAM) and dynamic RAM (DRAM). The primary difference between them is the lifetime of the data they store. SRAM retains its contents as long as electrical power is applied to the chip. If the power is turned off or lost temporarily, its contents will be lost forever. DRAM, on the other hand, has an extremely short data lifetime-typically about four milliseconds. This is true even when power is applied constantly. In short, SRAM has all the properties of the memory you think of when you hear the word RAM. Compared to that, DRAM seems kind of useless. By itself, it is. However, a simple piece of hardware called a DRAM controller can be used to make DRAM behave more like SRAM. The job of the DRAM controller is to periodically refresh the data stored in the DRAM. By refreshing the data before it expires, the contents of memory can be kept alive for as long as they are needed. So DRAM is as useful as SRAM after all. When deciding which type of RAM to use, a system designer must consider access time and cost. SRAM devices offer extremely fast access times (approximately four times faster than DRAM) but are much more expensive to produce. Generally, SRAM is used only where access speed is extremely important. A lower cost-per-byte makes DRAM attractive whenever large amounts of RAM are required. Many embedded systems include both types: a small block of SRAM (a few kilobytes) along a critical data path and a much larger block of DRAM (perhaps even Megabytes) for everything else. Types of ROM Memories in the ROM family are distinguished by the methods used to write new data to them (usually called programming), and the number of times they can be rewritten. This classification reflects the evolution of ROM devices from hardwired to programmable to erasable-and-programmable. A common feature of all these devices is their ability to retain data and programs forever, even during a power failure. The very first ROMs were hardwired devices that contained a preprogrammed set of data or instructions. The contents of the ROM had to be specified before chip production, so the actual data could be used to arrange the transistors inside the chip. Hardwired memories are still used, though they are now called masked ROMs to distinguish them from other types of ROM. The primary advantage of a masked ROM is its low production cost. Unfortunately, the cost is low only when large quantities of the same ROM are required. One step up from the masked ROM is the PROM (programmable ROM), which is purchased in an unprogrammed state. If you were to look at the contents of an unprogrammed PROM, you would see that the data is made up entirely of 1's. The process of writing your data to the PROM involves a special piece of equipment called a device programmer. The device programmer writes data to the device one word at a time by applying an electrical charge to the input pins of the chip. Once a PROM has been programmed in this way, its contents can never be changed. If the code or data stored in the PROM must be changed, the current device must be discarded. As a result, PROMs are also known as one-time programmable (OTP) devices. An EPROM (erasable-and-programmable ROM) is programmed in exactly the same manner as a PROM. However, EPROMs can be erased and reprogrammed repeatedly. To erase an EPROM, you simply expose the device to a strong source of ultraviolet light. (A window in the top of the device allows the light to reach the silicon.) By doing this, you essentially reset the entire chip to its initial--unprogrammed--state. Though more expensive than PROMs, their ability to be reprogrammed makes EPROMs an essential part of the software development and testing process.

Hybrids As memory technology has matured in recent years, the line between RAM and ROM has blurred. Now, several types of memory combine features of both. These devices do not belong to either group and can be collectively referred to as hybrid memory devices. Hybrid memories can be read and written as desired, like RAM, but maintain their contents without electrical power, just like ROM. Two of the hybrid devices, EEPROMand flash, are descendants of ROM devices. These are typically used to store code. EEPROMs are electrically-erasable-and-programmable. Internally, they are similar to EPROMs, but the erase operation is accomplished electrically, rather than by exposure to ultraviolet light. Any byte within an EEPROM may be erased and rewritten. Once written, the new data will remain in the device forever--or at least until it is electrically erased. The primary tradeoff for this improved functionality is higher cost, though write cycles are also significantly longer than writes to a RAM. So you wouldn't want to use an EEPROM for your main system memory. Flash memory combines the best features of the memory devices described thus far. Flash memory devices are high density, low cost, nonvolatile, fast (to read, but not to write), and electrically reprogrammable. These advantages are overwhelming and, as a direct result, the use of flash memory has increased dramatically in embedded systems. From a software viewpoint, flash and EEPROM technologies are very similar. The major difference is that flash devices can only be erased one sector at a time, not byte-by-byte. Typical sector sizes are in the range 256 bytes to 16KB. Despite this disadvantage, flash is much more popular than EEPROM and is rapidly displacing many of the ROM devices as well. The third member of the hybrid memory class is NVRAM (non-volatile RAM). Nonvolatility is also a characteristic of the ROM and hybrid memories discussed previously. However, an NVRAM is physically very different from those devices. An NVRAM is usually just an SRAM with a battery backup. When the power is turned on, the NVRAM operates just like any other SRAM. When the power is turned off, the NVRAM draws just enough power from the battery to retain its data. NVRAM is fairly common in embedded systems. However, it is expensive--even more expensive than SRAM, because of the battery--so its applications are typically limited to the storage of a few hundred bytes of system-critical information that can't be stored in any better way. Table 1 summarizes the features of each type of memory discussed here, but keep in mind that different memory types serve different purposes. Each memory type has its strengths and weaknesses. Side-by-side comparisons are not always effective. Erase Size Byte Byte Max Erase Cycles Unlimited Unlimited

Type

Volatile? Yes Yes

Writeable? Yes Yes

Cost (per Byte) Expensive Moderate

Speed Fast Moderate

SRAM DRAM Masked ROM

No

No

n/a

n/a

Inexpensive

Fast

PROM

No

Once, with a device programmer Yes, with a device programmer

n/a

n/a

Moderate

Fast

EPROM

No

Entire Chip

Limited (consult datasheet)

Moderate

Fast

EEPROM

No

Yes

Byte

Limited (consult datasheet) Limited (consult datasheet)

Expensive

Fast to read, slow to erase/write Fast to read, slow to erase/write

Flash

No

Yes

Sector

Moderate

NVRAM

No

Yes

Byte

Unlimited

Expensive (SRAM + battery)

Fast

Table 1. Characteristics of the various memory types When working with microcontrollers, many of the tasks usually consist of controlling the peripherals that are connected to the device, respectively programming the subsystems that are contained in the controller (which by itself communicate with the circuitry connected to the controller). The AVR series of microcontrollers offers two different ways to perform this task: There's a separate I/O address space available that can be addressed with specific I/O instructions that are applicable to some or all of the I/O address space (in, out, sbi etc.), known as I/O mapping. The entire I/O address space is also made available as memory-mapped I/O, i. e. it can be accessed using all the MCU instructions that are applicable to normal data memory. The I/O register space is mapped into the data memory address space with an offset of 0x20 since the bottom of this space is reserved for direct access to the MCU registers. (Actual SRAM is available only behind the I/O register area, starting at either address 0x60, or 0x100 depending on the device.).

This is why there are two sets of addresses in the AVR data sheets. The first address is using I/O mapping and the second address in brackets is the memory mapped approach.

Registers Registers are special storages with 8 bits capacity and they look like this: 7 6 5 4 3 2 1 0

Note the numeration of these bits: the least significant bit starts with zero (20 = 1). A register can either store numbers from 0 to 255 (positive number, no negative values), or numbers from -128 to +127 (whole number with a sign bit in bit 7), or a value representing an ASCII-coded character (e.g. 'A'), or just eight single bits that do not have something to do with each other (e.g. for eight single flags used to signal eight different yes/no decisions). The special character of registers, compared to other storage sites, is that they can be used directly in assembler commands, operations with their content require only a single command word, they are connected directly to the central processing unit called the accumulator,

they are source and target for calculations. There are 32 registers in an AVR. They are originally named r0 to r31. However certain instructions will not work in registers r0 to r15 e.g. ldi will only work on registers r16 to r31.

About Keil Software


About the Keil Compiler Keil Software publishes one of the most complete development tool suites for 8051 software, which is used throughout industry. For development of C code, their Developer's Kit product includes their C51 compiler, as well as an integrated 8051 simulator for debugging. The C programming language was designed for computers, though, and not embedded systems. It does not support direct access to registers, nor does it allow for the reading and setting of single bits, two very important requirements for 8051 software. In addition, most software developers are accustomed to writing programs that will by executed by an operating system, which provides system calls the program may use to access the hardware. However, much code for the 8051 is written for direct use on the processor, without an operating system. To support this, the Keil compiler has added several extensions to the C language to replace what might have normally been implemented in a system call, such as the connecting of interrupt handlers. The purpose is to further explain the limitations of the Keil compiler, the modifications it has made to the C language, and how to account for these in developing software for the 8051 micro controller.

Keil Limitations
There are several very important limitations in the evaluation version of Keil's Developer's Kit that users need be aware of when writing software for the 8051. Object code must be less than 2 Kbytes The compiler will compile any-sized source code file, but the final object code may not exceed 2 Kbytes. If it does, the linker will refuse to create a final binary executable (or HEX file) from it. Along the same lines, the debugger will refuse any files that are over 2Kbytes, even if they were compiled using a different software package. Program code starts at address 0x4000 All C code compiled and linked using the Keil tools will begin at address 0x4000 in code memory. Such code may not be programmed into devices with less than 16Kbytes of Read-Only Memory. Code written in assembly may circumvent this limitation by using the "origin" keyword to set the start to address 0x0000. No such work-around exists for C programs, though. However, the integrated debugger in the evaluation software may still be used for testing code. Once tested, the code may be compiled by the full version of the Keil software, or by another compiler that supports the C extensions used by Keil.

C Modifications The Keil C compiler has made some modifications to an otherwise ANSI-compliant implementation of the C programming language. These modifications were made solely to facilitate the use of a higher-level language like C for writing programs on micro controllers. Variable Types The Keil C compiler supports most C variable types and adds several of its own. Standard Types

The evaluation version of the Keil C compiler supports the standard ANSI C variable types, with the exception of the floating-point types. These types are summarized below.

Type Char unsigned char enum short unsigned short int unsigned int long unsigned long

Bits 8 8 16 16 16 16 16 32 32

Bytes 1 1 2 2 2 2 2 4 4

Range -128 to +127 0 to 255 -32,768 to +32,767 -32,768 to +32,767 0 to 65,535 -32,768 to +32,767 0 to 65,535 -2,147,483,648 to +2,147,483,647 0 to 4,294,697,295

In addition to these variable types, the compiler also supports the struct and union data structures, as well as type redefinition using typedef. Keil Types To support a micro controller and embedded systems applications, Keil added several new types to their compiler. These are summarized in the table below Type Bit Sbit Sfr sf16 Bits 1 1 8 16 Bytes 0 0 1 2 Range 0 to 1 0 to 1 0 to 255 0 to 65,535

Of these, only the bit type works as a standard variable would. The other three have special behavior that a programmer must be aware of. bit This is a data type that gets allocated out of the 8051's bit-addressable on-chip RAM. Like other data types, it may be declared as either a variable. However, unlike standard C types, if may not be used as a pointer. An example of its usage follows.

/* declare two bit variables - the compiler will decide which */ /* addresses they are at. Initialize them to 0 and 1. */ bit testbit1 = 0; bit testbit2 = 1; /* set testbit1 to the value in testbit2 */

testbit1 = testbit2; /* clear testbit2 */ testbit2 = 0; /* testbit1 is now a 1, and testbit2 is now a 0 */ /* Note that the assignment of testbit2 to testbit1 only copied */ /* the contents of testbit2 into testbit1. It did *not* change */ /* the location of testbit1 to be the same as testbit2. */ sbit, sfr, and sf16 These are special types for accessing 1-bit, 8-bit, and 16-bit special function registers. Because there is no way to indirectly address registers in the 8051, addresses for these variables must be declared outsite of functions within the code. Only the data addressed by the variable may be manipulated in the code. An example follows: /* create an sbit variable that points to pin 0 of port 1 */ /* note that this is done outside of any functions! */ sbit P10 = 0x90; /* now the functions may be written to use this location */ void main (void) { /* forever loop, toggling pin 0 of port 1 */ while (1==1) { P10 = !P10; delay (500); /* wait 500 microseconds */ } }

Conveniently, the standard special function registers are all defined in the reg51.h file that any developer may include into their source file. Only registers unique to the particular 8051-derivative being used for the project need have these variable declared, such as registers and bits related to a second on-chip serial port Keil Variable Extensions In writing applications for a typical computer, the operating system handles manages memory on behalf of the programs, eliminating their need to know about the memory structure of the hardware. Even more important, most computers having a unified memory space, with the code and data sharing the same RAM. This is not true with the 8051, which has separate memory spaces for code, on-chip data, and external data. To accommodate for this when writing C code, Keil added extensions to variable declarations to specify which memory space the variable is allocated from, or points to. The most important of these for student programmers are summarized in the following table.

Extension Data Idata Xdata Code

Memory Type Directly-addressable data memory (data memory addresses 0x00-0x7F) Indirectly-addressable data memory (data memory addresses 0x00-0xFF) External data memory Program memory

Related ASM MOV A, 07Fh MOV R0, #080h , MOV A, R0 MOVX @DPTR MOVC @A+DPTR

These extensions may be used as part of the variable type in declaration or casting by placing the extension after the type, as in the example below. If the memory type extension is not specified, the compiler will decide which memory type to use automatically, based on the memory model (SMALL, COMPACT, or LARGE, as specified in the project properties in Keil). /* This is a function that will calculate and return a checksum of */ /* a range of addresses in code memory, using a simple algorithm */ /* that simply adds each consecutive byte together. This could be */ /* useful for verifying if the code in ROM got corrupted (like if */ /* the Flash device were wearing out). */ unsigned int checksum (unsigned int start, unsigned int end) { /* first, declare pointers to the start and end of */ /* the range in code memory. */ unsigned int code *codeptr, *codeend;

/* now declare the variable the checksum will be */ /* calculated in. Because direct-addressable data */ /* is faster to access than indirect, and this */ /* variable will be accessed frequently, we will */ /* declare it in data memory (instead of idata). */ /* In reality, if left unspecified, the compiler */ /* would probably leave it in the accumulator for */ /* even faster access, but that would defeat the */ /* point of this example. */ unsigned int data checksum = 0;

/* Initialize the codestart and codeend pointers to */

/* the addresses passed into the function as params. */ /* because start and end are passed in as values, */ /* not pointers, they must be cast to the correct */ /* pointer type */ codeptr = (unsigned int code *)start; codeend = (unsigned int code *)end;

/* Now perform the checksum calculation, looping */ /* until the end of the range is reached. */ while (codeptr <= codeend) { checksum = checksum + (unsigned int data)*codeptr; codeptr++; /* go to the next address */ }

return (checksum); } Keil Function Extensions As in most other C compilers, functions may be declared in one of two fashions: unsigned int functionname (unsigned int var) { .... return (var); } functionname (var)

unsigned int var { .... return (var); }

Most modern programmers use the first syntax, as do the examples in this document.

Keil provides two important extensions to the standard function declaration to allow for the creation of interrupt handlers and reentrant functions. interrupt In writing applications for a typical computer, the operating system provides system calls for setting a function, declared in the standard manner, as the handler for an interrupt. However, in writing code for an 8051 without an operating system, such a system would not be possible using solely C code. To eliminate this problem, the Keil compiler implements a function extension that explicitly declares a function as an interrupt handler. The extension is interrupt, and it must be followed by an integer specifying which interrupt the handler is for. For example:

/* This is a function that will be called whenever a serial */ /* interrupt occurs. Note that before this will work, interrupts */ /* must be enabled. See the interrupt example in the appendix. */ void serial_int (void) interrupt 4 { ... } In the example, a function called serial_int is set as the handler for interrupt 4, which is the serial port interrupt. The number is calculated by subtracting 3 from the interrupt vector address and dividing by 8. The five standard interrupts for the 8051 are as follows: Interrupt Reset External 0 Timer 0 External 1 Timer 1 Serial Flag IE0 TF0 IE1 TF1 RI/TI Vector Address 0000 0003h 000Bh 0013h 001Bh 0023h

Other interrupts are dependent on the implementation in the particular 8051-derivative being used in the project, but may be calculated in the same manor using the vector addresses specified by the manufacturer. using Since the processor only save the current program counter before executing an interrupt handler, the handler can potentially damage any data that was in the registers prior to the interrupt. This in turn would corrupt the program once the processor goes back to where it left off. To avoid this, the Keil compiler determines which registers will be used by the interrupt handler function, pushes them out to the stack, executes the handler, and then restores the registers from the stack, before returning to the interrupted code. However, this incurs extra time, especially if a lot of registers will be used. It is preferred that as little time be spent in interrupts as possible. To decrease this time, Keil provides an optional extension, using, to the interrupt extension that tells the compiler to simple change to a new register bank prior to executing the handler, instead of pushing the registers to the stack. /* This is a function that will be called whenever a serial */ /* interrupt occurs. Prior to executing the handler, the */

/* processor will switch to register bank 1 void serial_int (void) interrupt 4 using 1 { ... } In the 8051, interrupts have two possible priorities: high and lo. If, during the processing of an interrupt, another interrupt of the same priority occurs, the processor will continue processing the first interrupt. The second interrupt will only be processed after the first has finished. However, if an interrupt of a higher priority arrives, the first (low priority) interrupt will itself be interrupted, and not resume until the higher priority interrupt has finished. Because of this, all interrupts of the same priority may use the same register bank. The using extension should be used when quick execution time is of high importance, or when other functions are called from the interrupt handler, as it would otherwise push all of the registers on to the stack prior to calling the function, incurring more time penalties. Reentrant Similar to the case described for interrupts above, it is possible for a single function to be interrupted by itself. For example, in the middle of normal execution of the function, the interrupt occurs, and that interrupt makes a call to the same function. While the interrupt handler will save the registers before entering this function, no protective measures are taken from overwriting the contents of local variables allocated in data memory. When the interrupt is serviced and control is passed back to normal execution, the corrupted data in those variables could ruin the entire program. The general term for a function that may be called more than once simultaneously is "reentrant." Accordingly, the reentrant extension may be used in a function declaration to force the compiler to maintain a separate data area in memory for each instance of the function. While safe, this does have the potential to use large area of the rather limited data memory. An example of such a function follows. /* Because this function may be called from both the main program */ /* and an interrupt handler, it is declared as reentrant to */ /* protect its local variables. */

int somefunction (int param) reentrant { ... return (param); }

/* The handler for External interrupt 0, which uses somefunction() */ void external0_int (void) interrupt 0 { ... somefunction(0);

/* the main program function, which also calls somefunction() */ void main (void) { while (1==1) { ... somefunction(); } }

Apart from knowing Keil Software for programming a Microcontroller we have pre-defined functions and usage of variables for interfacing LEDs, switches and LCDs. LOOPS IN C: Loops are used to repeat one statement or set statements more than one time. Most real programs contain some construct that loops within the program, performing repetitive actions on a stream of data or a region of memory. There are several ways to loop in C. For Loop For loop is a counter loop. The for loop allows automatic initialization of instrumentation of a counter variable. The general form is for (initialization; condition; increment/decrement) { statements block } If the statement block is only one statement, the braces are not necessary. Although the for allows a number of variations, generally the initialization is used to set a counter variable to its starting value. The condition is generally a relational statement that checks the counter variable against a termination value, and the increment increments (or decrements) the counter value. The loop repeats until the condition becomes false. Example Main(){ int i;

for(i = 0; i < count; i++) { printf(%d\n,i); } }

While Loop The while loop repeats a statement until the test at the top proves false. The while loop has the general form: while(condition) { statement block }

The while tests its condition at the top of the loops. Therefore, if the condition is false to begin with, the loop will not execute at all. The condition may be any expression. An example of a while follows. It reads characters until end-of-file is encountered. Example main(){ int t = 0; while(t<=10) { printf(%d\n,t); t=t+1; } } do-while loop This is very similar to the while loop except that the test occurs at the end of the loop body. This guarantees that the loop is executed at least once before continuing. Such a setup is frequently used where data is to be read. The test then verifies the data, and loops back to read again if it was unacceptable. void main(void){ int val; do { printf("Enter 1 to continue and 0 to exit :"); scanf("%d\n", &val); } while (val!= 1 && val!= 0) } SWITCH BOUNCING & DEBOUNCING: Switch debounce and switch bounce are two different things. Switch Bounce happens when you close a mechanical switch. When you close a switch it tends to literally bounce upon the metal contact which connects the circuit. It's almost like dropping a basketball. The basketball will hit then ground (analogous to a closed switch) then bounce back up (analogous to a open switch) then bounce back down, then up, then down, etc... until it permanently stays on the ground (permanently closed). Usually switches take a few microseconds to a few milliseconds to completely close. What this means in terms of digital logic is that as the switch physically bounces your logic can switch back and forth low-to-high-to-low-etc... until your switch settles down. Switch Debounce is the process of getting rid of switch bounce. One solution to get rid of switch bounce is given above by dlgoff

Set and forget


Figure 1 shows the classic debounce circuit. Two cross-coupled NAND gates form a simple Set-Reset (SR) latch. The design requires a double throw switch. Two pull-up resistors generate a logic one for the gates; the switch pulls one of the inputs to ground.

Figure 1: The SR debouncer The SR latch is a rather funky beast, as confusing to non-EEs as recursion is to, well, just about everyone. With the switch in the position shown the upper gate's output will be a one, regardless of the value of the other input. That and the one created by the bottom pull-up resistor drives the lower NAND to a zero, which races around back into the other gate. If the switch moves between contacts and is for a while suspended in the nether region between terminals, the latch maintains its state because of the looped-back zero from the bottom gate. The switch moves a rather long way between contacts. It may bounce around a bit, but will never bang all the way back to the other contact. Thus, the latch's output is guaranteed bounce-free. The circuit suggests an alternative approach, a software version of the same idea. Why not skip the NAND pair and run the two contacts, with pull-ups, directly to input pins on the CPU? Sure, the computer will see plenty of bounciness, but write a trivial bit of code that detects any assertion of either pole, which means the switch is in that position, as follows: if(switch_hi())state=ON; if(switch_lo())state=OFF; The functions switch_hi and switch_lo each read one of the two poles. Other functions in the program examine variable stateto determine the switch's position. This saves two gates but costs one extra input pin on the processor. It's the simplestand most reliabledebounce code possible. (OK, so I slipped some code in after all). An RC debouncer The SR circuit is the most effective of all debouncing approaches but it's rarely used. Double-throw switches are bulkier and more expensive than the simpler single-pole versions. An awful lot of us use switches that are plated onto the circuit board, and it's impossible to make double-pole versions of these. So EEs prefer alternative designs that work with cheap single-pole switches.

Though complex circuits using counters and smart logic satisfy our longing for pure digital solutions to all problems, from signal processing to divorce, it's easier and cheaper to exploit the peculiar nature of a resistorcapacitor (RC) network. Charge or discharge a capacitor through a resistor and you'll find the voltage across the cap rises slowly; it doesn't snap to a new value like a sweet little logic circuit. Increase the value of either component and the time lag ("time constant" in EE lingo) increases. Figure 2 shows a typical RC debouncer. A simple circuit, surely, yet one that hides a surprising amount of complexity.

8051 Architecture:

LCD : The most commonly used Character based LCDs are based on Hitachi's HD44780 controller or other which are compatible with HD44580. In this tutorial, we will discuss about character based LCDs, their interfacing with various microcontrollers, various interfaces (8-bit/4-bit), programming, special stuff and tricks you can do with these simple looking LCDs which can give a new look to your application. The most commonly used LCDs found in the market today are 1 Line, 2 Line or 4 Line LCDs which have only 1 controller and support at most of 80 charachers, whereas LCDs supporting more than 80 characters make use of 2 HD44780 controllers. Most LCDs with 1 controller has 14 Pins and LCDs with 2 controller has 16 Pins (two pins are extra in both for back-light LED connections). Pin description is shown in the table below.

Pin No. Pin no. 1 Pin no. 2 Pin no. 3 Pin no. 4

Name VSS VCC VEE RS

Description Power supply (GND) Power supply (+5V) Contrast adjust 0 = Instruction input 1 = Data input 0 = Write to LCD module 1 = Read from LCD module Enable signal Data bus line 0 (LSB) Data bus line 1 Data bus line 2 Data bus line 3 Data bus line 4

Pin no. 5 Pin no. 6 Pin no. 7 Pin no. 8 Pin no. 9 Pin no. 10 Pin no. 11

R/W EN D0 D1 D2 D3 D4

Pin no. 12 Pin no. 13 Pin no. 14

D5 D6 D7

Data bus line 5 Data bus line 6 Data bus line 7 (MSB)

Table 1: Character LCD pins with 1 Controller

Pin No. Pin no. 1 Pin no. 2 Pin no. 3 Pin no. 4 Pin no. 5 Pin no. 6 Pin no. 7 Pin no. 8 Pin no. 9 Pin no. 10

Name D7 D6 D5 D4 D3 D2 D1 D0 EN1 R/W

Description Data bus line 7 (MSB) Data bus line 6 Data bus line 5 Data bus line 4 Data bus line 3 Data bus line 2 Data bus line 1 Data bus line 0 (LSB) Enable signal for row 0 and 1 (1stcontroller) 0 = Write to LCD module 1 = Read from LCD module 0 = Instruction input 1 = Data input Contrast adjust Power supply (GND) Power supply (+5V) Enable signal for row 2 and 3 (2ndcontroller) Not Connected

Pin no. 11 Pin no. 12 Pin no. 13 Pin no. 14 Pin no. 15 Pin no. 16

RS VEE VSS VCC EN2 NC

Table 2: Character LCD pins with 2 Controller

LCD interfacing with Microcontrollers tutorial - LCD Commands and Insturctions

Commands and Instruction set


Only the instruction register (IR) and the data register (DR) of the LCD can be controlled by the MCU. Before starting the internal operation of the LCD, control information is temporarily stored into these registers to allow interfacing with various MCUs, which operate at different speeds, or various peripheral control devices. The internal operation of the LCD is determined by signals sent from the MCU. These signals, which include register selection signal (RS), read/write signal (R/W), and the data bus (DB0 to DB7), make up the LCD instructions (Table 3). There are four categories of instructions that:

Designate LCD functions, such as display format, data length, etc. Set internal RAM addresses Perform data transfer with internal RAM Perform miscellaneous functions

Table 3: Command and Instruction set for LCD type HD44780

Although looking at the table you can make your own commands and test them. Below is a breif list of useful commands which are used frequently while working on the LCD.

No. Instruction

Hex

Decimal

1 2 3 4

Function Set: 8-bit, 1 Line, 5x7 Dots Function Set: 8-bit, 2 Line, 5x7 Dots Function Set: 4-bit, 1 Line, 5x7 Dots Function Set: 4-bit, 2 Line, 5x7 Dots

0x30 0x38 0x20 0x28

48 56 32 40

5 6 7 8 9 10 12 13 14 15 16 17

Entry Mode Display off Cursor off (clearing display without clearing DDRAM content) Display on Cursor on Display on Cursor off Display on Cursor blinking Shift entire display left Shift entire display right Move cursor left by one character Move cursor right by one character Clear Display (also clear DDRAM content) Set DDRAM address or coursor position on display Set CGRAM address or set pointer to CGRAM location

0x06 0x08 0x0E 0x0C 0x0F 0x18 0x1C 0x10 0x14 0x01

6 8 14 12 15 24 30 16 20 1

0x80+add* 128+add* 0x40+add** 64+add**

Table 4: Frequently used commands and instructions for LCD * DDRAM address given in LCD basics section see Figure 2,3,4 ** CGRAM address from 0x00 to 0x3F, 0x00 to 0x07 for char1 and so on.. The table above will help you while writing programs for LCD. But after you are done testing with the table 4, i recommend you to use table 3 to get more grip on working with LCD and trying your own commands. In the next section of the tutorial we will see the initialization with some of the coding examples in C as well as assembly.

You might also like