Programming AVR Micro Controllers in C

50
(Revised) Rough Notes on Programming AVR Microcontrollers in C. Mechanical Engineering Report 2007/04 P. A. Jacobs School of Engineering The University of Queensland. February 21, 2008 Preface These notes follow on from the material that you studied in CSSE1000 Introduction to Computer Systems. There you studied details of logic gates, binary numbers and instruction set architectures using the Atmel AVR microcontroller family as an example. In your present course (METR2800 Team Project I ), you need to get on to designing and building an application which will include such a microcontroller. These notes focus on programming an AVR microcontroller in C and provide a number of example programs to illustrate the use of some of the AVR peripheral devices. Session Contents 1. Introduction to the hardware and software development environment. A small but complete application example is implemented with an ATmega88 microcontroller on the STK500 development board. 2. An example embedded application. Elements of C programming: data types, vari- ables, operators, expressions and statements. C quick reference sheet. 3. A more extensive application the uses serial communication and more C control structures. Decision and control statements. Functions, scope of variables. 4. An application using the analog-to-digital converter. Pointers and addresses. Pass by reference. Arrays and strings. The C preprocessor. Interrupts. 1

Transcript of Programming AVR Micro Controllers in C

Page 1: Programming AVR Micro Controllers in C

(Revised) Rough Notes on ProgrammingAVR Microcontrollers in C.

Mechanical Engineering Report 2007/04P. A. Jacobs

School of EngineeringThe University of Queensland.

February 21, 2008

Preface

These notes follow on from the material that you studied in CSSE1000 Introductionto Computer Systems. There you studied details of logic gates, binary numbers andinstruction set architectures using the Atmel AVR microcontroller family as an example.In your present course (METR2800 Team Project I ), you need to get on to designing andbuilding an application which will include such a microcontroller. These notes focus onprogramming an AVR microcontroller in C and provide a number of example programsto illustrate the use of some of the AVR peripheral devices.

Session Contents

1. Introduction to the hardware and software development environment. A small butcomplete application example is implemented with an ATmega88 microcontrolleron the STK500 development board.

2. An example embedded application. Elements of C programming: data types, vari-ables, operators, expressions and statements. C quick reference sheet.

3. A more extensive application the uses serial communication and more C controlstructures. Decision and control statements. Functions, scope of variables.

4. An application using the analog-to-digital converter. Pointers and addresses. Passby reference. Arrays and strings. The C preprocessor. Interrupts.

1

Page 2: Programming AVR Micro Controllers in C

CONTENTS 2

Contents

1 Embedded computing system based on Atmel’s AVR 4

2 Example: flash a LED 72.1 Example peripheral: PORTD bidirectional port . . . . . . . . . . . . . . . 72.2 Development tools – software and hardware . . . . . . . . . . . . . . . . . 82.3 Preparing the firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.4 C source code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Example 2: a task loop and a hardware timer 133.1 C source code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.2 Your own prototype board with ISP . . . . . . . . . . . . . . . . . . . . . . 15

4 Elements of a C program 174.1 Types of data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184.2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204.3 Assignment statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

5 Example 3: Serial-port communication 235.1 C source code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

6 Decision and flow-control statements 266.1 Conditional statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266.2 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276.3 Unconditional control statements . . . . . . . . . . . . . . . . . . . . . . . 29

7 Functions 30

8 Pointers-to and addresses-of variables 32

9 Functions revisited: pass-by-reference 33

10 Arrays 3410.1 Pointers and arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3510.2 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

11 The C preprocessor 36

12 Example 4: Using the analog-to-digital converter 3812.1 C source code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

13 Interrupts 4213.1 Example 5: Using interrupts with a hardware timer. . . . . . . . . . . . . . 4413.2 Example 6: Using interrupts to count button presses . . . . . . . . . . . . 45

14 Software architectures of embedded systems 4614.1 Round-Robin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4614.2 Round-Robin with interrupts . . . . . . . . . . . . . . . . . . . . . . . . . 47

Page 3: Programming AVR Micro Controllers in C

CONTENTS 3

A ANSI C Reference Card 49

Page 4: Programming AVR Micro Controllers in C

1 EMBEDDED COMPUTING SYSTEM BASED ON ATMEL’S AVR 4

1 Embedded computing system based on Atmel’s AVR

• AVR microcontroller units (MCUs) all have the same core, i.e. same instruction setand memory organisation.

• “flavours” are based on features and complexity

– tinyAVR: reduced feature set

– megaAVR: lots of features and peripheral devices built in

– AVR or classic AVR: in between range of features

• selection based on

– tight budget - choose one with just enough functionality

– convenience of development - choose one with “bells and whistles”

• in CSSE1000/COMP1300, you used the ATmega8515, a digital-only MCU

• for these demonstrations, we will work with the ATmega88

– has a nice selection of features (see following page), including a serial port andan analog-to-digital converter (with several input channels)

– 28-pin narrow DIL package is convenient for prototyping and there are enoughI/O pins to play without needing very careful planning.

– pinout is shown at the start of the Atmel datasheet (book) on the ATmega88[1]. You will be reading the pages of this book over and over...

– internal arrangement is around an 8-bit data bus

– “Harvard architecture” with separate paths and storage areas for program in-structions and data

– We won’t worry too much about the details of the general-purpose registers,the internal static RAM or the machine instruction set because we will let theC compiler handle most of the details.

– However, memory layout, especially the I/O memory layout is important forus as C programmers; the peripheral devices are controlled and accessed viaspecial function registers in the I/O memory space. For the ATmega88 datamemory, we have:

∗ 32 general purpose registers (0x0000–0x001F)

∗ 64 I/O registers (0x0020–0x005F)

∗ 160 extended I/O registers (0x0060–0x00FF)

∗ 1kbytes internal SRAM (0x0100–0x04FF)

Page 5: Programming AVR Micro Controllers in C

1 EMBEDDED COMPUTING SYSTEM BASED ON ATMEL’S AVR 5

Page 6: Programming AVR Micro Controllers in C

1 EMBEDDED COMPUTING SYSTEM BASED ON ATMEL’S AVR 6

Block diagram for the ATmega88, as scanned from the datasheet [1].

Pin layout for the ATmega88 for the 28-pin Plastic Dual Inline Package (PDIP), asscanned from the datasheet.

Page 7: Programming AVR Micro Controllers in C

2 EXAMPLE: FLASH A LED 7

2 Example: flash a LED

• The microcontroller version of the “Hello, World” program.

• We’ll look at the hardware, development environment and software required to makethis happen.

2.1 Example peripheral: PORTD bidirectional port

Schematic dragram for a digital I/O pin, as scanned from the datasheet.

• peripheral device can be used for digital input or output

• three I/O memory addresses are assigned to this portI/O address bits name

0x0B (0x2B)

01234567

PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0 PORTDdata register

0x0A (0x2A)DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0 DDRD

data direc-tion register

0x00 (0x29)PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0 PIND

input regis-ter

• The names for the registers and the bits are contained in the header file suppliedwith the C compiler. On my Linux computer, these definitions may be found in/usr/avr/include/avr/iomx8.h.

Page 8: Programming AVR Micro Controllers in C

2 EXAMPLE: FLASH A LED 8

• Registers DDRD and PORTD are readable and writeable with initial values for allbits being 0. Register PIND is readable only.

• Writing a 0 to a bit in DDRD sets the corresponding pin to input (and a 1 will setthe pin to output. Note that initial value for DDRD bits being 0 implies that allpins are initially configured for input.

• When set as an input pin, a pull-up resistor can be activated by writing a 1 to thecorresponding PORTD bit.

• Output buffers can source or sink an absolute maximum current of 40mA per I/Opin and the whole device can cope with a total of 200mA. See section 27 of thedatasheet.

2.2 Development tools – software and hardware

• We will be using Atmel’s AVR Studio 4 as our Integrated Development Environment.

– Consists of editor, simulator, device programming software.

– We don’t have to remember so much about the individual tools because we canusually select actions and options from the menus.

– Visit http://www.atmel.com to download a copy for home.

• We will use the WinAVR programming tools.

– Consists of the GNU C compiler and the AVR-libc standard C library andperipherals library.

– Visit http://winavr.sourceforge.net to download a copy for home.

• Atmel’s STK500 development hardware which supports the “target” MCU by pro-viding power, clock signal and input/output devices (such as switches, LEDs andan RS232 port).

• To install our ATmega88 MCU in the STK500,

– use socket SCKT3200A2 (the green one)

– use the In-System Programming (ISP) header SPROG2 and connect (with the6-pin cable) to the appropriate header (green)

– Other jumpers that should be installed:

∗ VTARGET, supply voltage to the MCU

∗ AREF, analogue reference voltage

∗ RESET, allow the master MCU (on the top of the STK500) to control thetarget’s reset pin.

∗ XTAL1, use STK500 on-board clock as the main clock to the target MCU.

Page 9: Programming AVR Micro Controllers in C

2 EXAMPLE: FLASH A LED 9

∗ OSCSEL, jumper 1→2 selects the on-board software-generated clock. Thisis handy on the STK500 because you can adjust its frequency but remem-ber that, when you build your own board, you must have a working clockfor the MCU to respond to in-system programming. It could be the MCU’sinternal 8MHz clock if you don’t want to build an external clock circuit.

∗ make sure that BSEL2 is not jumpered.

– Finally, connect a 10-pin jumper cable from PORTD header to the LEDsheader.

2.3 Preparing the firmware

(a) Start AVR Studio

(b) Create a new project and configure settings.project type: AVR GCCproject name: flashleds1create initial file

create folder√

location: C:\avr-worknextdebug platform: AVR Simulatordevice: ATmega88Also, at this time, configure the editor (Tools→Options→Editor) to set tab width4 and check “replace tabs with spaces”.

(c) Type in source code (from the following section)Save as “flashleds1.c” and use Ctrl-s frequently.

(d) Build the project. (Build→Rebuild All) and check for errors.

– Behind the GUI, avr-gcc has cross-compiled the program and then linked itwith the standard library and start-up code to produce an executable programthat can be downloaded to the MCU. Alternatively, this code may be run inthe simulation environment.

– Note the messages in the lower window (labelled “Build”).

– Note the creation of an “Intel HEX” file that we will later download to theMCU.

(e) Start the simulator (Debug→Start Debugging)

– Note that the yellow arrow points to the first line of code to be executed.

– Stepping options are shown in the toolbar (nongreyed now).

– Open the IO View entry I/O ATmega88, PORTD.

– “Step into” the code a couple of times to see the DDRD bits change.

– Hover the cursor over the “which bit” variable name to see details of thisvariable’s value and location in memory. This doesn’t work for DDRD becausethat is a macro name, however, one can see its address as well as its contentin the I/O View window.

Page 10: Programming AVR Micro Controllers in C

2 EXAMPLE: FLASH A LED 10

(f) Download/program the executable program into the MCU.

– Tools→Program AVR...→Connect→Select “STK500 or AVRISP” and we shouldget “STK500 Window” showing the state of the target MCU.

– Make sure that the power is supplied to the board and that the “status” LEDis a steady green.

– Press “Program” to download the executable program and run it.

– Note messages in the log window telling us how the download process went.

– Note the “Fuse” settings. The factory-set default settings on the ATmega88seem to be

∗ Boot flash section size=1024 words, Boot start address=$0c00.

∗ Serial program downloading enabled (greyed on).

∗ Brown-out detection disabled.

∗ Divide clock by 8 internally.

∗ Internal RC oscillator 8MHz; Start up time: 6CK/14CL+65ms

We could try setting

∗ External clock; Start up time: 6CK/14CL+65ms

∗ Unset divide clock by 8 internally

then experiment with setting the STK500 Oscillator frequency. Values line3.686 MHz seem odd but are good for RS232 communications.

• Close the STK500 connection window.Save project.Exit AVR Studio.The MCU should continue to run independently so long as power is applied.

Page 11: Programming AVR Micro Controllers in C

2 EXAMPLE: FLASH A LED 11

2.4 C source code

// f l a s h l e d s 1 . c// Try out the AVR Studio + AVRGCC + STK500 .// PJ , 26−Feb−2007

// get the proces sor−s p e c i f i c d e f i n i t i o n s f o r the IO memory space#inc lude <avr / i o . h>

// macro d e f i n i t i o n to s e l e c t b i t n , assuming 0 <= n <= 7#de f i n e BIT(n) (1 << (n ) )

void my delay ( unsigned char c 1 s t a r t ){

unsigned char c1 , c2 ;unsigned i n t count = 0 ;f o r ( c1 = c 1 s t a r t ; c1 > 0 ; −−c1 ) {

f o r ( c2 = 255 ; c2 > 0 ; −−c2 ) {count += 1 ;

}}// we ignore the value o f countre turn ;

}

i n t main ( void ){

unsigned char which b i t ;DDRD = 0xFF ; // a l l outputwhich b i t = 0 ;whi l e (1 ) { // never−ending loop

which b i t += 1 ;i f ( wh ich b i t > 7 ) which b i t = 0 ;// Turn on a LED by wr i t i ng 0 to i t s cor re spond ing MCU pinPORTD = ˜BIT( which b i t ) ;my delay ( 1 0 ) ;

}r e turn 0 ; // we should never get here .

}

