Monday 21 September 2015

Embedded C programming based on 8051 microcontroller

Embedded C programming based on 8051 microcontroller

  1. 1. EMBEDDED ‘C’ Gaurav Verma Assistant Professor Department of Electronics and Communication Engineering Jaypee Institute of Information and Technology Sector-62, Noida, Uttar Pradesh, India 1 Copyright to gaurav verma
  2. 2. What is Embedded ‘C’ Whenever the conventional ‘C’ language and its extensions are used for programming embedded systems, it is referred to as “Embedded C” programming.
  3. 3. Advantages Š It is a ‘mid-level’, with ‘high-level’ features (such as support for functions and modules), and ‘low-level’ features (such as good access to hardware via pointers). Š C is the most common Embedded language 85%, of embedded applications are coded in C. Š C , when used correctly is as safe and robust as any other high level language. ŠŠ It directly manipulates the hardware and memory addresses. Š It is very efficient, It is popular and well understood. Š Good, well proven compilers are available for every embedded processor(8-bit to 32-bit) Š Cx51 Cross compiler supports all of the ANSI Standard C directives.
  4. 4. ‘C’ Versus Embedded ‘C’ y ‘C’ is a well structured, well defined and standardized y Embedded ‘C’ can be id d b f generalpurpose programming language. l f f considered as a subset of conventional ‘C’ language. y A software program called yA platform specific application , known as , compiler is used for the f p g ‘Cross compiler’ is used for the conversion of programs conversion of programs ritten in Embedded ‘C’ to written in C to the target processor specific binary written C target processor/controller specific instructions(machine files. language).
  5. 5. ‘p Compiler’ Versus ‘Cross p Compiler’ y C il i ft t lth t t d itt Compiler is a software tool that converts a source code written in a high level language on top of a particular operating system running g on a specific target processor architecture. y Cross compilers are software tools used in cross platform development applications. (In cross platform development , the compiler running on a particular target processor/OS converts the source code to machine code for a target processor whose architecture and instruction set is different from the current development environment OS).
  6. 6. y Keywords ¾These are the reserved names used by the ‘C ’ language language. ¾All keywords should be written in ‘lowercase’ letters. Examples- int, char, double, float, void, while, for, long etc.ANSI ‘C’ supports 32 such keywords.
  7. 7. Identifiers ¾ Identifiers are user defined names and labels. ¾ Can contain letters of English alphabet(both upper and lower case) and numbers. ¾¾Note: The starting character of an identifier should be a letter and the only special character allowed in identifier is underscore(_).
  8. 8. g Storage Classes y Keywords related to storage class provide information on the scope i.e. visibility or accessibility and lifetime i.e. existence of a variable. yy ‘C’ supports four types of storage classes .
  9. 9. Storage Class Meaning Comments auto Variables declared inside a function Scope and accessibility is function. restricted within the Default storage class is auto. function where the variable is declared. No initialization. register Variables stored in the CPU register of Same as auto in scope and access processor. Reduces access time of variable. access. The decision on whether a variable needs to be kept in CPU register of the processor depends on the compiler. static Local variable with i h l lifetime same as that of the program. Retains the value throughout the program. By default initializes to zero on variable creation.
  10. 10. Cont… Storage Class Meaning Comments static Accessibility depends on where the variable is declared. extern Variables Can be modified accessible to all functions in a file by any function within a file or and all files in a multiple file program. across multiple files. p g
  11. 11. Data Types Data types Bits Bytes Value range y Bit 1 0 to 1 y Signed char 8 1 -128 to +127 y Unsigned char 8 1 0 to 255 y enum 816 12 -128 to +127 or -32768 to +32767 y Signed short 16 2 -32768 to +32767 y Unsigned short 16 2 0 to 65535 y Signed int 16 2 -32768 to +32767 y Unsigned int 16 2 0 to 65535 y Signed long 32 4 -2147483648 to 2147483647 yy Unsigned long 32 4 0 to 4294967295 y Float 32 4 ±1.175494E-38 to ±3.402823E+38 y sbit 1 0 to 1 y sfr 8 1 0 to 255 Note: The storage size may vary for data type depending on the cross compiler in use for embedded applications.
  12. 12. Unsigned Char y 8 bits range :0 to 255 y Character data type is preferred data type for many applications, like setting a counter value and ASCII characters instead of signed char. y It is important to specify the keyword unsigned in front of the char else compiler will use the signed char by default. y As 8051 has a limited number of registers and data RAM locations, using the int in place of char can lead to a larger size hex file.
  13. 13. yy Example : Write an 8051 C program to send hex values for ASCII characters of 0, 1, 2, 3, 4, 5, A, B, C, and D to port P0. y #include <reg51.h> void main( ) { unsigned char num[ ]=“012345ABCD”; unsigned char z; for (z = 0 ; z <= 10; z++) P0=num[z]; }
  14. 14. y Write an 8051 C program to toggle all the bits of P1 continuously. #include <reg51.h> void main(void) { for (;;) ;repeat forever { P1=0x55; P1=0xAA; } }
  15. 15. Signed Char y 8 bit data type MSB D7 to represent or +value Range 128 8-– value. –to +127. y Use unsigned char unless the data needs to be represented as signed numbers.
  16. 16. y Write an 8051 C program to send temperature range of –4 to +4 to port P1. #include <reg51.h> void main(void) { char mynum[]={0,+1,-1,+2,-2,+3,-3,+4,-4}; unsigned char z; for (z = 0; z<=8 ; z++) P1=mynum[z]; } Note: The negative values will be displayed in the 2’s complement form as 1, FFH, 2, FEH, 3, FDH, 4, FCH.
  17. 17. Unsigned int: y 16-bit data type range : 0 to 65535 (0000 – FFFFH). yy Used to define 16-bit variables such as memory addresses, set counter values of more than 256. y Registers and memory accesses are in 8-bit chunks, the misuse of int variables will result in a larger hex file. y 8051 programming, unsigned char will do the job of unsigned int . NOTE : C compiler uses signed int as default if unsigned keyword is not used. Signed int: y Signed int is a 16-bit data type that uses the MSB D15 to represent – or +value. We have 15 bits for the magnitude of the number from – 32768 to +32767
  18. 18. sbit (Single bit): y 8 bit keyword is a 8051 C data types used to access single-bit addressable register. y Allows access to the single bits of the SFR registers, that are bit addressable. bit and sfr : y The bit data type allows access to single bits of bit-addressable memory spaces 20 – 2FH. To access the byte-size SFR registers, we use the sfr data type.
  19. 19. y Example :Write an 8051 C program to toggle bit D0 of the port P1 (P1.0) 50,000 times. #include <reg51.h> sbit MYBIT=P1^0; void main() { unsigned int z; for (z = 0; z<50000; z++) { MYBIT=0; MYBIT=1; } }
  20. 20. y Example :Write an 8051 C program to toggle only bit P2.4 continuously without disturbing the rest of the bits of P2. #include <reg51.h> sbit mybit = P2^4; void main(void) { while (1) { mybit=1; //turn on P2.4 mybit=0; //turn off P2.4 } }
  21. 21. yy Example :Write an 8051 C program to monitor bit P1.5. If it is high, send 55H to P0; otherwise, send AAH to P2. #include <reg51.h> sbit mybit=P1^5; void main(void) { mybit=1 //mybit (P1.5)an input pin while (1) { if (mybit==1) P0=0x55; else P2=0xAA; } }
  22. 22. y Write an 8051 C program to get the status of bit P1.2, save it, and send it to P2.5 continuously. #include <reg51.h> sbit inbit=P1^2; sbit outbit=P2^5; bit mbit; //use bit to declare bit- addressable void main(void) { while (1) { mbit=inbit; //get a bit from P1.2 outbit=mbit; //send it to P2.5 } }
  23. 23. Time Delays y Using the 8051 timer y Using a simple for loop y Delays can be observed either on the oscilloscope or using a simulator. y In creating a time delay using for loop factors need to be considered 1. Number of machine cycles and number of clock periods per machine cycle. 2. Crystal frequency connected between XTAL1 and XTAL2. Duration of the clock period for the machine cycle is the function of crystal frequency. 3. Compiler selected. Accuracy of the time delay is mainly due to the compiler used .
  24. 24. yy In assembly language programming, delay generated can be controlled by the user, as the number of instructions and the cycles per instruction are known. y In case of C program, the C compiler will convert the C statements and functions to assembly language instructions. y Different compilers produce different delay.
  25. 25. y Write an 8051 C program to toggle bits of P1 continuously with some delay. #include <reg51.h> void main(void) { unsigned int x; for (;;) { P1=0x55; for (x=0;x<20000;x++); //delay size unknown P1=0xAA; for (x=0;x<20000;x++); } }
  26. 26. y Write an 8051 C program to toggle bits of P1 ports continuously with a 250ms. #include <reg51.h> void Delay1(unsigned int); void main(void) { while(1) //repeat forever { P1=0x55; Delay1(250); P1=0xAA; Delay1(250); } } void Delay1(unsigned int itime) { unsigned int i,j; for (i=0;i<itime;i++) for (j=0;j<1275;j++); }
  27. 27. y Write an 8051 C program to get a byte of data from P1,wait ½ second, and then send it to P2. #include <reg51.h> void Delay(unsigned int); void main(void) { unsigned char mybyte; P1=0xFF; //make P1 input port while (1) { mybyte=P1; //get a byte from P1 Delay(500); P2=mybyte; //send it to P2 } }
  28. 28. y Write an 8051 C program to get a byte of data form P0. If it is less than 100, send it to P1; otherwise, send it to P2. #include <reg51.h> void main(void) { unsigned char mybyte; P0=0xFF; //make P0 input port while (1) { mybyte=P0; //get a byte from P0 if (mybyte<100) P1=mybyte; //send it to P1 else P2=mybyte; //send it to P2 } }
  29. 29. Accessing SFR Addresses 80 – FFH y Another way to access the SFR RAM space 80H-FFH is to use the sfr data type. When this data type is used no need of using the header file reg51.h. Table 4 shows the single bit addresses of ports. Ports D7 D6 D5 D4 D3 D2 D1 D0 PO 87 (P0.7) 86 85 84 83 82 81 80 (P0.0) P1 97 (P1.7) 96 95 94 93 92 91 90 (P1.0) P2 A7 (P2.7) A6 A5 A4 A3 A2 A1 A0 (P2.0) P3 B7 B6 B5 B4 B3 B2 B1 B0 (P3.7) (P3.0)
  30. 30. Write an 8051 C program to toggle all the bits of P0 and P2 continuously with a 250 ms delay. Use the sfr keyword to declare the port addresses. If reg51.h is not included in the program, keyword sfr is used to define the port address sfr P0=0x80; sfr P1=0x90; sfr P2=0xA0; void Delay(unsigned int); void main(void) { while (1) { P0=0x55; P2=0x55; Delay(250); P0=0xAA; P2=0xAA; Delay(250); } }
  31. 31. Logic Operation in 8051 C y The most important feature of the C language is its ability to perform bit manipulation. y The bitwise operators used in C are y AND (&), y OR ( | ), y EX-OR ( ^ ), y inverter (~), y Shift right (>>) y Shift left (<<)
  32. 32. y Example : The following program will explain the different logical operations that are run on simulator. #include <reg51.h> void main(void) { P0=0x6E & 0x0F; //ANDing P1=0x34 | 0x68; //ORing P2=0x54 ^ 0x88; //XORing P0=~0x55; //inversing P1=0xCA >> 3; //shifting right 3 P2=0x77 >> 4; //shifting right 4 P0=0x5 << 4; //shifting left 4 }
  33. 33. y Example : Write an 8051 C program to toggle all the bits of P0 and P2 continuously with a 250 ms delay. Use the inverting and Ex-OR operators. #include <reg51.h> void Delay(unsigned int); void main(void) { P0=0x55; P2=0x55; while (1) { P0=~P0; P2=P2^0xFF; Delay(250); } }
  34. 34. y Example : Write an 8051 C program to get bit P1.0 and send it to P2.7 after inverting it. #include <reg51.h> sbit inbit=P1^0; sbit outbit=P2^7; bit mbit; void main(void) { while (1) { mbit=inbit; //get a bit from P1.0 outbit=~mbit; //invert it and send to P2.7 } }
  35. 35. y Example :Write an 8051 C program to read the P1.0 and P1.1 bits and issue an ASCII character to P0 that is if P1.1 and P1.0 is 00 send ‘0’ if 01 send ‘1’, if 10 send ‘2’ . yy Make P1 as input port. Read P1. y Mask all bits except D0 & D1 of P1 ad put the masked value in x. y If x=0; send ‘0’ to P0, else if x=1; send ‘1’ to P0, else if x=2; send ‘2’ to P0,. (use Repeat from step 2. #include <reg51.h> void main(void) { unsigned char z; z=P1; //read P1 z=z&0x3; //mask the unused bits
  36. 36. switch (z) //make decision { case(0): { P0=‘0’; break; //send ASCII 0 } case(1): { P0=‘1’; break; //send ASCII 1 } case(2): { P0=‘2’; break; //send ASCII 2 } } }
  37. 37. Data conversion programs in 8051 C y Packed BCD to ASCII conversion y ASCII to Packed BCD conversion yy Binary (hex) to decimal and ASCII conversion
  38. 38. Packed BCD to ASCII conversion Example : Write an 8051 C program to convert packed BCD number 0x45 to ASCII and display on P1 and P2. Get the packed BCD number. Convert it to unpacked BCD by masking the lower and upper digit. Add 30H individually and send the ASCII number to P1 and P2 #include <reg51.h> void main(void) { unsigned char x,y,z; unsigned char mbyte=0x45; x=mbyte&0x0F; P1=x|0x30; y=mbyte&0xF0; y=y>>4; P2=y|0x30; }
  39. 39. ASCII to Packed BCD conversion Example : Write an 8051 C program to convert ASCII digits to packed BCD and display them on P1. Get the 1st ASCII number and mask the higher nibble. Shift the number to get the higher nibble of BCD. Get the 2nd ASCII number and mask the higher nibble. Add the result to the first number. Display the BCD number on P1. #include <reg51.h> void main(void) { unsigned char bcdbyte; unsigned char w=‘4’; unsigned char z=‘7’; w=w&0x0F; w=w<<4; z=z&0x0F; bcdbyte=w|z; P1=bcdbyte; }
  40. 40. Binary (hex) to decimal and ASCII conversion Example : Write an 8051 C program to convert 11111101(FDH) to decimal and display the digits on P0, P1 and P2. Divide the binary number by 10 and save it in x. Modulo divide the binary by 10 & save the result in units. Divide x by 10 & save it in hundred. Modulo divide x by 10 & save it in tens Display units, tens & hundreds on P0,P1 & P2. #include <reg51.h> void main(void) { unsigned char x,binbyte,d1,d2,d3; binbyte=0xFD; x=binbyte/10; d1=binbyte%10; d2=x%10; d3=x/10; P0=d1; P1=d2; P2=d3; }
  41. 41. Delay Using Timers y Example : Write an program to toggle all the bits of port continuously with some delay in between. Use Timer 0, 16-bit mode to generate the delay. E l W it 8051 C t t l ll th bit f t P1 #include <reg51.h> void Delay(void); void main(void) { while (1) { //repeat forever P1=0x55; Delay(); //toggle all the bits of P1 P1=0xAA; // delay unknown Delay(); } }
  42. 42. Void Delay() { TMOD=0x01; // timer 0 mode 1 TL0=0x00; TH0=0x35; // load TH and TL TR0=1; // turn on T0 while (TF0==0); // wait for TF0 to roll over TR0=0; // turn off T0 TF0=0; // clear TF0 }
  43. 43. y Example 11: Write an 8051 C program to toggle only bit P1.5 continuously every 50ms. Use Timer 0, mode 1 (16-bit) to create the delay. Assume XTAL=11.0592 MHz=> T=1.085μs Count=50ms/1.085μs =46083 Initial count = 65536-46083 =19453, Count in Hex = 4BFDH #include <reg51.h> void Delay(void); sbit mybit=P1^5; void main(void) { while (1) { mybit=~mybit; //toggle P1.5 Delay(); }}
  44. 44. void Delay(void) { TMOD=0x01; // Timer 0, mode 1 TL0=0xFD; TH0=0x4B; TR0=1; while (TF0==0); TR0=0; TF0=0; }
  45. 45. Example : A switch is connected to pin P1.2. Write an 8051 C program to monitor SW and create the following frequencies on pin P1.7:SW=0: 500Hz, SW=1: 750Hz, use Timer 0, mode 1 Values to be loaded into TH and TL for 500Hz and 750Hz can be calculated as in previous ex. #include <reg51.h> sbit mybit=P1^5; sbit SW=P1^7; void Delay(unsigned char); void main(void){ SW=1; // make P1.7 as input while (1) { mybit=~mybit; // toggle P1.5 if (SW==0) // check switch Delay(0); else Delay(1); }}
  46. 46. Void Delay(unsigned char c) { TMOD=0x01; if (c==0) { TL0=0x67; TH0=0xFC; } else { TL0=0x9A; TH0=0xFD; } TR0=1; while (TF0==0); TR0=0; TF0=0; }
  47. 47. 8051 C programming of Timers 0 and 1 Delay Using Mode 2 Write an 8051 C program to toggle only pin P1.5 continuously every 250 ms. For the delay of 250ms the count exceeds 256. hence, count for 25μs is calculated which is 23 .Therefore for 250ms =>25μs × 250 × 40 = 250 ms #include <reg51.h> Void Delay(void); sbit mybit=P1^5; void main(void){ unsigned char x,y; while (1) { mybit=~mybit; for (x=0;x<250;x+ +) for (y=0;y<36;y+ +) //we put 36, not 40 Delay(); }}
  48. 48. Void Delay(void){ TMOD=0x02; TH0=-23; TR0=1; while (TF0==0); TR0=0; TF0=0; }
  49. 49. Problem: Write an 8051 C program to create a frequency of 2500 Hz on pin P2.7. UseTimer 1, mode 2 to create delay Time Period=1/2500Hz = 400μs Ton=Toff= 400μs /2 = 200μs Count = 200μs / 1.085μs = 184 Initial count =256-184 = 72 In hex = 48H
  50. 50. Counter Programming: y Timers can also be used as counters, counting events happening real world. When it is used as a counter, it is an external pulse that increments theTH,TL register. y TMOD and TH, TL registers are used as in timer programming except for the source of the frequency. y C/T bit inTMOD register y The C/T bit in the TMOD registers decides the source of the clock for the timer. When C/T = 1, the timer is used as a counter and gets its pulses from outside. The counter counts up as pulses are fed from pins 14 and 15, these pins are called T0 (timer 0 input) and T1 (timer 1 input).
  51. 51. y Example : Assuming that clock pulses are fed into pin T1, write a program for p g counter 1 in mode 2 to count the pulses and display the state of theTL1 count on P2, which connects to 8 LEDs. MOV TM0D,#01100000B ;counter 1, mode 2,C/T=1 MOV TH1,#0 ;clear TH1 SETB P3.5 ;make T1 input AGAIN: SETB TR1 ;start the counter BACK: MOV A,TL1 ;get copy of TL MOV P2,A ;display it on port 2 JNB TF1,Back ;keep doing, if TF = 0 CLR TR1 ;stop the counter 1 CLR TF1 ;make TF=0 SJMP AGAIN ; keep doing it Notice in the above program the role of the instruction SETB P3.5.
  52. 52. Example : Assume that a 1-Hz external clock is being fed into pin T1 (P3.5). Write a C program for counter 1 in mode 2 to count up and display the state of the TL1 count on P1. Start the count at 0H. #include <reg51.h> sbit T1=P3^5; void main(void){ T1=1; TMOD=0x60; TH1=0; while (1) { do { TR1=1; P1=TL1; } while (TF1==0); TR1=0; TF1=0; }}
  53. 53. Example : Assume that a 1-Hz external clock is being fed into pin T0 (P3.4). Write a C program for counter 0 in mode 1 (16-bit) to count the pulses and display the state of the TH0 and TL0 registers on P2 and P1, #include <reg51.h> void main(void){ T0=1; TMOD=0x05; TL0=0 TH0=0; while (1) { do { TR0=1; P1=TL0; P2=TH0; } while (TF0==0); TR0=0; TF0=0; }}
  54. 54. Memory in 8051 C Programming 8051 Memory Types y The 8051 separates the data segments from the code segments in memory. The register related data, interrupt service data, stack data and any frequently accessed data are kept in on-chip internal memory but the code and large data structures such as arrays and lookup tables are kept in EPROM or extended RAM off-chip memory. y 8051 C allows C programmers to decide which memory segment to assign the data items to. The capacity of on-chip memory is very limited (256 bytes). The on-chip memory is faster but more expensive while the extended RAM can be up to 64K byte which is slower but cheaper.
  55. 55. 8051 Memory Areas The 8051 architecture supports a number of physically separate memory areas for program and data. Each memory area offers certain advantages and disadvantages. Program Memory code Internal Data memory bdata, data, idata External Data memory xdata, pdata
  56. 56. Explicitly declared Memory types code: Program memory (64 Kbytes); accessed by opcode MOVC A, @A+DPTR. data: Directly addressable internal data memory; fastest access to full internal address space (256 bytes). idata: Indirectly addressable internal data memory; accessed across the internal address space (128 bytes). bdata: Bit-addressable internal data memory; allows mixed bit and byte access (16 bytes). xdata: External data memory (64 Kbytes); accessed by opcode MOVX @DPTR. pdata: Paged (256 bytes) external data memory; accessed by opcode MOVX @Rn.
  57. 57. Contd. There are five typical memory data types used for data memory in 8051 C: code, data, idata, bdata, xdata and pdata. There is one typical code memory type for code, but you can also assign large, constant data items in the code type segment (64kB). The 8051 Memory Space
  58. 58. data type memory y The data type memory is a 128 byte on-chip memory segment with an address starting at 000H(0) and ending at 07FH(127). yy This directly accessible internal memory segment is mostly used to store frequently used variables in the program such as parameter variables, temp variables, function variables and especially interrupt service variables which must be quickly accessible otherwise program performance will be affected. y From 080H(128) to 0FFH(255) in RAM is the Special Function Register (SFR) memory segment which are used to control timer/counter, Acc, interrupts, and I/O ports.
  59. 59. Bdata, idata, xdata y Within the data segment there is a 16-byte special segment called bdata with an address from 020H to 02FH which is bit addressable. Each individual bit in this segment has its unique bit address for fast access and manipulation. y The idata segment (128 byte) is the second memory segment at 080H-0FFH available in the extended on-chip RAM(8052). It is indirect accessible. it must be accessed with the indirect address mode (address is held in a register). y The xdata segment (64KB) from 00000H-0FFFFH (65,535) is available on off-chip RAM which augments the internal memory.
  60. 60. pdata y The paged pdata segment is within the first 256 bytes of the xdata which accommodate up to 256 bytes for data variables although it is not as efficient as internal memory access. y The code segment (64kB) available on off-chip external EPROM is used for program storage. It can also be used to store lookup tables and other large but less frequently changed data.
  61. 61. Memory Models y With memory models you can simply determine the default memory type used for function parameters and variables declared with no explicit memory type. You can override the default memory type by explicitly declaring variables with specified memory types. y The three memory models are SMALL, COMPACT, LARGE.
  62. 62. SMALL model In the small memory model all variables default to the internal data memory of the 8051.This is the same as if they were declared explicitly by the data memory type. y The small mode data access is the fastest because the direct memory access is used on the on-chip RAM, but is limited to 128 bytes(256 bytes for 8052). You always try to use small memory in your application unless it can not work out before trying other two memory models. y 8051 programmers with a single 8051 chip can only use the SMALL memory model unless external memory is utilized.
  63. 63. COMPACT model In the compact memory p y model all variables default to one page (256 bytes off-chip) of external data memory. This is the same as if they were explicitly declared as the pdata memory type. The programmer can still access internal data memory. The compact mode data access is slower than the small mode access because byte registers R0 and R1(@R0,@R1 in assembly) are used to indirectly address the data which can only reach 28 = 256 bytes.
  64. 64. LARGE model In the large model all variables default to external off-chip xdata memory(up to 64k bytes). The data in this model as if were explicitly declared as the xdata memory type (64k). The memory access is slower than the small and compact models because it uses 2 bytes data pointer (DPTR) to address the external memory.
  65. 65. Accessing Code ROM Space in 8051 C y Three spaces to store data: y The 128 bytes of RAM space with address range 00-7FH y The 64KB of code space with address 0000-FFFFH - used for storing program & under control of PC - data accessed using MOVCA,@A+DPTR yy The problems using this code space for data: y Can burn predefined data and tables but can’t write during the execution of program. More of code space is used for data and less for program code
  66. 66. y Intel created another memory space called external memory especially for data. yy The 64KB of external memory – RAM & ROM y The 8051 C compiler allocates RAM locations as y Bank 0 – addresses 0 – 7 y Individual variables – addresses 08 and beyond y Array elements – addresses right after variables y Array elements need contiguous RAM locations and that limits the size of the array due to the fact that we have only 128 bytes of RAM for everything y Stack – addresses right after array elements
  67. 67. Example : Compile and single-step the following program on your 8051simulator. Examine the contents of the 128-byte RAM space to locate the ASCII values. #include <reg51.h> void main(void) { unsigned char mynum[]=“ABCDEF”; //RAM space unsigned char z; for (z=0;z<=6;z++) P1=mynum[z]; }
  68. 68. Example : Write, compile and single-step the following program on your 8051simulator. Examine the contents of the RAM space to locate the values. #include <reg51.h> void main (void) { unsigned char mydata[100]; //RAM space unsigned char x, z=0; for (x=0;x<100;x++) { z--; mydata [x]=z; P1=z; } }
  69. 69. Example : Compile and single-step the following program on your 8051simulator. Examine the contents of the code space to locate the ASCII values. #include <reg51.h> void main(void) { code unsigned char mynum[]=“ABCDEF”; unsigned char z; for (z=0;z<=6;z++) P1=mynum[z]; }
  70. 70. #pragma y You can use the #pragma directive in your C program to specify the memory model. The default memory model is SMALL. y The compiler is directed to use the LARGE memory model but each individual data variable can override the LARGE memory model (default to xdata type) by explicit specification with data type or bdata type. #pragma LARGE unsigned int data data1; // override data1 to data type int data2; // default xdata type bit bdata bit1; // override bit1 to bdata type
  71. 71. Mix C and Assembly Code y Trade off between C and assembly language in the embedded software development. y You can take advantage of assembly code to call an assembly routine from your C program or embed assembly code inline in your C program. y For example, some particular standard assembly functions are available to use, some time critical task needs to be written in assembly for fast execution, or you need to access SFRs or memory-mapped I/O devices directly using assembly code. y It is not very difficult to call assembly code from C and vice-versa because the C51 provides the mechanisms to do so. y You can use pair of inline assembly directive #pragma ASM and #pragma ENDASM to include the assembly code in your C program
  72. 72. #include <reg51.h> void sub(unsigned char x); void main() { . . . sub(10); . . .} sub(unsigned char x) { #pragmaASM movA, #x //or use R7 register to get the value of //parameter and put in Acc mov@R0,A // put it in buffer #pragma ENDASM }
  73. 73. Calling an assembly code from C51 program extern void a_func(unsigned int x); void main() { int y; y =_func(); } Create a separate C file with the definition of a_fun() as follows: #pragma SRC //let C compiler generate a .src file //instead of obj file unsigned int a_func(unsigned int x) { return x-1; //this may be a fake statement, //the purpose of it to generate a skeleton //for your true assembly code replacement }
  74. 74. y Then use c51 compiler command to compile this C file with option of src to generate the assembly source code in a .src file. y Modify the source code in assembly to fit your need and rename it to .a51 file and use a51 command assemble it into objective code. y Finally, link this object code with the object code from the main program to get the target code.
  75. 75. Function Declaration Cx51 provides you with a number of extensions for standard C function declarations.These extensions allow you to: - Specify a function as an interrupt procedure - Choose the register bank used - Select the memory model return_type funcname (args) [{small | compact | large}] [interrupt n] [using n] where: return_type is the type of the value returned from the function. If no type is specified, int is assumed.
  76. 76. y funcname is the name of the function. y args is the argument list for the function. y small, compact, or large is the explicit memory model for the function. y interrupt indicates that the function is an interrupt function. y using specifies which register bank the function uses.
  77. 77. Interrupt Functions y An interrupt is a triggered event that temporarily suspends the foreground g program and lets another background program called an interrupt service routine (ISR) or interrupt handler to deal with the event. y An interrupt driven system can do multiple tasks simultaneously. It allows the system to respond to an event and handle the event asynchronously. After the ISR completes its job, control returns to the foreground program.
  78. 78. yy Most embedded system software is time critical so programmers adopt the interrupt (event) driven approach instead of inefficient busy polling. While(TF0 != 1) { . . . } Or while( p7^1 == 0){ . . . } yy Here the program continuously checks all ““service request flags”, waiting for the events to occur. Once it finds a request, it services the device and keeps polling. In an interrupt driven program, the main foreground program can handle other things without wasting time waiting for the event.
  79. 79. How Interrupt Works In an interrupt system, when the CPU is informed of an interrupt, it first completes its current instruction and saves the Program Counter (PC) and current status on the stack. The CPU then fetches the ISR address (interrupt vector) and puts it into the PC and runs the ISR until it reaches the RETI instruction. After that, the CPU pops up the old PC from the stack and resumes the interrupted program. Most embedded systems are interrupt driven since the interrupt can not be predicted in advance. Meanwhile, the CPU is free to do other things.
  80. 80. y A foreground program is interrupted g p g p by a level 1 interrupt and the CPU switches the control to its ISR0. Somehow during the execution of ISR0 another level 1 interrupt occurs which interrupts the ISR0. After ISR1 completes, ISR0 is resumed and in turn the original program is resumed. Interrupt Example
  81. 81. Simple interrupt application yy with an external interrupt #2 which is connected to p3^2 (bit 3 of pin 2 for INT0, see reg51.h). Once there is an interrupt caused by a edge trigger, the interrupt 0 event is fired and ISR myISR ( ) is called. #include <reg51.h> void myISR() interrupt 0 { . . . } main() { EA = 1; // enable global interrupt EX0 = 1; // enable external interrupt 0 IT0 = 1; // 0 level triggered, 1 edge triggered while(1) { . . . } }
  82. 82. Example using Timer 0 ISR connected to INT1 #include <reg51.h> unsigned int count; void myRT0() interrupt 1 { TF0=0; //Timer 0 overflow flag count++; } main() { TMOD = 0x02; // timer 0 in mode 2(8 bits), counts up to 256 TH0 = 56; // reload value, 256-56=200, Overflows every // 200 CPU clocks TF0 = 0; ET0 = 1; // enable Timer 0 interrupt EA = 1; // enable global interrupt TR0 = 1; // start timer 0 While(1); // wait for INT } }
  83. 83. Register bank y An interrupt p function has a “using” attribute to specify the register bank. The "using" attribute tells the compiler to switch register banks on entry to an interrupt routine. y The 8051 has a register bank of eight general-purpose registers (R0-R7). Due to the time spent on the stack for saving the status and risk of stack damage while switching to an ISR, the 8051 provides four register banks you can use.
  84. 84. y Register bank 0 is used by default; the registers R0 to R7 are used extensively for the temporary storage of library routines and for locals. y Register banks 1, 2, or 3 are best used by ISRs to avoid saving and restoring registers on the stack and to avoid the risk of stack damage because the same priority interrupts can share a register bank. y Here is the syntax of ISR declaration with the “using” attribute void <ISR_name>(void) interrupt <interrupt_handler__number> [ using <register_bank> ]
  85. 85. y The “using” g attribute in an ISR definition above is optional. Small interrupt routines are not recommended to use the “using” attribute, since they use the default register bank 0. Complex and time critical interrupts which call other functions must use the “using” attribute. y A simple example of an ISR for Timer0 using register bank #2. unsigned int count; void timer0 (void) interrupt 1 using 2 { if (++count == 1000) count = 0; }
  86. 86. Reentrant Functions y In embedded system software, a function may need to call itself recursively, or to be interrupted by another function which calls the same function indirectly, or to be shared by multiple processes simultaneously. y The interrupted function must save its status including the Program Counter(PC) and values of all register and local variables so that the function can be resumed correctly later. y The normal C51 function can not be invoked recursively because the context data is stored in a fixed memory location and the recursive calls will corrupt the stack data area.
  87. 87. y This requires such functions to be reentrant. The extension of reentrant function is used to force the compiler to make a separate stack area for each instance of the function so that the function will always work correctly regardless of the circumstances. y The cost of the reentrant function is the consumption of the memory space.
  88. 88. y A normal 8051 C function does not guarantee such features because it can not protect its own current status well when it switches. y The reentrant function extension attribute allows you to declare functions to be reentrant. The stack for a reentrant function is simulated in internal or external memory depending on the memory model. y The first example given here is a function A() interrupted by a ISR which calls this function A() recursively so that the function A() should be declared as a reentrant function.
  89. 89. A(int x) reentrant { //actions; } Void myINT (void) interrupt 2 { A(10); } Main() { while(1) { int i; i = 5; A(i); . . . }
  90. 90. Table lookup function shared by multiple processes char data[] ={‘A’, ‘B’, ‘C’}; char lookup(int i) reentrant { char x; x = data[i]; return (x); } This function may also be interrupted by another ISR which calls this function as well so that this lookup function is declared as a reentrant function.
  91. 91. Simple reentrant function which calls itself void recursive(unsigned int value) reentrant {if (value>0) recursive(--value); } If a reentrant function calls another function, the latter must also be reentrant as well.
  92. 92. Real Time Function y The C51 provides the _task_ and _priority_ keywords to the function extensions y the _task_ tells the function as a real time task function y _priority_ tells the priority level of the task if task is run in a priority-based multi-tasking scheduling environment. E.g. Void myFuction (void) _task_ 2 _priority_ 3. y You can define up to 256 real time functions numbering from 0 to 255. y You can specify up to 5 priority levels from 0 to 4.
  93. 93. Modular Programming in C y It is clear that a single source file or “module” is sufficient to hold the entire C program. y Modular programming, p g g however, is a “divide and conquer” software design and programming technique which breaks up a large program into manageable subprogram units such as functions and subroutines. y Each module represents a separation of concerns which improves software maintainability and reusability by enforcing logical boundaries between modules.
  94. 94. Contd. y An embedded system is composed of several modules, each with a unique function, so the embedded software system is built from a number of discrete tasks and then finally assembled into a complete, working software.
  95. 95. y A modular program consists of a main module and many auxiliary modules, such as device drivers in embedded software systems. y In reality each module is a separate source file. If you need to revise or update functions in one module, you only need to work on that file containing the function. y For example, most embedded systems have an initialization and configuration function called init() which is included in one of the modules. y Each individual module is much shorter than the entire program, hence it is much easier to read and understand.
  96. 96. Contd. y Modular programming also helps debugging and testing programs and reduces the likelihood of bugs. y Local scopes of variables in modules and smaller size of the individual modules make it easier to understand the effects and impacts of changing a variable.
  97. 97. yy Modular programming in C is to organize a program in multiple files. There is a main module which contains the main() function. This is the entrance of the entire program and many other modules in formats of C source code files or header files. y First, you must decide how to divide your program into multiple files or modules. For example, you can make each interrupt service subroutine as a separate module, same as other interrupt handlers.
  98. 98. Contd. y Next, after you determine all modules you need to decide how to interface with each other. In other words, you need to decide the visibilities of the variables and functions in each module. y For these private data variables or helper functions, you should define them as private visibility by C static scope to make them accessible within the module file where they are defined. y For most functions, data variables and data types, you need to make them public to expose to all other modules that need to access or share and reuse these resources.
  99. 99. Scope of Functions and Variables y In a multi-module C program, one module may need to call functions defined in other modules. Multiple modules may share some data, and some data may need to be transferred from one module to other modules. y The scope of data and functions must be specified properly to avoid data and program corruption. y A typical 8051 application consists of many modules in multiple source files where each has a number of functions accessing variables in RAM. y Each function has some temporary variables which will be used to store intermediate process values for internal use, but some functions need to access global variables shared by multiple functions.
  100. 100. y C uses the extern keyword to make an external reference to a variable or function residing in other modules. y The keyword static is used to specify the scope of variable of function to be the enclosing module. y A variable defined outside any function is treated as a global variable which is often used for main program and interrupt service routines to share or exchange data. y You can find that the variable “a” is defined outside any function in main.c so that it can be accessed everywhere in this module and can also be seen from any other module which makes an external reference to this variable.
  101. 101. yThe main.c module makes an external reference to exfunc() defined in module1.c so that exfunc() can be called within this module. yThe scopes of variables “b” and “c” are within the main() function because they are defined inside the main() function. main.c: int a ; extern int exfunc(int) ; int func( int x) { return(x*x); } main() { Int b; int c; b = exfunc(c); a = func(b); }
  102. 102. MODULE1.c extern int a; int exfunc(int x) { int d ; static int count ; count++ ; d = x * a ; return(d) ; ) The module1.c makes an external reference to the global variable a to use it in exfunc(). The local variable count is defined as a static variable so that it will remember its value after the exfunc() function call exits. When the exfunc() function is called again, the count variable will operate on its previous kept value, which is different from local variables in a function that doesn’t keep their data once the function exits.
  103. 103. Header Files y The main model includes the reg51.h in order to use port #1 defined in reg51.h. y You can place public (global) parts of a module in a header (.h) file. This header is included by other files that use its corresponding module. y A header file typically contains global variable definitions, typedef of data type declarations and function prototypes. This ensures that the module and all the files that use the module agree on data types, global data, and functions.
  104. 104. Contd. y It is also common for one header to include other headers. If both header files include a common header file and a C source code file includes these two header files, it will cause a compiler error due to multiple declarations of a type or macro. y The conditional compilation directive of the C preprocessor directives can be used to solve this kind problem
  105. 105. delay.h #ifndef _DELAY_ #define _DELAY_ /* body of header */ #endif y This directive checks to see if the identifier is not currently defined. If the _DELAY_ identifier has not been defined by a #define statement, then the code immediately following the command will be compiled. This prevents any duplicated inclusion. y Notice that for a function, the header file can only contain the prototype of a function, but never contains its complete implementation code. y The header plays a decoupling role between the function implementation in its source file and the function execution in the destination file where the function is called.
  106. 106. Multi‐module C Programming y The header file plays a role of interface between the modules with data and function definition and the modules referencing these data and functions. Here is a simple example with two modules connected by a header file. y The main program has an infinite loop calling a function f() which is defined in another module named module1. The MyHeader file provides a constant identifier PI, a type definition of “Real” and a function prototype of f().
  107. 107. main.c #include ”MyHeader.h” void main( void ) { int x; while(1){ f(x);} } MyHeader.h #ifndef _MYHEADER_H #define _MYHEADER_H #DEFINE PI 3.14259 // typedef double Real; // void f( Real ); // external function prototypes #endif
  108. 108. module1.c #include <stdio.h> #include <math.h> #include "MyHeader.h" void f( int x ) { int i; for (i=1; i<x; i++) circle(i);; } static void circle( Real R ) // internal scoped function { Static count; //static variable count ++; Printf(“%f %d”, PI*sqr(R), count); } Because neither main.c nor module1.c has the _MYHEADER_H identifier defined, the header file will be included and compiled.
  109. 109. y For a large embedded system it is not practical to have a single header file incorporated in each source file regardless of whether the incorporated files need them or not. y A good practical solution is to generate module-specific include header files as shown in the next diagram. Each module is paired with its corresponding header file.
  110. 110. y The header file consists of two parts: y Part1: original data, type, macro definitions and function prototypes used for host modules y Part2: external references to the items listed in part1 for referencing modules y The template for module1.c is shown below: #ifdef _module_ //_module_ is a identifier used for //conditional compilation // part1 #else //part2 #endif
  111. 111. Assume there are two modules, module1.c and module2.c. The module1.c is shown below. #define _module1_ #include <module1.h> #include <module2.h> . . . function1(){ . . . }; //function1 definition . . . function2(); //call function2
  112. 112. The corresponding module1.h is shown below. #ifdef _module_ //_module_ is a identifier used for // conditional compilation function1(); // prototype of function2 #else extern function1(); #endif The module2.c is shown as below. #define _module1_ #include <module1.h> #include <module2.h> . . . Function1(){ . . .; function2(); } // call function2 in the definition of function1
  113. 113. y The header file for module2.c is listed below. #ifdef _module2_ //_module_ is a identifier used for //conditional compilation function2(); // prototype of function2 #else extern function2(); #endif yy Although both header files are included in both modules, the original function prototype declarations are compiled in the host modules and external references are compiled in the referencing modules by the conditional compilation directives in the header files.
  114. 114. Practice is the key to success in embedded ‘C’ THANK YOU 116 Copyright to gaurav verma

No comments:

Post a Comment