libro 1 v1.pdf

Upload: vlseis2831

Post on 02-Jun-2018

261 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/11/2019 Libro 1 V1.pdf

    1/67

  • 8/11/2019 Libro 1 V1.pdf

    2/67

    2

    CONTENTS

    1. Introduction 1

    2. Algorithms 4

    3. Flowcharting 8

    4. Program Structure 13

    5. Variables and Constants 18

    6. I/O Operations 23

    7.

    C Operators 27

    8. Control Statements 32

    9. Functions 38

    10.Arrays 42

    11.Pointers 45

    12.

    RAM vs. FLASH 47

    13.

    Appendix 49

    Cesar Contreras

    http://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Flowcharts/Structured_Flowcharting.pdf
  • 8/11/2019 Libro 1 V1.pdf

    3/67

    1

    1. Introduction

    The development or writing of software is only one piece of a puzzle. It is important for aprogrammer to understand and work through the entire problem solving sequence beforeattempting to write software. This document will outline the steps necessary to solve a

    problem and implement a solution.

    After covering the basic problem solving sequence, this document will continue with theother tools necessary to develop a solution. The document will cover the development ofalgorithms to solve given problems. Flowcharting will be used to aid in the visualizationof the algorithm(s) and as a tool to convert the algorithm into working C software. The Cprogramming language will be covered as a tool to implement a solution to the given task.The C programming language has several advantagesassociated with it when compared toassembly or other high level languages. These advantages make the C language well suitedfor use with microcontrollers. Once the C software has been written, it must go through aprocess to create the actual softwarethat is loaded into the microcontroller. The creation of

    software should also follow a set of standards. Standards aid in the readability andmaintainability of software.

    This document will utilize examples to illustrate the topics being discussed. In addition,this document offers a number of references to aid in the development of microcontrollersoftware. These references include the Atmel data sheets, information on interrupts,number conversions, the ASCII character table, lab hardware, and options for programmingthe microcontroller with the desired source code.

    Embedded Microcontroller Software

    Embedded microcontroller software poses a unique challenge. Embedded systems areexpected to operate without fail, 24 hours a day, 7 days a week, 365 days a year, year afteryear. To this end, microcontroller software requires good coding practices, gooddocumentation, and thorough testing.

    The C programming language is a general purpose, high-level programming language. TheC language was not specifically designed to be used for microcontrollers. What makes theC language popular for microcontrollers is that it allows software to be developed in astructured method and compiles into efficient machine level code.

    The use of any high-level language keeps the programmer at a distance from the actual

    microcontroller hardware. The C compiler takes care of the details of the software likeregister allocation, memory access, and the like. This allows the programmer toconcentrate on the details of the software and not the intricate details of the specificmicrocontroller. This separation from the hardware also allows the software to be portable(movable to other microcontrollers) with a minimal amount of effort.

    C for microcontrollers has several unique features not found in standard Cimplementations, so even experienced C programmers have to spend some time on the

    Cesar Contreras

    http://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/C_Advantages/C_advantages.htmhttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Process_to_Software/Processes_to_Software.htmhttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Programming_Standards/C_Programming_Standards.htmhttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Programming_Standards/C_Programming_Standards.htmhttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Process_to_Software/Processes_to_Software.htmhttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/C_Advantages/C_advantages.htm
  • 8/11/2019 Libro 1 V1.pdf

    4/67

    2

    learning curve. The major difference between a program written for a PC and a programwritten for an embedded microcontroller is that the PC program will most likely end atsome point and turn control back to an underlying operating system. Embedded systems donot have an operating system and therefore, embedded applications never end. Embeddedapplications are not allowed to run out of things to do.

    Problem Solving

    The key to creating a successful embedded application is understanding and following asequence of designed steps to solve the given task. The problem solving steps shown willbe used throughout this document.

    Problem Solving Steps

    1. Understand the problem statementa. The programmer must understand the overall purpose

    2. Develop an algorithm to solve the problema. The programmer must know why each task is performed3. Stepwise refinement of the algorithm

    a. The programmer must fully understand the components being usedi. Interfacing with special devicesii. Using timing diagramsiii. Special needs of devices (controls)

    4. Create an action plana. Pseudo code development and/orb. Flowchartingc. Function recognition

    5. Generate a solution (All the programming goes here)

    6. Testing and verificationa. Function testing using stubs.

    The first step in the process is to understand what is being asked. If the programmer doesnot understand the question or what is being asked of them, then the programmer must seekout additional information. In the "real world", this may involve asking the "customer" indepth questions to arrive at the answers. In the context of this class, the customer will bethe instructor (lab or lecture). The student should ask the instructor for additionalinformation to clarify the question or problem statement. If the programmer does not havea clear picture or destination in mind, then arriving at a solution is going to be difficult atbest.

    Once the problem is understood, the programmer must next develop a plan that will solvethe problem. It is important for the programmer to understand why each task must bedone. The development of algorithms will be covered more in depth in the next section, but

    Cesar Contreras

    http://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Problem_Solving/problem_solving_steps.pdfhttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Problem_Solving/problem_solving_steps.pdf
  • 8/11/2019 Libro 1 V1.pdf

    5/67

    3

    for now, it's safe to state that if the programmer can't solve the problem on paper, then theprogrammer has little if no chance at solving the problem by blindly writing software.

    Once an algorithm has been developed, the programmer must get down to the nuts andbolts of things, so to speak. An algorithm may require the temperature of a process to be

    read or monitored. The temperature monitoring device may require certain control signalsto manipulate its functionality. The programmer must know what is necessary and in whatorder the control signals must be operated. This may require the programmer to spend sometime reading the datasheets and researching the components used. This additionalinformation is then used to tailor the algorithm to the specific target microcontroller. Somesystems may not require external components, but the algorithm must still be tailored to themicrocontroller.

    With the algorithm tailored to the microcontroller, the next step is to create an action planto implement the solution. To aid in this process, flowcharts will be used. A flowchartgraphically shows the flow through the algorithm. The graphical symbols and structures

    can then be transformed in software. In addition to aiding or making the software easier towrite, developing flowcharts also aid in identifying steps or sequences of tasks that areperformed multiple times through the software. Once these tasks are identified, they can beimplemented as software functions or code segments that are only typed once, yet called orexecuted multiple times throughout the program. This is a key concept in structuredprogramming and will be explored more in depth later. Flowcharting of an algorithm alsoprovides documentation for the customer.

    Withallthe preliminary development complete, the programmer is now ready to actuallywrite the software and thus, solve the problem at hand. Many programmers, both new andexperienced, want to jump to this phase without working through the previous steps. As aprogrammer gains experience, less and less time can be spent on the prior steps and stillachieve good results. However, the less experienced programmers should spend as muchtime as needed to complete the steps. Completing the preliminary development steps willmake the actual software writing much, much easier. The focus of this document is on theuse of the C programming language to implement the solution. It should be noted that theC programming language is not the only choice for writing software, but it is the onlylanguage used in this particular class. The later portions of this document will cover theactual C language.

    The final phase in the development cycle is testing and verification of the software. Thisstep will require the software to actually be tested. The testing of software can beaccomplished in several different ways. Simulators and emulators can be used to simulatethe software while watching the variables and such. This technique can aid theprogrammer in finding minor, or sometimes major, bugs within the software. The coursedoes utilize a simulator but the primary testing will be performed by programming theactual microcontroller and testing the software with the lab hardware available at theLICA. This will allow the student to literally see the successful results.

    Complex software and sometimes simple programs do not perform the desired results onthe first attempt. In some cases, the programmer may have to go back and repeat prior

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    6/67

    4

    phases of the problem solving sequence to ensure the desired results are eventuallyobtained. One thing is for certain when it comes to software development, softwaredevelopment is an iterative process.Like most problems, problems that involve writing software are easier to solve when theyare broken into smaller or more manageable pieces. Breaking the software into more

    manageable sections not only makes the software easier to write, but it also makes thesoftware easier to test.

    2. Algorithms

    One of the most important topics associated with software development is algorithmdevelopment. An algorithm is defined as the steps necessary to provide a solution to agiven task. If the programmer is unable to solve the problem at hand on paper, then theprogrammer has little if no chance at all of solving the problem with a microcontrollerthrough the use of software. The software and microcontroller are simply tools to

    implement a solution. Some

    problems must be solved by aspecific order of steps while otherproblems may be solved through avariety of different combinations ofsteps. For example, in order to adda series of numbers to find the totalsum, the order in which thenumbers are added does not matteror make a difference. On the otherhand, some problems do require aspecific order. For instance,

    converting a temperature fromdegrees Fahrenheit to degreesCelsius requires the number 32 tobe subtracted from the Fahrenheitvalue before the value is multipliedby 5/9. Multiplying by 5/9 firstand then subtracting 32 will

    produce the wrong equivalent temperature. This section is dedicated to understanding howto develop a solution.

    An algorithm is a step-by-step method for solving a problem. Enough detail is required so

    that a person unfamiliar with the problem could follow the steps and arrive at the desiredsolution. Computers are extremely powerful tools used to solve problems. However,before a computer can solve a problem, a programmer must specify the order and the actualinstructions to follow to solve the problem.

    The items listed below will be used to describe an algorithm. The steps of the algorithmshould be stated clearly and precisely. Anyone following the algorithm must obtain aunique value for each of the steps along the way to the solution. For example, anyone

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    7/67

    5

    adding two numbers together should arrive at the same answer. In addition, the algorithmcan only rely on information already stated in the algorithm or information that has beenderived during the algorithm. An algorithm cannot use information that it does not have.The algorithm must have a definite starting and stopping point, providing a finite number ofinstructions to be executed. The algorithm must list the input information for the system as

    well as the specific range or ranges for which the algorithm covers. If an algorithm holdstrue for only positive integers, then the algorithm must clearly state this fact. The algorithmmust state the outputs that are produced. When possible, algorithms should be kept generalto allow re-use for different sets of data. For example, an algorithm designed to average aset of numbers should work for any number of terms.

    Algorithms:

    1. Precision: The steps are clearly stated.

    2.

    Uniqueness: The intermediate results of each step of execution are uniquely definedand depend only on the input and results of the preceding steps.

    3. Finiteness: The algorithm stops after a finite number of instructions have beenexecuted.

    4. Input: The algorithm receives input.

    5. Output: The algorithm produces output.

    6. Generality: The algorithm applies to a set of inputs.

    Example 1 Adding a series of numbers

    Add the following set of numbers: 17, 20, 1, 22, 18

    Step 1 in the problem solving sequence states:

    Understand the problem statementThe purpose of the algorithm is to add together the above five numbers to calculatetheir combined total.

    Step 2 in the problem solving sequence states:

    Develop an algorithm to solve the problemThe inputs to the system are the numbers: 17, 20, 1, 22, and 18.

    These inputs can be represented by the symbols:

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    8/67

  • 8/11/2019 Libro 1 V1.pdf

    9/67

    7

    fall under the implementation phase of problem solving. Since this section is onlyconcerned with developing possible solutions, we will leave this conversation for later. Thisexample will be re-visited later during the lessons on flowcharting and control statements.

    Recap:

    Looking back to the previous description of an algorithm:

    The inputs to the algorithms are the actual numbers n1

    through n5

    found in the data set. The

    output of the algorithm is the calculated sum of the numbers. The steps necessary to solvethis algorithm are stated precisely (steps 1 through 5). Each step in the algorithm produces aunique value. The algorithm works for the given set of numbers (finite, ends after fivenumbers). The algorithm is also general in nature, meaning that the steps will work for anyset of numbers.

    Example 2 - Averaging a set of numbers

    Average the following set of numbers: 19, 14, 9, 18, 10, 6

    Solution steps:1. sum = 02. i = 03. i = i + 1

    4. sum = sum + ni5. repeat steps 3 and 4 until i = 66. average = sum / 6

    Example 3 - Calculate the slope of a line

    Calculate the slope of the line passing through the points (2,2) and (6,4):

    Step 1 in the problem solving sequence states:

    Understand the problem statementThe purpose of the algorithm is to take the two given data points and calculate theslope of the line.

    Step 2 in the problem solving sequence states:

    Develop an algorithm to solve the problem

    Remember the slope of a line (m) passing through two points (x1, y

    1) and

    (x2, y

    2) is defined as: m = (y

    2 y

    1) / (x

    2 x

    1)

    The inputs to the system are the numbers:

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    10/67

    8

    x

    1: 2

    x2: 6

    y1: 2

    y2: 4

    The output of the system is the calculated slope of the line.slope = (4 - 2) / (6 - 2)

    Solution steps:1. change in y = y

    2- y

    1

    2. change in x = x2- x

    1

    3. slope = change in y / change in x

    Following the above steps will produce the slope of the line for the given data points.

    3. Flowcharting

    A flowchart is a graphical representation of an algorithm.Flowcharts are often restricted to a one page limit to keepthings simple. The basic shapes that make up a flowchartare shown to the right. These will be the only actualsymbols used for this document. In addition to thesesymbols, flow lines and arrows are used to represent theprogram flow through the steps. The Terminal symbol is

    used as both the entry and exit point of a flowchart. TheProcess symbol is used to represent a process that needsto be completed. This process could be as simple asadding two numbers together to as complicated ascalibrating a piece of machinery. The Decision symbol isused to represent a "fork in the road". This is the place inthe algorithm where a decision must be made.Structured flowcharts, by definition, have a single entry

    lowcharts are also a good source of documentation. Some programmers has to generate

    point and a single exit point. Structured programmingforces this property. A flowchart can be used as apowerful tool to make the transformation from an

    algorithm to software. This transformation will becomemore clear when dealing with the C programmingstructures for program control which will be covered later.

    Fflowcharts, for documentation purposes, for software that was written by otherprogrammers.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    11/67

    9

    Flowcharts are not only used to document software. Flowcharts can also be used todocument any process flow. For example, the process for problem solving can be showngraphically with a flowchart:

    the above flowchart, the process of generating a solution is shown as a single block. InInreality, the process of generating a software solution is more complex. As mentionedearlier, processes are typically shown as a single block to simplify the flowchart. There are

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    12/67

  • 8/11/2019 Libro 1 V1.pdf

    13/67

    11

    Both of the above flowcharts have decisions at the bottom of the flowchart. Thesedecisions are questions about the operation of the software or the overall solution. In eithercase, if the software or solution contains errors, the flow is diverted back to a previousstep. The previous steps are then repeated to refine or rework them in an attempt to reach adesirable result. Again, the results are tested and the process repeats until the desiredresults are reached.

    The above flowcharts deal with the processes involved in problem solving and software

    generation. These are definitely good examples of using a flowchart to illustrate a processor algorithm, but they are not processes that one would implement with a microcontroller.Therefore, the algorithms developed earlier during the section on Algorithm Developmentwill be revisited. These processes are more like a "real world" application that aprogrammer may have to solve with a microcontroller.Example 1 Adding a series of numbers

    Revisiting Example 1 from the section on Algorithm Development

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    14/67

    12

    Add the following set of numbers: 17, 20, 1, 22, 18

    Solution steps:

    1.start with the sum equal to zero2.take the first number3.add the first number to the sum4.take the second number5.add the second number to the sum6.take the third number7.add the third number to the sum8.take the fourth number9.add the fourth number to the sum10.take the last number11.add the last number to get the final sum

    The flowchart for the above algorithm is shown at theright. Notice that the Terminal symbol at the top of theflowchart contains a description for the flowchart. TheTerminal symbol at the bottom denotes the ending pof the algorithm. The Process steps show what stepsmust be performed. The flow lines that connect theProcess symbols show the flow through the algo

    oint

    rithm.

    ow lets look at the second algorithm developed for

    olution steps:

    1+ n

    4 until i = 5

    he flowchart for this algorithm is shown at the right.

    Nadding the series of numbers.

    S1. sum = 02. i = 03. i = i +4. sum = sum

    i

    5. repeat steps 3 and

    TAgain, notice that the Terminal symbol at the top of theflowchart contains a description for the flowchart. TheTerminal symbol at the bottom denotes the ending pointof the algorithm as well. The Process steps show whatsteps must be performed and the flow lines that connectthe Process symbols show the flow through thealgorithm. Notice the Decision symbol located at the

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    15/67

    13

    bottom of the flow chart. The decision checks to see if the value of i is equal to five (seestep number 5 in the algorithm).If the value of i is not equal to five, then the program flow goes back to step number 3,repeats steps 3 & 4, and then re-tests the value of i. This process repeats until the value of iequals five. Once the value of i is equal to five, the algorithm ends.

    The process of repeating steps 3 & 4 through the use of a decision is a part of thefoundation for structured programming. This gives the program power and flexibility.Simply changing the test value used in the Decision can change the algorithm to add anynumber of numbers. In order to change the first algorithm to add additional numbers, moresteps must be added to the bottom of the sequence increasing the program size without anyflexibility.

    4. Program Structure

    A basic embedded C program for the ATmega16 is shown below:

    /*Simple C program to illustrate the basic components of a program.This program actually performs no tasks, calls no functions, and uses no variables*/

    #include

    void main(void){

    while(1); // stay here forever...never ending}

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    16/67

    14

    Block comments and program headermust contain important informationincluding but not limited to theprogrammers name, the date, and adescription of the purpose of theprogram.

    /*Simple C program to illustrate the basic components of a program.This program actually performs no tasks, calls no functions, and uses no variables*/

    #include

    void main(void){

    while(1); // stay here forever...never ending

    }

    This includes the microcontroller specificheader information. This must match theactual microcontroller being used.

    All functions must beenclosed by braces.

    Single line comments begin wittwo forward slashes.

    All C statements end with asemicolon.

    Braces and code are

    indented by one level (tabspace).

    Statement that safely ends the programprevents undesired actions.

    Block comments or multiple linecomments must be enclosed by thecharacter combination of /* and */

    Most C programs are written in lower case letters. C is case sensitive meaning that thecompiler DOES make a distinction between a capital letter and its matching lower caseletter. Capital letters are generally used for constants found commonly in #definestatements (discussed later). ALL C statements end with a semicolon.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    17/67

    15

    The Preprocessor Directives

    C programs are constructed of statements and directives. Directives are instructions to thecompiler. The preprocessor is a program that performs these compiler instructions beforethe actual C code is compiled. The two most commonly used preprocessor directives are

    the #include and #define directives.

    The #include directive tells the compiler to readin the entire contents of another file. The#include preprocessor directive is generally used with header files. Header files have anextension ofhand are used to add information about the actual microcontroller or libraryinformation. The < > construct of the statement tell the compiler to look in a standardlocation or directory. This standard location is usually an INC directory or folder found inthe compiler main directory structure. An alternate location can be specified by usingdouble quotes ( " " ) instead of the < > symbols. When using the double quote method, thecompiler will start in the current directory. To specify a different directory or even drive,the programmer must type in the appropriate path information. The following examples

    shows the use of double quotes to specify a file located in the current directory.

    #include "my_header_file.h"

    The #define preprocessor is used to define a constant. A constant is exactly that, a valuethat never changes. A constant may be used to define the maximum size of something inthe program or simply used to make the code more readable. The preprocessor simplyreplaces the text used in the #define statement with the information following it.Regardless of the use, it is common to use all capital letters.

    For example:

    #define MAX_SIZE 256

    value = MAX_SIZE; // use a Constant to load the variable

    In the above example, the line of code value = MAX_SIZE is transformer by thepreprocessor to value = 256. The word or constant MAX_SIZE is replaced with thenumber 256. Constants can also be used in control statements. Control statements will bediscussed in depth later, but the following example demonstrates the basic principle.

    #define MAX_SIZE 256

    if ( current_value > MAX_SIZE) // Test the value against a known maximum limit{// code omitted for clarity}

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    18/67

    16

    The Main( ) Function

    All C programs contain at least one function, namely the main function. A function can bedefined as a section of a program that performs a well-defined service. However, the mainfunction is slightlydifferent than normal functions. Functions will be discussed in greater

    detail in a later section, but for now, the major difference between the main function and anormal function is that the main function is called or executed automatically when theprogram starts and any other function must be called either directly or indirectly from themain function. For this reason, the main function has been described as the lowest leveltask, because it is the first thing executed when the program starts.

    Code Blocks

    Program structure is part of the format used when creating a program. Structuredprogramming is a technique used to organize the program code. Use of a structuredtechnique can aid in debugging (finding errors in the code) and improves the readability of

    the source code.

    A code block can be defined as a group of statements that are joined or surrounded by curlybraces to form a compound statement and are the basic building blocks of structuredprograms. A code block begins with an opening brace { and ends with a closing brace } .The braces define the body or block of code. Braces are used to bound functions andvarious control statements. Indenting the code block, one tab space for instance, will makethe block of code standout from the surrounding code segments. This makes the programeasier to read and thus easier to debug. A convention should be set and followedthroughout the program to facilitate reading of the source code. The standard used for allprograms associated with this document will be the above mentioned one tab space.

    The braces do not have to be placed on their own line, but doing so will also aid in thereadability of the source code. These braces should match the indentation of the codeblock. The C programming language ignores so called white spaces. White spaces aregenerally referred to as any character that does not have a readable symbol associated withit. For example, a space simply leaves a gap between letters. A carriage return places avertical gap between characters. The compiler ignores both of these typesof characters.To the compiler, a curly brace at the beginning or ending of a line of code is the same as ifthe curly brace was occupying its own line. If the compiler interprets the different cases asthe same thing, then the difference only benefits the person reading the code. Theunderlying goal is to write code that is easy to read. Therefore, this author suggests placingthe braces on their own line. On occasion, curly braces may be placed at the beginning orending of a line of code to potentially save paper when printing large programs.

    void main(void){

    while(1); // stay here forever...never ending}

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    19/67

    17

    The above code is taken from the example program at the beginning of this section. Notethat the braes are both indented and located on their own line of the code. This helps theprogrammer and anyone else reading the code recognize the presence of a block of code.

    Comments

    Comments are a tool used by programmers to aid in the readability of software. Thesuccessful use of comments is critical to the readability of source code. Comments shouldallow the software to be read easily by someone who may not be familiar with the software(or even the original programmer at a later time). One of the hallmarks of a "good"program is that the program can be read and understood by anyone, even if the personreading the code does not know how to program. Properly commented code will make thispossible.

    Barnett, Cox, and O'Cull state that every line of code should be commented (except thetruly obvious). They continue by stating that the comment should not just echo the

    instructions but should explain the purpose of the instructions. The comments do not causeany code to be generated. Thus, comments do not cause the target microcontroller toexecute any instructions. They only assist someone attempting to read the software.

    Comment blocks are essential at the beginning of any function (including the mainfunction). In the case of the main function, the comment block is located at the very top ofthe source code. The remainder of the functions should have a code block immediatelypreceding the function declaration. This block should contain the following information:

    name of the function, operation performed, name of the programmer, date the function waswritten, names of other functions that may be called, the names of any global variablesused, and explanations of the local variables.

    The above listing is just a sample of the type of information that should be included. Thislist is not set in stone, but should provide a baseline for the type of information that shouldbe present. The following is an example of a comment block located prior to a function:

    /*Routine: init_lcdBy: Jeffrey J. RichardsonDate: Jan. 17, 2003Description:

    Routine that will initialize a two line LCD.The cursor is on, non-blink, cursor style is an underscore.The display is configured to shift the cursor right after each character.No local or global variables are used.

    Functions Called:delay_msputcmd_lcd

    */

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    20/67

    18

    Comments come in two styles:

    The first type is the above mentioned block comment. Block comments are bounded by theopening comment marker, a forward slash followed by an asterisks /*, and the closingcomment mark, an asterisks followed by a forward slash */. The compiler ignores all the

    information between the opening and closing markers. Most compilers nowadays changethe color of the actual text between the markers to help denote that the information is partof a comment.

    The second type of comment is a single line comment which is denoted by two forwardslashes //. The comment ends at the end of the line of source code usually denoted by acarriage return and linefeed.

    A word of caution...a backslash at the end of a line of C code, tells the compiler to appendthe next line of code to the end of the current line of code. This has significances if theprogrammer leaves a backslash at the end of a single line comment. A potential line of C

    code following the comment will become part of the comment and not be compiled as partof the software. If the GUI or graphical user interface does indicate comments through adifferent color, it may not indicate this condition and thus not call this condition to theattention of the programmer.

    y = mx + b; // solve for the y value in this system \printf("The y intercept is %d\n\r.", y);

    Don't get caught up in the details of the above example. It is only to illustrate that thebackslash that appears at the end of the comment line will tell the compiler that the printstatement is part of the comment. Therefore, the print statement will never be executed(because it is not really part of the code) and the program will not operate as desired.

    5. Variables and Constants

    Variables

    Embedded microcontroller programs are generally written to input information, performsome type of manipulation, and produce an output based on the input information andmanipulation. Variables are used to store information in the memory of a microcontrollerand they allow the programmer to refer to them by a meaningful name.

    Before a variable can be used, it must first be declared by specifying the data type andname of the variable. C is case sensitive meaning that it recognized a lower case letter andits upper case equivalent as being different. It is conventional to avoid using capital lettersin variable names. Capital letters are generally reserved for constants (more on constants ina moment). Using meaningful and descriptive names for all variables is critical in writingreadable software. Descriptive names make the software easier to understand. Whenselecting the names for variables, the names should be as long as necessary to indicate howthe variable is used. The length of the variable name should however, be limited to a

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    21/67

    19

    maximum of 31 characters. The variable name must start with a letter, but the remainder ofthe name can be made up of letters, numbers, and the underscore character. Variables canbe declared at the start of any block of code, but they are traditionally only declared at thebeginning of functions (for local variables). The declarations must be placed after theopening (left) brace and before any executable statement. Multiple variables of the same

    data type can be declared on the same line by separating the variable names with a comma.It is recommended that any separating comma be followed by a space to aid in thereadability of the various variable names.

    void main(void){unsigned char number_of_pulses; // variable to count pulsesunsigned int loop_cntr, count_value; // variables for loop control

    // omitted code for clarity}

    Variables can be initialized when they are declared. To initialize a variable, place an equalssign after the variable name followed by the initial value for the variable. TheCodeVisionAVR compiler will initialize variables to zero if not explicitly specified.

    unsigned char number_of_pulses = 100; // variable to count pulses

    Multiple variables declared on the same line can also be initialized to whatever value theprogrammer desires. However, doing so may create code that is harder to read. Therefore,this author offers the following suggestion: When initializing variables at the time ofdeclaration, only place one variable on each line of code. For example:

    unsigned int loop_cntr = 25, count_value = 100; // variables for loop controlmay be easier to read as:unsigned int loop_cntr = 25; // variable for the control loopunsigned int count_value = 100; // variable for counting

    Global vs. Local Variables

    There are two basic types of variables used in C code. A local variable is declared insidethe body of a function and is only available within the confines of that function. Mostlocalvariables are created when the function is called and are destroyed when the functionterminates. If it is necessary to maintain the value stored in a local variable after thefunction ends, then the staticvariable type can be used. Static variables are not destroyedwhen the function terminates. Instead, the value is preserved. Static variables can beinitialized like any other variable, however, the initialization is only performed the firsttime that the function is called.

    The above example shows the creation of local variables inside the main function of thesoftware. These variables only exist or are only valid inside the main function.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    22/67

    20

    The second type of variable used in C code is the global variable. Global variables arecreated outside of any of the functions (usually at the top of the source code after anypreprocessor directives) and are available to any and all functions. Using global variablesincreases the complexity of the software and can complicate debugging of the code. Ageneral rule is to only use global variables when absolutely necessary. The following is an

    example of declaring global variables:

    /*Simple C program to illustrate Global variablesThis program actually performs no tasks, calls no functions, and uses no variables*/#include

    unsigned char global_ch; // global character variable for storing serial informationunsigned int int_counter = 0; // global counter for use in the interrupt routine

    void main(void){

    // code omitted for clarity}

    Variable Types and SelectionType # of bytes # of bits Minimum Maximum

    bit - 1 0 1

    char 1 8 -128 127signed char 1 8 -128 127unsigned char 1 8 0 255

    int 2 16 -32,768 32,767signed int 2 16 -32,768 32,767unsigned int 2 16 0 65,535

    long 4 32 -2,147,483,648 2,147,483,647signed long 4 32 -2,147,483,648 2,147,483,647unsigned long 4 32 0 4,294,967,295

    float 4 32 1.28E-38 3.4E38

    The Atmel AVR Family of microcontrollers are eight bit microcontrollers. Therefore, thedefault data type for all variables should be the single byte character, unless the sizerequirements of the variable dictate a larger value. Choosing the proper size of variablescan be critical to the proper operation of the microcontroller software. Improper selectionof the data type can cause inaccurate or undesired results as well as slow down the

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    23/67

    21

    execution of the code. Variables should be of the unsigned data type unless they areactually used for signed operations.Looking back at Example 1 from the section on algorithm development:

    The programmer must know how big any result will be in order to select the proper data

    type for the total value. The problem stated that the five numbers: 17, 20, 1, 22, and 18 areto be added together. Doing so will produce the decimal value 78. In this case, a charactersized variable is adequate to store the resulting value. However, if the problem statementstated that the input range of the five numbers was from 0 to 100, then the total value couldbe as high as 500. An unsigned character is only capable of storing a value from 0 to 255.Therefore, the variable to store this "new" total would have to be of the data type integer.Again, since the program is not designed to do signed operations, an unsigned integervariable should be selected.

    The architecture of the microcontroller is most efficient when dealing with character sizedvariable ( 8-bits). For this reason, a character sized variable should be used whenever

    possible to allow the program to operate as quickly as possible. Using a 16-bit integer typevariable can require the microcontroller to perform approximately twice the number ofinstructions to handle the variable when compared to an 8-bit value. However, if a 16-bitvalue is required, then the programmer has no choice except to use an integer.

    It is also important for the programmer to keep track of intermediate data sizes. Perhapsthis is best illustrated by using the second example from algorithm development. Thisexample requires the average of six numbers to be calculated. In order to calculate theaverage, the sum of the numbers must be calculated at some point. Changing the problemstatement to state that the input numbers can range from 0 to 50 will produce an averagevalue also in this range. On the surface, unsigned character variables appear to be morethan adequate to store the results since the values are all below 50. However, it is quitepossible for the total of the six numbers to exceed the maximum limit of an unsignedcharacter. For example, given 48, 49, 47, 49, 48, and 50, the intermediate sum of the dataset is 291. This value is too large to be stored in a character sized variable. Attempting todo so will produce an inaccurate result. The inaccuracy happens because the value 291 is"stuffed" into an 8-bit variable. In actuality, the decimal number 291 requires 9-bits of datato be stored. Forcing the value into an 8-bit number causes the most significant bit of thedata to be lost because there is no place for it to be stored. Therefore, using an 8-bit valueto store the result of the above six numbers produces the value 35. Clearly, 35 is not thetotal of the above numbers. Dividing 35 by 6 would then produce an average valuebetween 5 and 6 instead of the proper result which is between 48 and 49.

    Looking inside the numbers:

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    24/67

    22

    The above example also brings to light a major element of mathematical operations andmicrocontroller data types. Specifically, the issue of integer math. Integer math has nodecimal point which is associated with floating point math. When performing integer math,the results are truncated (no rounding) to a whole number result. Looking back at theabove example, 291 divided by 6 is 48.5 assuming floating point math. Since the values

    above assume character and integer variables (not floating point), the result would betruncated to 48 instead of 48.5 if the proper sized variables were used. Assuming that onlycharacter sized variables were used, dividing 35 by 6 would produce 5.833 which would betruncated to 5. Integer math is a key concept that must be taken into account whenselecting data types for a program.

    When an application requires the accuracy associated with floating point math, the floatdata type can and should be used. Utilizing floating point variables will force themicrocontroller to performing floating point math. Since the Atmel microcontrollers arenot designed to perform floating point math, this will slow down their operation as they areforced to perform a significant amount of extra instructions to produce the results. The

    programmer needs to be aware of the accuracy requirements of the software and utilizefloating point variables only when they are absolutely necessary.

    /*This is a basic program that does nothing, but it demonstrates the necessary components tocreate a C program and has both global and local variable declarations.*/

    #include

    unsigned int global_cntr; // variable to count (available everywhere in the program)

    void main(void){

    unsigned char port_value; // local variable to store an 8-bit value

    while(1); // stay here forever

    Global 16-bit variable declaration

    Local 8-bit variable declaration

    }

    From time to time, the programmer needs to only keep track of a single bit. This bit issometimes referred to as a flag and is declared in the same manner as any othervariable. The data type for this declaration is the bitand can be assigned the value of either1 or 0.

    Constants

    Constants are just the written version of a number. Constants can be in any format(decimal, hexadecimal, etc). Constants are typically created by using the #definepreprocessor directive which was discussed during the section on Program Structure.

    Cesar Contreras

    http://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Program_Structure/program_structure.htm#The%20Preprocessor%20Directiveshttp://www2.tech.purdue.edu/ecet/courses/referencematerial/atmel/Program_Structure/program_structure.htm#The%20Preprocessor%20Directives
  • 8/11/2019 Libro 1 V1.pdf

    25/67

    23

    When long constants are used, it is common to place a trailing L at the end. Constantsallow the software to be somewhat configurable and easier to read.

    #define XTAL 6000000L

    For example, the preprocessor directive #define XTAL 6000000L allows the programmer torefer to the value of the crystal oscillator by the name XTAL. If the crystal frequency ischanged after the software has been written, changing the preprocessor directive willchange the value of the clock frequency throughout the program.

    /* Serial.C: Simple program that first initializes the serial port for 9600, N, 8, 1. Second,the program initializes PortC for output to the LEDs. Third, the program enters an endlessloop that... Uses the standard library function to get a serial character Display the characteron the LEDs Echo the character back to the sending device. Uses an ATmega163 controlleroperating at 6MHz. */

    #include#include#define XTAL 6000000L#define BAUD 9600

    main(){unsigned char ch; // 8 bit variable to store the serial characterunsigned int UBR; // 16 bit variable to hold serial port calculations

    UBR = XTAL / 16 / BAUD - 1; // calculate the load valuesUBRR = (unsigned char)(UBR & 0xFF); // load the lower 8 bits

    Constants used to calculate theUART configuration registers.

    UBRRHI = (unsigned char)(UBR >> 8); // load the upper bitsUCSRB = 0x18; // enable transmit and receive

    DDRC = 0xFF; // setup PortC for outputPORTC = 0x00;

    while(1) // do forever...{ch = getchar(); // get a character from the serial portPORTC = ~ch; // display the character on the LEDsputchar(ch); // send the character back to the terminal}

    }

    6. I/O Operations

    As mentioned during the discussion of variables, microcontroller programs are generallywritten to input information, perform some type of data manipulation, and produce an

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    26/67

    24

    output. According to the previous statement, there are three key elements necessary toaccomplish this task. This section of the document is devoted to the first and last: thereading of the input information and the controlling of the outputs of the microcontroller.The data manipulation portion of this document will start with the next section,

    Expressions.

    Sensory inputs are one of the key elements in any embedded system. Any device must"perceive" that there is a need to take action before deciding what action or actions to takeand finally acting out those actions. An embedded microcontroller may be used to monitorand control the temperature of a process. The system would require the microcontroller tohave the ability to "read" and control the process temperature.

    Input Operations

    In order for an embedded microcontroller to make appropriate decisions, it must be able tosee

    the world around it or at least the key elements necessary to make the appropriatedecisions. Looking back at the example from above, the microcontroller needs to know thetemperature of the process. It may also be helpful to know the position of any controlvalves used in the process. The details of how these sensor work or would work are not ourarea of concern (for the moment), instead we are interested in how the information wouldget inside the microcontroller so that the microcontroller can take the appropriate or desiredactions.

    The exact assignment of the ports to measure the temperature and valve positions are notimportant (for this discussion). However a decision must be made and therefore thetemperature will be monitored on Port A and the valve positions will monitored on Port Band Port D.

    The Atmel AVR Family of microcontrollers requires that the ports be configured for eitherinput or output. The microcontroller has a data direction register for each port that controlsthe direction (input or output) of the desired port. A more detailed description ofconfiguring port for input and output can be found in appendix 1.

    The main register of concern for configuring the Port's Data Direction is the DDRnregister. The lower case n symbolizes that multiple registers have the same general name.Replacing the lower case n with the capital letter of the desired port will access the desireddata port direction register. For exampe, replacing the lower case n with the letter A allowsthe programmer to control the data direction register associated with PORTA. To set theentire port for input, the data direction register must be set to zero. The software commandto do this is simply:

    DDRA = 0;

    This line of code must be repeated for PortB and PortD as well producing the followingthree lines of code:

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    27/67

    25

    DDRA = 0; // set PortA for InputDDRB = 0; // set PortB for InputDDRD = 0; // set PortD for Input

    The data registers must be configured before the port can be used to read information.

    With the data ports configured for inputs, the actual sensor information can be readby themicrocontroller. In order to save or store the information for later use, three variablesshould be created to store the sensor values. (Variables were discussed in a previoussection. If necessary go back and review the information). Since the microcontroller portsare 8-bits wide, a character sized variable is appropriate to store the values. Assuming thatwe are not going to be measuring any negative numbers for temperatures, an unsignedcharacter type variable will be chosen. The variable declarations are listed below:

    unsigned char water_temp; // 8-bits for the actual temperatureunsigned char hot_position; // 8-bit variable to store the hot position

    unsigned char cold_position; // 8-bit variable to store the cold position

    With the data direction registers setup as inputs and with a place to store the informationfrom the sensors, the values are now ready to be read. Perhaps the biggest or mostimportant thing to remember when reading inputs is the actual register name that must beread. The actual input information or data is read from the PIN register associated witheach port. To read information from the input pins on PortA, the following instruction isused: water_temp = PINA; . This basic structure is repeated for each value that needs to beread. Continuing with this example, the following three lines of code are used to read theactual sensor values:

    water_temp = PINA; // get the actual faucet water temperaturehot_position = PINB; // get the hot water positioncold_position = PIND; // get the cold water position

    Output Operations

    Once the microcontroller has the required information to and has made a decision, theappropriate action or actions must be taken. This will require some type of output action tobe taken. Microcontrollers, at least in this class, provide low current TTL compatibleoutput signals. These signals can be amplified to different voltages and currents if required,but that is covered in a different course. Looking back at the example from above, theassumption will be made that turning on, or setting an output to a logic level, will besufficient to control the outputs.Before a port can be used as an output, the port's corresponding data direction register mustbe set as an output. This procedure is the same as setting a port for input with the onlyexception being the value written to the data direction register. A zero was written to thedata direction register to configure the port for input, whereas a logic one must be written tothe data direction register to configure the port as an output. Setting the data directionregister for PortC, DDRC, to all ones, will configure the 8-bits of the port for output. Theactual value to be written to the direction register is the binary number 11111111 which can

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    28/67

    26

    be written as the hex number 0xFF. The C statement to assign this value to the datadirection register is as follows: DDRC = 0xFF; . This line of code should be added withthe previous lines of code for configuring the input ports and should also contain acomment as to the function of the statement. The four statements are grouped togetherbelow:

    DDRA = 0; // set PortA for InputDDRB = 0; // set PortB for InputDDRD = 0; // set PortD for Input

    DDRC = 0xFF; // set PortC as an Output

    A device can now be controller by placing either a logic value of one or zero on theappropriate or corresponding port pin. The values used to control the output pins must bewritten to the PORT register associated with the corresponding port. In this example,output information must be written to PORTC. The value written to the port can come

    from a variable or from a constant value located inside the software. To place informationon the output pins of the port, the following statement is used: PORTC = 0x00; . Thisexample shows the constant value 0 being written to the output port. The example shownbelow shows an instance in which the output value comes from a variable, which must firstbe declared.

    unsigned char water_temp; // 8-bits for actual temperatureunsigned char hot_position; // 8-bit variable to store the hot positionunsigned char cold_position; // 8-bit variable to store the cold positionunsigned char output_value; // 8-bits for output control

    PORTC = output_value; // place the value stored in the variable on PortC

    Advanced Topics

    Single Bit Manipulations

    One of the key characteristics of a microcontroller is the ability to manipulate a single portpin without influences the other pins on the port. The CodeVisionAVR C compiler allowsthe programmer to refer to the port pins symbolically. In other words, the port pins can bereferred to by their respective port name and bit location. Assuming that an output islocated on PortC bit 0, the output can be set to a logic high by using the followingstatement: PORTC.0 = 1;. The prior statement assumes that the port has been configuredas an output.

    A similar technique can be used to monitor a single input pin. Assuming that an input ofinterest is located on PortA bit 5, the following would be used to monitor the input: value =PINA.5 .

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    29/67

    27

    Using the #define Preprocessor DirectiveThe #define preprocessor directive is used to make software easier to read and maintain.To this end, it is often used in conjunction with input and output functions. The earlierexample had the water temperature sensor connected to PortA. The exact statement to readthis input from above was: water_temp = PINA;. Using a #define can potentially make this

    statement easier to read and maintain. Starting with the following preprocessor directive:

    #define WATER_TEMP_SENSOR PINA.

    The previous statement that read the water temperature can be re-written as:

    water_temp = WATER_TEMP_SENSOR; // get the actual water faucet temperature

    The same technique can be used to control an output port or port pin. In the case of anindividual port pin, the #define directive must include the bit number. Assuming a statusLED is connected to PortC bit 0, then the status led could be referred to by name. For

    example:

    #define STATUS_LED PORTC.0

    then

    STATUS_LED = 1; // turn on the status LED

    7. C Operators

    C operators are how the mathematical functions in a program are performed. C operators

    are symbols that tell the compiler to perform certain types of data manipulations orevaluations. The evaluations are things like checking for equality or determining if oneparticular value is greater or less than another value. Data manipulations can includemathematical expressions like adding, subtracting, multiplying, or dividing of numbers.Data manipulations also can include Boolean operations such as the logical ANDing orORing of data bits. The C operators fall into one of five categories. These categories are asfollows: Relational, Arithmetic, Assignment, Logical, and Bitwise Operators.

    Relational Operators

    Operator Description Example== Equal to if (x == 5)

    != Not equal to if (x != 5)

    < Less than if ( x < 5 )

    > Greater than if ( x > 5 )

    >= Greater than or equal to if ( x >= 5 )

  • 8/11/2019 Libro 1 V1.pdf

    30/67

    28

    Arithmetic Operators

    Operator Description Example

    + Addition a = b + c

    - Subtraction a = b - c

    * Multiplication a = b * c/ Division a = b / c

    % Modulus a = b % c

    ++ Increment a++

    -- Decrement a--

    Assignment Operators

    Operator Description Example

    = Assignment x = 5

    += Assign and sum x += 5-= Assign and subtract x -= 5

    Logical Operators

    Operator Description Example

    && Logical AND if (( x > 5) && ( x < 10 ))

    || Logical OR if (( x == 5) || ( x == 6 ))

    Bitwise Operators

    Operator Description Example

    & AND a = b & 0x0F| OR a = b | 0x80

    ^ Exclusive OR a = b ^ 0x0F

    Shift right a = b >> 4

    ~ Complement a = ~

    Assignment Operators

    Programming languages need a mechanism to place a constant values into variables andregisters. The C language is no different. The assignment operator performs this exacttask. The basic assignment operator is the equal sign. The assignment operator is also usedto copy values from one variable to another.

    Operator Description

    = Assignment

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    31/67

    29

    Given: Results:Assign the value 25 to the variable num. num = 25;

    Assign the value in the variable num to the variableold_num.

    old_num = num;

    Relational Operators

    As the name implies, the Relational Operators are used to determine how one value orvariable relates to another. The relational operators allow the testing of equality and for thetesting of greater than or less than operations. The operators also allow for a subset orcombination of these conditions. Relational operators are typically used in controlstructures.

    The relational operators allow the program to test two values to see if they are equal or notequal. The relational operators also allow two values to be compared to determine if one

    value is greater than or less than the other value. A subset of these commands allow theprogram to combine the equality and magnitude operations together to determine if a valueis equal to or greater than a value as well as determine if the value is less than or equal tothe value of interest.

    The result of any Relational operation is a True or a False indication. In the Cprogramming language, a false condition is define as a value of zero. A true condition isindicated or defined as Not false. Therefore, a true condition is defined as a non-zerovalue.

    Operator Description

    == Equal to!= Not equal to

    < Less than

    > Greater than

    >= Greater than or equal to

    y Falsex < y Truex >= y Falsex

  • 8/11/2019 Libro 1 V1.pdf

    32/67

    30

    Arithmetic Operators

    The Arithmetic Operators allow the program to perform the basic mathematical operations.These include adding, subtracting, multiplication, and division. The arithmetic operatorsalso include a modulus, an increment, and a decrement instruction.

    Adding, subtracting, multiplying, and dividing numbers in a computer program follow allthe basic mathematical rules that most people learned in elementary school. The modulusoperator is related to division in that the result of the operation is the integer value of theremainder of the division of the two numbers. The increment and decrement operations arerelated to adding or subtracting one from the value. The increment and decrementoperations are simply a shortcut method of adding or subtracting one.

    Operator Description

    + Addition

    - Subtraction* Multiplication/ Division% Modulus++ Increment-- Decrement

    Given: Evaluate: Results:

    x + y 15

    x - y 9x * y 36

    x = 12, y = 3

    x / y 4x % y 1x++ 11

    x = 10, y = 3

    y-- 2

    Logical Operators

    The result of a logical operation is either true or false. As defined earlier, false is defined as

    a value of zero and true is defined as not false. The logical operators treat the multiple-bitvalues or variables as a single value. The logical operators are the logical AND and thelogical OR. The logical operators are frequently combined with the relational operators tocreate compound statements.In the case of the logical AND, all the the relational operations must be true for the result tobe true. If just one of the components of a logical AND operation is false, the entirestatement is false. The logical OR only requires one of the conditional or relationaloperations to be true in order for the entire statement to be true.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    33/67

    31

    Operator Description

    && Logical AND|| Logical OR

    Given: Evaluate: Results:

    x = 8 ( ( x >= 8 ) && ( x

  • 8/11/2019 Libro 1 V1.pdf

    34/67

    32

    Operator Description

    & AND

    | OR

    ^ Exclusive OR

    > Shift right

    ~ Complement

    Given: (values in binary) Evaluate: Results:

    mask = 10000000, value = 10101010 ( value & mask ) 10000000mask = 10000000, value = 01000000 ( value & mask ) 00000000

    output= 00000010, value = 01010000 ( value | output ) 01010010output= 00000011, value = 00000010 ( value | output ) 00000011

    mask = 01010011, value = 10101111 ( value ^ mask ) 11111100

    value = 00001100 ( value > 4 ) 00000110

    value = 01100101 ( ~value ) 10011010

    8. Control Statements

    Introduction

    Microcontrollers are usually used to perform tasks that have or display intelligence. Thekey to intelligence lies in the ability to make decisions and then act on these decisions.Control statements are used in the C language to make decisions and control the flow of theprogram based on the results of these decisions.

    Program Blocks and Loops

    A program block is a group of statements that have the following two characteristics: Theyhave a single entry point and a single exit point. A loop has a program block at its heart. Aloop is used to repeatedly perform an operation or a block of code through the use of aconditional expression. (Code blocks were covered in more detailed during the discussionof Program Structure.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    35/67

    33

    The conditional expressions were covered in depth under the C operators section. Theimportant concept to remember is that a false condition is define as a value of zero and atrue condition is defined as NOT false.

    The proper use of braces and indentations are important to maintain readable code.

    Control Structures

    The C language control statements include the if/else, the do/while, the while, the for loop,and the switch/case. The nature of the loop or control structure used determines the numberof times the statements (or code block) are executed, if executed at all. This section willintroduce and apply the control statements to perform useful tasks that add "intelligence" tothe software. With the above listed control statements, a block of code can be executedonce, executed repeatedly, executed a certain number of times, or skipped over completely.These control statements are key in writing structured software. Nesting of controlstructures also allows for more detailed and complex software.

    Structured programming is a technique for organizing and coding programs that reducescomplexity, improves clarity, and facilitates debugging and modifying. The benefits arelisted below:

    1. Operation is simple to trace2. Structures are self-documenting3. Structures are easy to define in flowcharts4. Structured programming increases programmer productivity5. Structures lead to functions

    Number 3 above refers to flowcharts. Flowcharts are graphical representations ofalgorithms. A properly drawn flowchart is an invaluable tool for identifying the propercontrol structure.

    IF / Else

    The IF/ELSE statement can be referred to as a "fork in the road". This statement directsthe flow of the software according to the result of the conditional expression. Theconditional expression in an if statement is a comparison between two values. If theconditional expression is true, then the "true" block of code is executed. If the conditionalexpression is evaluated as false, then the else branch or block of code is executed. It shouldbe noted that not having the microcontroller perform any task in the event that theconditional is false is quite common. Therefore, the else condition may be omittedaltogether.

    The flowchart for both an IF and an IF / ELSE structure are shown below. Thedistinguishing characteristic that identifies an IF statement over the other control structuresis the flow of the program after the decision and resulting process. In either an IF or IF /ELSE structure, the program flow continues to go down the page.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    36/67

    34

    if (the conditional expression is true){perform these statements}

    else{perform these statements if the conditional is false}

    While Loop

    In a While Loop, the expression is evaluated when the program enters the top of the loop.If the expression is true, the statements within the loop are executed. When the bottom ofthe code block is reached, program flow is directed back to the top of the loop and theconditional is re-evaluated. As long as the conditional is evaluated as true, the processrepeats. IF the conditional is evaluated as false, then the code block is skipped. Again, theflowchart for a While Loop is shown below.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    37/67

    35

    while (some conditional expression is true){perform the statements located between the braces}

    DO / While

    The Do/While loop is very similar to the while loop. The major difference is that theexpression or conditional is tested at the bottom of the loop. This means that the body ofthe loop is executed at least one time regardless of the results of the conditional. If theresult of the conditional is true, then the loop body is repeated. This process is repeateduntil the conditional is evaluated as false.

    do{perform the statements located between the braces} while (this conditional expression is true)

    The while and do/while loops are frequently used to monitor a particular input or register incontrol type applications.

    For Loop

    The For Loop is traditionally used to perform a task or repetitive event for a known numberof iterations or in other words, it is used to implement count-controlled loops. The for loopis made up of an initial condition, a conditional expression, a modifier, and the body or thecode block. When the for loop is encountered, the initial condition is executed. Theconditional expression is then evaluated as either true or false. If the conditional isdetermined to be true, then the body of the loop is executed. Upon reaching the bottom of

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    38/67

    36

    the loop, the modifier is executed. Program control is then returned to the conditional. Theconditional expression is re-evaluated, and if true, the body of the loop is executed again.Each time the bottom of the code block is reached, the modifier is executed. The loopcontinues to be executed until the conditional is evaluated as no longer true.The flowchart for a For Loop is shown below. The basic shape of the flowchart resembles

    that of a While Loop. The difference or characteristic that determines that it is a For Loopis that the initial condition, conditional, and modifier all refer to the same variable.

    for ( variable initialized ; conditional expression ; variable modifier ){perform these statements while the conditional expression is true}

    The resemblance or similarities between the For Loop and While Loop go beyond the factthat the flowcharts look similar. In actuality, any For Loop can be replaced or implementedwith a While Loop. However, not all While Loops can be replaced by a For Loop.

    Switch / Case

    The Switch Case structure is similar to a host of if statements. The switch case structuremay have a default condition that is executed if none of the statements match. Aswitch/case structure is used when one statement must be chosen from many.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    39/67

    37

    switch ( variable of interest ){case value1:

    code to be executed.

    break;case value2:

    code to be executed.

    break;case value3:

    code to be executed.

    break;

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    40/67

    38

    ...default:

    code to be executed.

    break;}

    Choosing the proper control statements

    Picking the appropriate control structure will ensure the proper operation of the softwareand aid in the readability of the software. The use of a properly developed flowchart canaid in the selection of the control structure. Each control structure has its own uniqueprogram flow which is evident in a flowchart. Flowcharts can now be used as a tool totranslate an algorithm into C code.

    Control structures have the common element of a decision located at some point in theflowchart. The location of the processes associated with the decision aid in theidentification of the structure. In other words, the relationship of the processes and decisiondetermine the type of control statement. Another key element in the identification of thecontrol structure is the flow through the processes. The While, DO / While, and For Loopsall have the flow of the algorithm going back towards the top of the flowchart. The IF /Else and Case / Switch structures both have their program flow going towards the bottomofthe flowchart.

    9. Functions

    One of the most important concepts underlying any high-level language is the notion offunctions. In other languages, they may be called subroutines or procedures, but the idea isthe same. A C function is a collection of C language operations that usually performs anoperation that is more complex than any of the operations built into the C language. Inother words, a function performs multiple operations or statements that cannot beaccomplished through a single line of C code.

    Modular Software Through Functions

    Functions can be thought of as abbreviations for long, possibly complicated sets of

    commands. Functions can, and frequently do, call other functions. Despite being complex,a function should not be so complex that it is difficult to understand. Functions allow theprogrammer to modularize a program or break the program into smaller more manageableportions. Any set of operations that are performed more than once is a candidate forbecoming a function. Packaging code as a function allows the code to be executed frommany different locations in a program simply by calling the function.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    41/67

    39

    Function Usage

    There are several motivations for functionalizing a program. Using functions properlycan make the software much easier to read and thus understand. Another motivation issoftware reusability, which is using existing functions as building blocks to create new

    programs. An additional motivation is to avoid repeating code in a program whichproduces several benefits. Software located inside a function can be easier to update andmaintain. The divide-and-conquer approach makes program development moremanageable.

    The proper use of functions improves the readability of a program. Using meaningfulnames for the functions that represent the true operation of the function is a must. Thisallows the programmer to refer to a sequence of multiple operations with a single functioncall. Functions allow the main code of the software to remain uncluttered and easy tomaintain. The proper use of functions almost documents the code for the programmerwithout the use of comments (ALMOST). Any process block in a simplified flowchart is a

    candidate for a function. In other words, any process in a simplified flowchart that is or canbe replaced by a series of processes or control structures is a possible candidate for afunction.

    The ability to reuse software blocks or functions is powerful for several reasons. The firstbenefit is in program development. Using a function that has been previously created andtested saves the programmer time. The programmer can add the function to the programand be reasonably certain that the software will work without the need to debug thefunction.

    The reuse of functions also reduces the overall size of the software. Creating functionswith repeated code segments shrinks the overall size of the software and can free upadditional code space inside the microcontroller. Embedded microcontrollers usually havea limited amount of program memory that must be conserved whenever possible.Functions allow the programmer to execute the same set of instructions from multipleplaces within the program. The function only needs to be defined once, but it can be calledany number of times.

    If the need arises to make changes to the software, having the code segmented intofunctions can expedite the process. Functions allow the programmer to make the requiredchanges in one place and have the change appear to take place in multiple places throughthe software. In other words, if the function is called five times in the software, changingthe function once, influences all five of the processes that call the function.When programs get longer or when several people are writing pieces of the overallprogram, modular programming is better. Modular programming involves separating thedevelopment of the software into pieces and then linking or combining the modulestogether to make up the final program. This allows the program to be broken down intofunctions and distributed among the developers.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    42/67

    40

    Creating Functions

    The first step in creating a function is choosing a meaningful function name that will beused to identify the function. The same rules apply to naming functions and variables. Thefunction name should represent the actual function that is going to be performed. The name

    can consist of letters, number, and symbols but MUST NOT start with a number.

    Once an appropriate name has been selected for the function, the parameters of the functionmust be determined. Functions have the ability to communicate with other functionsthrough parameters. The parameters of the function identify the type of information that iseither passed to the function or the information that is returned from the function. Theparameters are also similar to the variables used through the program. In fact, theparameters are usually variables that are used inside the function. The parameters havedata types that identify the type of information being used. The common data types are theunsigned char and unsigned int. In the event that no parameters are passed to the function,or a parameter is not returned from the function, the data type of void will be used. Thistells

    the compiler that no data will be exchanged in this case.

    Functions have the following basic characteristics when it comes to parameters: Functionsmay receive data during the function call, they may return information upon completion, orthey may not receive or return any information, or a combination of the above. Forexample, a function may not require any outside information to perform the desired task,therefore no information is passed to the function. The function may or may not need tosend information back to the function that called it. For example, a function may place avalue on a port to control an operation and have no feedback information to supply.Another function may actually supply feedback information about a process and thereforeneed to return a value at the completion of the function. As programs increase in size andcomplexity, it is quite common to find functions that do not return values, functions that donot except values, and functions that do both.

    The C language, as it pertains to embedded microcontrollers, has limits on the parametersthat can be passed to a function or received from a function. At most, a function is onlycapable of returning one value. The value being returned can be any of the following datatypes: character, integer, long, or float. Passing variables to a function is a different story.The CodeVision compiler uses the stack pointer to pass variables to the functions. Thisallows multiple variables of different types to be passed to a function. The limit on thenumber of parameters and data types of these parameters is only limited by the availablememory of the microcontroller.

    Once all the necessary information has been determined, a function prototype is created.Functions must be defined before they can be used in a program. Prototypes inform thecompiler about data being passed to and returned by functions. Function prototypes havethe general form of: return data type function name ( passed data size(s) );

    The following is an example of a function prototype:

    unsigned char current_temperature (void);

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    43/67

    41

    /* function prototype for acquiring the current temperature */

    In this example, the name of the function is current_temperature. The function does notreceive any parameters and returns an unsigned character.

    The next example illustrates a function prototype that sends multiple values to a function:

    void heater_control (unsigned char, unsigned int);

    /* function that sends two parameters to the heater control routine */In this example, the function receives two parameters. The first parameter is an unsignedchar and the second parameter is an unsigned integer. Note that the function prototype onlydefines the type of variables being passed and not the actual name(s) of the variables.Once program flow enters the function, local variables hold the values of the parameterspassed to the function. The variables receiver their names and data types from the functiondeclaration. Using the second function prototype from above, the following function

    declaration can be formed:

    void heater_control (unsigned char set_point, unsigned int time){(actual function statements are omitted for clarity)}

    The statements of the function have been omitted. The function has two local variables thatcome directly from the function declaration. The first local variable is set_point and is ofthe data type unsigned character. The second variable is time and is of the data typeunsigned integer. Since this particular function does not return a value, the function endswhen the closing brace is encountered.

    The following example illustrates a function that returns a value:

    unsigned char current_temperature (void){unsigned char temp;temp = PINA; // get value from the temp sensorreturn temp; // send temp back to the calling routine}

    The above example is over simplified, but still illustrates the returning of a value from afunction. A function that passes information back from it, ends with a return statementfollowed by the information that is being returned.

    Perhaps the most important thing to remember about functions is that the variable typesmust match between the prototype, the declaration, and the values being passed.

    Calling a function is accomplished by simplyreferring to the function name. If a functiondoes not receive any parameters and does not return a value, the function is executed by

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    44/67

    42

    using the function name, followed by an opening and closing parenthesis, followed by asemicolon. For example, given a function named heater_on that has no parameters, thefollowing statement will execute the function:

    heater_on(); // execute the function called heater on

    When executing a function that returns a value, the value being return needs a place to bestored or used. Using the example from above, current_temperature, the return value couldbe stored in a variable or used in a conditional operation. The following two examplesillustrate the above concepts:

    temperature = current_temperature();

    /* store the return value in a variable for later use */

    or

    if ( current_temperature() < 100 ) // is returned less than 100 ??

    Sending information into a function is accomplished by placing the information inside theparenthesis. Multiple values are separated by commas. The values being passed tofunctions can come from variables or from constants within the software. The followingillustrates these concepts:

    heater_control( desired_temp, set_time );

    /* call the function passing the values stored in these variables */or passing constants:heater_control( 100, 3000 );/* set the temperature to 100 degrees in 3000 seconds */

    10.Arrays

    An array can be described as a simple collection of values that are closely related. Inreality, an array is a group of variables that share the same common reference name and thesame data type.

    Arrays Defined

    An array is a group of variables of the same data type that share a common name. Arraysare stored in sequential memory locations inside the memory of the microcontroller.Arrays can be stored in the volatile RAM portion of memory or stored in the non-volatileFlash of the microcontroller.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    45/67

    43

    An array must be declared, like any other variable, before it can be used. An array can bedeclared with any of the data type used in the C programming language. Arrays require anadditional piece of information when compared to normalvariables. The additional pieceof information required is the length of the array or in other words, the number of elements

    that will be stored in the array.

    unsigned char array[ 10 ]; // character array with 10 elements

    The individual elements of the array may be initialized when they are declared (just likeother variables). The initial values for the array elements are placed between an openingand closing brace with commas separating the values.

    unsigned char ch_array [ 3 ] = { 0x32, 0x39, 0x41 }; // init the array elements

    Arrays are used when groups of information are closely linked. Some examples of arraysinclude serial queues, data stacks, and control words. Data arrays are commonly used forlookup tables.

    Array usage

    An array is referenced through the use of an index. The index for the array is located inside

    a set of square brackets. ALL arrays start with an index of zero. The last index number ofthe array is determined by taking the length or number of elements in the array andsubtracting one.

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    46/67

    44

    value = ch_array[ 0 ]; // places the number 0x32 into value

    The above array is accessed with the hard-coded number 0. Arrays can be (and often are)accessed through a variable that is used as the index value. For example:

    unsigned char index = 2; // array index variablevalue = ch_array[ index ]; // places the value 0x41 into the variable value

    Arrays can be filled with information by using the index. To access a particular valuestored in an array, the name of the array is used along with the index position for thedesired information. The position index may be an integer or an integer expression that isevaluated to determine the index.

    ch_array[ 1 ] = 0x55; // place 0x55 into the array

    The C language does not automatically check the index used to access an array with thesize of the array. If the index is assigned to access a location outside of the actual array,other memory locations will be accessed. This can lead to unpredictable results inoperation.

    ch_array[ 3 ] = 0xAA; // attempts to place information into the array

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    47/67

    45

    11.Pointers

    Pointers are variables that contain an address location and therefore naturally point to amemory location. Usually, the value of interest is then located in the particular address thatthe pointer is pointing to. Pointers are commonly used to index, access, and move data in

    the microcontroller.

    Pointer can be very confusing to beginning and even experienced programmers. The mainpurpose of a pointer is to access memory. C pointers are extremely powerful and effectivefor accessing the memory of a microcontroller. A pointer can be made to point to ANYdata item or object in a C program. Pointers can be consider unsigned integers becausethey contain a 16-bit address (in Atmel Embedded Microcontroller environment). Pointersallow indirect access to important information.

    Pointer Usage

    Pointers deal with locations and data stored in those locations. There is not a pointer datatype per say. Instead, a pointer is declared by placing an asterisks (*) in front of theidentifier or variable name in the declaration statement. For example:

    unsigned char *ptr; // ptr is a pointer to an unsigned character

    Like other variables, a pointer can be initialized. The catch is that the value must be anaddress. It cannot be overstressed that a pointer holds an address of a variable, not theactual variable data. The pointer is indicating which memory location the program isinterested in.

    unsigned char *ptr = 0x0160; // set the pointer to the hex address 160

    Cesar Contreras

  • 8/11/2019 Libro 1 V1.pdf

    48/67

    46

    A pointer can also be assigned a value or address by using the & operator. The & tells thecompiler to use the address of the variable, not the value stored in the variable. Thefollowing example sets the pointer to the address of the variable x.

    ptr = &x; // set the pointer to the address of the variable x

    Once a pointer has been initialized, the data that it points to can be accessed through a de-reference operation. The asterisk is also used to de-reference a pointer or in other words, toget to the value stored in the address pointed to by the pointer. The following exampleillustrates using a pointer to copy a value stored in RAM into a variable.

    x = *ptr; // take the value stored in the memory location and place it in x

    Pointer and Character Strings

    Pointers are commonly used to access data stringsor sets of characters that represent text

    messages. For example, the following declaration can be used to access a lists of ASCIIcharacters that make up a text message:

    unsigned char *str = "Hello World."; // store the message in memory

    Remember that the pointer only points to the first memory location of the string whichcontains the capital letter 'H'. To access the subsequent characters, the pointer must beincremented. Pointer ma