Notes on this program:• Have used C++-style comments.

• Simple statements end with “;”.

• Compound statements are delimited by “{” and “}”.

• Execution starts at the main function.

• Nonzero values are interpreted at “true” in a Boolean context.

• Operations on individual bits in GCC.

// bit position macro

#define BIT(n) (1 << (n))

// turn on bit n, leaving the others unchanged

PORTD |= BIT(n);

Page 12: Programming AVR Micro Controllers in C

2 EXAMPLE: FLASH A LED 12

// turn off bit n, leaving the others unchanged

PORTD &= ~BIT(n);

// toggle bit n

PORTD ^= BIT(n);

• Standard C integer objects (desktop computing)

– int is at least 16 bits

– sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long)

• GCC on AVR

– char is 8 bits

– can use shift operators to multiply or divide by powers of 2

– there is no hardware divide but newer MCUs have hardware multiply

– avoid the use of floating-point data and operations

• LED connection on STK500

Q1

C

E

B

LED1

12

R2

R1

+5V

VTG

10K

150

LEDn

Page 13: Programming AVR Micro Controllers in C

3 EXAMPLE 2: A TASK LOOP AND A HARDWARE TIMER 13

3 Example 2: a task loop and a hardware timer

• The simplest arrangement for an embedded program that performs a loop of taskswith a fixed period.

• Flowchart is somewhat trivial but does visualize the task loop clearly.

reset t imer

return

set init ial countin t imer register

setup tumer

set registerfor prescale CK/1024

return

Start main

init ial ize hardwaresetup_timer()

reset t imer

select bit

l ight up LED

wait for t imer

wait for t imer

t imer overflow?

return

Yes

No

Page 14: Programming AVR Micro Controllers in C

3 EXAMPLE 2: A TASK LOOP AND A HARDWARE TIMER 14

3.1 C source code

// f l a s h l e d s 2 . c//// The app l i c a t i on doesn ’ t do much ; i t j u s t l i g h t s one LED at a time// ac ro s s the bottom of the STK500 board .// I t does , however , demonstrate the use o f a hardware t imer// to prov ide a r e gu l a r per iod f o r the main loop o f the app l i c a i on .//// PJ , 27−Feb−2007 o r i g i n a l f o r AT90S4433// 11−Feb−2008 update to ATmega88

// get the proces sor−s p e c i f i c d e f i n i t i o n s f o r the IO memory space#inc lude <avr / i o . h>

// macro d e f i n i t i o n to s e l e c t b i t n , assuming 0 <= n <= 7#de f i n e BIT(n) (1 << (n ) )

void se tup t imer1 ( void )// We w i l l use the 16−b i t t imer / counter 1 without i n t e r r up t s// and we w i l l s low th ing s down by p r e s c a l i n g the system c lock .{

// Normal port operat ion , OC1A and OC1B di sconnected// Leave b i t s COM1A1 through COM1B0 o f TCCR1A as d e f au l t ze ro va lue s// p r e s c a l e CK/1024TCCR1B |= BIT(CS12) | BIT(CS10 ) ;r e turn ;

}

void r e s e t t ime r 1 ( unsigned i n t counts )// With a c l o ck f requency o f 3 .686 MHz on the STK500 and// a 1024 p r e s c a l i n g f a c to r , we expect a count o f 360 to r e s u l t// in t imer1 over f l ow a f t e r 100 m i l l i s e c ond s .{

TIFR1 |= BIT(TOV1) ; // c l e a r the over f l ow b i t by wr i t i ng l o g i c a l 1TCNT1 = 0xFFFF − counts ; // s e t the s t a r t i n g count as a 16−b i t va luere turn ;

}

void wa i t f o r t ime r 1 ( void ){

whi le ( (TIFR1 & BIT(TOV1) ) == 0 ) /∗ do nothing ∗/ ;r e turn ;

}

i n t main ( void ){

unsigned char which b i t ;DDRD = 0xFF ; // a l l outputse tup t imer1 ( ) ;wh ich b i t = 0 ;whi l e (1 ) { // never−ending loop

r e s e t t ime r 1 ( 3 6 0 ) ; // Now, we have 100ms to do our work .

// The body o f t h i s loop doesn ’ t do much work .// I t j u s t makes the next LED turn on be f o r e wast ing time// wai t ing f o r t imer / counter 1 to over f l ow .which b i t += 1 ;i f ( wh ich b i t > 7 ) which b i t = 0 ;// Turn on a LED by wr i t i ng 0 to i t s cor re spond ing MCU pinPORTD = ˜BIT( which b i t ) ;

// Hopeful ly , the re i s some time to wait f o r the t imer to over f l ow .wa i t f o r t ime r 1 ( ) ;

}r e turn 0 ; // we should never get here .

}

Page 15: Programming AVR Micro Controllers in C

3 EXAMPLE 2: A TASK LOOP AND A HARDWARE TIMER 15

3.2 Your own prototype board with ISP

• Encourage groups to make a prototype on stripboard.

• Allows software development well before printed-circuit boards have been manufac-tured.

• Soldered joints are more reliable than spring contacts in breadboards.

• Photograph shows a partly constructed prototype board for a timer. The colouredribbon cable connects the 6-pin ISP header from the STK500 to a 6-pin inline headeron the prototype board. The other pairs of wires are to LEDs that will eventuallybe mounted on the front panel of the device.

• There is a voltage regulator on the top part of the board for when the board is notpowered through the ISP cable.

• An external full-swing crystal oscillator is used for the clock signal.

• Current-limiting resistors are used with the peripheral connectors.

• One pair of lines (RXD and TXD) can be connected to PC’s serial port through thelevel-shifting chip on the STK500.

Page 16: Programming AVR Micro Controllers in C

3 EXAMPLE 2: A TASK LOOP AND A HARDWARE TIMER 16

Circuit-diagram for the prototype board, including the voltage regulator and the ISPheader.

FILE: REVISION:

DRAWN BY: PAGE OF

TITLE

ATmega88

PCINT14/!RESET/PC61

PCINT16/RXD/PD02

PCINT17/TXD/PD13

PCINT18/INT0/PD24

PCINT19/OC2B/INT1/PD35

PCINT20/XCK/T0/PD46

VCC7

GND8

PCINT6/XTAL1/TOCS1/PB69

PCINT7/XTAL2/TOSC2/PB710

PCINT21/OC0B/T1/PD511

PCINT22/OC0A/AIN0/PD612

PCINT23/AIN1/PD713

PCINT0/CLKO/ICP1/PB014

PB1/OC1A/PCINT115

PB2/!SS/OC1B/PCINT216

PB3/MOSI/OC2A/PCINT317

PB4/MISO/PCINT418

PB5/SCK/PCINT519

AVCC20

AREF21

GND22

PC0/ADC0/PCINT823

PC1/ADC1/PCINT924

PC2/ADC2/PCINT1025

PC3/ADC3/PCINT1126

PC4/ADC4/SDA/PCINT1227

PC5/ADC5/SCL/PCINT1328

U2RESET/

RXD

INT0

SCK

MOSI

MISO

TXD

+5V100n

100n

100n

C?

470

470

470

470

+5V

15p

15p

20MHz

INT1

+5V

10K

470

12

S_RESET

470PD4

MISO

VTG

SCK

MOSI

RESET/

GND

2

4

6

1

3

5

ISP_CONNECTOR

FILE: REVISION

DRAWN BPAGE OF

TITLE

2

1

CONN_PLUG_PACK

21

J1_5V

2

1

J2_POWER_LED

+5V

D2

D1

IN OUT

7805

GND

1

2

3

U1

12

C110u

12

C210u

R1470

VTG

Page 17: Programming AVR Micro Controllers in C

4 ELEMENTS OF A C PROGRAM 17

4 Elements of a C program

