The HCS12/MC9S12 Microcontroller Chapter 5: C Language Programming The HCS12 Microcontroller Han-Way Huang Minnesota State University, Mankato September 2009 Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-1 The HCS12/MC9S12 Microcontroller Introduction to C - C has gradually replaced assembly language in many embedded applications. - A summary of C language constructs that will be used in HCS12 programming. - Books on C language 1. Kernighan & Ritchie, “The C Programming Language”, Prentice Hall, 1988. 2. Deitel & Deitel, “C: How to Program”, Prentice Hall, 2008. 3. Kelly & Pohl, “A Book on C: Programming in C”, Addison-Wesley, 1998. - A C program consists of functions and variables. - A function contains statements that specify the operations to be performed. - Types of statements: 1. Declaration 2. Assignment 3. Function call 4. Control 5. Null - A variable stores a value to be used during the computation. - The main () function is required in every C program. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-2 The HCS12/MC9S12 Microcontroller A C Program Example (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) #include <stdio.h> /* this is where program execution begins */ int main () { int a, b, c; a = 3; b = 5; c = a + b; printf (“ a + b = %d\n”, c); return 0; } -- causes the file stdio.h to be included -- a comment -- program execution begins -- marks the start of the program -- declares three integer variables a, b, and c -- assigns 3 to variable a -- assigns 5 to variable b -- assigns the sum of a and b to variable c -- prints the string a + b = followed by value of c -- returns 0 to the caller of main( ) -- ends the main( ) function Types, Operators, and Expressions - Variables must be declared before they can be used. - A variable declaration must include the name and type of the variable and may optionally provide its initial value. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-3 The HCS12/MC9S12 Microcontroller - The name of a variable consists of letters and digits. - The underscore character “_” can be used to improve readability of long variables. Data Types - C has five basic data types: void, char, int, float, and double. The void type represents nothing and is mainly used with function. A variable of type char can hold a single byte of data. A variable of type int is an integer that is the natural size for a particular machine. The type float refers to a 32-bit single-precision floating-point number. The type double refers to a 64-bit double-precision floating-point number. Qualifiers short and long can be applied to integers. For GNU C compiler, short is 16 bits and long is 32 bits. - Qualifiers signed and unsigned may be applied to data types char and integer. Declarations - A declaration specifies a type, and contains a list of one or more variables of that type. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-4 The HCS12/MC9S12 Microcontroller Examples of declarations int i, j, k; char cx, cy; int m = 0; char echo = ‘y’; /* the ASCII code of letter y is assigned to variable echo. */ Constants - Types of constants: integers, characters, floating-point numbers, and strings. - A character constant is written as one character within single quotes, such as ‘x’. A character constant is represented by the ASCII code of the character. - A string constant is a sequence of zero or more characters surrounded by double quotes, as “MC9S12DP256 is made by Motorola” or “”, which represented an empty string. Each individual character in the string is represented by its ASCII code. - An integer constant like 1234 is an int. A long constant is written with a terminal l or L, as in 44332211L. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-5 The HCS12/MC9S12 Microcontroller - A number in C can be specified in different bases. - The method to specify the base of a number is to add a prefix to the number. Arithmetic Operators + * / add and unary plus subtract and unary minus multiply divide -- truncate quotient to integer when both operands are integers. % ++ -- modulus (or remainder) -- cannot be applied to float or double increment (by 1) decrement (by 1) Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-6 The HCS12/MC9S12 Microcontroller Bitwise Operators C provides six operators for bit manipulations; they may only be applied to integral operands. & | ^ ~ >> << AND OR XOR NOT right shift left shift & is often used to clear one or more bits of an integral variable to 0. PTH = PTH & 0xBD // clears bit 6 and bit 1 of PTH to 0 // PTH is of type char | is often used to set one or more bits to 1. PTB = PTB | 0x40; // sets bit 6 to 1 (PTB is of type char) ^ can be used to toggle a bit. abc = abc ^ 0xF0; // toggles upper four bits (abc is of type char) Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-7 The HCS12/MC9S12 Microcontroller >> can be used to shift the involved operand to the right for the specified number of places. xyz = xyz >> 3; -- shift right 3 places << can be used to shift the involved operand to the left for the specified number of places. xyz = xyz << 4; -- shift left 4 places The assignment operator = is often combined with the operator. For example, PTH PTB xyz xyz &= 0xBD; |= 0x40; >>= 3; <<= 4; Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-8 The HCS12/MC9S12 Microcontroller Relational and Logical Operators - Relational operators are used in expressions to compare the values of two operands. - The value of the expression is 1 when the result of comparison is true. Otherwise, the value of the expression is 0. - Relational and logical operators: == != > >= < <= && || ! equal to not equal to greater than greater than or equal to less than less than or equal to and or not (one’s complement) Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-9 The HCS12/MC9S12 Microcontroller Examples of Relational and Logical Operators if (!(ATD0STAT0 & 0x80)) statement1;// if bit 7 is 0, then execute statement1 if (i > 0 && i < 10) statement2;// if 0 < i < 10 then execute statement2 if (a1 == a2) statement3;// if a1 == a2 then execute statement3 Control Flow - The control-flow statements specify the order in which computations are performed. - Semicolon is a statement terminator. - Braces { and } are used to group declarations and statements together into a compound statement, or block. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-10 The HCS12/MC9S12 Microcontroller If-Else Statement if (expression) statement1 else statement2 -- The else part is optional. Example if (a != 0) r = b; else r = c; A more concise way for this statement is r = (a != 0)? b : c; Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-11 The HCS12/MC9S12 Microcontroller Multiway Conditional Statement if (expression1) statement1 else if (expression2) statement2 else if (expression3) statement3 … else statementn Example if (abc > 0) return 5; else if (abc = 0) return 0; else return -5; Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-12 The HCS12/MC9S12 Microcontroller Switch Statement switch (expression) { case const_expr1; statement1; break; case const_expr2; statement2; break; … default: statementn; } Copyright © 2010 Delmar Cengage Learning Example switch (i) { case 1: pay = 10; break; case 2: pay = 20; break; case 3: pay = 30; break; case 4: pay = 40; break; case 5: pay = 50; break; } H. Huang Transparency No.5-13 The HCS12/MC9S12 Microcontroller For-Loop Statement for (expr1; expr2; expr3) statement; where, expr1 and expr2 are assignments or function calls and expr3 is a relational expression. Example sum = 0; for (i = 1; i < 10; i++) sum += i * i; for (i = 1; i < 20; i++) if (i % 2) printf(“%d “, i); Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-14 The HCS12/MC9S12 Microcontroller While Statement while (expression) statement Example int_cnt = 5; while (int_cnt); Do-While Statement do statement while (expression); Copyright © 2010 Delmar Cengage Learning // do nothing while the variable int_cnt 0 Example int digit = 9; do printf(“%d “, digit--); while (digit >= 1); H. Huang Transparency No.5-15 The HCS12/MC9S12 Microcontroller Input and Output Examples - Not part of the C language itself. - Four I/O functions will be discussed. 1. int getchar ( ). -- returns a character when called char xch; xch = getchar (); 2. int putchar (int). -- outputs a character on a standard output device 3. int puts (const char *s). -- outputs the string pointed by s on a standard output device putchar(‘a’); puts (“Welcome to USA! \n”); 4. int printf (formatting string, arg1, arg2, …). -- converts, formats, and prints its arguments on the standard output device. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-16 The HCS12/MC9S12 Microcontroller Formatting String for Printf - The arguments of printf can be written as constants, single variable or array names, or more complex expressions. - The formatting string is composed of individual groups of characters, with one character group associated with each output data item. - The character group starts with %. - The simplest form of a character group consists of the percent sign followed by a conversion character indicating the type of the corresponding data item. - Multiple character groups can be contiguous, or they can be separated by other characters, including whitespace characters. These “other characters” are simply sent to the output device for display. - Examples printf (“this is a challenging course ! \n”); printf(%d %d %d”, x1, x2, x3); // outputs x1, x2, and x3 using minimal number // of digits with one space separating each value printf(“Today’s temperature is %4.1d\n”, temp); Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-17 The HCS12/MC9S12 Microcontroller Rules for Conversion String - Between the % and the conversion character there may be, in order: 1. 2. 3. 4. A minus sign, -- specify left adjustment. A number that specifies the minimum field width. A period that separates the field width from precision. A number, the precision, that specifies the maximum number of characters to be printed from a string, or the number of digits after the decimal point, or the minimum of digits for an integer. 5. An h if the integer is to be printed as a short, or l (letter ell) if as a long. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-18 The HCS12/MC9S12 Microcontroller Functions and Program Structure Every C program consists of one or more functions. Definition of a function cannot be embedded within another function. A function will process information passed to it from the calling portion of the program, and return a single value. Syntax of a function definition: return_type function_name (declarations of arguments) { declarations and statements } Example char lower2upper (char cx) { if cx > ‘a’ && cx <= ‘z’) return (cx - (‘a’ - ‘A’)); else return cx; } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-19 The HCS12/MC9S12 Microcontroller Example 5.4 Write a function to find the square root of a 32-bit integer using the successive approximation method. Solution: unsigned long int FindSqr (unsigned long int xval) { unsigned long int mask, temp, sar; unsigned int ix; mask = 0x8000; // Initialize mask for making bit value guessing sar = 0; for (ix = 0; ix < 16; ix++){ temp = sar | mask; if((temp * temp) <= xval) sar = temp; mask >>= 1; } if ((xval - (sar * sar)) > ((sar+1)*(sar+1) - xval)) sar += 1; return sar; } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-20 The HCS12/MC9S12 Microcontroller Example 5.5 Write a function to test whether a 32-bit nonnegative integer is a prime number Solution: An integer is a prime if it cannot be divided by any integer between 2 and its square root. unsigned int PrimeTest(unsigned long int xval) { unsigned long int TLimit; unsigned int ptest; if ((xval == 1) || (xval == 2)) return 0; TLimit = FindSqr(xval); // call FIndSqr() to find the limit for test divide for (ptest = 2; ptest <= TLimit; ptest++){ if ((xval % ptest) == 0) // is remainder zero? return 0; } return 1; } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-21 The HCS12/MC9S12 Microcontroller Example 5.6 Write a program to find the number of prime numbers between 100 and 1000. Solution: #include "c:\cwHCS12\include\hcs12.h" unsigned long int FindSqr (unsigned long int xval); unsigned int PrimeTest(unsigned long int xval); unsigned int prime_count; void main(void) { unsigned long int i; prime_count = 0; for (i = 100; i <= 1000; i++) { if (PrimeTest(i)) prime_count ++; } while(1); } #Include PrimeTest here #Include FindSqr here Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-22 The HCS12/MC9S12 Microcontroller Function Prototype A function cannot be called before it has been defined. This dilemma is resolved by using the function prototype statement. The syntax for a function prototype statement is as follows: return_type function_name (declarations of arguments); Exmaple unsigned int PrimeTest (unsigned long int xval); Creating Header File To reuse functions that we have created, we can collect the set of functions that are of the same nature into one file and also put the prototype declarations of these functions into one header file. When reusing these functions, we need to add the C file that contains them into the project and also add the header file into the file that invoke these functions. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-23 The HCS12/MC9S12 Microcontroller Pointers and Addresses - A pointer is a variable that holds the address of a variable. - Pointers provide a way to return multiple data items from a function via function arguments. - Pointers also permit references to other functions to be specified as arguments to a given function. - Syntax for pointer declaration: type_name *pointer_name; Examples int *ax; char *cp; - Use the dereferencing operator * to access the value pointed by a pointer. int a, *b; … a = *b; /* assigns the value pointed by b to a */ Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-24 The HCS12/MC9S12 Microcontroller - Use the unary operator & to assign the address of a variable to a pointer. For example, int x, y; int *ip; ip = &x; y = *ip; // y gets the value of x Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-25 The HCS12/MC9S12 Microcontroller Example 5.7 Write a bubble sort function to sort an array of integers. Solution: void swap (int *px, int *py); /* function prototype declaration */ void bubble (int a[], int n) /* n is the array count */ { int i, j; for (i = 0; i < n - 1; i++) for (j = 0; j < n – i - 1; j++) if (a[j] > a[j+1]) swap (&a[j], & a[j+1]); } void swap(int *px, int *py) { int temp; temp = *px; *px = *py; *py = temp; } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-26 The HCS12/MC9S12 Microcontroller Arrays An array consists of a sequence of data items that have common characteristics. Each array is referred to by specifying the array name followed by one or more subscripts, with each subscript enclosed in brackets. Each subscript is a nonnegative integer. The number of subscripts determines the dimensionality of the array. For example, x[i] is an element of an one-dimensional array y[i][j] refers to an element of a two-dimensional array Syntax for one-dimensional array declaration: data-type array_name [expression]; Syntax for two-dimensional array declaration: data-type array_name [expr1] [expr2]; Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-27 The HCS12/MC9S12 Microcontroller Pointers and Arrays Any operations that can be achieved by array subscripting can also be done with pointers. The pointer version will in general be faster but, somewhat harder to understand. For example, int ax[20]; int *ip; /* array of 20 integers */ /* ip is an integer pointer */ ip = &ax[0] /* ip contains the address of ax[0] */ x = *ip; /* copy the contents of ax[0] into x. If ip points to ax[0], then ip + 1 points to ax[1], and ip + i points to ax[i], etc. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-28 The HCS12/MC9S12 Microcontroller Passing Arrays to a Function - An array name can be used as an argument to a function. - To pass an array to a function, the array name must appear by itself, without brackets or subscripts, as an actual argument within the function call. - When declaring a one-dimensional array as a formal argument, the array name is written with a pair of empty square brackets. - When declaring a two-dimensional array as a formal argument, the array name is written with two pairs of empty square brackets. int average (int n, int arr[ ]); main ( ) { int n, avg; int arr[50]; … avg = average (n, arr); /* function call with array name as an argument */ … } int average (int k, int brr [ ]) /* function definition */ { … } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-29 The HCS12/MC9S12 Microcontroller Structures - A group of related variables that can be accessed through a common name. - Each item within a structure has its own data type, which can be different. - The syntax of a structure is as follows: struct struct_name { type1 member1; type2 member2; … }; /* struct_name is optional */ The struct_name is optional and if it exists, defines a structure tag that defines a type. For example, struct catalog_tag { char author [40]; char title [40]; char pub [40]; unsigned int date; unsigned char rev; } card; where, the variable card is of type catalog_tag. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-30 The HCS12/MC9S12 Microcontroller Unions A variable that may hold (at different times) objects of different types and sizes, with the compiler keeping track of size and alignment requirements. The syntax is as follows: union union_name { type-name1 type-name2 … type-namen }; element1; element2; elementn; where, union_name is optional. When exists, it defines a union-tag. The current temperature can be represented as follows: union u_tag { int i; char c[4]; } temp; A member of a union can be accessed as union-name.member Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-31 The HCS12/MC9S12 Microcontroller Writing C Programs to Perform Simple I/O The user needs to configure the direction of each I/O pin A pin can be configured for output by setting the corresponding bit in the associated data direction register to 1. For example, DDRB = 0xFF; // configure Port B for output DDRA = 0x0F; // configure Port A upper 4 pins for input, lower // four pins for output DDRT = 0x20; // configure Port T pin 5 for output, other pins // for input The following instructions perform simple I/O operations: PTB = 0x56; // output 0x56 to Port B PTP |= 0x20; // pull Port P pin 5 to high PTJ &= 0xFD; // pull Port J pin 1 to low xyz = PTA; // read the value of Port A and store it in xyz. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-32 The HCS12/MC9S12 Microcontroller Example 5.8 Write a program to display one LED at a time from the circuit in Figure 4.16 with each LED to be lighted for 200 ms. Solution: #include "c:\cwHCS12\include\hcs12.h" void SetClk8(void); // need to include SetClk.c to project void delayby100ms(int k); // include delay.c to project void main (void) { unsigned char led_tab[16]= {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01, 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; char i; DDRB = 0xFF; // configure Port B for output DDRJ |= 0x02;// configure PJ1 pin for output PTJ &= 0xFD; // enable LEDs to light SetClk8(); // set E clock to 24-MHz while (1) { for (i = 0;i < 16; i++) { PTB = led_tab[i]; // output a new LED pattern delayby100ms(2);// wait for 200 ms } } } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-33 The HCS12/MC9S12 Microcontroller PB6 PB1 PB0 Example 5.9 Write a program to display the following patterns from the seven-segment display circuit shown in Figure 4.18 from display #0 to #5 and repeat with each pattern lasting for 600 ms: 123456 234567 345678 #0 #1 #5 456789 800 a a . . . a . . . b b b 567890 . . . 678901 . 800 g . g . . . g . 789012 74HC244 common common common 890123 cathode cathode cathode 901234 74HC367 012345 A0 Y0 PP0 Solution: PP1 A1 Y1 PP2 A2 Y2 PP3 A3 Y3 PP4 A4 Y4 PP5 A5 Y5 . . . Figure 4.18 Port B and Port P together drive six seven-segment displays (MC9S12DG256) Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-34 The HCS12/MC9S12 Microcontroller Solution: There are ten different pattern sequences and two adjacent sequences are offset by 1. The overlapping these sequences are shown in Figure 5.2. Let SegPat, i, j, and k represent the segment table of 15 segment patterns, the start index of the sequence to be displayed, the number of times of the current sequence remained to be repeated, and the display to be lighted at the moment. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-35 The HCS12/MC9S12 Microcontroller #include "c:\cwHCS12\include\hcs12.h" #include "c:\cwHCS12\include\delay.h“ // include delay.c to the project void SetClk8(void); // include SetClk.c to the project unsigned char SegPat[16] = {0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67,0x3F, 0x06,0x5B,0x4F,0x66,0x6D}; unsigned char digit[6] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF}; void main(void) { int i, j, k; SetClk8(); // set E clock frequency to 24 MHz DDRB = 0xFF; //configure Port B for output DDRP = 0xFF; //configure Port P for output while(1) { for (i = 0; i < 10; i++) { // pattern array start index for (j = 0; j < 100; j++) { // repeat loop for each pattern sequence for (k = 0; k < 6; k++) { // select the display # to be lighted PTB = SegPat[i+k]; // output segment pattern PTP = digit[k]; // output digit select value delayby1ms(1); // display one digit for 1 ms } } } } } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-36 The HCS12/MC9S12 Microcontroller External Variables - A variable declared inside a function is called an internal variable. A variable defined outside of a function is called an external variable. An external variable is available to many functions. External variables provide an alternative to function arguments and return values for communicating data between functions. - Any function may access an external variable by referring to it by name if the name has been declared somewhere. - The use of static with a local variable declaration inside a block or a function causes a variable to maintain its value between entrances to the block or function. Scope Rules - The functions and external variables that make up a C program can be compiled separately. The source text of the program may be kept in several files. The scope of a name is the part of the program within which the name can be used. For a variable declared at the beginning of a function, the scope is the function in which the name is declared. - Local (internal) variables of the same name in different functions are unrelated. - The scope of an external variable or a function lasts from the point at which it is declared to the end of the file being compiled. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-37 The HCS12/MC9S12 Microcontroller In the following program segment The use of external variables are illustrated in the following 2-file C program … void f1 (…) { … } in file 1 extern int xy; extern long arr [ ]; main ( ) { … } void foo (int abc) { … } long soo (void) { … } int a, b, c; void f2(…) { … } Variables a, b, and c are accessible to function f2 but not f1. Copyright © 2010 Delmar Cengage Learning in file 2 int xy; long arr [100]; H. Huang Transparency No.5-38 The HCS12/MC9S12 Microcontroller Type Casting Type casting forces a variable of some type into a variable of different type. The format is (type) variable. It is often used to avoid size mismatch among operands for computation. long result; int x1, x2; … result = x1 * x2; The value of the product of x1 and x2 would be truncated when it exceeds 16 bits. The solution to the problem is to use type casting: result = ((long)x1) *((long)x2); Type casting also allows one to treat a variable of certain type as a variable of different type to simplify the computation. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-39 The HCS12/MC9S12 Microcontroller For the following declaration: struct personal { char name[10]; char addr [20]; char sub1[5]; char sub2[5]; char sub3[5]; char sub4[5]; } ptr1; char *cp; One can use type casting technique to treat the variable ptr1 as a string: cp = (char *)&ptr1; Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-40 The HCS12/MC9S12 Microcontroller Using the C Compilers The special edition C compiler from CodeWarrior has a size limit of 32 kB. The demo version of ImageCraft C compiler has a size limit of 8 kB. The GNU C compiler does not have size limit but the EGNU IDE cannot program flash memory which limits it to download program into the on-chip SRAM only. Accessing Peripheral Registers Depending on the size of a peripheral register, it can be declared in one of the following methods: #define reg_name *(volatile unsigned char *) reg_addr // 8-bit wide register #define reg_name *(volatile unsigned int *) reg_addr // 16-bit wide register The HCS12 allows all of the peripheral registers to be relocated as a block. For this reason, the ImageCraft uses the following method to define peripheral registers: #define #define #define reg_base reg_name1 reg_name2 0x0000 // base address *(volatile unsigned char *) (reg_base + offset1) *(volatile unsigned int *) (reg_base + offset2) Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-41 The HCS12/MC9S12 Microcontroller The header file hcs12.h provided in the complementary CD uses the following format: #define IOREGS_BASE 0x0000 #define _IO8(off) *(unsigned char volatile *)(IOREGS_BASE + off) #define _IO16(off) *(unsigned short volatile *)(IOREGS_BASE + off) #define PORTA _IO8(0x00) // port A data register #define PTA _IO8(0x00) // alternate name for PORTA #define ATD0DR0 _IO16(0x90) // ADC result 0 register (a 16-bit register Peripheral Register Bit Definitions A value is assigned to each bit in the peripheral register that represents its weight. For example, the ADPU bit of the ATD0CTL2 register is defined to be 0x80 that is the positional weight (bit 7) of this bit. It is defined as follows: ADPU equ $80 This bit can be set using the following statement: ATD0CTL2 |= ADPU; Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-42 The HCS12/MC9S12 Microcontroller In-line Assembly Instructions Syntax asm (“string”); Examples asm(“swi”); asm(“cli”); Copyright © 2010 Delmar Cengage Learning // string is one of the valid assembly instructions // software interrupt // enable interrupt globally H. Huang Transparency No.5-43 The HCS12/MC9S12 Microcontroller Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-44 The HCS12/MC9S12 Microcontroller Using the ImageCraft C Compiler ICC12 IDE can work with Dragon12 demo board programmed with the D-Bug12 monitor. The startup screen of the ICC12 is shown in Figure 5.25. ICC12 is a simple IDE that consists of a text editor, a project manager, and a C compiler. When the user uses the ICC12 IDE for the first time, he or she needs to set up the compiler options. Compiler options can be brought up by pressing the Project menu in Figure 5.25 and selecting Options… A dialog box as shown in Figure 5.26 appears to allow the user to set up all options. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-45 The HCS12/MC9S12 Microcontroller The setting in Figure 5.26 works for the Dragon12 demo board. After setting up the options and clicking OK, the ICC12 C compiler will remember all the settings until the user change them. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-46 The HCS12/MC9S12 Microcontroller Creating a New Project A new project is created by pressing the Project menu and select New. A dialog as shown in Figure 5.27 will appear to allow the user to enter the project name and select the project directory. Suppose the user enters icctutor as the project name and set project directory at c:\books\hcs12\programs\ch05 and then clicks Save. The screen will change to that in Figure 5.28. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-47 The HCS12/MC9S12 Microcontroller Adding Files to the Project A new file can be created by pressing the File menu and selecting New to convert the work space pane in Figure 5.25 into an editor work space. We will enter the program that finds the greatest common divisor (gcd) into the editor work space as shown in Figure 5.29. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-48 The HCS12/MC9S12 Microcontroller Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-49 The HCS12/MC9S12 Microcontroller ICC12 Compiler requires a putchar function for the printf function to work. We created this function and add it to this example project. This is done by pressing the Project menu and selecting Add File(s)… to bring up the dialog for adding a file. The add file dialog is shown in Figure 5.30. After adding gcd.c and putchar.c into the project, the screen changes to that in Figure 5.31. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-50 The HCS12/MC9S12 Microcontroller Build the Project A project can be built by pressing function key F9 or pressing the Project menu and selecting Make Project. Figure 5.32 shows the project build screen without any errors. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-51 The HCS12/MC9S12 Microcontroller ICC12 IDE does not allow the user to set up a watch list to monitor the change of program variables. The user needs to find out the address of program variables by looking at the program map file. For example, by making result a global variable and recompiling the program and browse the icctutor.mp file, we find that result is assigned to location $1000 as shown in Figure 5.33. The user can then use the D-Bug12 command md $1000 to display the value of result. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-52 The HCS12/MC9S12 Microcontroller Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-53 The HCS12/MC9S12 Microcontroller Activating the Terminal Window The user needs to activate the terminal window before he/she can download the program onto the demo board. Terminal window is activated by pressing Terminal menu and selecting Show terminal Window. After this, the ICC12 screen changes to that in Figure 5.34. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-54 The HCS12/MC9S12 Microcontroller Setup Terminal Window The user needs to setup options of the terminal window when using it for the first time. To set up the terminal window options, press the Tools menu and select Environment Options to bring out the dialog as shown in Figure 5.35. The user should set the baud rate to 9600 and set flow control to none for the Dragon12 demo board. Click OK and the screen change to that in Figure 5.36. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-55 The HCS12/MC9S12 Microcontroller Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-56 The HCS12/MC9S12 Microcontroller Downloading Program for Execution The first step to communicate with the D-Bug12 monitor of the demo board from the ICC12 is to press the Open Com Port button in Figure 5.36. The user can then press the Enter key to bring out the D-Bug12 monitor prompt in Figure 5.36. To download a file to the demo board for execution, type the command Load and then press the Enter key. After this, the user can use the mouse to browse the directory to select the appropriate .s19 file (icctutor.s19) to download. Click on the Open button in Figure 5.37 causes Windows to transfer the selected file into main memory from the hard disk. Click on the Download! button in Figure 5.37 starts the download operation. After icctutor.s19 is downloaded, the screen will change to that in Figure 5.38. To execute the downloaded program, type g 1500 and then press the Enter key. After executing the program, the user can examine the value of result by typing the md 1000 command. The user can use all of the D-Bug12 monitor commands described in in Chapter 3 to perform program debugging. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-57 The HCS12/MC9S12 Microcontroller Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-58 The HCS12/MC9S12 Microcontroller Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-59 The HCS12/MC9S12 Microcontroller C Programming Style Programming style refers to a set of rules and guidelines used when writing a program. The essence of good programming style is communication. The objective of a good programming style is to make the program easy to understand and debug. A programmer uses three primary tools to communicate their intentions: comment, naming of variables, constants, and functions, and program appearance (spacing, alignment, and indentation). General Guidelines to Comments The programmer should explain what every function does, what every variable does, and every tricky expression or section of code. The comment should be added before the programmer defines a variable or writing a function or section of code. Avoid obscure programming language constructs and reliance on language-specific precedence rules. Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-60 The HCS12/MC9S12 Microcontroller Program Documentation All programs should include, at the beginning of the program, a comment block that Includes at least: The programmer’s name The date of creation The operating system and IDE for which the program was written Hardware environment (circuit connection) to run the program Program structure (organization) Algorithm and data structures of the program How to run the program An Example is in the next page: Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-61 The HCS12/MC9S12 Microcontroller // ---------------------------------------------------------------------------------------------------------------// Program: RtiMultiplex7segs // Author: Han-Way Huang // Build Environment: CodeWarrior IDE under Windows XP // Date: 07/09/2008 // Hardware connection: shown in Figure 4.18 of Huang’s HCS12 text // Operation: This program shifts seven-segment patterns of 4 consecutive BCD digits // by using time-multiplexing technique with each pattern lasting for 0.5 s. The // time-multiplexing operation is controlled by the real-time interrupt. The patterns are // 1234 // 2345 // 3456 // 4567 // 5678 // 6789 // 7890 // 8901 // 9012 // 0912 // ------------------------------------------------------------------------------------------------------------------ Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-62 The HCS12/MC9S12 Microcontroller Function Documentation Every function should be preceded by a comment describing the purpose and use of that Function. An example is as follows: //-------------------------------------------------------------------------------------------------------// Function: FindSquareRoot // Purpose: Computes and returns the square root of a 32-bit unsigned integer // Parameter: A 32-bit unsigned integer of which the square root is to be found // Called by: PrimeTest() // Returned value: the square root of a 32-bit unsigned integer // Side effects: none //--------------------------------------------------------------------------------------------------------Code Appearance Program reability can be improved by Proper spacing Proper indentation Vertical alignment Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-63 The HCS12/MC9S12 Microcontroller Proper Spacing for (i=0;i<15;i++) & for (i = 0; i < 15; i++) easier to read Proper Indentation The following code is hard to read without proper indentation: while(TRUE) { for (i = 0; i < 10; i++) { // pattern array start index for (j = 0; j < 100; j++) { // repeat loop for each pattern sequence for (k = 0; k < 6; k++) { // select the display # to be lighted PTB = SegPat[i+k]; // output segment pattern PTP = digit[k]; // output digit select value delayby1ms(1); // display one digit for 1 ms } } } } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-64 The HCS12/MC9S12 Microcontroller With proper indentation, the code section becomes easier to read: while(TRUE) { for (i = 0; i < 10; i++) { // pattern array start index for (j = 0; j < 100; j++) { // repeat loop for each pattern sequence for (k = 0; k < 6; k++) { // select the display # to be lighted PTB = SegPat[i+k]; // output segment pattern PTP = digit[k]; delayby1ms(1); // output digit select value // display one digit for 1 ms } } } } Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-65 The HCS12/MC9S12 Microcontroller Vertical Alignment It is often helpful to align similar elements vertically, to make typo-generated bugs more obvious. Compare the next two sections of code. It is obvious that the second one is easier to Identify errors: Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-66 The HCS12/MC9S12 Microcontroller Naming of Variables, Constants, and Functions The names of variables, constants, and functions should spell out their meaning or purpose. A variable name may have one word or multiple words. Use lowercase when the name contains only one word. For example, sum, limit, and average. A multiple-word variable name should be in mixed case starting with lowercase. For example, inBuf, outBuf, squareRoot, and arrayMax. Function names should follow the same principle. A few examples follow: sevenSegShift(), putcSPI(), putsSPI(), openLCD(), and putsLCD() Named constants should be all uppercase using underscore (_) to separate words. SONG_TOTAL_NOTES, HI_DELAY_COUNT, LO_DELAY_COUNT Copyright © 2010 Delmar Cengage Learning H. Huang Transparency No.5-67