• We will be dealing with data (variables, register values) and instructions (programcode, functions) on what should be done with the data.

• If you want some further reading, see the book [2]. It has a good tutorial introductionbut uses a different compiler for the AVRs.

• Basic program structure

// heading comments

... data declarations, function definitions ...

int main( void ) // this function is special; execution starts here

{

... local difinitions ...

... executable statements ...

return 0;

}

For a small embedded program, it is unlikely that we should never arrive at thereturn statement. For a desktop computing application, the zero will be returnedto the operating system.

• Comments

// C++ style comment

/* C style comment */

Be careful to avoid nesting the C-style comments.

• Statements

– consist of identifiers, keywords, expressions and other statements

– a single statement ends with a semicolon;

b = 10; /* assignment of integer value 10 to variable b */

if ( i > 1 ) b = a - 2;

The second statement contains a keyword, expression and another single state-ment.

– a compound statement is delimited by braces

if ( i > 1 ) { // begin compound statement

b = a - 2;

j = j + 1;

} // end if statement

Note that there is no semicolon at the end of the compound statement. Puttingone there would introduce a null statement.

Page 18: Programming AVR Micro Controllers in C

4 ELEMENTS OF A C PROGRAM 18

• An identifier is the name of a variable or function.

– must start with a letter of the alphabet or an underscore

– this can be followed by any number of letters, digits or underscores

– usually the first 32 characters are significant

– case sensitive

– recommendations

∗ identifiers starting with underscores are usually reserved for system names

∗ don’t rely on case sensitivity to distinguish names

∗ use descriptive names

• keywords (or reserved words) are names that have special meaning to the compiler

– examples: if while and for

– for a complete list, see the appendix A

– these cannot be used for variable or function names

• A variable labels a specific memory location (or register) that is set aside to hold aparticular type of data.

– Each variable is identified by its name.

– Each must be defined before use in a declaration statement that may alsoinitialize the value of the variable.

– General form of the variable declaration statementtype name ; // comment

– Examples:

int count; // This will accumulate the number of key presses.

int count = 0; // On startup, we know that nothing has happened.

4.1 Types of data

• Internally, all data is stored and handled as binary numbers. All other types areinterpretations of the bit patterns.

• Characters

– Examples:

char letter; // 8-bit quantity on the AVR.

letter = ’a’; // Note the use of single quotes.

– Some special characters’\b’ backspace’\f’ form feed’\n’ new line’\r’ carriage return

Page 19: Programming AVR Micro Controllers in C

4 ELEMENTS OF A C PROGRAM 19

’\t’ tab’\’’ apostrophe’\¨’ double quote’\\’ backslash’\nnn’ character number nnn in the ASCII table where nnn is octal

– In AVR programming, we will use char variables to hold 8-bit data (a byte)without necessarily interpreting the data as a character.

• strings are arrays of characters

char my_name[] = "Peter";

The square brackets signify an array. Note that we use double quotes for stringconstants.The storage in memory is ’P’,’e’,’t’,’e’,’r’,’\000’ where the trailing nullcharacter marks the end of the string.

• int variables are used to store 16-bit data.

– unsigned int is used to represent a whole number in the range 0 .. 65535

– (signed) int has the range -32768 .. 32767

– Be careful with large values; the number system wraps around.

– Usually integers are written in base 10 (or decimal) with digits 0..9.

– When working with AVR MCUs, it is often convenient to use other bases.base 2 (binary) for single bitsbase 8 (octal) for groups of 3 bitsbase 16 (hexadecimal) for groups of 4 bits

– Examples:0b1011 binary (0b prefix)

11 decimal (no prefix or leading zero)013 octal (leading zero)0xB hexadecimal (0x prefix)

• float variables are used to represent numbers with a fractional part

– Can only represent a subset of real numbers, for example, 5.5, -2.31 and 9.0.

– Note the decimal point. This is what tells the compiler to use a floating-pointrepresentation.

– floats are represented as 32-bit patters on AVR MCUs.

– Operations are done in software and are slow.

– Try to avoid using float data on AVR, however, it’s hard to beat the convenienceof representing real numbers as float data.

– Range for float numbers -3.4e+38 .. 3.4e+38

– Precision is about 6 decimal digits.

Page 20: Programming AVR Micro Controllers in C

4 ELEMENTS OF A C PROGRAM 20

• boolean or logical values

– There is no dedicated type.

– Use an interpretation of integer data.0 is equivalent to false.Any nonzero value is interpreted as true.

– Logical expressions evaluate to 1 (for true) or 0 (for false).

• program spaceData may be stored in the flash memory of the AVR. This is separate to the normalRAM data space.

#include <avr/pgmspace.h>

...

prog_char c;

prog_int16_t j;

There are also a number of functions in AVR libc to copy data into and out ofprogram space.

4.2 Expressions

Expressions are used to specify simple computations. An expression is a combination ofoperands and operators that express a single value.

• Examples:

int a = 1;

int b = 2;

...

a + 2 // expresses an arithmetic value 3

a >= b // expresses a logical value 0

a = b // expresses an assignment of the value 2

• arithmetic operators+ addition (binary operator)− subtraction∗ multiplication

/division (note that newer AVR MCUs havehardware multiplication but not division)

% modulus (or remainder)++, −− increment and decrement (one operand only)

• precedence1. ()2. negation3. ∗, /4. +, −

Page 21: Programming AVR Micro Controllers in C

4 ELEMENTS OF A C PROGRAM 21

• relational operators== is equal to> is greater than>= is greater than or euqal to< is less than<= is less than or equal to! = is not equal to

• logical operators result in true (1) or false (0) values&& and! not|| or

• bitwise operators∼ ones complement<< shift bit pattern left (with zero fill)>> shift bit pattern right& and| or∧ exclusive-or

• More examples:

char i = 0b0011;

char j = 0xB; // 0b00001011

~i has the value 0b11111100

i << 2 0b00001100

i & j 0b00000011

– The right operand for the shift operators gives the number of bit-places toshift.

– Each left shift is equivalent to multiplying the left operator by 2.

– Right shift treats signed and unsigned quantities differently.unsigned: shifts zero into the most-significant bit signed: the sign bit will bereplicated

• Rules of thumb for precedence1. multiply and divide come before add and subtract2. put parentheses around everything else

• For arithmetic operations, the operand of smaller type is coerced to the larger type.For example, int is a larger type than char so, if we have an addition operationinvolving both int and char operands, the char value will be promoted to an int

value before the operation is performed.

Page 22: Programming AVR Micro Controllers in C

4 ELEMENTS OF A C PROGRAM 22

4.3 Assignment statements

• A declaration sets aside space in memory for the variable.

unsigned char z; // 8-bit quantity

• An assignment statement is is used to give the variable a value.General form:variable = expression ;Example:z = 22;

• The assignment operator means: compute the value of the expression on the rightand assign that value to the variable.

• May initialize variables in their declaration statement.int upper limit = 10000;

• Sometimes we want a value that does not change.const int upper limit = 10000;

• Interacting with the AVR hardware via the special function registers in I/O memory.

#include <avr/io.h>

int main( void )

{

unsigned char z;

DDRD = 0xFF; // sets all port pins as output

while (1) {

z = PINB; // read the binary value from port B

PORTD |= (z & 0xF); // set the least-significant 4 bits

// to look like those at port B

}

return;

}

The read-modifiy-write statement could be written asPORTD = PORTD | (z & 0xF);

Page 23: Programming AVR Micro Controllers in C

5 EXAMPLE 3: SERIAL-PORT COMMUNICATION 23

5 Example 3: Serial-port communication

This example also demonstrates some of the C flow-control structures. The implicit com-munication between the blocks is via variables.

Start main

Initialize hardware,ports, t imer, RS232

to ta l=0

reset t imer

read PORTB switches

increment or decrementor reset the total

send updated totalto PC via RS232 port

wait for t imer

VTG

12

S1

SWn 150

10K

Page 24: Programming AVR Micro Controllers in C

5 EXAMPLE 3: SERIAL-PORT COMMUNICATION 24

5.1 C source code

// countupdown . c//// This app l i c a t i on takes input from the buttons at the bottom of// the STK500 board and accumulates a count o f the key p r e s s e s .// SW0 == c l e a r t o t a l// SW1 == increment t o t a l// SW2 == decrement t o t a l// Remember to connect PORTB to the sw i t che s .//// The t o t a l i s output to the spare RS232 port as a hexadecimal number .// Remember to connect p ins PD0,PD1 to the header RxD,TxD−spare// with a 2−wire jumper cab l e .//// PJ , 28−Feb−2007 o r i g i n a l f o r AT90S4433// 12−Feb−2008 r e v i s e d f o r ATmega88

#inc lude <avr / i o . h>

// −−−−−−−−−−−−−−−−−− t imer −−−−−−−−−−−−−−−−−−−−−−−

void se tup t imer1 ( void )// We w i l l use the 16−b i t t imer / counter 1 without i n t e r r up t s// and we w i l l s low th ing s down by p r e s c a l i n g the system c lock .{

TCCR1B |= (1 << CS12) | (1 << CS10 ) ; // p r e s c a l e CK/1024return ;

}

void r e s e t t ime r 1 ( unsigned i n t counts )// With a c l o ck f requency o f 3 .686 MHz on the STK500 and// a 1024 p r e s c a l i n g f a c to r , we expect a count o f 360 to r e s u l t// in t imer1 over f l ow a f t e r 100 m i l l i s e c ond s .{

TIFR1 |= (1 << TOV1) ; // c l e a r the over f l ow b i t by wr i t i ng l o g i c a l 1TCNT1 = 0xFFFF − counts ; // s e t the s t a r t i n g countre turn ;

}

void wa i t f o r t ime r 1 ( void ){

whi le ( (TIFR1 & (1 << TOV1) ) == 0 ) /∗ do nothing ∗/ ;r e turn ;

}

// −−−−−−−−−−−−−−−−−−−−−− s e r i a l port −−−−−−−−−−−−−−−−−−−−−−−−

// Assume that we run the STK500 c l o ck at f u l l speed .#de f i n e FOSC 3686400#de f i n e BAUD 9600#de f i n e MYUBRR FOSC/16/BAUD − 1// See t ab l e 18−1 o f datasheet f o r the baud−r a t e r e g i s t e r formula .

void s e tup uar t ( void ){

UBRR0 = MYUBRR; // a value o f 23 f o r 9600 baud with FOSC=3.686 MHzUCSR0B |= (1 << TXEN0) ; // connect the transmit to PD1return ;

}

void s end cha rac t e r ( unsigned char c ){

// Note the nu l l s tatements in the bod ie s o f the f o l l ow i n g loops .whi l e ( (UCSR0A & (1 << UDRE0) ) == 0 ) /∗ wait u n t i l empty ∗/ ;UDR0 = c ; // send the charac t e rwhi l e ( (UCSR0A & (1 << TXC0) ) == 0 ) /∗ wait u n t i l complete ∗/ ;

}

unsigned char hex repr ( unsigned char n)

Page 25: Programming AVR Micro Controllers in C

5 EXAMPLE 3: SERIAL-PORT COMMUNICATION 25

// Return a hexadecimal cha rac t e r r ep r e s en t i ng the binary value .{

n &= 0x0F ; // keep only 4 b i t s , j u s t in case the user has sent morei f ( n < 10 ) {

r e turn n+ ’0 ’ ;} e l s e {

r e turn (n−10)+’A’ ;}

}

void send number ( unsigned i n t n)// Send a 4−d i g i t hexadecimal r ep r e s en t a t i on o f the number// to the s e r i a l port , s t a r t i n g with the most s i g n i f i c a n t d i g i t .{

unsigned char nybble , i ;f o r ( i = 0 ; i < 4 ; i++ ) {

nybble = (n & 0xF000 ) >> 12 ; // get most s i g n i f i c a n t d i g i ts end cha rac t e r ( hex repr ( nybble ) ) ;n = n << 4 ; // move remaining b i t s l e f t

}}

// −−−−−−−−−−−−−−−−−−− the main program/ loop −−−−−−−−−−−−−−−−−−−

i n t main ( void ){

unsigned char to ta l , o l d t o t a l , k e y b i t s ;// PORTB de f au l t s to input ; t h i s i s where the sw i t che s are connected .s e tup t imer1 ( ) ;s e tup uar t ( ) ;t o t a l = 0 ;whi l e (1 ) { // never−ending loop

r e s e t t ime r 1 ( 3 6 0 ) ; // Now, we have 100ms to do our work .

// Attend to a l l o f our chores . . .o l d t o t a l = t o t a l ;k e y b i t s = PINB & 0b00000111 ; // only look at SW2, SW1 and SW0// Note that , when pressed , the sw i t che s pu l l the MCU pins low .i f ( ( k e y b i t s & 0b001 ) == 0 ) {

t o t a l = 0 ;} e l s e i f ( ( k e y b i t s & 0b010 ) == 0 ) {

t o t a l++;} e l s e i f ( ( k e y b i t s & 0b100 ) == 0 ) {

t o ta l −−;}i f ( o l d t o t a l != t o t a l ) {

// Only send value when that has been a change .send number ( t o t a l ) ;s end cha rac t e r ( ’\n ’ ) ; // new l i n es end cha rac t e r ( ’\ r ’ ) ; // c a r r i a g e re turn

}// Hopeful ly , the re i s some time to wait f o r the t imer to over f l ow .wa i t f o r t ime r 1 ( ) ;

}r e turn 0 ; // we should never get here .

}

Page 26: Programming AVR Micro Controllers in C

6 DECISION AND FLOW-CONTROL STATEMENTS 26

6 Decision and flow-control statements

Some of these notes were adapted from texts [3] and [4].

6.1 Conditional statements

• simplest form

if ( expression ) statementexpression?

statement

false true

The statement may be a single or a compound statement.

• else clause for a case where the condition is false

if ( expression )statement-1

else

statement-2

expression?

statement-1

false true

statement-2

• Even if statemenst 1 and 2 are single statements, it is a good idea to use braces andindentation to show the structure unambiguously.

• We can nest if statements to get more than two execution paths.

• Unless otherwise indicated by the use of braces, an else clause belongs to theinnermost if statement that does not yet have an associated else clause. (page 52,[3])

• For many execution paths, use a switch statement.switch ( expression ) {

case const-expr-1 : statements-1case const-expr-2 : statements-2case const-expr-3 : statements-3default : statements

}The expression is evaluated and is tested for a match with a number of integer-valued

Page 27: Programming AVR Micro Controllers in C

6 DECISION AND FLOW-CONTROL STATEMENTS 27

constants (the const-expr values) If a match is found, execution starts at that case.All of the statements from that point until the end of the switch construct will beexecuted or until a break statement is encountered. Using a break statement is thenormal way to stop “fall-through” between case clauses. However, making use offall-through, we may have several cases for one particular set of statements. Theoptional default case is executed if none of the others are satisfied.

6.2 Loops

• pretested loop

while ( expression ) statement expression?

statement

false

true

• post-tested loop

do statement while ( expression );

expression?

statement

false

true

Page 28: Programming AVR Micro Controllers in C

6 DECISION AND FLOW-CONTROL STATEMENTS 28

• for statement

for ( init expr ; cond expr ; final expr )statement

cond_expr?

statement

false

true

final_expr;

init_expr;

– init expr is usually an assignment expression.

– The statement is executed if cond expr is nonzero (true). Note that cond exprdoes not have to be a boolean expression.

– final expr is evaluated each time, after the statement is executed. It is usuallyan increment expression.

– Note the semicolons separating the expressions.

– An example of a never-ending loop with a null statement as the body.for (;;) ;

Page 29: Programming AVR Micro Controllers in C

6 DECISION AND FLOW-CONTROL STATEMENTS 29

6.3 Unconditional control statements

• break;

– Flow of control jumps to the statement immediately following the body of thestatement containing the break statement.

– Use for exceptional situations where a loop must be abandoned.

– Also used to stop execution “falling through” from one case to the next in aswitch statement.

• continue;

– Execution starts the next iteration of the innermost enclosing do, for or whileloop.

– Useful for skipping the body of a loop in an exceptional situation.

• goto label ;

– May be useful in exceptional situations, for example, when breaking out ofmultiply-nested loops.

– The label needs to be part of a full statement (which could be a null statement).

– Execution can only jump to a target within a single function body.

– Example:

Start:

i = 0; // this is part of the labelled statement

...

if ( i > 200 ) goto Start;

Page 30: Programming AVR Micro Controllers in C

7 FUNCTIONS 30

7 Functions

• Functions are a form of procedural abstraction, so we don’t have to deal with toomuch detail at any one point in time.

• The idea is to encapsulate an operation or procedure, give it a name, and subse-quently use this operation in other parts of the program simply by using its name.

• There is a special function called “main” which is entered when your program startsrunning (possibly after power-on or some other reset condition for the AVR MCUs).

• All other functions are called directly or indirectly from main except interrupt rou-tines which are called directly by the MCU hardware. (More on that in Section13.)

• type of the function

– Functions return a value of their declared type whenever they are used.

– The value returned may be ifnored (implicitly discarded). If you wish to alwaysdo this, it is probably best to declare the type of the function to be void toindicate that no value is returned.

• definition of the function

– declares the name and type of the function and the argument list.

– provides the body of the function as a compound statement.

• formal parameters (or arguments)are the names used inside the function to refer to its arguments.

• actual parameters (or arguments)are the expressions or values used as arguments when the function is actually called.

• If we wish to refer to the function before defining it, we need to declare it to thecompiler by specifying its prototype.In the function prototype, we don’t need to specify the formal parameter names,just their type, however, specifying the names improves readability of your code.

• function body

– The body of a function is always a compound statement.

– New variables may be declared within this compound statement (or block).These will be local to the function and not be visible to code outside thefunction.

– If any new variable has the same name as any global variable, the local variablewill hide the global variable.

– Formal parameters are effectively local variables.

Page 31: Programming AVR Micro Controllers in C

7 FUNCTIONS 31

• passing arguments (pass-by-value mechanism)

– When a function is called, any arguments that are provided by the caller aresimply treated as expressions.

– The value of each expression is used to initialize the corresponding formalparameter.

– The formal parameters behave the same way as other local variables withinthe function. Any changes to them are not seen outside the function.

• scope of variables

– The scope of a variable is the area of the program code in which the variableis valid (or is visible).

– A global variable is one that is declared outside any function and is validanywhere (within the source code module).

– A local variable has a scope that is limited to the block in which it is declaredand cannot be accessed outside of that block. (A block is a section of codeenclosed in curly braces { ... }).

Page 32: Programming AVR Micro Controllers in C

8 POINTERS-TO AND ADDRESSES-OF VARIABLES 32

8 Pointers-to and addresses-of variables

unsigned int i, j; // defines 16-bit variables

unsigned int *p; // defines a pointer variable

The variable p will contain the address of an unsigned int variable (as opposed to thevalue of the int).

Conceptual model of the data memory.

address ?

int value ?

int value ?

p

j

i

The memory locations will have numerical addresses as seen in the AVR datasheet. Thenames of the variables are shown to the right of the memory locations that they label.The question marks in the memory locations indicate undefined values (presently).

// assign some values

i = 1;

j = 3;

p = &i;

&i

3

1

p

j

i

p now points to the variable i because p contains the address (numerical location in datamemory) of the variable i.& is the address-of operator.

Page 33: Programming AVR Micro Controllers in C

9 FUNCTIONS REVISITED: PASS-BY-REFERENCE 33

To change the value of a variable, given its address, we use the ∗ (prefix) operator. It isequivalent to “what is pointer to” and is sometimes called the “dereference” operator.

*p = 4;

j = (*p);

&i

4

4

p

j

i

The expression ∗p evaluates to 4. Also, we may have more than one pointer variablepointing to any particular memory location.

9 Functions revisited: pass-by-reference

Sometimes we would like a mechanism to affect the variables used as actual parametersto a function. Even though values only are passed through to the formal arguments of afunction, we may pass the address of any variable that we want to affect from within thefunction.

void double_it( int *v )

{

(*v) = (*v) * 2;

return;

}

int main( void )

{

int i = 4;

...

double_it( &i );

...

}

Page 34: Programming AVR Micro Controllers in C

10 ARRAYS 34

10 Arrays

• An array is a collection of variables with identical type and a single name.

• General definition of a single-dimensional array:type variable[size];

• Example:int data list[3];

int value ?

int value ?

int value ?

data_list[1]

data_list[0]

Increasing address

data_list[2]

Although the size may be an expression, it must be evaluated at compile time. Notealso that the array elements start at index 0 and are numbered up to n − 1 wheren is the number of elements. We can consider this index as an offset from the firstelement in the array.

• Initialize each element:

int i;

for ( i = 0; i < 3; i += 1 ) {

data_list[i] = i + 1;

}

2

1

3

data_list[1]

data_list[0]

Increasing address

data_list[2]

Page 35: Programming AVR Micro Controllers in C

10 ARRAYS 35

• Use the same notation to access the elements:

int sum = 0;

for ( i = 0; i < 3; i += 1 ) {

sum += data_list[i];

}

10.1 Pointers and arrays

• The name of the array itself is a pointer to the first element (at index 0).

• Example:

int data_list[3];

int *p;

...

p = data_list;

// or

p = &data_list[0];

...

*p = 5;

int value ?

5

&data_l ist[0]

int value ?

data_list[1]

data_list[0]

data_list[2]

p

• We could use “pointer arithmetic” to step through the array.

for ( p = data_list; p <= &data_list[2]; ++p ) *p = 0;

Page 36: Programming AVR Micro Controllers in C

11 THE C PREPROCESSOR 36

10.2 Strings

• Strings are created out of arrays of characters with the last character being thespecial null character.

• Example:

char name[10];

...

name[0] = ’P’; name[1] = ’e’; name[2] = ’t’;

name[3] = ’e’; name[4] = ’r’; name[5] = ’\000’;

• Alternatively:

#include <string.h>

...

strcpy(name, "Peter");

11 The C preprocessor

• The preprocessor is essentially a specialized text editor which changes your sourcecode before passing it (the transformed source code) onto the compiler.

• All preprocessor directives (also known as commands or macros) begin with a sharp“#” character in the first column and terminate at the end of the line unless theyare continues by having a backslash “\” character as the very last character on theline.

• Be careful that the syntax of the preprocessor is different to the C language. Youcannot use C constructs as preprocessor directives.

• include files

– The include directive allows the program to use source code from another file.

– Examples

#include <avr/io.h>

#include "my_defs.h"

The angle brackets tell the preprocessor to look in the system area for theinclude file. The double quotes tell the preprocessor start looking in the currentarea.

– We can include any file we like but, usually, the file will contain functionprototypes and parameter definitions.

• replacement directive

– General form:#define name substitute-text

Page 37: Programming AVR Micro Controllers in C

11 THE C PREPROCESSOR 37

– Examples:

#define BIT(n) (1 << (n))

...

#define NDIM 10

int x[NDIM];

...

for ( i = 0; i < NDIM; ++i ) x[i] = 0;

The convention is to use captial letters for the name of the definition. Also,when parameters are passed to a definition, use parentheses substitute text inorder to be safe. The definition may be used in all sorts of places.

– We can also remove a definition:#undef NDIM

– Definitions remain in force until they are removed or until the end of the sourcecode file is reached.

– The AVR libc writers have provided definitions for all of the useful I/O regis-ters, for example:

#include <avr/io.h>

...

DDRD = 0xFF;

• conditional compilationWe may have multiple versions of the source code in one file.

#define DEBUG

...

#ifdef DEBUG

...

code for the debugging version

...

#else

...

code for the production version

...

#endif

Page 38: Programming AVR Micro Controllers in C

12 EXAMPLE 4: USING THE ANALOG-TO-DIGITAL CONVERTER 38

12 Example 4: Using the analog-to-digital converter

• This example demonstrates the construction of a program from several modules.Add source files to the project “tree-view” in the top-left of the IDE.

– adc demo.c

– my adc.c

– my serial.c

– my timer.c

• The header files are automatically put under the heading “External Dependencies”when you next build the project.

12.1 C source code

main module

// adc demo . c//// This app l i c a t i on takes input from channel 0 o f the ADC and// sends those va lue s to the s e r i a l port (when they change ) .//// PJ , 02−Mar−2007 ve r s i on f o r AT90S4433// 12−Feb−2008 r e v i s e d f o r ATmega88//// Also , d iv ided the code in to s e v e r a l source f i l e s .// The names are a b i t ugly but are reasonab ly c e r t a i n not to be// the same as the l i b r a r i e s supp l i ed by the compi le r vendor .

#inc lude ”my timer . h”#inc lude ” my s e r i a l p o r t . h”#inc lude ”my adc . h”

i n t main ( void ){

unsigned i n t adc value , o l d va lu e ;s e tup t imer0 ( ) ;s e tup uar t ( ) ;se tup adc ( ) ;adc va lue = 0 ;whi l e (1 ) { // never−ending loop

r e s e t t ime r 0 ( 1 8 0 ) ; // Now, we have 50ms to do our work .

// Attend to a l l o f our chores . . .o l d va lu e = adc va lue ;adc va lue = ge t adc va lu e ( 0 ) ;i f ( o l d va lu e != adc va lue ) {

// Only send value when that has been a change .send number ( adc va lue ) ;s end cha rac t e r ( ’\n ’ ) ; // new l i n es end cha rac t e r ( ’\ r ’ ) ; // c a r r i a g e re turn

}// Hopeful ly , the re i s some time to wait f o r the t imer to over f l ow .wa i t f o r t ime r 0 ( ) ;

}r e turn 0 ; // we should never get here .

}

Page 39: Programming AVR Micro Controllers in C

12 EXAMPLE 4: USING THE ANALOG-TO-DIGITAL CONVERTER 39

ADC module

// my adc . c// Functions to a c c e s s the analogue−to−d i g i t a l conve r t e r .//// PJ , 12−Feb−2008

#inc lude <avr / i o . h>

void setup adc ( void ){

ADCSRA &= ˜(1 << ADATE) ; // s e l e c t s i n g l e sample modeADCSRA |= (1 << ADEN) ; // enable ADC hardware// Set p r e s c a l e r d i v i s i o n f a c t o r to 8 .ADCSRA |= (1 << ADPS0) ;ADCSRA |= (1 << ADPS1) ;ADCSRA &= ˜(1 << ADPS2) ;r e turn ;

}

unsigned i n t g e t adc va lu e ( unsigned char channe l i d ){

unsigned char low byte , h igh byte ;i f ( channe l i d > 5 ) channe l i d = 5 ;

ADMUX = channe l i d ;ADCSRA |= (1 << ADSC) ; // s t a r t conver s i onwhi l e ( (ADCSRA & (1 << ADIF) ) == 0 ) /∗ wait ∗/ ;low byte = ADCL; // Datasheet says to read ADCL f i r s t .h igh byte = ADCH;ADCSRA |= (1 << ADIF ) ; // c l e a r the convers ion−complete f l a gre turn ( i n t ) h igh byte ∗ 256 + low byte ;

}

Page 40: Programming AVR Micro Controllers in C

12 EXAMPLE 4: USING THE ANALOG-TO-DIGITAL CONVERTER 40

Timer module

// my timer . c// Functions to s e t and wait f o r hardware t imers .//// PJ , 12−Feb−2008 , updated f o r ATmega88

#inc lude <avr / i o . h>

void se tup t imer0 ( void )// We w i l l use the 8−b i t t imer / counter 0 without i n t e r r up t s// and we w i l l s low th ing s down by p r e s c a l i n g the system c lock .{

TCCR0B |= (1 << CS02) | (1 << CS00 ) ; // p r e s c a l e CK/1024return ;

}

void r e s e t t ime r 0 ( unsigned char counts )// With a c l o ck f requency o f 3 .686 MHz on the STK500 and// a 1024 p r e s c a l i n g f a c to r , we expect a count o f 36 to r e s u l t// in t imer1 over f l ow a f t e r 10 m i l l i s e c ond s .{

TIFR0 |= (1 << TOV0) ; // c l e a r the over f l ow b i t by wr i t i ng l o g i c a l 1TCNT0 = 0xFF − counts ; // s e t the s t a r t i n g countre turn ;

}

void wa i t f o r t ime r 0 ( void ){

whi le ( (TIFR0 & (1 << TOV0) ) == 0 ) /∗ do nothing ∗/ ;r e turn ;

}

//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

void se tup t imer1 ( void )// We w i l l use the 16−b i t t imer / counter 1 without i n t e r r up t s// and we w i l l s low th ing s down by p r e s c a l i n g the system c lock .{

TCCR1B |= (1 << CS12) | (1 << CS10 ) ; // p r e s c a l e CK/1024return ;

}

void r e s e t t ime r 1 ( unsigned i n t counts )// With a c l o ck f requency o f 3 .686 MHz on the STK500 and// a 1024 p r e s c a l i n g f a c to r , we expect a count o f 360 to r e s u l t// in t imer1 over f l ow a f t e r 100 m i l l i s e c ond s .{

TIFR1 |= (1 << TOV1) ; // c l e a r the over f l ow b i t by wr i t i ng l o g i c a l 1TCNT1 = 0xFFFF − counts ; // s e t the s t a r t i n g countre turn ;

}

void wa i t f o r t ime r 1 ( void ){

whi le ( (TIFR1 & (1 << TOV1) ) == 0 ) /∗ do nothing ∗/ ;r e turn ;

}

Page 41: Programming AVR Micro Controllers in C

12 EXAMPLE 4: USING THE ANALOG-TO-DIGITAL CONVERTER 41

Serial port module

// my s e r i a l p o r t . c// Functions to send cha ra c t e r s v ia the hardware USART.//// PJ , 12−Feb−2008

#inc lude <avr / i o . h>

// Assume that we run the STK500 c l o ck at f u l l speed .#de f i n e FOSC 3686400#de f i n e BAUD 9600#de f i n e MYUBRR FOSC/16/BAUD − 1// See t ab l e 18−1 o f datasheet f o r the baud−r a t e r e g i s t e r formula .

void s e tup uar t ( void ){

UBRR0 = MYUBRR; // a value o f 23 f o r 9600 baud with FOSC=3.686 MHzUCSR0B |= (1 << TXEN0) ; // connect the transmit to PD1return ;

}

void s end cha rac t e r ( unsigned char c ){

// Note the nu l l s tatements in the bod ie s o f the f o l l ow i n g loops .whi l e ( (UCSR0A & (1 << UDRE0) ) == 0 ) /∗ wait u n t i l empty ∗/ ;UDR0 = c ; // send the charac t e rwhi l e ( (UCSR0A & (1 << TXC0) ) == 0 ) /∗ wait u n t i l complete ∗/ ;

}

unsigned char hex repr ( unsigned char n)// Return a hexadecimal cha rac t e r r ep r e s en t i ng the binary value .{

n &= 0x0F ; // keep only 4 b i t s , j u s t in case the user has sent morei f ( n < 10 ) {

r e turn n+ ’0 ’ ;} e l s e {

r e turn (n−10)+’A’ ;}

}

void send number ( unsigned i n t n)// Send a 4−d i g i t hexadecimal r ep r e s en t a t i on o f the number// to the s e r i a l port , s t a r t i n g with the most s i g n i f i c a n t d i g i t .{

unsigned char nybble , i ;f o r ( i = 0 ; i < 4 ; i++ ) {

nybble = (n & 0xF000 ) >> 12 ; // get most s i g n i f i c a n t d i g i ts end cha rac t e r ( hex repr ( nybble ) ) ;n = n << 4 ; // move remaining b i t s l e f t

}}

Page 42: Programming AVR Micro Controllers in C

13 INTERRUPTS 42

13 Interrupts

• The hardware may signal that it needs servicing via an interrupt request1.

• If the processor has its interrupts enabled, it suspends whatever it is doing andexecutes the corresponding interrupt service routine before resuming work on thetask code.

• AVR MCUs have a number of interrupt sources, each enabled by one enable bitand each with an entry in the interrupt vector table in the lowest part of programmemory. Entries in the table are typically jump instructions.

• When an interrupt occurs, the Global Interrupt Enable bit is cleared and all inter-rupts are disabled. The program counter is vectored to the actual interrupt vector inorder to jump to the interrupt handling routine. Hardware clears the correspondingflag that generated the interrupt.

• See section 6.26 in the AVR-libc reference manual for details of setting up an inter-rupt handler. For example:

#include <avr/interrupt.h>

...

ISR(TIMER1_OVF_vect)

{

// Our interrupt handling code here

// for dealing with the timer overflow signal.

}

We are provided with a macro to define the ISR and a table of interrupt vectornames for our particular processor.

• Interrupt service routines (ISRs) must save the context of the task code and restorethat context when they are finished. The C compiler usually handles that detail forus by writing suitable code at the start and at the end of our code in the ISR.

• Usually, it is neither desirable nor possible to do all of the work in an interruptroutine so the routine needs to signal the task code to do follow-up processing. Todo this communication, the ISR shares one or more variables.

• Once one or more variables are shared, we have to be careful because, while in thetask code, the interrupt routins may change the data at any instant. This is theclassic data-sharing problem.

• It may be difficult to identify when programming in C because single statements inC may be translated to several assembler instructions and the interrupt event mayoccur within these assembler statements.

1Some of these notes from Simon’s text [5].

Page 43: Programming AVR Micro Controllers in C

13 INTERRUPTS 43

• One cure for the data-sharing problem is to disable interrupts in “critical sections”of task code. (These are sections of code that must not be interrupted for the systemto work properly.)

• Be sure to use the volatile keyword to indicate that the content of a variable maychange because of interrupts or other things that the compiler doesn’t know about.

static volatile int my_flag;

• Interrupt latency is the amount of time it take a processor to respond to an interrupt.It is determined by:

1 The longest period of time during which the interrupt is disabled.

2 The period of time that it takes to execute routines for higher-priority inter-rupts.

3 The length of time that it takes the MCU to stop what it is doing (in thetask code), do the necessary book-keeping and start executing code in the ISR.Look this up in the AVR datasheet.

4 The length of time it takes the ISR to save the context of its just-left task anddo the work that constitutes the “response” to the interrupt signal.

Item 2 leads to the desire to make interrupt routines short.

Page 44: Programming AVR Micro Controllers in C

13 INTERRUPTS 44

13.1 Example 5: Using interrupts with a hardware timer.

// f l a s h l e d s 3 . c//// The app l i c a t i on doesn ’ t do much ; i t j u s t l i g h t s one LED at a time// ac ro s s the bottom of the STK500 board .// I t does , however , demonstrate the use o f a hardware t imer// with i n t e r r up t to prov ide a r e gu l a r per iod f o r the d i sp l ay update .//// PJ , 28−Aug−2007// 21−Feb−2008 updated f o r ATmega88

// get the proces sor−s p e c i f i c d e f i n i t i o n s#inc lude <avr / i o . h>#inc lude <avr / i n t e r r up t . h>

// We w i l l use the 16−b i t t imer / counter 1 with over f l ow in t e r r up t// and we w i l l s low th ing s down by p r e s c a l i n g the system c lock .// With a c l o ck f requency o f 3 .686 MHz on the STK500 and// a 1024 p r e s c a l i n g f a c to r , we expect a count o f 360 to r e s u l t// in t imer1 over f l ow a f t e r 100 m i l l i s e c ond s .unsigned i n t s t a r t c oun t = 360 ;

// We s l s o need some other data that i s pre se rved between updates// o f the d i sp l ay .unsigned char which b i t ;

void se tup t imer1 ( void ){

// Normal port operat ion , OC1A and OC1B di sconnected// Leave b i t s COM1A1 through COM1B0 o f TCCR1A as d e f au l t ze ro va lue s// p r e s c a l e CK/1024TCCR1B |= (1 << CS12) | (1 << CS10 ) ;TIFR1 |= (1 << TOV1) ; // c l e a r the over f l ow f l a gTIMSK1 |= (1 << TOIE1 ) ; // enable over f l ow in t e r r up tre turn ;

}

ISR(TIMER1 OVF vect )// This r ou t in e i s exectuted on the Timer 1 over f l ow in t e r r up t .// Note that i t i s not c a l l e d d i r e c t l y by any o f our other code .// Also note that the body o f t h i s s e r v i c e r ou t in e should not// do much work because the i n t e r r up t s are cu r r en t l y turned o f f .{

// over f l ow b i t i s a l r eady c l e a r ed by hardwareTCNT1 = 0xFFFF − s t a r t c oun t ; // r e s e t the counter// Decide the next LED to turn on then make i t happen and l eavewhich b i t += 1 ;i f ( wh ich b i t > 7 ) which b i t = 0 ;// Turn on a LED by wr i t i ng 0 to i t s cor re spond ing MCU pinPORTD = ˜(1 << which b i t ) ;

}

i n t main ( void ){

DDRD = 0xFF ; // a l l output so that we can turn on the LEDsse tup t imer1 ( ) ;TCNT1 = 0xFFFF − s t a r t c oun t ; // r e s e t the counterwhich b i t = 0 ;s e i ( ) ;

// At t h i s point , we can get one with whatever work needs to be done// and the Timer1 i n t e r r up t w i l l r e g u l a r l y be s e r v i c ed by the ISR .

whi l e (1 ) /∗ do nothing ∗/ ;r e turn 0 ; // we should never get here .

}

Page 45: Programming AVR Micro Controllers in C

13 INTERRUPTS 45

13.2 Example 6: Using interrupts to count button presses

// button−i n t e r r up t . c//// Demonstration o f us ing ex t e rna l i n t e r r up t s on the AVR.// Port B i s output with the 10−pin jumper connected to LEDs on STK500 .// I t shows the cur rent count o f button p r e s s e s .// Note that only LED0 . . LED5 are connected f o r ATmega88 .// Port D i s input with PD2=INT0 ( count up) and PD3=INT1 ( count down ) .// Use 10−pin jumper to connect to buttons on STK500 .//// PJ , August 2007 ve r s i on f o r AT90S4433// 21−Feb−2008 ve r s i on f o r ATmega88//#inc lude <avr / i o . h>#inc lude <avr / i n t e r r up t . h>

unsigned char count = 0 ;

ISR( INT0 vect ){count++;PORTB = ˜count ;

}

ISR( INT1 vect ){count−−;PORTB = ˜count ;

}

i n t main ( ) {// Set input and outputDDRD &= ˜(1 << PD2) ; // INT0 as inputDDRD &= ˜(1 << PD3) ; // INT1 as inputDDRB = 0xFF ; // Al l outputPORTB = 0xFF ; // turn o f f LEDs on STK500

// Enable s p e c i f i c e x t e rna l i n t e r r up t sEIMSK |= (1 << INT0 ) ;EIMSK |= (1 << INT1 ) ;// Set up i n t e r r up t sense c on t r o l so that f a l l i n g edges// on INT0 and INT1 generate i n t e r r up t r eque s t s .EICRA |= (1 << ISC01 ) ;EICRA |= (1 << ISC11 ) ;

s e i ( ) ;

// Al l o f the i n t e r e s t i n g code i s now in the ISRs so// we j u s t wait around f o r the hardware to make r eque s t s .whi l e (1 ) ;

r e turn 0 ;}

Page 46: Programming AVR Micro Controllers in C

14 SOFTWARE ARCHITECTURES OF EMBEDDED SYSTEMS 46

14 Software architectures of embedded systems

• It’s all about system response. For the source of these note, see section 5 of Simon’stext [5].

• How we structure our software depends on how much the MCU needs to do andhow strict the time requirements are.

• Options discussed by Simon [5] are:

– Round-Robin

– Round-Robin with interrupts

– Function-queue scheduling

– Real-time operating system

14.1 Round-Robin

• This is the simplest architecture (and was used in the early examples).

• No interrupts

• No shared-data issues

• Structure of task code:

int main( void )

{

// initialize hardware

while ( 1 ) {

if ( device A needs service ) {

// service device A; handle data transfer to or from device

}

if ( device B needs service ) {

// service device B; handle data transfer to or from device

}

// ... more devices ...

} // end Round-Robin Loop

return 0;

} // end main

• Provided that we have slack in our processing needs, we can make the Round-Robinloop regular by adding a wait-for-timer-tick at the end of the loop.

• If any device needs a response time less than the time needed to do all of the tasks,the system won’t work properly.

• If any task does a large amount of processing, the system response will be poor.

• We may be able to improve response time for one device by testing the device morethan once in the loop: ABACADA...

Page 47: Programming AVR Micro Controllers in C

14 SOFTWARE ARCHITECTURES OF EMBEDDED SYSTEMS 47

• The system is fragile. After changing the task sequence to meet response needs, onechange or addition can mess it up again.

14.2 Round-Robin with interrupts

• Interrupt routines deal with the urgent needs of any devices and set flags.

• The main (task) loop polls the flags and does follow-up processing requested by theinterrupts.

• Structure of the code:

char flag_dev_A = 0;

char flag_dev_B = 0;

...

void ISR( device_A )

{

// service device A

flag_dev_A = 1; // to signal follow-up processing

}

void ISR( device_B )

{

// service device B

flag_dev_B = 1; // to signal follow-up processing

}

...

int main( void )

{

while ( 1 ) {

if ( flag_dev_A ) {

flag_dev_A = 0;

// Do follow-up processing for device A.

}

if ( flag_dev_B ) {

flag_dev_B = 0;

// Do follow-up processing for device B.

}

...

} // end Round-Robin Loop

return 0;

} // end main

• All processing that is in the interrupt routines gets higher priority than the task-loopcode.

• This ability to set priority for a piece of code is an advantage but it comes with thecost of having to deal with shared-data.

Page 48: Programming AVR Micro Controllers in C

REFERENCES 48

References

[1] Atmel. Atmega48/88/168. Datasheet doc2545, http://www.atmel.com/.

[2] Richard F. Barnett, Larry O’Cull, and Sarah Cox. Embedded C Programming and theAtmel AVR. Clifton Park, Delmar, New York, 2003.

[3] Steven R. Lerman. Problem solving and computation for scientists and engineers : anintroduction using C. Prentice-Hall, Englewood Cliffs, New Jersey, 1993.

[4] B. W. Kernighan and D. M. Richie. The C Programming Language. Prentice HallPTR, Upper Saddle River, New Jersey, 1988.

[5] David E. Simon. An embedded software primer. Addison-Wesley, 1999.

Page 49: Programming AVR Micro Controllers in C

A ANSI C REFERENCE CARD 49

A ANSI C Reference CardC

Ref

eren

ceC

ard

(AN

SI)

Pro

gram

Str

uct

ure

/Funct

ions

type

fnc(ty

pe1,

...);

funct

ion

pro

toty

pe

type

nam

e;

vari

able

dec

lara

tion

int

main(void)

{m

ain

routi

ne

dec

lara

tions

loca

lvari

able

dec

lara

tions

state

men

ts} ty

pefn

c(arg

1,

...)

{fu

nct

ion

defi

nit

ion

dec

lara

tions

loca

lvari

able

dec

lara

tions

state

men

tsreturn

valu

e;

} /*

*/

com

men

tsint

main(int

argc,

char

*argv[])

main

wit

harg

sexit(arg);

term

inate

exec

uti

on

CP

repro

cess

orin

clude

libra

ryfile

#include

<file

nam

e>

incl

ude

use

rfile

#include

"file

nam

e"

repla

cem

ent

text

#define

nam

ete

xtre

pla

cem

ent

macr

o#define

nam

e(va

r)

text

Exam

ple

.#define

max(A,B)

((A)>(B)

?(A)

:(B))

undefi

ne

#undef

nam

equote

dst

ring

inre

pla

ce#

Exam

ple

.#define

msg(A)

printf("%s

=%d",

#A,

(A))

conca

tenate

arg

sand

resc

an

##

condit

ionalex

ecuti

on

#if,#else,

#elif,

#endif

isnam

edefi

ned

,not

defi

ned

?#ifdef,

#ifndef

nam

edefi

ned

?defined(nam

e)

line

conti

nuati

on

char

\

Dat

aT

ypes

/Dec

lara

tion

sch

ara

cter

(1byte

)char

inte

ger

int

realnum

ber

(sin

gle

,double

pre

cisi

on)

float,

double

short

(16

bit

inte

ger

)short

long

(32

bit

inte

ger

)long

double

long

(64

bit

inte

ger

)long

long

posi

tive

or

neg

ati

ve

signed

non-n

egati

ve

modulo

2m

unsigned

poin

ter

toint,float,.

..int*,

float*,..

.en

um

erati

on

const

ant

enum

tag

{nam

e1=va

lue1,..

.};

const

ant

(rea

d-o

nly

)valu

ety

peconst

nam

e;

dec

lare

exte

rnalvari

able

extern

inte

rnalto

sourc

efile

static

loca

lper

sist

ent

bet

wee

nca

lls

static

no

valu

evoid

stru

cture

struct

tag

{..

.};

crea

tenew

nam

efo

rdata

type

typedef

type

nam

e;

size

ofan

obje

ct(t

ype

issize_t)

sizeof

obj

ect

size

ofa

data

type

(type

issize_t)

sizeof(ty

pe)

Init

ializa

tion

init

ialize

vari

able

type

nam

e=va

lue;

init

ialize

arr

ay

type

nam

e[]={va

lue1,..

.};

init

ialize

char

stri

ng

char

nam

e[]="st

ring";

c ©2007

Jose

ph

H.Silverm

an

Perm

issi

ons

on

back.

v2.2

Con

stan

tssu

ffix:

long,unsi

gned

,float

65536L,

-1U,

3.0F

exponen

tialfo

rm4.2e1

pre

fix:

oct

al,

hex

adec

imal

0,

0x

or0X

Exam

ple

.031

is25,0x31

is49

dec

imal

chara

cter

const

ant

(char,

oct

al,

hex

)'a',

'\oo

o',

'\xhh'

new

line,

cr,ta

b,back

space

\n,

\r,

\t,

\b

spec

ialch

ara

cter

s\\,

\?,

\',

\"

stri

ng

const

ant

(ends

wit

h'\0')

"abc..

.de"

Poi

nte

rs,A

rray

s&

Str

uct

ure

sdec

lare

poin

ter

toty

pety

pe*nam

e;

dec

lare

funct

ion

retu

rnin

gpoin

ter

toty

pety

pe*f();

dec

lare

poin

ter

tofu

nct

ion

retu

rnin

gty

pety

pe(*pf)();

gen

eric

poin

ter

type

void

*

null

poin

ter

const

ant

NULL

obje

ctpoin

ted

toby

poin

ter

*po

inte

raddre

ssofobje

ctnam

e&nam

earr

ay

nam

e[dim

]

mult

i-dim

arr

ay

nam

e[dim

1][dim

2]..

.Str

uctu

res

struct

tag

{st

ruct

ure

tem

pla

tedec

lara

tions

dec

lara

tion

ofm

ember

s};

crea

test

ruct

ure

struct

tag

nam

em

ember

ofst

ruct

ure

from

tem

pla

tenam

e.m

embe

rm

ember

ofpoin

ted-t

ost

ruct

ure

poin

ter

->

mem

ber

Exam

ple

.(*p).x

andp->x

are

the

sam

esi

ngle

obje

ct,m

ult

iple

poss

ible

types

union

bit

fiel

dw

ith

bbit

sunsigned

mem

ber:

b;

Oper

ator

s(g

rouped

by

pre

ceden

ce)

stru

ctm

ember

oper

ato

rnam

e.m

embe

rst

ruct

mem

ber

thro

ugh

poin

ter

poin

ter->m

embe

r

incr

emen

t,dec

rem

ent

++,

--

plu

s,m

inus,

logic

alnot,

bitw

ise

not

+,

-,

!,

~

indir

ecti

on

via

poin

ter,

addre

ssofobje

ct*po

inte

r,

&nam

eca

stex

pre

ssio

nto

type

(ty

pe)

expr

size

ofan

obje

ctsizeof

mult

iply

,div

ide,

modulu

s(r

emain

der

)*,

/,

%

add,su

btr

act

+,

-

left

,ri

ght

shift

[bit

ops]

<<,

>>

rela

tionalco

mpari

sons

>,

>=,

<,

<=

equality

com

pari

sons

==,

!=

and

[bit

op]

&

excl

usi

ve

or

[bit

op]

^

or

(incl

usi

ve)

[bit

op]

|

logic

aland

&&

logic

alor

||

condit

ionalex

pre

ssio

nex

pr1

?ex

pr2

:ex

pr3

ass

ignm

ent

oper

ato

rs+=,

-=,

*=,

...

expre

ssio

nev

alu

ati

on

separa

tor

,

Unary

oper

ato

rs,co

ndit

ionalex

pre

ssio

nand

ass

ignm

ent

oper

-ato

rsgro

up

right

tole

ft;all

oth

ers

gro

up

left

tori

ght.

Flo

wof

Con

trol

state

men

tte

rmin

ato

r;

blo

ckdel

imit

ers

{}

exit

from

switch,while,do,for

break;

nex

tit

erati

on

ofwhile,do,for

continue;

go

togoto

labe

l;la

bel

labe

l:statement

retu

rnvalu

efr

om

funct

ion

return

expr

Flo

wC

onst

ructi

ons

if

state

men

tif(ex

pr1)

state

men

t 1elseif

(ex

pr2)

state

men

t 2else

state

men

t 3while

state

men

twhile(ex

pr)

state

men

tfor

state

men

tfor(ex

pr1;

expr2;

expr3)

state

men

tdo

state

men

tdo

state

men

twhile(ex

pr);

switch

state

men

tswitch(ex

pr)

{case

const

1:

state

men

t 1break;

case

const

2:

state

men

t 2break;

default:

state

men

t}

AN

SI

Sta

ndar

dLib

rari

es<assert.h>

<ctype.h>

<errno.h>

<float.h>

<limits.h>

<locale.h>

<math.h>

<setjmp.h>

<signal.h>

<stdarg.h>

<stddef.h>

<stdio.h>

<stdlib.h>

<string.h>

<time.h>

Char

acte

rC

lass

Tes

ts<ctype.h>

alp

hanum

eric

?isalnum(c)

alp

habet

ic?

isalpha(c)

contr

olch

ara

cter

?iscntrl(c)

dec

imaldig

it?

isdigit(c)

pri

nti

ng

chara

cter

(not

incl

space

)?isgraph(c)

low

erca

sele

tter

?islower(c)

pri

nti

ng

chara

cter

(incl

space

)?isprint(c)

pri

nti

ng

char

exce

pt

space

,le

tter

,dig

it?

ispunct(c)

space

,fo

rmfe

ed,new

line,

cr,ta

b,vta

b?

isspace(c)

upper

case

lett

er?

isupper(c)

hex

adec

imaldig

it?

isxdigit(c)

conver

tto

low

erca

setolower(c)

conver

tto

upper

case

toupper(c)

Str

ing

Oper

atio

ns

<string.h>

sis

ast

ring;cs,ct

are

const

ant

stri

ngs

length

ofs

strlen(s)

copyct

tos

strcpy(s,ct)

conca

tenate

ct

aft

ers

strcat(s,ct)

com

pare

cs

toct

strcmp(cs,ct)

only

firs

tn

chars

strncmp(cs,ct,n)

poin

ter

tofirs

tc

incs

strchr(cs,c)

poin

ter

tola

stc

incs

strrchr(cs,c)

copyn

chars

from

ct

tos

memcpy(s,ct,n)

copyn

chars

from

ct

tos

(may

over

lap)

memmove(s,ct,n)

com

pare

nch

ars

ofcs

wit

hct

memcmp(cs,ct,n)

poin

ter

tofirs

tc

infirs

tn

chars

ofcs

memchr(cs,c,n)

putc

into

firs

tn

chars

ofs

memset(s,c,n)

Page 50: Programming AVR Micro Controllers in C

A ANSI C REFERENCE CARD 50

CR

efer

ence

Car

d(A

NSI)

Input/

Outp

ut

<stdio.h>

Sta

ndard

I/O

standard

input

stre

am

stdin

standard

outp

ut

stre

am

stdout

standard

erro

rst

ream

stderr

end

offile

(type

isint)

EOF

get

ach

ara

cter

getchar()

pri

nt

ach

ara

cter

putchar(ch

r)

pri

nt

form

att

eddata

printf("fo

rmat",arg

1,..

.)pri

nt

tost

rings

sprintf(s,"fo

rmat",arg

1,..

.)re

ad

form

att

eddata

scanf("fo

rmat",&nam

e1,..

.)re

ad

from

stri

ngs

sscanf(s,"fo

rmat",&nam

e1,..

.)pri

nt

stri

ngs

puts(s)

File

I/O

dec

lare

file

poin

ter

FILE

*fp;

poin

ter

tonam

edfile

fopen("nam

e","m

ode")

modes

:r

(rea

d),w

(wri

te),a

(appen

d),b

(bin

ary

)get

ach

ara

cter

getc(fp)

wri

tea

chara

cter

putc(ch

r,fp)

wri

teto

file

fprintf(fp,"fo

rmat",arg

1,..

.)re

ad

from

file

fscanf(fp,"fo

rmat",arg

1,..

.)re

ad

and

store

nel

tsto

*ptr

fread(*ptr,eltsize,n,fp)

wri

ten

elts

from

*ptr

tofile

fwrite(*ptr,eltsize,n,fp)

close

file

fclose(fp)

non-z

ero

ifer

ror

ferror(fp)

non-z

ero

ifalr

eady

reach

edE

OF

feof(fp)

read

line

tost

rings

(<max

chars

)fgets(s,max,fp)

wri

test

rings

fputs(s,fp)

Codes

for

Form

att

ed

I/O

:"%-+

0w

.pm

c"-

left

just

ify

+pri

nt

wit

hsi

gn

space

pri

nt

space

ifno

sign

0pad

wit

hle

adin

gze

ros

wm

infiel

dw

idth

ppre

cisi

on

mco

nver

sion

chara

cter

:h

short

,l

long,

Llo

ng

double

cco

nver

sion

chara

cter

:d,i

inte

ger

uunsi

gned

csi

ngle

char

sch

ar

stri

ng

fdouble

(printf)

e,E

exponen

tial

ffloat

(scanf)

lf

double

(scanf)

ooct

al

x,X

hex

adec

imal

ppoin

ter

nnum

ber

ofch

ars

wri

tten

g,G

sam

easf

ore,E

dep

endin

gon

exponen

t

Var

iable

Arg

um

ent

Lis

ts<stdarg.h>

dec

lara

tion

ofpoin

ter

toarg

um

ents

va_list

ap;

init

ializa

tion

ofarg

um

ent

poin

ter

va_start(ap,la

starg);

last

arg

isla

stnam

edpara

met

erofth

efu

nct

ion

acc

ess

nex

tunnam

edarg

,update

poin

terva_arg(ap,ty

pe)

call

bef

ore

exit

ing

funct

ion

va_end(ap);

Sta

ndar

dU

tility

Funct

ions

<stdlib.h>

abso

lute

valu

eofintn

abs(n)

abso

lute

valu

eoflongn

labs(n)

quoti

ent

and

rem

ain

der

ofintsn,d

div(n,d)

retu

rns

stru

cture

wit

hdiv_t.quot

anddiv_t.rem

quoti

ent

and

rem

ain

der

oflongsn,d

ldiv(n,d)

retu

rns

stru

cture

wit

hldiv_t.quot

andldiv_t.rem

pse

udo-r

andom

inte

ger

[0,RAND_MAX]

rand()

set

random

seed

ton

srand(n)

term

inate

pro

gra

mex

ecuti

on

exit(status)

pass

stri

ngs

tosy

stem

for

exec

uti

on

system(s)

Conversi

ons

conver

tst

rings

todouble

atof(s)

conver

tst

rings

toin

teger

atoi(s)

conver

tst

rings

tolo

ng

atol(s)

conver

tpre

fix

ofs

todouble

strtod(s,&endp)

conver

tpre

fix

ofs

(base

b)

tolong

strtol(s,&endp,b)

sam

e,butunsigned

long

strtoul(s,&endp,b)

Sto

rage

Allocati

on

alloca

test

ora

ge

malloc(size),calloc(nobj,size)

change

size

ofst

ora

ge

newptr

=realloc(ptr,size);

dea

lloca

test

ora

ge

free(ptr);

Array

Functi

ons

searc

harray

forkey

bsearch(key,array,n,size,cmpf)

sort

array

asc

endin

gord

erqsort(array,n,size,cmpf)

Tim

ean

dD

ate

Funct

ions

<time.h>

pro

cess

or

tim

euse

dby

pro

gra

mclock()

Exam

ple

.clock()/CLOCKS_PER_SEC

isti

me

inse

conds

curr

ent

cale

ndar

tim

etime()

time2-time1

inse

conds

(double)

difftime(time2,time1)

ari

thm

etic

types

repre

senti

ng

tim

esclock_t,time_t

stru

cture

type

for

cale

ndar

tim

eco

mps

structtm

tm_sec

seco

nds

aft

erm

inute

tm_min

min

ute

saft

erhour

tm_hour

hours

since

mid

nig

ht

tm_mday

day

ofm

onth

tm_mon

month

ssi

nce

January

tm_year

yea

rssi

nce

1900

tm_wday

days

since

Sunday

tm_yday

days

since

January

1tm_isdst

Daylight

Savin

gs

Tim

eflag

conver

tlo

calti

me

toca

lendar

tim

emktime(tp)

conver

tti

me

intp

tost

ring

asctime(tp)

conver

tca

lendar

tim

ein

tp

tolo

calti

me

ctime(tp)

conver

tca

lendar

tim

eto

GM

Tgmtime(tp)

conver

tca

lendar

tim

eto

loca

lti

me

localtime(tp)

form

at

date

and

tim

ein

fostrftime(s,smax,"fo

rmat",tp)

tp

isa

poin

ter

toa

stru

cture

ofty

petm

Mat

hem

atic

alFunct

ions

<math.h>

Arg

um

ents

and

retu

rned

valu

esare

double

trig

funct

ions

sin(x),

cos(x),

tan(x)

inver

setr

igfu

nct

ions

asin(x),

acos(x),

atan(x)

arc

tan(y

/x)

atan2(y,x)

hyper

bolic

trig

funct

ions

sinh(x),

cosh(x),

tanh(x)

exponen

tials

&lo

gs

exp(x),log(x),

log10(x)

exponen

tials

&lo

gs

(2pow

er)

ldexp(x,n),

frexp(x,&e)

div

isio

n&

rem

ain

der

modf(x,ip),fmod(x,y)

pow

ers

pow(x,y),

sqrt(x)

roundin

gceil(x),

floor(x),

fabs(x)

Inte

ger

Type

Lim

its

<limits.h>

The

num

ber

sgiv

enin

pare

nth

eses

are

typic

al

valu

esfo

rth

eco

nst

ants

on

a32-b

itU

nix

syst

em,

follow

edby

min

imum

re-

quir

edvalu

es(i

fsi

gnifi

cantl

ydiff

eren

t).

CHAR_BIT

bit

sin

char

(8)

CHAR_MAX

max

valu

eofchar

(SCHAR_MAX

orUCHAR_MAX)

CHAR_MIN

min

valu

eofchar

(SCHARMIN

or

0)

SCHAR_MAX

maxsignedchar

(+127)

SCHAR_MIN

min

signed

char

(−128)

SHRT_MAX

max

valu

eofshort

(+32,7

67)

SHRT_MIN

min

valu

eofshort

(−32,7

68)

INT_MAX

max

valu

eofint

(+2,1

47,4

83,6

47)

(+32,7

67)

INT_MIN

min

valu

eofint

(−2,1

47,4

83,6

48)

(−32,7

67)

LONG_MAX

max

valu

eoflong

(+2,1

47,4

83,6

47)

LONG_MIN

min

valu

eoflong

(−2,1

47,4

83,6

48)

UCHAR_MAX

maxunsignedchar

(255)

USHRT_MAX

maxunsignedshort

(65,5

35)

UINT_MAX

maxunsignedint

(4,2

94,9

67,2

95)

(65,5

35)

ULONG_MAX

maxunsignedlong

(4,2

94,9

67,2

95)

Flo

atT

ype

Lim

its

<float.h>

The

num

ber

sgiv

enin

pare

nth

eses

are

typic

al

valu

esfo

rth

eco

nst

ants

on

a32-b

itU

nix

syst

em.

FLT_RADIX

radix

ofex

ponen

tre

p(2

)FLT_ROUNDS

floati

ng

poin

tro

undin

gm

ode

FLT_DIG

dec

imaldig

its

ofpre

cisi

on

(6)

FLT_EPSILON

smalles

tx

so1.0

f+

x6=

1.0

f(1

.1E−

7)

FLT_MANT_DIG

num

ber

ofdig

its

inm

anti

ssa

FLT_MAX

maxim

um

float

num

ber

(3.4

E38)

FLT_MAX_EXP

maxim

um

exponen

tFLT_MIN

min

imum

float

num

ber

(1.2

E−

38)

FLT_MIN_EXP

min

imum

exponen

tDBL_DIG

dec

imaldig

its

ofpre

cisi

on

(15)

DBL_EPSILON

smalles

tx

so1.0

+x6=

1.0

(2.2

E−

16)

DBL_MANT_DIG

num

ber

ofdig

its

inm

anti

ssa

DBL_MAX

maxdouble

num

ber

(1.8

E308)

DBL_MAX_EXP

maxim

um

exponen

tDBL_MIN

min

double

num

ber

(2.2

E−

308)

DBL_MIN_EXP

min

imum

exponen

t

January

2007

v2.2

.C

opyri

ght

c ©2007

Jose

ph

H.Silverm

an

Perm

issi

on

isgra

nte

dto

make

and

dis

trib

ute

copie

sof

this

card

pro

-

vid

ed

the

copyri

ght

noti

ce

and

this

perm

issi

on

noti

ce

are

pre

serv

ed

on

all

copie

s.

Send

com

ments

and

corr

ecti

ons

toJ.H

.Silverm

an,M

ath

.D

ept.

,B

row

n

Univ

.,Pro

vid

ence,R

I02912

USA

.〈j

hs@

math

.bro

wn.e

du〉