Uploaded by Adham Abusalah

The Atmel AVR Microcontroller MEGA and XMEGA in Assembly and C (Han-Way Huang) (z-lib.org)

advertisement
The Atmel AVR
Microcontroller:
Mega and XMega in Assembly and C
Han-Way Huang
Minnesota State University • Mankato
Australia • Brazil • Japan • Korea • Mexico • Singapore • Spain • United Kingdom • United States
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
This is an electronic version of the print textbook. Due to electronic rights restrictions,
some third party content may be suppressed. Editorial review has deemed that any suppressed
content does not materially affect the overall learning experience. The publisher reserves the right
to remove content from this title at any time if subsequent rights restrictions require it. For
valuable information on pricing, previous editions, changes to current editions, and alternate
formats, please visit www.cengage.com/highered to search by ISBN#, author, title, or keyword for
materials in your areas of interest.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
The Atmel AVR Microcontroller: Mega
and XMega in Assembly and C
Han-Way Huang
Vice President, Editorial: Dave Garza
Director of Learning Solutions: Sandy Clark
Acquisitions Editor: Stacy Masucci
Managing Editor: Larry Main
© 2014 Delmar, Cengage Learning
ALL RIGHTS RESERVED. No part of this work covered by the copyright herein
may be reproduced, transmitted, stored, or used in any form or by any means
graphic, electronic, or mechanical, including but not limited to photocopying,
recording, scanning, digitizing, taping, Web distribution, information networks,
or information storage and retrieval systems, except as permitted under
Section 107 or 108 of the 1976 United States Copyright Act, without the prior
written permission of the publisher.
Senior Product Manager: John Fisher
Editorial Assistant: Kaitlin Murphy
Director, Brand Management: Jason Sakos
Brand Manager: Kristin McNary
Director, Market Development: Debbie Yarnell
For product information and technology assistance, contact us at
Cengage Learning Customer & Sales Support, 1-800-354-9706
For permission to use material from this text or product,
submit all requests online at www.cengage.com/permissions.
Further permissions questions can be e-mailed to
permissionrequest@cengage.com
Market Development Manager: Erin Brennan
Senior Production Director: Wendy Troeger
Production Manager: Mark Bernard
Content Project Manager: Barbara LeFleur
Production Technology Assistant: Emily Gross
Library of Congress Control Number: 2012934976
ISBN-13: 978-1-133-60729-8
ISBN-10: 1-133-60729-2
Senior Art Director: David Arsenault
Technology Project Manager: Joe Pliss
Delmar
5 Maxwell Drive
Clifton Park, NY 12065-2919
USA
Cengage Learning is a leading provider of customized learning solutions with
office locations around the globe, including Singapore, the United Kingdom,
Australia, Mexico, Brazil, and Japan. Locate your local office at:
international.cengage.com/region
Cengage Learning products are represented in Canada by Nelson Education, Ltd.
To learn more about Delmar, visit www.cengage.com/delmar
Purchase any of our products at your local college store or at our preferred
online store www.cengagebrain.com
Notice to the Reader
Publisher does not warrant or guarantee any of the products described herein or perform any independent
analysis in connection with any of the product information contained herein. Publisher does not assume,
and expressly disclaims, any obligation to obtain and include information other than that provided to it by
the manufacturer. The reader is expressly warned to consider and adopt all safety precautions that might be
indicated by the activities described herein and to avoid all potential hazards. By following the instructions
contained herein, the reader willingly assumes all risks in connection with such instructions. The publisher
makes no representations or warranties of any kind, including but not limited to, the warranties of fitness for
particular purpose or merchantability, nor are any such representations implied with respect to the material set
forth herein, and the publisher takes no responsibility with respect to such material. The publisher shall not be
liable for any special, consequential, or exemplary damages resulting, in whole or part, from the readers’ use of,
or reliance upon, this material.
Printed in the United States of America
1 2 3 4 5 6 7 16 15 14 13 12
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Contents
Preface
Chapter 1 Introduction to Microcontroller
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
1.11
1.12
1
Objectives 1
A Brief History of the Computer 2
1.2.1
Mainframe Computers 3
1.2.2
Minicomputers 4
1.2.3
Microcomputers 4
1.2.4
Supercomputers 5
Computer Hardware Organization 6
The Processor 6
1.4.1
The Arithmetic Logic Unit (ALU) 6
1.4.2
Registers 7
1.4.3
The Control Unit 8
1.4.4
The Language Issue 8
The Microprocessor 9
The Microcontroller 10
Embedded Systems 10
1.7.1
Characteristics of Embedded Systems 11
1.7.2
User Interfaces 11
Memory 11
1.8.1
Magnetic Memory 11
1.8.2
Optical Memory 12
1.8.3
Semiconductor Memory 12
1.8.4
Nonvolatile and Volatile Memory 12
1.8.5
Random Access Memory (RAM) 12
1.8.6
Read-Only Memory (ROM) 13
Memory-System Operation 14
1.9.1
Read Operation 15
1.9.2
Write Operation 15
Program Execution 16
1.10.1
The Program Counter Circuit 16
1.10.2
Starting Program Execution 17
1.10.3
Instruction Execution Process 18
Summary 18
Exercises 20
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
iv
Contents
Chapter 2 Introduction to the AVR Microcontroller
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
Objectives 21
An Overview of the AVR Microcontroller Family 22
The AVR Memory Space 22
The AVR CPU Register 24
2.4.1
The RAMPX, RAMPY, and RAMPZ Registers 25
2.4.2
The Extended Indirect Register (EIND) 25
2.4.3
The RAMPD Register 25
2.4.4
The Status Register (SREG) 26
The AVR Instruction Set 27
AVR Addressing Modes 27
2.6.1
Register Direct Mode 28
2.6.2
I/O Direct Mode 28
2.6.3
Direct Data Mode 28
2.6.4
Data Indirect with Displacement Mode 28
2.6.5
Data Indirect Mode 29
2.6.6
Data Indirect with Pre-Decrement 29
2.6.7
Data Indirect with Post-Increment 29
2.6.8
Program Memory Constant Addressing Using the LPM, ELPM,
and SPM Instructions 30
2.6.9
Program Memory with Post-Increment Using the LPM Z+
and ELPM Z+ Instructions 30
2.6.10
Direct Addressing, JMP and CALL 30
2.6.11
Indirect Program Addressing, IJMP and ICALL 31
2.6.12
Relative Program Addressing, RJMP and RCALL 31
A Sample of AVR Instructions 31
2.7.1
The Data Transfer Instructions 31
2.7.2
Addition Instruction 35
2.7.3
Subtract Instructions 37
Summary 38
Exercises 39
Chapter 3 AVR Assembly Language Programming
3.1
3.2
3.3
21
Objectives 41
AVR Assembly Language Program Structure
3.2.1
Label Field 42
3.2.2
Operation Field 42
3.2.3
Operand Field 43
3.2.4
Comment Field 43
Expressions 43
3.3.1
Operands 43
3.3.2
Functions 44
3.3.3
Operators 44
3.3.4
Formats of Constants 45
41
42
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
v
Contents
3.4
3.5
3.6
3.7
3.8
3.9
3.10
3.11
3.12
3.13
3.14
3.15
3.16
Memory Class 46
Assembler Directives 47
3.5.1
The BYTE Directive 47
3.5.2
The CSEG Directive 48
3.5.3
The DB Directive 48
3.5.4
The DEF Directive 48
3.5.5
The DEVICE Directive 49
3.5.6
The DSEG Directive 49
3.5.7
The DW Directive 49
3.5.8
The MACRO and ENDMACRO Directives
3.5.9
The EQU Directive 50
3.5.10
The ESEG Directive 51
3.5.11
The EXIT Directive 51
3.5.12
The INCLUDE Directive 51
3.5.13
The LIST and NOLIST Directives 51
3.5.14
The LISTMAC Directive 51
3.5.15
The ORG Directive 51
3.5.16
The Set Directive 52
AVR Assembly Program Template 52
Software Development Issue 53
Writing Programs to Perform Arithmetic 55
3.8.1
The Carry/Borrow Flag 57
3.8.2
Multiprecision Addition 57
3.8.3
The C Flag and Subtraction 58
3.8.4
Multiprecision Subtraction 59
3.8.5
Multiplication and Division 59
Accessing Data in Data and Program Memory 61
Writing Program Loops 62
3.10.1
The Infinite Loop 62
3.10.2
The For-Loop 63
3.10.3
The While-Loop 65
3.10.4
The Repeat-Until Loop 67
Shift and Rotate Instructions 70
Boolean Instructions 74
Bit Manipulating Instructions 75
Create Time Delay Using Program Loops 76
Summary 77
Exercises 78
49
Chapter 4 Hardware and Software Development Tools for the AVR 81
4.1
4.2
4.3
Objectives 81
Development Tools for the Atmel AVR 82
Hardware Development Tools 82
4.3.1
Choosing a Demo Board for Learning the AVR
4.3.2
The EasyAVR M1280 Demo Boards 83
82
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
vi
Contents
4.4
4.5
4.6
4.7
4.8
4.9
4.3.3
Stingray XMega Demo Board 84
4.3.4
Arduino Demo Kits 85
4.3.5
Debug Adapters from Atmel 86
Software Development Tools 88
Using the AVR Studio IDE 88
4.5.1
Create a Project 89
4.5.2
Enter the Program 90
4.5.3
Assemble (or Build) the Project 90
4.5.5
Program Execution and Debugging 93
Tips for Assembly Program Debugging 98
4.6.1
Syntax and Semantic Errors 98
4.6.2
Logical Errors 101
4.6.3
General Debug Strategy 101
4.6.4
Common Program Logical Errors 101
Project File Structure 102
Summary 102
Lab Assignments 103
Chapter 5 Advanced Assembly Programming and Subroutine Calls 105
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
5.10
Objectives 105
Introduction 106
The Stack Data Structure 106
5.3.1
Initializing the Stack Pointer 107
5.3.2
Instructions for Stack Operation 107
An Example of Subroutine 108
Issues Related to Subroutine Calls 109
5.5.1
Parameter Passing 109
5.5.2
Local Variable Allocation and Deallocation 109
5.5.3
Result Returning 110
5.5.4
Accessing Local Variables in the Stack 111
5.5.5
Register Usage Issue 111
5.5.6
Instructions for Subroutine Call 111
Writing Subroutines to Perform Multiprecision Arithmetic 114
5.6.1
Writing Subroutines to Perform 16-Bit Unsigned
Multiplication 114
5.6.2
Writing a Subroutine to Perform 16-bit Signed Multiplication 116
5.6.3
Writing Subroutines to Perform Unsigned Multiprecision
Division 118
5.6.4
Converting an Internal Binary Number into a BCD String 120
5.6.5
Signed Division Operation 122
5.6.6
Finding the Square Root 123
5.6.7
Prime Test Subroutine 126
Subroutines with Local Variables in Stack 128
5.7.1
Subroutine to Convert a BCD String to a Binary Number 128
5.7.2
Bubble Sort 133
Summary 138
Exercises 139
Lab Assignments 140
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
vii
Contents
Chapter 6 C Language Programming
6.1
6.2
6.3
6.4
6.5
6.6
6.7
6.8
6.9
6.10
143
Objectives 143
Introduction to C 144
Types, Operators, and Expressions 145
6.3.1
Data Types 145
6.3.2
Variable Declarations 145
6.3.3
Constants 146
6.3.4
Arithmetic Operators 146
6.3.5
Bitwise Operators 148
6.3.6
Relational and Logical Operators 149
6.3.7
Precedence of Operators 149
Control Flow 150
6.4.1
If Statement 150
6.4.2
If-Else Statement 151
6.4.3
Multiway Conditional Statement 151
6.4.4
Switch Statement 152
6.4.5
For-Loop Statement 152
6.4.6
While Statement 153
6.4.7
Do-While Statement 153
6.4.8
Goto Statement 153
Input and Output 154
Functions and Program Structure 155
6.6.1
Function Prototype 157
6.6.2
Writing a C Program with Multiple Functions 157
Pointers, Arrays, Structures, Unions, and Type Definition 158
6.7.1
Pointers and Addresses 158
6.7.2
Arrays 159
6.7.3
Pointers and Arrays 160
6.7.4
Passing Arrays to a Function 160
6.7.5
Initializing Arrays 161
6.7.6
Structures 161
6.7.7
Unions 163
6.7.8
The typedef Statement 163
6.7.9
Enumerated Data Types 164
Miscellaneous Items 165
6.8.1
Automatic/External/Static/Volatile 165
6.8.2
Scope Rules 165
6.8.3
Type Casting 166
6.8.4
Pointer to Functions 167
The C Preprocessor 168
6.9.1
The #define Statement 168
6.9.2
The ## Operator 169
6.9.3
The #include Statement 170
6.9.4
Conditional Compilation 171
Using the AVR Studio C Compiler 172
6.10.1
AVR Peripheral Register Naming Convention 173
6.10.2
AVR Peripheral Register Bit Naming Convention 173
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
viii
Contents
6.11
6.12
6.13
6.14
6.15
6.10.3
Accessing AVR Mega Device Peripheral Registers in C 174
6.10.4
Accessing AVR XMega Device Peripheral Registers in C 174
Using the AVR Studio IDE to Develop C Programs 177
6.11.1
Create a New Project 177
6.11.2
Entering C Programs in AVR Studio IDE 180
6.11.3
Add C Files into the Project 181
6.11.4
Compile (or Build) the Project 182
6.11.5
Execute and Debug the Project 183
Multiple-File Project 190
Summary 193
Exercises 194
Lab Assignments 195
Chapter 7 System Clock Configuration
7.1
7.2
7.3
7.4
7.5
7.6
Objectives 197
Overview of System Clock Generation 198
The Clock System of the AVR Mega Devices 198
7.3.1
Clock Sources 198
7.3.2
Default Clock Source 199
7.3.3
External Clock 200
7.3.4
Watchdog Oscillator 200
7.3.5
Low-Frequency Oscillator 200
7.3.6
Timer/Counter Oscillator 200
7.3.7
System Clock Prescaler 200
Clock System of the XMega Devices 204
7.4.1
Internal Oscillators 205
7.4.2
External Clock Sources 205
7.4.3
System Clock Selection and Prescalers 206
7.4.4
PLL Circuit 209
7.4.5
DFLL 2 MHz and DFLL 32 MHz 210
7.4.6
External Oscillator Failure Detector 213
Summary 215
Exercises 216
Chapter 8 Parallel I/O
8.1
8.2
8.3
197
217
Objectives 217
I/O Introduction to I/O PORTs 218
8.2.1
I/O Addressing Issue 218
8.2.2
I/O Synchronization 219
8.2.3
Synchronization Issue for Parallel PORTs 219
8.2.4
Synchronization Issue for Serial Interface 219
I/O Pin Driving Circuit Structure 220
8.3.1
Totem Pole 220
8.3.2
Bus Keeper 221
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
ix
Contents
8.4
8.5
8.6
8.7
8.8
8.9
8.10
8.11
8.3.3
Wired-OR 222
8.3.4
Wired-AND 222
Electrical Characteristic Consideration for I/O Interfacing 222
8.4.1
Voltage-Level Compatibility 223
8.4.2
Current Drive Capability 225
8.4.3
Timing Compatibility 226
Overview of the AVR Mega Parallel PORTs 227
8.5.1
Configuring the Mega I/O Pins 228
8.5.2
Toggling the Mega I/O Pin 228
8.5.3
Reading the Pin Value 228
8.5.4
Unconnected Pins 229
8.5.5
Alternate PORT Functions 229
Overview of AVR XMega Parallel PORTs 233
8.6.1
Setting the Direction of PORT Pins 234
8.6.2
Controlling the Output Value of PORT Pins 235
8.6.3
Reading the Logic State of PORT Pins 235
8.6.4
Pin Configuration 235
8.6.5
Multipin Configuration 237
8.6.6
Virtual PORTs 237
8.6.7
Alternate PORT Functions of XMega 239
Simple I/O Devices 239
8.7.1
Interfacing with LEDs 239
8.7.2
Interfacing with Seven-Segment Displays 242
8.7.3
Generating a Digital Waveform Using an I/O Pin 247
8.7.4
Making a Sound using an I/O Pin 248
8.7.5
Interfacing with DIP Switches 250
Interfacing with a D/A Converter 251
8.8.1
The AD7302 DAC 251
8.8.2
Interfacing the AD7302 with the AVR Mega or XMega Devices
Summary 254
Exercises 254
Lab Assignments 256
Chapter 9 Interrupt Handling, Resets, and Power Management
9.1
9.2
9.3
9.4
252
259
Objectives 259
Basic Concepts on Interrupt 260
9.2.1
Why Interrupt Is Useful 260
9.2.2
Enabling and Disabling Interrupts 260
9.2.3
Prioritizing Multiple Interrupts 261
9.2.4
Servicing the Interrupt 261
9.2.5
The Interrupt Vector 261
9.2.6
Writing an Interrupt-Driven Program 262
Resets 262
The AVR Mega Interrupts 263
9.4.1
AVR Mega Device Interrupt Vectors 263
9.4.2
The Mega AVR Microcontroller Configuration Register (MCUCR) 266
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
x
Contents
9.5
9.6
9.7
9.8
9.9
9.10
9.11
9.12
9.4.3
AVR Mega External Interrupt Pins 267
9.4.4
Pin Change Interrupt 268
9.4.5
Writing Interrupt Service Routine in C for AVR Mega Devices
The XMega Device Interrupts 272
9.5.1
PMIC Operation 273
9.5.2
XMega Maskable Interrupts 273
9.5.3
XMega Nonmaskable Interrupt 273
9.5.4
XMega Interrupt Level 273
9.5.5
XMega Interrupt Priority 274
9.5.6
PMIC Registers 274
9.5.7
XMega Interrupt Sources 276
9.5.8
XMega PORT Interrupt 277
AVR Mega Reset 283
AVR Mega Watchdog Timer 284
XMega Reset 286
9.8.1
XMega Brown-Out Reset 287
9.8.2
Spike Detector Reset 288
9.8.3
XMega Watchdog Timer 288
9.8.4
XMega WDT Programming 291
Power Management and Sleep Modes 293
9.9.1
Mega Sleep Modes 293
9.9.2
XMega Sleep Modes 297
Summary 300
Exercises 302
Lab Assignments 302
Chapter 10 Advanced Parallel I/O
10.1
10.2
10.3
10.4
10.5
10.6
270
305
Objectives 305
Interfacing a Parallel PORT to a Keypad 306
10.2.1
Keypad Scanning 306
10.2.2
Keyboard Debouncing 307
10.2.3
ASCII Code Lookup 309
Driving the Stepper Motor 311
10.3.1
Principles of Rotation 311
10.3.2
Discrete Stepper Motor Drivers 315
10.3.3
Integrated Stepper Motor Driver 318
Direct Memory Access (DMA) Transfer 319
10.4.1
Overview of the XMega DMA Controller 319
10.4.2
DMA Registers 319
10.4.3
DMA Channel Operation 321
Liquid Crystal Displays (LCDs) 329
The HD44780 LCD Controller 330
10.6.1
Display Data RAM 334
10.6.2
Character Generator ROM (CGROM) 334
10.6.3
Character Generator RAM (CGRAM) 334
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xi
Contents
10.7
10.8
10.9
10.6.4
LCD Controller Registers 334
10.6.5
Instruction Description 335
10.6.6
Interfacing the HD44780 to the AVR Microcontroller
10.6.7
LCD Startup Sequence 338
10.6.8
Writing LCD Programs 339
Summary 346
Exercises 347
Lab Assignments 348
Chapter 11 Timer Functions of the Mega AVR
11.1
11.2
11.3
11.4
11.5
11.6
11.7
11.8
11.9
11.10
336
351
Objectives 351
Introduction to the Microcontroller Timer System 352
11.2.1
Using a Timer to Create Time Delays 352
11.2.2
Input Capture 352
11.2.3
Output Compare 353
11.2.4
Pulse-Width Modulation (PWM) 353
Overview of the Mega AVR Timer System 355
11.3.1
Timers Pin Assignment 355
11.3.2
8-Bit Timer Building Blocks 355
11.3.3
16-Bit Timer Building Blocks 357
Timer Clock Source Selection 357
Timer/Counter Operation Modes 360
11.5.1
8-Bit Timer/Counter Operation Modes 360
11.5.2
16-Bit Timer/Counter Operation Modes 362
Applications of Each Timer/Counter Operation Mode 366
Using the Timer Normal Mode 366
11.7.1
Using the Normal Mode in Creating Time Delays 366
11.7.2
Using the Timer Normal Mode in Waveform Generation 368
11.7.3
Using the Normal Mode to Make Sound 373
11.7.4
Using the Normal Mode to Play a Song 375
11.7.5
Using the Normal Mode to Measure Signal Frequency 381
11.7.6
Measuring Signal Period Using the Normal Mode 384
Using the CTC Mode 386
11.8.1
Using the CTC Mode to Create Time Delay 386
11.8.2
Using the CTC Mode to Generate Waveform 387
Using the Fast PWM Mode 391
11.9.1
Compare Match Pin Action in Fast PWM Mode 391
11.9.2
Using OCRnA to Hold the TOP Value 391
11.9.3
Using ICRn to Hold the TOP Value 391
11.9.4
Extreme Cases for the Fast PWM 392
Using the Phase-Correct PWM Mode 393
11.10.1 The Choice of the TOP Value 394
11.10.2 Pin Action on Compare Match in the Phase-Correct PWM
Mode 394
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xii
Contents
11.11
11.12
11.13
11.14
11.15
Using the Phase and Frequency Correct PWM Mode 396
Driving the DC Motor 397
11.12.1 DC Motor Driver ICs 398
11.12.2 Driving a DC Motor Using the SN754410 398
Summary 399
Exercises 401
Lab Assignments 402
Chapter 12 Event System and Timer Functions of XMega
12.1
12.2
12.3
12.4
12.5
12.6
12.7
12.8
12.9
12.10
12.11
Objectives 405
The XMega Event System 406
12.2.1
Signaling Events 406
12.2.2
Data Events 406
12.2.3
Manually Generating Events 407
12.2.4
Event Routing Network 407
12.2.5
Event Timing 409
12.2.6
Applications of Events 410
An Overview of the XMega Timer System 410
XMega Timer Operation and Configuration 413
12.4.1
Timer Clock Source 413
12.4.2
Timer Operation Modes 413
12.4.3
Double Buffering 414
The Normal Mode 415
12.5.1
Input Capture 416
12.5.2
General Input Capture 417
12.5.3
Frequency Capture 420
12.5.4
Pulse-Width Capture 423
12.5.5
32-Bit Input Capture 423
12.5.6
Capture Overflow 426
12.5.7
Creating Time Delays 426
The Frequency (FRQ) Waveform Generation Mode
The Single-Slope PWM Generate Mode 439
The Dual-Slope PWM Mode 440
Summary 442
Exercises 443
Lab Assignments 443
405
433
Chapter 13 Universal Synchronous Asynchronous Receiver
Transmitter (USART) 449
13.1
13.2
13.3
Objectives 449
Fundamental Concepts of Serial Communication 450
The TIA-232 Standard 450
13.3.1
TIA-232 Electrical Specification 450
13.3.2
TIA-232 Functional Specification 451
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xiii
Contents
13.4
13.5
13.6
13.7
13.8
13.9
13.10
13.11
13.3.3
TIA-232 Mechanical Specification 454
13.3.4
TIA-232 Procedural Specification 455
13.3.5
Data Format 457
13.3.6
Data Transmission Errors 458
13.3.7
Null Modem Connection 459
The AVR USART 459
13.4.1
USART Signal Pin Assignment 459
13.4.2
Features of the USART Module 460
USART Baud Rate Generation 462
13.5.1
The Mega USART Baud Rate Generator 462
13.5.2
The XMega USART Baud Rate Generator 463
The USART Operation 465
13.6.1
USART Initialization 467
13.6.2
USART Data Transmission 470
13.6.3
USART Data Reception 475
Data Exchange with USART via the TIA-232 Interface 483
Terminal and Terminal Emulation 484
Summary 485
Exercises 486
Lab Assignments 488
Chapter 14 The SPI Function
14.1
14.2
14.3
14.4
14.5
14.6
14.7
14.8
14.9
491
Objectives 491
Introduction to the SPI Function 492
SPI Signal Pins 492
SPI-Related Registers 493
14.4.1
SPI Registers of Mega Devices 493
14.4.2
Registers Related to the XMega SPI Operation 494
The SPI Operation 496
14.5.1
Data Modes 496
14.5.2
SPI Circuit Connection 497
14.5.3
Configuring the SPI for Data Transfer 498
14.5.4
Writing Common SPI Data Transfer Functions 500
SPI-Compatible Chips 504
The 74HC595 Shift Register 504
The TC72 Digital Temperature Sensor 507
14.8.1
Operation of the TC72 507
14.8.2
The Temperature Data Format 508
14.8.3
The Serial Bus Interface 509
14.8.4
Internal Register Structure 509
The 12-Bit D/A Converter MCP4922 513
14.9.1
Signal Pins 514
14.9.2
Data Format 515
14.9.3
MCP4922 Output Voltage 515
14.9.4
Format Data to be Sent to the MCP4922 515
14.9.5
Interfacing the MCP4922 with the AVR 516
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xiv
Contents
14.10
14.11
14.12
14.13
14.14
Using the USART in the SPI Mode 519
14.10.1 Clock Generation in the MSPI mode 520
14.10.2 USART Registers of Mega Devices in MSPI Mode 520
14.10.3 USART Registers of XMega Devices in the MSPI Mode 521
14.10.4 USART Module Operation in MSPI Mode 523
Interfacing the MC14489 to the USART in the MSPI Mode 527
14.11.1 The Signal Pins of MC14489 528
14.11.2 Operation of the MC14489 529
14.11.3 Cascading the MC14489s 534
Summary 538
Exercises 539
Lab Assignments 541
Chapter 15 Two-Wire Interface (TWI)
15.1
15.2
15.3
15.4
15.5
15.6
15.7
15.8
543
Objectives 543
Introduction to the Two-Wire Interface (TWI) 544
15.2.1
TWI Addressing 544
15.2.2
The TWI Signal Components 545
15.2.3
Bus Arbitration in TWI 547
15.2.4
Clock and Clock Stretching 547
15.2.5
Clock Synchronization 548
15.2.6
Handshaking 548
15.2.7
Data Transfer Format 549
The TWI of the Mega MCU 550
15.3.1
The SCL and SDA Pins 551
15.3.2
The Bit-Rate Generator Unit 551
15.3.3
The Bus Interface Unit 551
15.3.4
The Address Match Unit 552
15.3.5
The Control Unit 552
Using the Mega TWI Module 554
Mega TWI Programming using the Polling Approach 555
15.5.1
Generating the START Condition 555
15.5.2
Generating the STOP Condition 555
15.5.3
Writing Data to the TWI Bus 556
15.5.4
Read Data Byte from the TWI Bus 556
Interfacing with Serial EEPROM AT24C08B 557
15.6.1
Pin Assignment and Block Diagram of AT24C08B
15.6.2
Device Addressing of AT24C08B 557
15.6.3
The AT24C08B Write Operation 558
15.6.4
The AT24C08B Acknowledge Polling 558
15.6.5
The AT24C08B Read Operation 559
Interrupt-Driven Mega TWI Programming 565
Using the Digital Thermostat DS1631A 571
15.8.1
The DS1631A Pin Assignment 571
15.8.2
The DS1631A Functional Description 571
557
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xv
Contents
15.9
15.10
15.11
15.12
15.13
15.14
15.8.3
DS1631A Registers 572
15.8.4
The DS1631A Operation 573
15.8.5
DS1631A Command Set 574
15.8.6
Interfacing the DS1631A with the AVR Mega MCU 574
The XMega TWI Module 589
15.9.1
The XMega TWI Bus States 589
15.9.2
XMega TWI Master Registers 590
15.9.3
The XMega TWI Master Mode Operation 593
15.9.4
The TWI Slave Mode Registers 596
15.9.5
The XMega TWI Slave Mode Operation 598
Using the XMega TWI Module 600
Using the Real-Time Clock DS1337 606
15.11.1 DS1337 Signal Functions 607
15.11.2 The DS1337 Address Map 607
15.11.3 The DS1337 Clock and Calendar 607
15.11.4 The DS1337 Special Registers 607
15.11.5 The DS1337 Alarms 609
15.11.6 Interfacing the DS1337 with the XMega128A1 610
Summary 616
Exercises 617
Lab Assignments 619
Chapter 16 Analog-to-Digital Converter
16.1
16.2
16.3
16.4
621
Objectives 621
Basics of A/D Conversion 622
16.2.1
A Data Acquisition System 622
16.2.2
Analog Voltage and Digital Code Characteristic 622
16.2.3
A/D Conversion Algorithms 623
16.2.4
Optimal Voltage Range for A/D Conversion 625
16.2.5
Scaling Circuit 626
16.2.6
Voltage Translation Circuit 627
16.2.7
Conversion Ranges 628
The Mega ADC Module 629
16.3.1
Signal Pins of Mega ADC 629
16.3.2
Prescaling and Conversion Timing of Mega ADC 632
16.3.3
Differential Channels of Mega ADC 633
16.3.4
Changing Channel or Reference Selection for Mega ADC 633
16.3.5
Mega ADC Noise Canceller 635
16.3.6
Mega ADC Conversion Result 637
The XMega ADC Module 639
16.4.1
Pipelined Architecture and Virtual Channels of XMega ADC 640
16.4.2
Input Gain Stage of XMega ADC 641
16.4.3
Input Sources of XMega ADC 643
16.4.4
Reference Voltage of XMega ADC 645
16.4.5
Conversion Result of XMega ADC 646
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xvi
Contents
16.5
16.6
16.7
16.8
16.9
16.10
16.11
16.4.6
Result Presentation of XMega ADC 647
16.4.7
Compare Function of XMega ADC 647
16.4.8
XMega ADC Interrupts 647
16.4.9
Starting an XMega ADC Conversion 649
16.4.10 XMega ADC Clock and Conversion Timing 650
16.4.11 XMega ADC Free-Running Mode 651
16.4.12 XMega ADC Calibration 652
Interfacing with Analog Temperature Sensor TC1047A 658
Measuring Barometric Pressure 661
Measuring Relative Humidity 666
XMega Digital to Analog Converter (DAC) 669
16.8.1
Enabling XMega DAC 670
16.8.2
XMega DAC Conversion Triggering 670
16.8.3
XMega DAC Single and Dual Channel Operation 672
16.8.4
Left- and Right-Adjusted Values 673
16.8.5
XMega DAC Calibration 674
16.8.6
The XMega DAC Status 674
Summary 681
Exercises 682
Lab Assignments 685
Chapter 17 Controller Area Network (CAN)
17.1
17.2
17.3
17.4
17.5
687
Objectives 687
Overview of Controller Area Network 688
17.2.1
Layered Approach in CAN 688
17.2.2
General Characteristics of CAN 689
CAN Messages 689
17.3.1
Data Frame 690
17.3.2
Remote Frame 693
17.3.3
Error Frame 693
17.3.4
Overload Frame 694
17.3.5
Interframe Space 695
17.3.6
Message Filtering 695
17.3.7
Message Validation 696
17.3.8
Bit Stream Encoding 696
Error Handling 696
17.4.1
Bit Error 696
17.4.2
Stuff Error 696
17.4.3
CRC Error 696
17.4.4
Form Error 696
17.4.5
Acknowledgment Error 696
17.4.6
Error Signaling 696
Fault Confinement 697
17.5.1
CAN Node Status 697
17.5.2
Error Counts 697
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xvii
Contents
17.6
17.7
17.8
17.9
17.10
17.11
17.12
17.13
17.14
17.15
17.16
17.17
CAN Message Bit Timing 697
17.6.1
Nominal Bit Time 697
17.6.2
Length of Time Segments 698
Synchronization Issue 698
17.7.1
Resynchronization Jump Width 698
17.7.2
Phase Error of an Edge 699
CAN System Configuration 699
Overview of the MCP2515 700
17.9.1
CAN Module 700
17.9.2
Control Logic 700
17.9.3
SPI Protocol 701
MCP2515 Transmit/Receive Buffers/Masks/Filters
17.10.1 Transmit Buffers 702
17.10.2 Transmit Priority 704
17.10.3 Initiating Transmission 704
17.10.4 One-Shot Mode 704
17.10.5 TXnRTS Pins 705
17.10.6 Aborting Transmission 706
Message Reception 706
17.11.1 Receive Buffers 707
17.11.2 Receive Priority 710
17.11.3 Start-of-Frame (SOF) Signal 710
17.11.4 RX0BF and RX1BF Pins 710
Message Acceptance Filters and Masks 711
17.12.1 Filter Matching 713
17.12.2 Filter Hits 713
17.12.3 Data Byte Filtering 714
Bit Timing 714
17.13.1 Oscillator Tolerance 715
17.13.2 Bit Timing Configuration 715
Modes of Operation 720
17.14.1 Configuration Mode 720
17.14.2 Sleep Mode 721
17.14.3 Listen-Only Mode 721
17.14.4 Loopback Mode 722
17.14.5 Normal Mode 722
Error Detection 722
Interrupts 723
17.16.1 Interrupt Code Bits 723
17.16.2 Transmit Interrupt 724
17.16.3 Receive Interrupt 724
17.16.4 Message Error Interrupt 724
17.16.5 Bus Activity Wake-up Interrupt 724
17.16.6 Error Interrupt 724
Oscillator 724
17.17.1 CLKOUT Pin 725
17.17.2 RESET Pin 725
702
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xviii
Contents
17.18
17.19
17.20
17.21
17.22
17.23
Appendices
759
A
B
C
D
E
F
G
References
Glossary
The SPI Interface 725
17.18.1 Reset Instruction 726
17.18.2 Read Instruction 726
17.18.3 Read RX Buffer Instruction 727
17.18.4 Write Instruction 727
17.18.5 Load TX Buffer Instruction 727
17.18.6 Request-to-Send (RTS) Instruction 728
17.18.7 Read Status Instruction 728
17.18.8 RX Status Instruction 728
17.18.9 Bit Modify Instruction 729
Physical CAN Bus Connection 729
17.19.1 The MCP2551 CAN Transceiver 730
17.19.2 Building a CAN Node Using AVR, MCP2515, and MCP2551 731
Programming the MCP2515 for Data Communications 732
17.20.1 MCP2515 Initialization 733
17.20.2 Transmit Message Frames to the MCP2515 737
17.20.3 Receive Message Frames 741
17.20.4 A Complete Program 745
Summary 753
Exercises 754
Lab Assignments 756
Summary of Atmel AVR Instruction Set 759
XMega Devices Interrupt Vector Symbolic Names 763
XMega Devices Interrupt Vector Number Symbolic Names 767
XMega Module Definitions 771
Alternate PORT Functions of XMega64A1/128A1/192A1/
256A1/384A1 773
Music Note Frequencies 781
Example of the LCD Circuit for Mega AVR and LCD Functions 783
787
789
Index 797
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Preface
A Brief History of AVR
The 8-bit Atmel AVR architecture was initially conceived and developed by two Norwegian
college students, Alf-Egil Bogen and Vegard Wollan, at the Norwegian Institute of Technology.
The AVR is a modified Harvard architecture machine where programs and data are stored in
separate physical memory systems that appear in different address spaces, but it has the capability to read data items from program memory, using special instructions.
The AVR is a reduced instruction set (RISC) microcontroller (MCU). The AVR CPU is pipelined, and hence the majority of AVR instructions are executed in one clock cycle. The AVR
CPU incorporates 32 general-purpose registers (GPR). Most of these registers can be used as
operands of arithmetic and logical instructions. An arithmetic or logical instruction can only
operate on a GPR or an immediate value. Only load and store instructions can access memory
locations.
The AVR family of microcontrollers is divided into four subgroups:
• Tiny AVR
• Mega AVR
• Application specific AVR
• XMega AVR
The first three groups of AVRs share the same peripheral design but differ in the number of
supported peripheral modules. These three groups can operate at a frequency up to 20 MHz.
The XMega was introduced later and has peripheral modules designed differently from the
other three subgroups. In addition to the peripheral modules implemented in the Mega AVR,
the XMega AVR supports direct-memory-access (DMA) transfer, implements event systems for
interperipheral communication, provides an on-chip digital-to-analog converter (DAC), and performs data encryption and decryption in hardware. The XMega can operate at a frequency up to
32 MHz. All four of these groups share the same instruction set. Not all instructions are implemented in all AVR devices.
Since its debut in 1996, the AVR MCU has attracted many adopters because of the following reasons:
• Atmel provides a free integrated development environment (IDE) AVR Studio.
By installing the free WINAVR C compiler, the user has a full-blown IDE with C
language support. Starting with version 5, the AVR Studio already includes the C
compiler.
• Inexpensive development boards are available from Atmel and third-party vendors.
• The AVR MCU is easy to use.
• The device is inexpensive.
Today, the Atmel AVR has become one of the most popular 8-bit microcontrollers (MCUs).
Many universities all over the world are teaching the AVR MCU. This text is written for learning the AVR MCU.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xx
Preface
Intended Audience
This book is written for two groups of readers:
1. Students in electrical and computer engineering and technology who are taking an
introductory course of microprocessor interfacing. For this group of readers, this text
serves as a systematic, step-by-step tutorial.
2. Senior electrical and computer engineering students and working engineers who want
to incorporate the AVR in their design projects. Because this book also provides many
more complicated examples, the reader can explore the possible applications of the
AVR peripheral modules in their design projects.
Prerequisites
The author of this book has assumed that the reader has taken a course on digital logic design
and has been exposed to at least one high-level language (preferably C) programming. Knowledge of digital logic design will greatly facilitate learning the AVR. Knowledge of assembly
language programming is not required because one of the goals of this book is to teach AVR
assembly language programming.
Organization of the Book
Chapter 1 gives a brief history of computing, outlines the computer hardware organization,
describes the overall organization of a processor, details the characteristics of a microcontroller and embedded system, classifies memory technologies according to volatility and read/
writability, and summarizes the 8-bit, 16-bit, and 32-bit microcontroller market.
Chapter 2 provides an overview of the AVR MCU family, discusses the AVR memory
space and CPU registers, and examines the AVR addressing modes and a subset of the AVR
instructions.
Chapter 3 introduces basic assembly language programming skills such as arithmetic
operations, program loops, data shifting, and time delay creation.
Chapter 4 introduces development tools, recommends demo boards for learning AVR, and
gives a tutorial on how to use the Atmel AVR Studio to enter, assemble, and execute the program, using a simulator or demo board.
Chapter 5 describes how to write subroutines and make subroutine calls, discusses the
issues related to subroutine calls, and makes recommendation on the use of registers.
Chapter 6 provides a brief tutorial on C language, describes the use of the AVR Studio C
to manipulate the AVR registers and bits, and provides a tutorial on using the AVR Studio to
develop C programs.
Chapter 7 deals with the issue of CPU clock signal generation.
Chapter 8 introduces the concepts of parallel I/O; discusses electrical compatibility
between integrated circuits made of different semiconductor technologies; explores the possible
I/O pin configurations; and demonstrates how to use parallel I/O PORTs to drive LEDs, sevensegment displays; and DAC, and how to generate waveforms.
Chapter 9 introduces the concepts of interrupts, delineates the interrupt mechanism of the
Mega and XMega devices, demonstrates interrupt programming, discusses the mechanism and
applications of reset and watchdog timers, and describes the AVR power management schemes.
Chapter 10 presents a few more applications of parallel I/O PORTs, including keypad input,
stepper motors driving, and liquid crystal display interfacing. This chapter also introduces the
direct memory access method to speed up data transfers.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Preface
xxi
Chapter 11 first discusses how to use timers to create a time delay, capture event arrival
time, perform output compare operation, and generate waveforms using pulse-width modulation (PWM). It then gives an overview on the Mega timers and their operation modes. Finally,
this chapter explores the applications of each operation mode.
Chapter 12 introduces the event system that is an interperipheral communication protocol
unique to XMega, provides an overview on the XMega timer system, and explores the applications of the XMega timer functions.
Chapter 13 introduces the TIA-232 protocol, delineates the operation modes of the USART
module of the Mega and XMega devices, and demonstrates the applications of the USART
module.
Chapter 14 introduces the serial peripheral interface (SPI) protocol, illustrates the SPI modules of the Mega and XMega devices, and demonstrates the applications of the SPI module.
Chapter 15 introduces the I2C and TWI protocols, describes the AVR TWI module, and
demonstrates how to use the TWI module to interface with the peripheral chips.
Chapter 16 describes the basic structure of a data acquisition system, delineates the AVR
ADC modules, and demonstrates how to use the ADC to measure physical quantities such as
voltage, temperature, humidity, and barometric pressure.
Chapter 17 introduces the controller area network (CAN) protocol, describes the configuration and operation modes of the CAN controller MCP2515, and demonstrates how to use the
MCP2515 and an AVR MCU to build a CAN node to perform data communication.
Pedagogical Features
Each chapter starts with a list of objectives. Every subject is presented in a step-by-step manner.
Background issues are presented before the specifics related to each AVR function are discussed.
Numerous examples are then presented to demonstrate the use of each AVR peripheral function. Procedural steps and flowcharts are used to help the reader understand the program logic
in most examples.
Both the assembly and C languages are used to illustrate the programming of the AVR functions. Using assembly language gives students an intimate feel about the functioning of the
MCU, whereas using C language yields higher productivity. The instructor can opt to use only
assembly language, only C language, or both in teaching the AVR MCU.
Development Tools
To learn the programming and interfacing of a microcontroller, the learner needs both the software and hardware development tools.
Software Development Tools
The software tools that the learner needs include the text editor, cross-assembler, crosscompiler, simulator, debugger, and the device driver for the hardware debug adapter. Software
vendors often put together these software programs and sell them as a package called an integrated development environment (IDE). Atmel provides a free IDE called AVR Studio to the
AVR user. Before version 5, the user had to install the WINAVR C compiler in order to use the
C language as his or her developing language. Starting with version 5, the C compiler became
part of the IDE. Currently, the AVR Studio supports all 8-bit and 32-bit AVR MCUs. Eventually,
the AVR Studio will also support the Atmel ARM microcontrollers.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xxii
Preface
Hardware Development Tools
The minimum hardware that a learner needs is a demo board and a programmer. The programmer connects to the host computer (usually a PC), and the demo board via a USB cable. The
programmer circuit can also be built into the demo board. This way the user only needs a demo
board and a USB cable. Both the demo board EasyAVR M1280 from AVRVI and the Stingray
XMega from XBIT Inc. have this capability built in. However, program debugging is a difficult
process. A debugger is highly desirable and consists of both the hardware and software.
First of all, the microcontroller must have a debug support circuit. The AVR provides a
proprietary programming debug interface called PDI that uses two dedicated pins (PDI_CLK
and PDI_DATA) for the host computer to access the MCU internal resources such as registers,
data memory, and program memory nonintrusively. Commands can be sent to reset the program counter, set breakpoint, step the program, run-to-cursor, read out register and memory
contents, and so on, through the PDI interface. The AVR also supports the industrial standard
JTAG interface that uses four pins (TMS, TCK, TDI, and TDO) to perform programming and
debugging. JTAG interface is the acronym for Joint Test Action Group interface, which is the
boundary-scan interface defined by the IEEE 1149.1 standard.
Second, software is needed to run on the host computer that sends commands to reset the
program counter, step the instruction, set the breakpoint, add program variables to the watch
list, execute the program until the cursor position, and so on. This software is called a debugger
and is part of the IDE.
Third, a debug adapter that connects the host computer and the demo board is required.
The debug adapter receives commands coming from the host computer, converts them into
appropriate PDI instructions, and sends them to the MCU in serial format.
Atmel provides four debug adapters (Dragon, JTAGICE3, JTAGICE mkII, and AVR ONE!)
to AVR users. Dragon is the least expensive, whereas the AVR ONE! is the most expensive
debug adapter. All of these debug adapters support all AVR 8-bit and 32-bit devices.
Demo Boards
Some of the demo boards include many I/O devices and peripheral chips, whereas other demo
boards are bare kits. Some of the peripheral chips are either very small or use a package that
is difficult to handle manually. If these chips are not pre-soldered on the demo board, then
it will be difficult to perform the experiment. Bare kits will be cheaper. However, when the
costs of all the I/O devices and peripheral chips required in learning the AVR MCU are added
up, the bare kits may be much more expensive. Because the instructor may opt to teach only
the Mega AVR or the XMega AVR, the learner will only need a Mega-based or an XMega-based
demo board.
Because the Mega MCUs were introduced a few years before the XMega MCUs, there
are a lot more Mega-based demo boards than XMega-based demo boards available in the
market. If the instructor wants to teach all the topics in the text, then the EasyAVR M1280
from AVRVI (enshop.avrvi.com) is the only Mega-based demo board, and the Stingray
XMega from XBIT Inc. (xbitinc.com) is the only XMega-based demo board that provides
all the required features. If the instructor does not plan to teach Chapter 17, which covers
CAN, then more demo boards can be used. The user can find additional AVR demo boards
from ebay.com by entering “Mega128” as the search key. For example, Waveshare Electronics (wvshare.com) produces quite a few Mega-based (for example, OpenM128 package B) and
XMega-based (for example, EVK XA1) demo boards that are suitable for learning the Mega
and XMega devices.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xxiii
Preface
Complementary Material
The following materials are useful in learning the AVR and are placed on the complementary CD:
• The source code of all example programs in the text
• The PDF files of datasheets of the Mega2560, XMegaA1, and all the peripheral
chips covered in the text
• Utility programs (in assembly and C languages) for time delay, system clock
generation, LCD, USART, and SPI
Supplements
An Instructor Resource CD is available for this text (ISBN 1133608884). The elements of the
instructor resource link directly to the text to provide a unified instructional system. With the
instructor resource you can spend your time teaching, not preparing to teach.
Features in the instructor resource include the following:
• A Solution Manual with solutions to the exercises is available to instructors as a
PDF file.
• An Image Gallery of all the figures and tables is also available.
• ExamView Test Bank: Questions of varying levels of difficulty are provided for each
chapter. This versatile tool enables the instructor to manipulate the test banks to
create original tests.
• Chapter Presentations in PowerPoint: These slides provide the basis for a
lecture outline to present concepts and material. Key points and concepts can be
graphically highlighted for student retention.
Professors can request a copy of the instructor resource from their sales representatives.
These files are also available through an instructor companion website.
Feedback and Update
The author has tried his best to eliminate errors from this text. However, it is impossible to get
rid of all of the errors. The solutions in the examples of this book may not be the best either.
Error reports and suggestions are welcomed. Please send them to han-way.huang@mnsu.edu.
Acknowledgments
This book would not have been possible without the help of a number of people. I would like to
thank the following reviewers who provided valuable opinions on how to improve the quality
of this book:
Rabah Aoufi DeVry, Irving, Texas
Christopher Cischke, Michigan Technological University
Fanourios Halkiadakis, CalState Polytechnic University, Pomona, California
Max Rabiee, University of Cincinnati, Cincinnati, Ohio
Roman Stembrok, San Diego, California
Ron Tinckham, Santa Fe College, Gainesville, Florida
Hanqi Zhuang, Florida Atlantic University, Boca Raton, Florida
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
xxiv
Preface
I would also like to thank Stacy Masucci, acquisitions editor, and John Fisher, senior product manager, of Cengage Learning for their enthusiastic support during the preparation of this
book, and the Cengage Learning staff for their outstanding production work. I would like to
express my heartfelt appreciation to my students and colleagues at the Department of ECET at
Minnesota State University, Mankato, who allowed me to test out the manuscript.
Finally, I would like to express my thanks to my wife, Su-Jane, and my sons, Craig and
Derek, for their encouragement and support during the entire preparation of this book.
Han-Way Huang
Mankato, Minnesota
March 1, 2012
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1
Introduction to Microcontroller
1.1 Objectives
After completing this chapter, you will be able to
• Describe the characteristics of a mainframe
computer.
•
•
•
•
•
•
Describe the characteristics of a minicomputer.
Describe the characteristics of a microcomputer.
Describe the characteristics of a supercomputer.
Describe the characteristics of a microprocessor.
Describe the characteristics of a microcontroller.
Describe the characteristics of an embedded
system.
• Explain the structure of a computer hardware.
• Explain the memory technologies.
• Explain the structure of an ALU that performs
ADD, SUB, AND, and OR operations.
• Explain the instruction execution process.
• Understand the 8-bit, 16-bit, and 32-bit
microcontroller markets.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2
Chapter 1
■
Introduction to Microcontroller
1.2 A Brief History of the Computer
The word computer first appeared in 1613 [1]. It refers to a person who performs the task
of computation, or calculation. At the end of the nineteenth century, the meaning of the word
changed so that it no longer refers to a person but instead to a machine that carries out the task
of calculation.
A computer consists of hardware and software. The computer hardware implements
the binary digital logic that performs the desired computation. The binary digital logic was
invented by Claude Shannon in 1937. Boolean algebra provides the theoretical foundation for
the binary digital logic. The subjects of binary digital logic and Boolean algebra are covered in
many textbooks [2,3,4] on digital logic design. The smallest unit of information manipulated
by the computer is referred to as a bit, which represents on or off, open or closed, or 1 or 0.
A group of 8 bits is referred to as a byte; a group of bytes (either 2 or 4) is referred to as a word;
and a group of 64 bits is referred to as a double word. The relationship among a bit, a byte, a
word, and a double word is illustrated in Figure 1.1, where a bit is represented by a rectangle;
a byte is represented by eight rectangles; a word is represented by 32 rectangles; and a double
word is represented by 64 rectangles. The number above a rectangle refers to the bit number, or
the bit position, within a byte, a word, or a double word. Within a byte, the bits are numbered
from 7 down to 0. Within a double word, the bits are numbered from 63 down to 0. A bit with a
higher bit number is more significant than a bit with a lower bit number.
0
7
6
5
4
3
2
1
0
Byte
31 30 29 28 27 26 25 24
7
6
5
4
3
2
1
0
Word
63 62 61 60 59 58 57 56
31 30 29 28 27 26 25 24
7
6
5
4
3
2
1
0
Double word
Figure 1.1
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Bit
Relative sizes of a bit, byte, word, and double word
The defining feature of modern computers that distinguishes them from other machines
is their programmability. The hardware of a modern computer consists of processor, input
devices, output devices, and memory. The processor carries out all the computations. It is
designed to execute a set of instructions. An instruction is simply a group of bits that tells
the computer what operation to perform. The operands are also specified in the instruction
(using addressing modes). An instruction may perform the operation of addition, subtraction,
multiplication, division, AND, OR, shift left, shift right, and so on. A program is a sequence of
selected instructions that performs certain tasks such as finding the square root of an integral
number or measuring the frequency of an unknown signal. By providing different programs to
the computer, the same computer can perform different operations. In early computers, programming was performed by changing wires and switches. This proved to be a difficult task.
Starting in 1940s, the stored program architecture was adopted to provide programmability
to the computer. The program is stored in memory, as are the data to be manipulated by the
program. Because this design was first proposed by John von Neumann in 1945, the stored
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.2
■
3
A Brief History of the Computer
Memory
Control
unit
Arithmetic logic
unit (ALU)
Input
Figure 1.2
■
Central processing
unit (CPU)
Output
Source: Atmel Corporation, The Atmel AVR
Microcontroller
program architecture is also called von Neumann Architecture. The outline of this architecture
is shown in Figure 1.2. The von Neumann Architecture has a processing unit and a single storage structure that holds both instructions and data. The combination of control unit and the
arithmetic logic unit is referred to as the central processing unit (CPU) or simply the processor.
A deviation from the von Neumann Architecture is the Harvard Architecture, in which program and data are stored in different memories. The Harvard Architecture allows the computer
to access program and data simultaneously.
von Neumann architecture
The maximum number of bits that can be operated on by the ALU in one operation is
referred to as the word length of the processor. A processor may be called 8-bit, 16-bit, 32-bit,
or 64-bit because it can operate on 8-bit, 16-bit, 32-bit, or 64-bit operands in one operation,
respectively.
1.2.1 Mainframe Computers
The earliest digital computers are made of vacuum tubes and were housed in enormous,
room-sized metal boxes or frames. Due to their huge size, they are called mainframe computers.
Mainframe computers are expensive, and only large companies and organizations can afford
them. Later on, the term was used to distinguish high-end commercial computers from less
powerful ones. A mainframe computer has a lot of storage serving simultaneously many users
through terminal stations. The CPU time of the mainframe is divided into slots, with each time
slot assigned to one user.
The mainframe computer market is dominated by the IBM System 360–compatible product line. The IBM System 360 product line was introduced in 1965. It allowed the users to start
with a small system and later on upgrade by adding more memory and faster CPU when their
needs grew. The IBM System 360 was considered one of the most successful computers in history. In 1970, the IBM System 370 family was introduced as the replacement of System 360.
System 370 was backward software compatible to the System 360; that is, all the programs
written for System 360 can also be executed by the System 370. The System 390 was introduced to take the place of System 370. The latest IBM mainframe family (as of December 2011)
is the system z, which is also software compatible with the earliest System 360.
In addition to a fast CPU, a mainframe has the following features:
1. High reliability and security is provided by the redundant design.
2. There are extensive input/output facilities.
3. It has strict backward compatibility with older software; a newer generation of
machines can run software written for older machines. This feature is extremely
important for a computer family to be successful in the market.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4
Chapter 1
■
Introduction to Microcontroller
4. The high utilization rate supports massive throughput.
5. Repairs and hardware upgrades take place during normal operation.
1.2.2 Minicomputers
Minicomputers, called mini because they are smaller than mainframe computers, appeared
in the 1960s. The small size of these computers is made possible by the use of transistors, core
memory, and the integrated circuit. Minicomputers usually took up one or a few cabinets the
size of a large refrigerator. The first successful minicomputer was Digital Equipment Corporation’s (DEC) 12-bit PDP-8 introduced in 1964. Other minicomputer vendors include Prime,
Data General, Wang Laboratory, Apollo Computer, and HP.
The off-the-shelf 7400 series digital logic integrated circuits started appearing in minicomputers in the later 1960s. These chips provide many functions useful in a computer and greatly
simplify the design and implementation of minicomputers. Starting in the 1980s, many minicomputers used very large-scale integration (VLSI) circuits. Many minicomputers in this period
were 32-bit and hence were called superminicomputers.
Minicomputers have decent processing power and capacity and hence satisfy the computation needs of many midsize organizations. Like mainframe computers, minicomputers
supported multi-users.
DEC was the leading minicomputer manufacturer. At one time, DEC was the second largest computer company after IBM. The PDP-11 and VAX-11 families of minicomputers from
DEC were very popular in the 1970s and 1980s but started to decline in the late 1980s. Today,
all of the minicomputer manufacturers have disappeared from the computer market due to
the competition of personal computers (PC) and servers. A server is a computer that provides
database access, file access, printing, email, web browsing services and so on to users of other
computers in the network.
1.2.3 Microcomputers
A microcomputer is a computer that uses a microprocessor as its central processing unit.
The microprocessor is explained in a later section. The first batch of microcomputers appeared
in the 1970s. Some of them were sold as kits to be assembled by the user and came with as
little as 256 bytes of memory and no input/output (I/O) devices other than indicator lights and
switches. As microprocessors and semiconductor memory became less expensive in the mid1970s, microcomputers in turn grew faster and cheaper. This resulted in an explosion in their
popularity during the later 1970s and 1980s. Companies such as Cromemco, Altos, and others
have been very successful in producing systems designed for a resourceful end user or consulting firms to deliver business applications such as accounting, database management, and word
processing to small businesses. Some of these microcomputers are single-user systems, whereas
others are multi-user systems.
The Apple II computer, introduced in 1977 by Apple, has become one of the most successful computers in the world. Due to its popularity, many clones have appeared. Unlike earlier
microcomputers, the Apple II was designed to target individual users. For this reason, the Apple
II was called a personal computer instead of a microcomputer. The introduction of Apple II
attracted the attention of many software developers. The Macintosh (often called MAC) introduced in 1984 was the successor of Apple II. The MAC has gone through several generations
and used several different microprocessors as its CPU. Today’s MAC has several versions that
cover desktop, laptop, and all-in-one categories.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.2
■
A Brief History of the Computer
5
The first IBM PC was introduced in 1981 and used the 8-bit microprocessor 8088 from
Intel as its CPU. In order to bring the product to market quickly, the IBM PC was designed to
use off-the-shelf components and hence was easy to clone. The IBM PC was a big success after
its introduction. The success of the IBM PC was the impetus for many compatibles. All these
compatibles were sold at a lower price and had more features than the true IBM PC. Before long,
there were more PC compatibles sold than true IBM PCs. In general, these IBM PC compatibles
were also sold at a much lower price than the MAC from Apple. As a result, the PC market
was dominated by the IBM compatibles. Today, the word PC has been used to refer to the IBM
PC compatibles, and IBM has been forced out of the PC business (IBM sold its PC division to
Lenovo in December 2004).
1.2.4 Supercomputers
A supercomputer is a computer with its speed of computation at the frontline. Control
Data Corporation (CDC) introduced the first commercial supercomputers in the 1960s. These
supercomputers were designed by Seymour Cray and dominated the market into the 1970s,
until Cray left CDC to form his own company, Cray Research. He then took over the supercomputer market with his new designs, holding the top spot for five years (1985–1990). In the
1980s, a large number of smaller competitors entered the supercomputer market, but most of
them disappeared in the supercomputer market crash. Today, the U.S. supercomputer market is
dominated by traditional companies such as Cray, HP, and IBM. The fastest supercomputer in
the world has changed position several times in the past. This situation will remain the same
in the future.
Supercomputers are used for calculation-intensive tasks such as problems involving
weather forecasting, climate research, quantum mechanics physics, molecular modeling
(calculating the structures and properties of chemical compounds, biological macromolecules,
polymers, and crystals), physical simulations (such as simulations of airplanes in wind tunnels,
simulation of the detonation of nuclear weapons, and research into nuclear fusion), cryptanalysis, and many others. Major universities, military agencies, and scientific research laboratories
are the main users of supercomputers.
Some supercomputers were designed using custom CPUs in order to gain speed over
conventional computers through the use of innovative designs that allow them to perform
many tasks in parallel. They tend to be specialized for certain types of operations, usually numerical calculations, and perform poorly at more general tasks of calculation. The
memory system of supercomputers is carefully designed to ensure that the processor is kept
fed with data and instructions at all times. In fact, much of the performance difference
between slower computers and supercomputers is due to the memory bandwidth. The
I/O systems of supercomputers are also designed to support high bandwidth, with
latency being less of an issue because supercomputers are not used in business transaction
processing.
In the 1960s, the supercomputers only ran instructions much faster than other types of
computers. In the 1970s, most supercomputers were vector processors in which one instruction
could operate on multiple data items. The early and mid-1980s saw machines with a modest
number of vector processors working in parallel become the standard. Typically, the number
of processors ranged from four to sixteen. In the late 1980s and 1990s, attention turned from
vector processors to massively parallel processing systems. These supercomputers were made
of thousands of either off-the-shelf ordinary commercial microprocessors (those from Intel or
AMD) or custom microprocessors. These microprocessors are grouped into clusters and connected using custom interconnects.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6
Chapter 1
■
Introduction to Microcontroller
1.3 Computer Hardware Organization
A computer consists of hardware and software. The hardware of a computer contains
the processor, input devices, output devices, and memory. These parts are interconnected by
buses made of groups of conducting wires. Inside each of these parts are thousands to trillions of small electronic circuits that are turned on or off by means of an electronic switch.
Each circuit represents a bit of information so that when the circuit is on, it represents a 1,
and when off, it represents a 0 (in positive logic representation). The circuits are arranged
in logic gates so that one or more of the circuits may control the state of one or more of the
other circuits.
•
Processor. The processor is responsible for performing all of the computational
operations and coordinating the usage of a computer’s resources. A computer
system may consist of one or multiple processors. A processor may perform
general-purpose computations or special-purpose operations, such as graphics
rendering, printing, or network accessing.
•
Input devices. A computer is designed to execute programs that manipulate certain
data. Input devices are needed to enter the program to be executed and data to be
processed into the computer. There are a wide variety of input devices: keyboards,
keypads, scanners, bar code readers, sensors, and so on.
•
Output devices. Whether the user uses the computer to perform computations
or to find information from the Internet or a database, the end results must be
displayed or printed on paper so that the user can see them. There are many media
and devices that are used to display information: cathode-ray-tube (CRT) displays,
flat-panel liquid crystal displays (LCD), seven-segment displays, light-emitting
diode (LED), and so on.
•
Memory devices. Users write programs to tell the computer what to do with the
data at hand. Programs to be executed and data to be processed must be stored in
memory devices so that the processor can readily access them.
1.4 The Processor
The processor is also referred to as the central processing unit (CPU). A processor consists
of three major components: arithmetic logic unit (ALU), control unit, and registers. Early CPUs
were composed of many separate components but since the mid-1970s CPUs have typically
been constructed on a single integrated circuit (IC) called a microprocessor.
1.4.1 The Arithmetic Logic Unit (ALU)
The ALU is designed to perform two classes of operations: arithmetic and logic. The
set of arithmetic operations that a particular ALU supports may be limited to addition and
subtraction or might include multiplication or dividing, trigonometry functions (sine, cosine, etc.), and square roots. Some only operate on whole numbers (integers), whereas others
operate on real numbers represented in floating-point format. However, any computer that
performs even the simplest operations can be programmed to break down the more complex operations into simple steps that it can perform. Therefore, any computer can be programmed to perform any arithmetic operation—although it takes more time to do so if its
ALU does not directly support the operation. An ALU may also compare two numbers and
return Boolean truth values (true or false) depending on whether one is equal to, greater than,
or less than the other.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.4
■
7
The Processor
Logic operations involve Boolean logic: AND, OR, XOR, and NOT. These are useful both
for creating complicated conditional statements and processing Boolean logic. A computer may
contain multiple ALUs so that it can execute several instructions at the same time.
The complexity of the ALU varies from one computer to another. If the processor designer
wants to implement more operations directly in the hardware, then the ALU gets more
complicated. An ALU that implements addition, subtraction, AND, and OR operation is illustrated in Figure 1.2. The four-operation ALU operates in the following manner:
1. When opcode = 00, the adder selects the n-bit A as it’s X input, the n-bit B as its Y
input, and CIN as its carry input (ci), and generates SUM and Carry as its outputs.
MUX3 selects SUM to become Result, whereas Carry is connected to Cout directly.
For this opcode, the ALU performs the ADD operation.
2. When opcode = 01, the comparator output is 1, and the inversion of B input (change
0 to 1 and 1 to 0) is selected as the Y input. Then 1 is selected as the ci input to the
adder. The adder essentially adds the two’s complement of B to A, which is equivalent
to performing the SUB operation. Because opcode is 01 and SUM is connected to
both the 00 and 01 inputs, it is selected and sent to Result. For this opcode, the ALU
performs the SUB operation.
3. When opcode = 10, the MUX3 multiplexer selects the value connected to the 10 input
and sends it to Result. Therefore, the ALU performs the AND operation.
4. When opcode = 11, the MUX3 multiplexer selects the value connected to the 11 input
and sends it to Result. Therefore, the ALU performs the OR operation.
An ALU that performs more operations can be implemented by expanding the circuit
shown in Figure 1.3.
B
n
OpCode
CIN 1
0 1
MUX1
0
1
MUX2
Comparator
ci
Y
X
Adder
Inverters
n
01
SUM
00
Carry
Cout
AND
OR
■
n
10
n
MUX3
01
Figure 1.3
Opcode
00 = ADD
01 = SUB
10 = AND
11 = OR
2
n
Result
11
Source: Atmel Corporation, The Atmel AVR Microcontroller
A
n
An ALU that implements ADD, SUB, AND, and OR operations
1.4.2 Registers
The operands to be operated by instructions are stored in memory. However, memory is
usually slower than the CPU. To speed up the CPU operation, a small set of high-speed memory
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8
Chapter 1
■
Introduction to Microcontroller
circuits are included in the CPU to hold operands to be used by instructions. These high-speed
memory circuits are called registers. The number of registers varies greatly from processor to
processor. Some processors add a special register called an accumulator and include it as one of
the operands for most instructions. This approach can shorten the machine instructions. A processor that has one or more accumulators is called an accumulator machine. Other processors,
however, may include many general-purpose data registers (16 or 32) in the CPU and allow any
data register to be used as any operand of most instructions with two or three operands. This
provides great freedom to the compiler during the program translation process. A processor
designed with this approach is considered to be orthogonal.
1.4.3 The Control Unit
The computer is designed to execute machine instruction only. A machine instruction
is a combination of 0s and 1s that instructs the CPU what operation to perform and what
operands to work on. The control units reads and interprets (decodes) the program instructions, transforming them into a series of control signals which activate other parts of the
computer.
Because computer programs consist of many instructions (stored in memory), the processor
has to keep track of the location in memory of the next instruction to be executed, using a special register called a program counter (PC). Whenever the processor fetches an instruction from
memory, the program counter is incremented by the length of that instruction so that it points
to the next instruction. The fetched instruction is placed in a circuit called the instruction
register (IR), decoded, and then executed.
To make the instruction execution time predictable, a clock signal is used to synchronize
and set the pace of instruction execution. A clock signal is also needed to control the access to
registers in the processor and external memory. The clock frequencies of the 8-bit and 16-bit
microcontrollers range from a few MHz to over 100 MHz.
A program normally is not sequential. The execution order of machine instructions may
be changed due to the need to execute instructions on the basis of the value of a certain condition or to repeat a group of instructions. This is called program flow control. The decision to
change program flow is often based on certain conditions, for example, whether the previous
instruction caused carry out to be 1, whether the result of the previous operation is zero, or
whether the result of the previous operation is negative. These conditions are often collected in
a status register so that they can be used to make decisions. This type of program flow change
is implemented by a conditional branch instruction (also called a conditional jump instruction). There is a limit to the distance that the processor can branch (or jump) conditionally. The
branch distance (referred to as branch offset or jump offset) is from –128 to 127 bytes for most
8-bit microcontrollers, because they use 8 bits to specify the branch offset. In other situations,
the programmer wants to force the processor to execute instruction in any location within the
available memory space. A jump instruction is used for this purpose. The jump target may be
specified in 16 bits, 21 bits, 32 bits, or 64 bits, depending on the width of the program counter.
1.4.4 The Language Issue
Because computers are designed to execute machine instructions only, the earliest programmers were forced to write programs directly in machine language. It is easy to figure out that
writing programs in machine language is extremely difficult and unproductive. The first logical
improvement to this difficulty is to use a mnemonic name to represent each machine instruction and write programs directly using the mnemonic names. The mnemonic name of a machine
instruction is called an assembly instruction. The complete set of mnemonic names is called the
assembly language, and a program written in assembly language is called an assembly program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.5
■
9
The Microprocessor
Machine instruction
Machine instruction
Operation
0000 1100 0001 0000
add r1, r0
r1 ← r1 + r0
0010 0000 0010 0011
and r2, r3
r2 ← r2 AND r3
0010 1011 0000 0010
or r16, r18
r16 ← r16 OR r18
1001 0100 0000 1010
dec r0
r0 ← r0 – 1
0010 1100 0100 1010
mov r4, r10
r4 ← r10
0001 1010 1010 0000
sub r10, r16
r10 ← r10 – r16
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 1.1
■
A sample of AVR machine and assembly instructions
A sample of the AVR machine and assembly instructions is given in Table 1.1. Because the
computer cannot execute an assembly program directly, a translator is needed to translate the
assembly program into machine instructions. The translator of the assembly program is called
an assembler.
A program written in assembly language is not hard to understand. However, assembly
language is still at a very low level. When the problem at hand is complicated, writing
programs in assembly language could be overwhelming. High-level languages were invented
to overcome the shortcoming of the assembly language. Over the years, FORTRAN, COBOL, ALGOL, PASCAL, BASIC, C, C++, JAVA, and many other high-level languages were
invented. These high-level languages improve the programmers’ productivity dramatically.
A translator is needed to translate a program written in a high-level language into machine
instructions before the program can be executed on the computer. The translator of a highlevel language is called either a compiler or an interpreter. A compiler translates the program
into machines instructions, whereas an interpreter performs the operation specified by the
program directly. The programs written in assembly and high-level languages are also called
source code.
1.5 The Microprocessor
The earlier processors may be implemented in one or multiple printed circuit boards. With
the advent of integrated circuit technology, a complete processor can be implemented in one
integrated circuit (an integrated circuit often is called a chip). A microprocessor is a processor
implemented in a single integrated circuit.
In 1971, the first microprocessors (Intel 4004 and TI TMS 1000) were introduced. Both
the Intel 4004 and TI TMS 1000 are 4-bit microprocessors. In 1972, Intel introduced the 8008,
which is the first 8-bit microprocessor in the world. Several other 8-bit microprocessors were
introduced after the Intel 8008, including the Intel 8080, Zilog Z80, Motorola 6800, and so on.
Microprocessors quickly were used as the controller of many products. Because of their small
size (compared to discrete logic), programmability, ease-of-use, and low cost, microprocessors
were well received and quickly replaced discrete logic devices.
However, the microprocessor still has a few disadvantages:
1. It does not have on-chip memory. The designer has to add external memory chips and
other “glue” logic circuits, such as decoder and buffer chips, to provide program and
data storage.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10
Chapter 1
■
Introduction to Microcontroller
2. The microprocessor cannot drive the I/O devices directly because the
microprocessor may not have enough current to drive the I/O devices or because
of the incompatibility in voltage levels between the microprocessor and I/O
devices. This problem is solved by adding peripheral chips as a buffer between the
microcontroller and the I/O devices. The Intel 8255 parallel interface chip is one of
the earliest interface chips.
3. The microprocessor does not have peripheral functions, such as timers, analog-todigital (A/D) converters, communication interfaces, and so on. These functions must
be implemented using external chips.
Because of these limitations, a product designed with microprocessors cannot be made as
compact as might be desired. One of the design goals of microcontrollers is to eliminate these
problems.
1.6 The Microcontroller
A microcontroller (MCU) incorporates the processor and one or more of the following modules in one very large-scale integrated (VLSI) circuit:
•
•
•
•
•
•
•
•
•
Memory
Timer functions
Serial communication interfaces, such as USART, SPI, I2C, and CAN
Analog-to-digital (A/D) converter
Digital-to-analog (D/A) converter
Direct memory access (DMA) controller
Parallel I/O interface (equivalent to the function of the Intel 8255)
Memory-component interface circuitry
Software-debugging support hardware
Most of these functions or modules need more explanation. However, the discussion of
these functions is the subject of this textbook. Since their introduction, MCUs have been used
in almost every application that requires a certain amount of intelligence. They are used as
controllers for displays, printers, keyboards, modems, charge-card phones, palm-top computers,
and home appliances (such as refrigerators, washing machines, and microwave ovens). They
also are used to control the operations of engines and machines in factories. One of the most
important applications of MCUs is probably the automobile control. A contemporary luxurious car may use more than 100 MCUs. Today, most homes have one or more MCU-controlled
electronic appliance.
1.7 Embedded Systems
An embedded system is a special-purpose computer system designed to perform a dedicated
function. Unlike a general-purpose computer (such as a personal computer), an embedded system
performs one or a few predefined tasks (usually with very specific requirements) and often
includes task-specific hardware and mechanical parts not usually found in a general-purpose
computer. Because the system is dedicated to specific tasks, design engineers can optimize it,
reducing the size and cost of the product. Embedded systems are often mass-produced, benefiting from the economy of scale.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.8
■
Memory
11
Physically, embedded systems range from portable devices (such as digital watches and
MP3 players) to large stationary installations (like traffic lights, factory controllers, or the systems that control power plants). In terms of complexity, embedded systems run from simple
(with a single microcontroller chip) to very complex (with multiple units, peripherals, and
networks mounted inside a large chassis or enclosure).
Mobile phones or handheld computers share some elements with embedded systems (such
as the operating systems and microprocessors which power them) but are not truly embedded
systems themselves, because they tend to be more general purpose, allowing different applications to be loaded and peripherals to be connected to them.
1.7.1 Characteristics of Embedded Systems
Embedded systems have the following characteristics:
•
Embedded systems are designed to perform a specific task, rather than being
a general-purpose computer for multiple tasks. Some also have real-time
performance constraints that must be met for reasons such as safety and usability;
others may have low or no performance requirements, allowing the system
hardware to be simplified to reduce costs.
•
An embedded system is not always a separate block—very often it is physically
built into the device it is controlling.
•
The software written for embedded systems is called firmware and is stored in
read-only memory or flash memory chips rather than a disk drive. It often runs
with limited computer-hardware resources: small or no keyboard, small screen, and
little memory.
1.7.2 User Interfaces
Embedded systems range from having no interface at all—dedicated to only one task—to
full user interfaces similar to desktop operating systems in devices such as PDAs.
A simple, embedded system may use buttons for input and use LEDs or a small characteronly display for output. A simple menu system may be provided for users to interface with.
A more complex system may use a full graphical screen that has touch sensing or screenedge buttons to provide flexibility while minimizing space. The function of the buttons changes
with the screen.
Handheld systems often have a screen with a “joystick button” for a pointing device.
The rise of the World Wide Web has given embedded designers another option: providing a Web page interface over a network connection. This avoids the cost of a sophisticated
display yet provides complex input and display capabilities when needed on another computer.
Network routers take advantage of this ability.
1.8 Memory
There are three major memory technologies in use today: magnetic, optic, and semiconductor.
1.8.1 Magnetic Memory
The magnetic drum, magnetic tape, and magnetic hard disk are three major magnetic memory devices that have been invented. The magnetic drum has long been obsolete, and magnetic
tape is only used for data archival. Currently, only the magnetic hard disk still is being used
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
12
Chapter 1
■
Introduction to Microcontroller
in almost every PC, workstation server, mainframe computer, and supercomputer. Hard-drive
vendors are still vigorously improving the hard disk density. It doesn’t seem possible that any
memory technology can totally replace the hard disk yet.
1.8.2 Optical Memory
There are two major optical memory technologies in use today: compact disc (CD) and
digital video disc (DVD). The CD was introduced to the market in 1982 and has several
variations. The most popular single-sided CD has a 12 cm diameter and holds about 700 MB
of data. The CD-R version of the compact disc can be recorded once, whereas the CD-RW
disc can be re-recorded many times. In 1993, two DVD storage formats were being developed. At the end of 1995, a unified DVD format was finalized. A single-sided DVD with
12 cm diameter holds 4.7 GB of data. There are several versions of DVD—among them, the
DVD-R that can be recorded only once, and the DVD-RW, which the end user can re-record
many times. In 2006, a new format called the Blu-ray Disc, designed by Sony, Philips, and
Panasonic, was released as the successor to DVD. A dual layer Blu-ray Disc stores 50 GB of
information.
1.8.3 Semiconductor Memory
Semiconductor memory is the dominant memory technology used in embedded systems.
Memory technologies are classified according to several criteria. Two common criteria are
volatility and read-writability. Based on volatility, semiconductor memories are divided into
volatile and nonvolatile memories. Based on read-writability, semiconductor memories are
divided into random access memory (RAM) and read-only memory (ROM).
1.8.4 Nonvolatile and Volatile Memory
A memory device is nonvolatile if it does not lose the information stored in it even without
the presence of power. If a memory device cannot retain its stored information in the absence of
power, then it is volatile.
1.8.5 Random Access Memory (RAM)
RAM allows the CPU to read from or write into any location within the chip for roughly
the same amount of time. RAM can be volatile or nonvolatile. RAM also is called read–write
memory, because it allows the processor to read from and write into it. As long as the power is
on, the processor can write data into a location in the RAM chip and later read back the same
contents. Reading memory is nondestructive. Writing memory is destructive. When the processor writes data to memory, the old data is written over and destroyed.
There are four types of commercially available RAM technology: dynamic RAM (DRAM),
static RAM (SRAM), magnetoresistive RAM (MRAM), and ferroelectric RAM (FRAM).
DRAMs are memory devices that require a periodic refresh of the stored information.
Refresh is the process of restoring binary data stored in a particular memory location. The
DRAM uses one transistor and one capacitor to store 1 bit of information. The information
is stored in the capacitor in the form of electric charges. The charges stored in the capacitor
leaks away over time, so a periodic refresh operation is needed to maintain the contents in
the DRAM. The time interval over which each memory location of a DRAM chip must be
refreshed at least once in order to maintain its contents is called its refresh period. Refresh
periods typically range from a few milliseconds to over a hundred milliseconds for today’s highdensity DRAMs.
SRAMs are designed to store binary information without needing periodic refreshes and require
the use of more complicated circuitry for each bit. Four to six transistors are needed to store 1 bit of
information. As long as power is stable, the information stored in the SRAM will not be degraded.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.8
■
Memory
13
MRAMs were first developed by IBM. Several other companies also were involved in the
research, development, and marketing of this technology. MRAMs use a magnetic moment
to store data. An MRAM chip combines a magnetic device with standard silicon-based microelectronics to achieve the combined attributes of nonvolatility, high-speed operation, and
unlimited read and write endurance. The first MRAM device from Freescale is the 4 Mbit
MR2A16A. This device is a parallel memory (8 or 16 bits are accessed in one operation) and
has a 35 ns access time (reported in 2006). In 2008, Freescale joined with several venture capital companies to form a company called Everspin to research and produce the MRAM product. The MRAM technology has good potential. Research teams from IBM and Germany have
demonstrated the MRAM devices with a 1 ns access time. To realize this access time would
require the most advanced semiconductor technology to be used (possibly 60 nm process
or less).
FRAMs use the property of ferroelectric crystal to store data bits. Much of the present
FRAM technology was developed by Ramtron International. The FRAM technology has already
achieved high maturity. Both the serial and parallel versions of FRAM chips are available. Ramtron even incorporates FRAM in some of its 8051 microcontroller products. At the time of this
writing, the fastest access time of FRAM from Ramtron is 55 ns (reported in 2009). However,
the access time of FRAM may improve over time in the future.
RAMs are mainly used to store dynamic programs or data. A computer user often wants to
run different programs on the same computer, and these programs usually operate on different
sets of data. The programs and data must therefore be loaded into RAMs from the hard disk or
other secondary storage, and for this reason they are called dynamic.
1.8.6 Read-Only Memory (ROM)
The ROM is nonvolatile. When power is removed from the ROM and then reapplied, the
original data is still there. As its name implies, ROM data only can be read. If the processor attempts to write data to a ROM location, the ROM does not accept the data, and the
data in the addressed ROM memory location are not changed. However, this statement is
not completely true. For some ROM technologies (EEPROM and flash memory), the user program can still write data into the memory by following a special procedure prescribed by the
manufacturer.
The mask-programmed read-only memory (MROM) is a type of ROM that is programmed
when it is manufactured. The semiconductor manufacturer places binary data in the memory
according to the request of the customer. To be cost-effective, many thousands of MROM memory units—each consisting of a copy of the same data (or program)—must be sold. MROM is
the major memory technology used to hold microcontroller application programs and constant
data. Most people simply refer to MROM as ROM. The design of MROM prevents it from being
written into.
The programmable read-only memory (PROM) was invented in 1956 by Wen Tsing Chow.
It is a form of memory where the setting of each bit is locked by a fuse or antifuse. The memory can be programmed just once after manufacturing by “blowing” the fuses (using a PROM
blower), which is an irreversible process. Blowing a fuse opens a connection, whereas blowing
an antifuse closes a connection (hence the name). Programming is done by applying high-voltage
pulses that are not encountered during normal operation (typically 12 to 21 volts). Fused-based
PROM technology is no longer used today.
The erasable programmable read-only memory (EPROM) was invented by Dov Frohman
in 1971. It is an array of floating-gate transistors individually programmed by an electronic
device that supplies higher voltages than those normally used in electronic circuits. Programming is achieved via hot carrier injection onto the floating gate. Once programmed, an EPROM
can be erased only by exposing it to strong ultraviolet (UV) light. That UV light usually has a
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
14
Chapter 1
■
Introduction to Microcontroller
wavelength of 235 nm for optimum erasure time. EPROMs are recognizable by the transparent
fuse-quartz window in the top of the package, through which the silicon chip can be seen and
which permits UV light to go through during erasing.
As the quartz window is expensive to make, one-time programmable (OTP) EPROM chips
were introduced; the only difference is that the EPROM chip is packed in an opaque package,
so it cannot be erased after programming. OTP versions are manufactured for both EPROMs
themselves and EPROM-based microcontrollers. However, the OTP EPROM (whether separate
or part of a larger chip) is being increasingly replaced by EEPROM for small amounts where the
cell cost isn’t too important and flash memory for larger amounts.
A programmed EPROM chip retains its data for about 10 to 20 years and can be read
an unlimited number of times. The erasing window must be kept covered with a foil label
to prevent accidental erasure by any type of light in the UV spectrum. Old PC basic input/
output system (BIOS) chips were often EPROMs, and the erasing window often was covered with a label containing the BIOS publisher’s name, the BIOS revision, and a copyright
notice.
The electrically erasable programmable read-only memory (EEPROM) was developed in
1983 by George Perlegos at Intel. It was built on earlier EPROM technology but used a thingate oxide layer so that the chip could erase its own bits without requiring a UV source. The
EEPROM is programmed and erased using the process called field emission (more commonly
known in industry as Fowler-Nordheim tunneling). The EEPROM allows the user to selectively erase a single location, a row, or the whole chip. This feature requires a complicated
programming circuitry. Because of this, the EEPROM cannot achieve the density of the EPROM
technology.
The flash memory was invented by Fujio Masuoka while he was working for Toshiba in
1984. It incorporates the advantages and avoids the drawbacks of the EPROM and EEPROM
technologies and can be erased and reprogrammed in the system without using a dedicated
programmer. The flash memory achieves the density of the EPROM, but it does not require a
window for erasure. Like the EEPROM, the flash memory can be programmed and erased electrically. However, it does not allow individual locations to be erased—the user can only erase
a block or the whole chip. Today, the BIOS programs of many high performance PCs are stored
in flash memory. Most microcontrollers introduced today use on-chip flash memory as their
program memory.
Flash memory chips also have been used in flash disk memory (also called solid state drive
(SSD)), personal digital assistant (PDA), digital cameras, cell phones, and so on. At the time of
this writing, more and more computer vendors provide SSD as a replacement for the hard drive.
With the widespread use of the SSD, its price will come down quickly.
1.9 Memory-System Operation
A simplified memory-system block diagram is shown in Figure 1.4. A memory system may
consist of one or multiple memory chips. Both memory chips and memory systems are organized as an array of memory locations. A memory location may hold any number of bits (most
common numbers are 4 bits, 8 bits, 16 bits, 32 bits, and 64 bits). The memory organization of a
memory chip or a memory system is often indicated by m × n, where m specifies the number of
memory locations in the memory chip or memory system and n specifies the number of bits in
each location. Every memory location has two components: contents and address.
The memory chip or system only can be accessed (read or write) one location at a time.
This is enforced by implementing a decoder on the memory chip to select one, and only one,
location to be accessed. There are two types of memory accesses: read and write.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
15
Memory-System Operation
Microprocessor
Address
RD
OE
WR
WE
Data
Figure 1.4
■
Memory system
Source: Atmel Corporation, The Atmel AVR
Microcontroller
1.9
Block diagram of a simplified memory system
1.9.1 Read Operation
Whenever the processor wants to read a memory, it sends out the address of the location
it intends to read. Because the memory access can be a read or a write, the processor needs
to use a control signal to inform the memory the type of access. In Figure 1.4, the RD signal from the processor indicates a read access, whereas the WR signal indicates a write
operation. The memory chip also has control signals to control the read or write operation.
The OE signal in Figure 1.4 means output enable and is connected to the RD signal from the
processor, whereas the WE signal means write enable and is connected to the WR signal from
the processor. For digital systems, there are three logic states for each signal: high, low, and
high-impedance (no current flows). When the OE input to the memory chip is low, the data pins
are in high-impedance state.
The processor uses a set of signal (referred to as address signals) to specify a memory location to access. The number of address signals needed for selecting a memory location is log2m,
where m is the number of memory locations in the memory. The set of conductor wires that
carry address signals is referred to as an address bus.
The number of conductor wires that carry the data must be equal to the number of bits
in each memory location. The set of conductors that carry the data to be accessed is called a
data bus.
To read a memory location, the processor sends out the address of the memory location to
be accessed and applies a logic 1 (high voltage) to the RD signal and a logic 0 to the WR signal
(this specifies a read operation). In response, the memory system decodes the address input and
enables the specified memory location to send out its contents to the data bus, to be read by the
processor.
1.9.2 Write Operation
To write a value to a location of the memory system in Figure 1.4, the processor places the
data to be written on the data bus, places the address of the memory location on the address
bus, applies a logic 1 (high voltage) to the WR signal, and a logic 0 to the RD signal (this specifies a write operation). In response, the memory system uses its address decoder to select a location and writes the value on the data bus to that location.
The actual memory system design and the signals involved may be different from those in
Figure 1.4, but the concept would be the same. The semiconductor vendors may use RD instead
of RD and WR instead of WR to refer to read and write signals. These types of signals are active
low (i.e., when they are low they are considered to be at logic 1).
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
16
Chapter 1
■
Introduction to Microcontroller
1.10 Program Execution
In order to allow the computer to execute a program immediately after the power is turned
on, part of the program must be stored in nonvolatile memory. All computers place the startup
program in the nonvolatile memory, which performs the system initialization. After the system initialization is completed, it loads additional programs from secondary storage, such
as hard disk or optical storage into the semiconductor memory (often called main memory),
for execution. Mainframe computers, minicomputers, and personal computers follow this
approach. After power is turned on, the processor starts to execute the program from the
basic input/output system (BIOS), which performs the system initialization. After the system
initialization is completed, the processor loads additional programs, such as the Windows operating system, into the main memory for execution. Other computers (including most embedded
systems) place all of their programs in the nonvolatile memory. After power-up, the processor
starts to execute programs from the nonvolatile memory.
The following sections deal with several important issues related to program execution.
1.10.1 The Program Counter Circuit
D
Q
clk
Set
Reset
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The program counter consists of flip-flops and other additional logic gates. There are several types of flip-flops in use. Among them, the D-type flip-flop is the most popular one. The
block diagram of a D-type flip-flop with set and reset capabilities is shown in Figure 1.5.
Figure 1.5 ■ Block diagram of
a D flip-flop with set and reset
In Figure 1.5,
•
Depending on the design, the D value may be transferred to Q on either the rising
or the falling edge (but not both edges) of the clk input.
•
•
The clk signal is the clock input of the D flip-flop.
•
The set and reset inputs are active low (low voltage means logic 1) and cannot be
low at the same time. When set is low, the Q signal is forced to 1. When reset is
low, the Q signal is forced to 0.
The Q signal of all the flip-flops of the program counter determines the address of
the next instruction to be executed.
As described in Section 1.4.3, a microprocessor or microcontroller has instructions to
change the program flow. The design of the program counter circuit must support the possible
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.10
■
17
Program Execution
program counter changes required by the instruction set. Figure 1.6 shows the block diagram of a possible program counter of an 8-bit microcontroller that allows the program
counter to be
Forced to 0
Incremented by 1
Incremented (or decremented) by a field in the IR register
Loaded with a jump target address
1
Branch
Branch
offset
0 1
MUX
16
Adder
To program
memory
Qs
16
16
1 0
MUX
Jump
target
clk
16
Ds
Reset
clk
Power
On
Jump
Source: Atmel Corporation, The Atmel AVR Microcontroller
•
•
•
•
Figure 1.6 ■ A simplified block diagram of the program
counter (PC) of an 8-bit microcontroller
For the program counter circuit shown in Figure 1.6,
•
Whenever power is turned on to the microcontroller, the program counter is forced
to 0, and the instruction fetch starts from address 0.
•
If the instruction being executed is a conditional branch instruction and the
branch condition is true, the Branch signal is 1 and the sum of the current PC
and branch offset is loaded into the PC, and instruction execution continues
from there.
•
If the instruction being executed is a jump instruction, then the value of the jump
target will be loaded into PC.
•
If the instruction being executed is not a program flow-control instruction, then
the PC is incremented by 1 after each instruction byte is fetched.
Other microprocessors or microcontrollers may have different program flow-control
schemes and may fetch more instruction bytes in one fetch; the program counter shown in
Figure 1.6 must be modified accordingly.
1.10.2 Starting Program Execution
Because the program counter holds the address of the next instruction to be fetched, the
value of the program counter must be known when the power is turned on. One approach is to
force the PC to a fixed value when the power is turned on. The circuit in Figure 1.6 forces the
PC to 0 whenever the power is turned on. Many 8-bit microcontrollers (including Atmel AVR)
use this approach because it is easy to implement.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
18
Chapter 1
■
Introduction to Microcontroller
Another approach is to fetch the program starting address from a fixed (known) memory
location whenever the power is turned on. The Freescale microcontrollers use this approach. The
16-bit HCS12 microcontroller from Freescale fetches the program starting address from memory
locations at 0×FFFE and 0×FFFF into the PC and then starts program execution from there.
Another way to restart program execution is to apply a reset signal to the processor. All
microprocessors and microcontrollers have a reset pin that allows the user to force the processor to start from scratch. The effect of the reset signal is identical to turning on the power.
1.10.3 Instruction Execution Process
After power on or a reset, the processor starts to fetch and execute instructions one after
another. The procedure for executing each instruction is as follows:
1. Read the next instruction from the memory location indicated by the program
counter.
2. Decode the fetched instruction into a set of commands or signals for each of the
components of the processor.
3. Increment the program counter so it points to the next instruction.
4. Read whatever data the instruction requires from memory (or input device).
The location of this required data is typically stored within the instruction code.
5. Provide the necessary data to an ALU or register.
6. If the instruction requires an ALU or specialized hardware to complete, the processor
instructs the hardware to perform the requested operation.
7. Write the result from the ALU back to a memory location or to a register or perhaps
an output device.
8. Jump back to step 1.
1.11 Summary
The invention of the microprocessor in 1968 resulted in a revolution in electronic history.
The first microprocessor, the Intel 4004, incorporated a simplified CPU into an integrated circuit. Following the introduction of 4004, Intel introduced the 8-bit 8008, 8080, and 8085 in the
following three years. The 8085 was a big success because of its programmability. Through this
programmability, many products could be designed and constructed. Other companies joined in
the design and manufacturing of microprocessors. Zilog, Motorola, and Rockwell are among the
more successful of these companies.
A microprocessor is limited in the fact that it does not have on-chip memory and peripheral
functions. The microcontroller incorporates the CPU, some memory, and several peripheral
functions onto the same chip. This approach has had the following impacts:
•
•
•
External memory is no longer needed for many applications.
I/O interfacing is greatly simplified.
System design time is dramatically reduced.
There are 8-bit, 16-bit, and 32-bit microcontrollers. Renesas/NEC, Microchip, ST Microelectronics, Freescale, and Atmel are the top five vendors of 8-bit microcontrollers in the world
at the time of this writing. The PIC16 and PIC18 of Microchip, the R8C from Renesas, the AVR
of Atmel, the 8051 variants from more than 50 vendors, and the S08 of Freescale are among the
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
1.11
■
Summary
19
most popular 8-bit microcontrollers in the market. Eight-bit microcontrollers are mainly used
in consumer electronics and automotive applications.
The MSP430 from TI, the M16C from Renesas, the C166 and XC166 from Infineon,
the HCS12 from Freescale, and the PIC24 from Microchip are the most popular 16-bit
microcontrollers in the market. The MSP430 is famous for its low-power design. The M16C,
C166, and XC166 have been in the market for a very long time. The HCS12 of Freescale is most
successful in the automotive market and is widely taught in universities in the United States.
The PIC24 is a latecomer but is growing fast.
The V850 from Renesas, the Coldfire from Freescale, the power PC from IBM and Freescale,
and the ARM microcontrollers from many vendors are the most successful 32-bit microcontrollers in the world. The V850 is dominating in the automotive and overall 32-bit markets.
The Coldfire- and power PC–based microcontrollers are also extremely popular in automotive
applications. The ARM microcontrollers have been very successful in mobile applications.
A microcontroller is not designed to build a desktop computer. Instead, it is used as the
controller of many products. End users of these products do not care what microcontrollers are
used in their appliances; they only care about the functionality of the product. A product that
uses a certain microcontroller as its controller and has this characteristic is called an embedded
system. Automobiles, cable modems, HDTVs, and home security systems are well-known
embedded systems.
Over the last 20 years, we have clearly seen that a microcontroller must incorporate some
or all of the following peripheral functions in order to be useful:
•
Timer modules that incorporate input capture, output compare, real-time interrupt,
and counting capability
•
•
•
•
•
•
•
•
Pulse-width modulation (PWM) functions for easy waveform generation
Analog-to-digital converters for data acquisition
Digital-to-analog converters for waveform generation
Temperature sensors
Direct memory access controllers
Parallel I/O interfaces
Serial I/O interfaces, such as UART, SPI, I2C, USB, and CAN
Memory component interface circuitry
The AVR from Atmel incorporates most of these peripheral modules and the CPU in one
VLSI chip.
Memory is where software programs and data are stored. Semiconductor memory chips
are classified into two major categories: random access memory and read-only memory. RAM
technology includes DRAM, FRAM, MRAM, and SRAM. MROM, PROM, EPROM, EEPROM,
and flash memory are read-only memories. Both the FRAM and MRAM have the advantages
available in flash memory and SRAM and also have good performance. They could be used to
replace the flash memory and SRAM in many applications, but that didn’t happen. Cost is the
main reason. However, the cost of memory chips is determined by the volume of production.
The true reason that FRAM and MRAM did not take off is because the semiconductor vendors
(such as Samsung and Micron) are not willing to allocate fabrication capacity to these two technologies. Therefore, there is no opportunity to lower the cost of MRAM and FRAM and thus
increase their popularity in the market.
Programs are known as software. A program is a set of instructions that the computer
hardware executes. In the past, system designers mainly used assembly language to write
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
20
Chapter 1
■
Introduction to Microcontroller
microcontroller application software. The nature of assembly language forces an assembly
programmer to work on the program logic at a relatively low level. This hampers programming
productivity. In the last 15 years, most people have turned to high-level language to improve
their programming productivity. C is the most widely used language for embedded system
programming.
Although system designers use assembly or high-level language to write their programs,
the microcontroller only executes machine instructions. Programs written in assembly or
high-level language must be translated into machine instructions before they can be executed.
The program that performs the translation work is called an assembler or compiler, depending
on the language to be translated.
1.12 Exercises
E1.1 What is a processor?
E1.2 What is a microprocessor? What is a microcontroller?
E1.3 What makes a microcontroller different from a microprocessor?
E1.4 How many bits can the AVR CPU manipulate in one operation?
E1.5 Modify the ALU circuit in Figure 1.3 so that it can also perform shift right, shift left, and
NOT operations on operand A, in addition to the four operations in Figure 1.3.
E1.6 Suppose a microcontroller has a 16-bit branch offset. What is its range of branch offset?
E1.7 Why must every computer have some amount of nonvolatile memory?
E1.8 Why must every computer have some amount of volatile memory?
E1.9 What is the source code? What is the machine code?
E1.10 How does a microprocessor or microcontroller start program execution after a reset or
power on?
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2
Introduction to the AVR
Microcontroller
2.1 Objectives
After completing this chapter, you will be able to
• Understand the AVR memory space
configuration.
• Describe the AVR CPU registers.
• Use X, Y, and Z registers together with
RAMPX, RAMPY, and RAMPZ to access data
and program memory space above 64 kB.
• Use appropriate addressing modes to specify
operands for instructions.
• Use appropriate load instructions to access
data memory and program memory locations.
• Perform the add operation on appropriate
operands.
• Perform the subtract operation on appropriate
operands.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
22
Chapter 2
■
Introduction to the AVR Microcontroller
2.2 An Overview of the AVR Microcontroller Family
The 8-bit Atmel AVR was introduced in 1996. It is believed that the AVR basic architecture
was conceived and developed by two students, Alf-Egil and Vegard, at the Norwegian Institute
of Technology.
The AVR adopts a modified Harvard architecture, with program and data stored in separate
physical memory address space, but has the ability to read data items from program memory,
using special instructions.
The AVR family of microcontrollers is divided into four subgroups:
•
•
•
•
TinyAVR
Mega AVR
XMega AVR
Application-specific AVR
The difference between these devices lies in the available features. The AVR architecture implements 142 instructions, but not all the devices implement all of the 142 instructions. The tinyAVR devices have less memory (1–8 kB), support fewer instructions (between
54 and 120 instructions, depending on the device), implement less peripheral functions, and
are housed in a very small package (6–32 pins). The highest clock frequency for the tinyAVR
is 20 MHz.
The Mega devices have from 4 to 256 kB of program flash memory, implement extensive
peripheral functions, support most of the AVR instructions (130–135), and are housed in a
package with from 28 up to 100 pins. The highest clock frequency for the Mega AVR is 20 MHz.
The XMega devices have from 32 to 384 kB of memory, implement all 142 instructions
and an extensive set of peripheral functions (more than Mega AVR), and are housed in a larger
package. The XMega devices may run at a clock with a frequency as high as 32 MHz. XMega
devices may be housed in a package with from 44 up to 100 pins.
Application-specific AVR are Mega AVR devices with special features not found on the
other members of the AVR family, such as LCD controller, USB controller, advanced PWM,
CAN controller, and so on.
This book focuses on the Mega and XMega AVR devices only.
2.3 The AVR Memory Space
The program and data are stored in separate memory spaces. Some Mega and XMega devices
also have EEPROM memory. For the Mega devices, EEPROM is separate from the data memory.
For the XMega devices, EEPROM and data memory share the same memory space.
The Mega AVR implements only internal program memory. As shown in Figure 1.6, the
on-chip flash memory is divided into two sections: application program section and boot
program section. An AVR instruction is either 16 bit or 32 bit. The AVR program memory is
organized as an m × 16 matrix; that is, every location has 16 bits. The flash program memory of the XMega is also divided into two sections similar to those shown in Figure 2.1.
A third section inside the Application section is referred to as the application table section,
which has separate lock bits for storage of write or read/write protection. The application
table section is used for storing nonvolatile data or application software. The flash program
memory map for the XMega384A1 is shown in Figure 2.2. Addresses in Figure 2.1 and 2.2 are
hexadecimal numbers.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.3
■
23
The AVR Memory Space
Application flash
section
Boot flash section
Figure 2.1
■
Mega AVR program flash memory map
0x00000
Application
section (384 kB)
0x2EFFF
0x2F000
0x2FFFF
0x30000
Application table
section (8 kB)
Boot section
(8 kB)
0x30FFF
Figure 2.2
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Upto 0x1FFFF
Source: Atmel Corporation,
The Atmel AVR Microcontroller
0x00000
XMega384A1 program memory map
The Mega AVR devices have a 64 kB data memory space that accommodates CPU registers,
I/O registers, and data memory (on-chip and external). The size of the on-chip data memory
varies with the device. For example, the data memory map of the Mega2560 is shown in
Figure 2.3. The XMega devices support a 16 MB data memory space. The on-chip EEPROM
also resides in this memory space. The data memory map of the XMega384A1 is shown in
Figure 2.4.
64 I/O Registers
0x60
0x1FF
0x200
0x21FF
0x2200
416 External I/O
registers
Internal SRAM
(8 kB)
External SRAM
(56832 bytes)
0xFFFF
Figure 2.3
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
32 Registers
Mega2560 data memory map
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 2
■
Introduction to the AVR Microcontroller
0x000000
I/O Registers
(4 kB)
0x001000
EEPROM
(4 kB)
0x002000
Internal SRAM
(32 kB)
0x00A000
External
memory
(0 to 16 MB)
0xFFFFFF
Figure 2.4
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
24
XMega384A1 data memory map
2.4 The AVR CPU Register
The AVR CPU has a register file of thirty-two 8-bit general-purpose registers with single
clock cycle access time. This allows single-cycle ALU operation. In a typical ALU cycle, the
operation is performed on two register operands, and the result is stored back in the register file.
Six of the 32 registers can form 16-bit address pointers (referred to as X, Y, and Z pointers) for
addressing data memory. The Z register can also be used as an address pointer to read from and/
or write to the flash program memory, signature rows, fuses, and lock bits. Each CPU register of
the Mega AVR devices is assigned a memory address, as shown in Figure 2.5.
Figure 2.5
0x00
R1
0x01
R2
0x02
R13
0x0D
R14
0x0E
R15
0x0F
R16
0x10
R17
0x11
R26
0x1A
X-register low byte (XL)
R27
0x1B
X-register high byte (XH)
R28
0x1C
Y-register low byte (YL)
R29
0x1D
Y-register high byte (YH)
R30
0x1E
Z-register low byte (ZL)
R31
0x1F
Z-register high byte (ZH)
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Addr.
R0
AVR CPU general purpose registers
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.4
■
25
The AVR CPU Register
To access program memory or data memory above 64 kB, the address pointer must be longer than 16 bits. This is done by concatenating one register to one of the X, Y, or Z registers.
This register (RAMPX, RAMPY, or RAMPZ) then holds the most significant byte (MSB) in a
24-bit address or address pointer. These registers are available only on devices with external bus
interface and/or more than 64 kB of program or data memory space. For these devices, only the
number of bits required to address the whole program and data memory space in the device is
implemented in the registers.
2.4.1 The RAMPX, RAMPY, and RAMPZ Registers
The RAMPX, RAMPY, and RAMPZ registers are concatenated with the X, Y, and Z
pointers, respectively, to enable indirect addressing of the whole data memory space above
64 kB and up to 16 MB. The combinations of these registers with X, Y, and Z registers are
shown in Figure 2.6.
16 15
8 7
RAMPX
23
XL
16 15
8 7
RAMPY
23
YL
16 15
■
0
YH
8 7
RAMPZ
Figure 2.6
0
XH
0
ZH
ZL
Source: Atmel Corporation, The Atmel AVR
Microcontroller
23
The combined RAMPX 1 X, RAMPY 1 Y, and TAMPZ 1 Z registers
When reading (extended load program memory [ELPM]) and writing (store program memory
[SPM]) program memory locations above the first 128 kB of the program memory, RAMPZ is
concatenated with the Z register to form the 24-bit address. The LPM instruction is not affected
by the RAMPZ setting.
2.4.2 The Extended Indirect Register (EIND)
The EIND register is added to support extended indirect subroutine call and indirect
jump in devices with program memory larger than 128 kB. To make extended subroutine
calls and indirect jump in these devices, the user must use the EICALL and EIJMP instruction, respectively. The EIND register is concatenated with the 16-bit ZH:ZL register, as
shown in Figure 2.7.
23
16 15
EIND
8 7
ZH
0
ZL
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 2.7
■
The Z-pointer used by EICALL and EIJMP instructions
2.4.3 The RAMPD Register
The XMega AVR devices provide this register to support direct addressing of the whole data
memory space above 64 kB. This register is concatenated with the k operand in the instruction,
as shown in Figure 2.8. The content of this register and the k field in the instruction are used as
the direct address to access data memory.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
26
Chapter 2
■
Introduction to the AVR Microcontroller
23
16 15
0
RAMPD
k
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Figure 2.8
The combined RAMPD 1 K register
2.4.4 The Status Register (SREG)
The SREG register contains information about the result of the most recently executed
arithmetic or logic instruction. The contents of the SREG register are shown in Figure 2.9.
7
6
5
4
3
2
1
0
I
T
H
S
V
N
Z
C
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 2.9
■
The SREG register
I: THE GLOBAL INTERRUPT ENABLE FLAG
This flag is the global interrupt enable flag and must be set to 1 in order for each individual
interrupt source to be enabled. If this flag is cleared to 0, all of the interrupt sources would be
disabled. This flag is set and cleared by the application with the SEI (set global interrupt flag)
and CLI (clear global interrupt flag) instructions. Interrupt handling is discussed in Chapter 9.
T: BIT COPY STORAGE
This flag is used by the bit load (BLD) and bit store (BST) instruction as the source or
destination operand bit. A bit from a register in the register file can be copied into T by the BST
instruction, and the BLD instruction can copy the T bit into a bit of a register in the register file.
H: HALF CARRY FLAG
The half carry flag (H) indicates a half carry in some arithmetic operation. Half carry is
useful in BCD (binary-coded decimal) arithmetic.
S: SIGN
BIT,
S = N { V
This flag indicates the sign of the previous operation result and is always the exclusive OR
of the N and V flags.
V: TWO’S COMPLEMENT OVERFLOW FLAG
This flag indicates whether an overflow occurs in the previous operation.
N : N E G AT I V E F L A G
This flag indicates whether the previous arithmetic or logical operation result is negative.
Z: ZERO FLAG
This flag indicates whether the previous arithmetic or logical operation result is zero.
C: CARRY FLAG
This flag indicates whether a carry is generated in the previous arithmetic or logical
operation.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.6
■
AVR Addressing Modes
27
2.5 The AVR Instruction Set
An AVR instruction can be divided into two parts: opcode and operand fields. The opcode
field specifies the operation to be performed, whereas the operand field specifies the operands to be operated on. Some instructions are 16 bit, whereas others are 32 bit. The AVR
instruction set consists of 142 instructions. These instructions are divided into the following
categories:
1. Arithmetic: Instructions in this category are used to perform addition, subtraction,
multiplication, increment, and decrement operations.
2. Control flow: Instructions in this category may perform jump, conditional branch,
conditional skip, compare, subroutine call, and return from subroutine operations.
These instructions are indispensible for implementing program loops and making
decisions.
3. Data transfer: Instructions in this category allow us to copy data from register
to register, from data memory to a register, from a register to data memory, from
program memory to a register, from a register to program memory, from input device
to a register, and from a register to an output device.
4. Bit field manipulation: Instructions in this category allow the user to shift or rotate
a register to the right, shift or rotate a register to the left, set one or a few bits in a
register to 1, clear one or a few bits in a register to 0 and so on.
5. Logical: Instructions in this category allow the user to perform logical operations such
as AND, OR, XOR, and NOT operations, and so on.
6. Miscellaneous: Instructions in this category include BREAK, NOP, SLEEP, and WDR.
An AVR instruction may have none, one, two, or three operands. When an instruction has
three operands, the third operand would be the carry flag. When an instruction has two operands, the first operand would be used as a source and the destination operand. For example, in
the instruction
add
r2, r3
Register r2 is both a source operand and the destination operand of the add instruction.
The operations performed by these operations are explained in appropriate chapters.
A summary of the AVR instruction set is given in Appendix A.
2.6 AVR Addressing Modes
Addressing modes are used to specify instruction operands. The explanation of addressing
modes cannot be done without some knowledge of AVR instructions and vice versa. To explain
addressing modes, appropriate instructions are also introduced.
To facilitate explanation, we use [] to refer to the contents of a register or a memory location. For example, [r0] and [0x1000] refer to the contents of register r0 and data memory location at 0x1000, respectively. We use the notation mem(addr) to refer to a data memory location
with the address addr. For example, the notation mem(0x1000) refers to data memory location
at 0x1000. We use the notation pmem(addr) to refer to a program memory location with the
address addr.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
28
Chapter 2
■
Introduction to the AVR Microcontroller
2.6.1 Register Direct Mode
This mode uses five bits to specify a register to be worked on. The programmer specifies the
names of the registers directly as the operands of the instruction, and the assembler translates
the register name into the corresponding 5-bit code of the register. This is the most common
addressing mode because every arithmetic or logic instruction specifies either one or two registers as operands. For example, the instruction
add
r0, r1
; r0 d [r0] 1 [r1]
adds the contents of registers r0 and r1 together and places the sum in r0. Both r0 and r1 are
specified using 5 bits.
The instruction
and
r16,r17
; r16 d [r16] AND [r17]
performs the bitwise AND operation to the contents of registers r16 and r17 and places the
result in r16.
The instruction
dec
r1
; r1 d [r1] 2 1
decrements r1 by 1.
2.6.2 I/O Direct Mode
In this mode, the AVR architecture allows the user to use 6 bits to specify one of the first
64 I/O registers as an operand of an instruction. When writing an assembly program, the user
uses the register name instead of the 6-bit I/O register to specify the I/O register as an operand.
For example,
in
r0,PORTB
; r0 d [PORTB]
reads the contents of the PORTB register and stores them in the r0 register.
out
PORTD,r1
; PORTD d [r1]
outputs the contents of the r1 register to PORTD.
Some complex AVR devices have more peripheral registers than can be supported within
the 64 locations reserved in the instruction for the I/O direct addressing. The extended I/O
memory can only be reached by using the data memory addressing. I/O registers in the
extended I/O memory space must be accessed using load (LD/LDS/LDD) and store (ST/STS/
STD) instructions.
2.6.3 Direct Data Mode
This mode uses a 16-bit value to specify the operand address. Instructions using this mode
are 32 bit. For example,
lds
r1,0x1000
copies the contents of the data memory location at 0x1000 to r1.
sts
0x1000,r0
; mem(0x1000) d [r0]
stores the contents of r0 in the data memory location at 0x1000.
2.6.4 Data Indirect with Displacement Mode
This addressing mode forms the data memory address by adding the 6-bit field from the
instruction and the Y or Z pointer. The operation of this mode is illustrated in Figure 2.10.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.6
■
29
AVR Addressing Modes
Depending on the instruction, the field that starts from bit 6 to 10 may specify the source (Rr)
or destination (Rd) register.
For example,
; r10 d [[Y] 1 20]
ldd r10,Y120
loads the content of the memory location at the address specified by the sum of the pointer Y
and 20 into the register r10.
; mem([Y] 1 10) d [r0]
std Y110,r0
Data memory space
0x0000
15
0
Y or Z register
15
10
6 5
Opcode Rr/Rd
0
q
RAMEND
Figure 2.10
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
stores the content of r0 to the memory location with address equal to the sum of the pointer Y
and 10.
Data indirect with displacement mode
2.6.5 Data Indirect Mode
This mode uses the contents of one of the pointers (X, Y, or Z) to specify the address of
the data memory location to access. For the AVR devices without on-chip SRAM, this mode is
called register indirect addressing, which is a subset of data indirect addressing because the data
space from 0 to 31 is the register file. For example,
ld
r0,X
; r0 d [[X]]
loads the contents of the memory location with address specified by the pointer X.
2.6.6 Data Indirect with Pre-Decrement
In this mode, the contents of the pointer X, Y, or Z are decremented by 1 and then used as
an address to access data memory. For example,
st
2X,r0
; X d [X] 2 1; mem([X]) d [r0]
decrements X by 1 and then stores the contents of r0 in the memory location pointed to by X.
ld
r1,2X
; X d [X] 2 1; r1 d [[X]]
decrements X by 1 and then copies the contents of the memory location pointed to by X to r1.
2.6.7 Data Indirect with Post-Increment
This addressing mode accesses the memory location pointed to by the pointer X, Y, or Z
and then increments the pointer by 1. For example,
st
X1,r0
; mem([X]) d [r0]; X d [X] 1 1
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
30
Chapter 2
■
Introduction to the AVR Microcontroller
stores the contents of r0 in the memory location pointed to by X and then increments X by 1.
ld
; r1 d [[Y]]; Y d [Y] 1 1
r1,Y1
copies the contents of the memory location pointed to by Y to r1 and then increments Y by 1.
2.6.8 Program Memory Constant Addressing Using the LPM, ELPM,
and SPM Instructions
These three instructions use the Z pointer to specify the program memory location to
access. The Z pointer specifies a byte address. When the ELPM instruction is used, the RAMPZ
register is used to extend the Z pointer. For example,
lpm
r0,Z
; r0 d [[Z]]
loads the contents of the program memory location pointed to by Z into r0.
elpm
r0,Z
; r0 d [[RAMPZ:Z]]
loads the contents of the program memory location pointed to by the concatenation of RAMPZ
and Z.
2.6.9 Program Memory with Post-Increment Using the LPM Z+
and ELPM Z+ Instructions
The LPM Z+ instruction uses the Z pointer to specify the program memory location to
access whereas the ELPM Z+ instruction uses the concatenation of the RAMPZ and Z to specify the program memory location to access. After the access either the Z pointer or the concatenation of RAMPZ and Z is incremented by 1. For example,
lpm
r0,Z1
loads the contents of the program memory location pointed to by Z into r0 and then increments
Z by 1.
2.6.10 Direct Addressing, JMP and CALL
These two instructions are 32 bit. The JMP instruction specifies the 22-bit address of the
target instruction to jump to. The CALL instruction specifies the 22-bit address of the subroutine to be called. The format of these two instructions is shown in Figure 2.11.
Program memory
6 msb
16 lsb
PC
FLASHEND
Figure 2.11
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
0x0000
Opcode
Data program addressing, JMP and CALL
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.7
■
31
A Sample of AVR Instructions
2.6.11 Indirect Program Addressing, IJMP and ICALL
The indirect jump (IJMP) instruction uses the Z pointer to specify the address of the target
instruction to jump to and the indirect call (ICALL) instruction uses the Z pointer to specify
the address of the subroutine to be called.
2.6.12 Relative Program Addressing, RJMP and RCALL
The relative jump (RJMP) instruction uses a 12-bit value to specify the distance (from the
instruction after RJMP) of the target instruction to jump to. The relative call (RCALL) instruction uses a 12-bit value to specify the distance (from the instruction after RCALL) of the
subroutine to call. The address calculation is illustrated in Figure 2.12.
Program memory
1
15 12 11
OP
0
k
FLASHEND
Figure 2.12
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
0x0000
PC
Relative program addressing, RJMP and RCALL
2.7 A Sample of AVR Instructions
It is very helpful to learn a small set of AVR instructions that is used most often, before
we formally learn the AVR assembly language programming. In the following, we examine
data movement, addition, and subtraction instructions. The AVR provides a large group of data
movement instructions. The arithmetic and logic instructions of the AVR cannot use memory
locations as their operand. The value stored in a memory location must be copied to a register
before it can be operated on.
2.7.1 The Data Transfer Instructions
The AVR supports the following types of data transfer instructions:
•
•
•
•
•
•
•
Data transfer from register to register
Loading a constant in a register
Data transfer from a data memory location to a register
Data transfer from a register to a data memory location
Data transfer from a program memory location to a register
Data transfer from a register to a program memory location
I/O operation
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
32
Chapter 2
■
Introduction to the AVR Microcontroller
INSTRUCTIONS
TO
T R A N S F E R D ATA
REGISTER
FROM
TO
REGISTER
The instruction mov Rd, Rr copies the contents of the register Rr to the register Rd. For
example,
mov
r0, r1
; r0 d [r1]
copies the contents of r1 to r0.
The instruction movw Rd, Rr copies the contents of the register pair Rr+1:Rr to the register
pair Rd+1:Rd. Both r and d must be an even number. For example,
movw r10,r20
; r11:r10 d [r21]:[r20]
copies the contents of r20 to r10 and the contents of r21 to r11, respectively. This instruction
can also be written as follows:
movw r11:r10,r21:r20
INSTRUCTION
TO
LOAD
A
C O N S TA N T
INTO A
REGISTER
There is often a need to provide an initial value to a program variable. The AVR provides
the following instruction for this purpose:
ldi
Rd,k
; Rd d k
For example,
ldi
r0,10
initializes r0 with the value of 10.
INSTRUCTION
TO
T R A N S F E R D ATA
FROM
D ATA M E M O R Y
TO A
REGISTER
There are 12 instructions in this category (listed in Table 2.1). For example,
lds
r0,0x100
loads the contents of the data memory location at the address 0x100 into register r0.
The instruction sequence
ldi
ldi
ld
r26,0x00
r27,0x10
r0,X
; place 0 in XL
; place 0x10 in XH
; r0 d [0x1000]
initializes the X pointer with the value of 0x1000 and then loads the contents of the data memory
location at 0x1000 into r0.
The instruction sequence
ldi
ldi
ld
r28,0x00
r29,0x20
r1,Y1
; place 0 in YL
; place 0x20 in YH
; r1 d [0x2000]; Y d 0x2001
initializes the Y pointer with the value of 0x2000, loads the contents of the data memory location at 0x2000 into r1, and then increments Y by 1 (Y holds 0x2001).
The instruction sequence
ldi
ldi
ld
r30,0x10
r31,0x10
r0,2Z
; place 0x10 in ZL
; place 0x10 in ZH
; Z d 0x100F; r0 d [0x100F]
initializes the Z pointer with the value of 0x1010, decrements Z by 1, and then loads the contents of the memory location at 0x100F into r0.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.7
■
33
A Sample of AVR Instructions
The instruction sequence
ldi
ldi
ldd
r30,0x00
r31,0x20
r0,Z15
; place 0x00 in ZL
; place 0x20 in ZH
; r0 d [0x2005]
initializes the Z pointer with the value of 0x2000 and then loads the contents of the data memory location at 0x2005 into r0.
Instruction
Description
Operation
Ids Rd, K
Load direct from data memory
Rd d [k]
Id Rd, X
Load indirect
Rd d [[X]]
Id Rd, X1
Load indirect and post-increment
Rd d [[X]]; X d [X] 1 1
Id Rd, 2X
Load indirect and pre-decrement
X d [X]21; Rd d [[X]]
Id Rd, Y
Load indirect
Rd d [[Y]]
Id Rd, Y1
Load indirect and post-increment
Rd d [[Y]]; Y d [Y] 1 1
Id Rd, 2Y
Load indirect and pre-decrement
Y d [Y]21; Rd d [[Y]]
Idd Rd, Y 1 q
Load indirect with displacement
Rd d [[Y] 1 q]
Id Rd, Z
Load indirect
Rd d [[Z]]
Id Rd, Z1
Load indirect and post-increment
Rd d [[Z]]; Z d [Z] 1 1
Id Rd, 2Z
Load indirect and pre-decrement
Z d [Z]21; Rd d [[Z]]
Idd Rd, Z 1 q
Load indirect with displacement
Rd d [[Z] 1 q]
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 2.1
INSTRUCTIONS
TO
■
Instructions to transfer data from data memory to register
T R A N S F E R D ATA
FROM
REGISTER
TO
D ATA M E M O R Y
The AVR provides 12 instructions that can be used to save the contents of a register in a
data memory location. These instructions are listed in Table 2.2. For example,
sts
0x2000,r0
; mem(0x2000) d [r0]
stores the contents of r0 in the data memory location at 0x2000.
The instruction sequence
ldi
ldi
st
XL,0x00
XH,0x10
X, r0
; XL d 0x00
; XH d 0x10
; mem(0x1000) d r0
initializes X with the value of 0x1000 and then stores the contents of r0 in the data memory
location at 0x1000.
The instruction sequence
ldi
XL,0x00
; XL d 0x00
ldi
XH,0x10
; XH d 0x10
st
X1, r0
; mem(0x1000) d r0; X d [X] 1 1
initializes X with the value of 0x1000, stores the contents of r0 at 0x1000, and then increments
X by 1 (becomes 0x1001).
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
34
Chapter 2
■
Introduction to the AVR Microcontroller
The instruction sequence
ldi
ZL,0x10
ldi
ZH,0x10 ; ZH d 0x10
; ZL d 0x10
st
2Z, r0
; Z d [Z] 2 1; mem(0x100F) d r0
initializes Z with the value of 0x1010, decrements Z by 1, and then stores r0 in the memory
location (at 0x100F) pointed to by Z.
The instruction sequence
ldi
ZL,0x00
; ZL d 0x00
ldi
ZH,0x10 ; ZH d 0x10
std
Z15, r0
; mem(0x1005) d r0
initializes Z with the value of 0x1000, and then stores r0 at the memory location at 0x1005.
Instruction
Description
Operation
sts K, Rr
Store direct to data memory
Mem (K) d [Rr]
st X, Rr
Store indirect
Mem ([X]) d [Rr]
st X1, Rr
Store indirect and post-increment
Mem ([X]) d [Rr]; X d [X] 1 1
st 2X, Rr
Store indirect and pre-decrement
X d [X]21; mem([X]) d [Rr]
st Y, Rr
Store indirect
Mem([Y]) d [Rr]
st Y1, Rr
Store indirect and post-increment
Mem([Y]) d [Rr]; Y d [Y] 1 1
st 2Y, Rr
Store indirect and pre-decrement
Y d [Y]21; mem([Y]) d [Rr]
std Y 1 q, Rr
Store indirect with displacement
Mem([Y] + q) d [Rr]
st Z, Rr
Store indirect
Mem([Z]) d [Rr]
st Z1, Rr
Store indirect and post-increment
Mem([Z]) d [Rr]; Z d [Z] 1 1
st 2Z, Rr
Store indirect and pre-decrement
Z d [Z] - 1; mem([Z]) d [Rr]
std Z 1 q, Rr
Store indirect with displacement
Mem([Z] + q) d [Rr]
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 2.2
■
Instructions store the contents of a register in data memory
I N S T R U C T I O N S T O T R A N S F E R D ATA
AND A REGISTER
BETWEEN
PROGRAM MEMORY
As shown in Table 2.3, the AVR provides six instructions for transferring data from program memory to a register and two instructions for storing the contents of a register to the
program memory. For example,
lpm
loads the contents of the program memory location pointed to by Z to register r0.
lpm
r10,Z
copies the contents of the program memory location pointed to by Z to r10.
lpm
r0,Z1
copies the contents of the program memory location pointed to by Z to r0 and then increments
Z by 1.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.7
■
35
A Sample of AVR Instructions
Instruction
Description
Operation
Ipm
Load program memory
r0 d [[Z]]
Ipm Rd, Z
Load program memory
Rd d [[Z]]
Ipm Rd, Z1
Load program memory and post increment
Rd d [[Z]]; Z d [Z] 1 1
elpm
Extended load program memory
r0 d [[RAMPD:Z]]
elpm Rd, Z
Extended load program memory
Rd d [[RAMPD:Z]]
elpm Rd,Z1
Extended load program memory and
post-increment
Rd d [[RAMPD:Z]]; Z d [Z] 1 1
spm
Store program memory
pmem([RAMPD:Z]) d r1:r0
spm Z1
Store program memory and post-increment by 2
pmem([RAMPD:Z]) d R1:r0; Z d [Z] 1 2
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 2.3
■
Instructions to transfer data between a register and the program memory
The AVR provides one input instruction (in Rd, A) and one output instruction (out A, Rr)
for transferring data between a CPU register and an I/O register. The value A is between 0 and
63. However, we often use the symbolic name to refer to an I/O register. For example,
in
r0, PORTD
; PORTD equals 0x0B (for Mega device)
reads the PORTD register that holds the current parallel PORTD pin values and places them in
r0.
out
PORTB, r1
; PORTB equals 0x05 (for Mega device)
writes the contents of r1 to the PORTB register and this value appears on the parallel PORTB pins.
Example 2.1
▼
Write an instruction sequence to copy the contents of the data memory location at 0x1000
to 0x1010.
Solution: We use the load-indirect instruction to fetch the source location and then use the
store-indirect-with-displacement instruction to place the fetched data in the destination. The
following instruction sequence performs the desired operation:
ldi
YL,0x00
; use Y to point to the source memory location
ldi
YH,0x10
;"
ld
r0,Y
; fetch the source data memory location
std
Y10x10,r0
; place the value at the destination data memory location
▲
2.7.2 Addition Instruction
The addition instructions supported by the AVR are listed in Table 2.4.
ADD
RD, RR
This instruction adds the contents of registers Rd and Rr and places the sum in Rd. For example,
add
r0, r1
adds the values in r0 and r1 together and places the sum in r0.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
36
Chapter 2
■
Introduction to the AVR Microcontroller
RD, RR
ADC
This instruction adds the values in Rd and Rr and the C flag of the SREG register, and
places the sum in Rd. For example,
adc
r1, r2
adds the values in r1 and r2 and the C flag of the SREG register, and then places the sum in r1.
ADIW
RD,
K
This instruction adds the constant k (0~63) to the register pair Rd+1:Rd and places the sum
in the register pair Rd+1: Rd. Here, Rd can only be 24, 26, 28, and 30. For example,
adiw
r24, 55
adds 55 to the register pair r25:r24 and places the sum in r25:r24.
Instruction
Description
Operation
add Rd, Rr
Add without carry
Rd d [Rd] 1 [Rr]
adc Rd, Rr
Add with carry
Rd d [Rd] 1 [Rr] 1 C
adiw Rd, k
Add immediate to word
Rd 1 1:Rd d [Rd + 1]:[Rd] 1 k
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 2.4
■
AVR addition Instructions
Example 2.2
▼
Write an instruction sequence to add the contents of the data memory location at 0x1000
and 0x2000 and store the sum at 0x2010.
Solution: We need to use two pointers to point to two source operands. The following instruction sequence performs the desired operation:
ldi
ldi
ldi
ldi
ld
ld
add
std
YL,0x00
YH,0x10
ZL,0x00
ZH,0x20
r0,Y
r1,Z
r1,r0
Y10x10,r1
; let Y point to 0x1000
;"
; let Z point to 0x2000
;"
; load the contents of 0x1000 to r0
; load the contents of 0x2000 to r1
; add two source operands
; store the sum at 0x2010
▲
Example 2.3
▼
Write an instruction sequence to add the value of data memory location 0x1000 and program memory location 0x2000 and leave the sum in register r0.
Solution: We need to use a register pointer (can be X or Y) to point to the data memory location
0x1000 and use the Z register to point to the program memory location 0x2000. The following
instruction sequence performs the desired operation:
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.7
■
A Sample of AVR Instructions
ldi
ldi
ldi
ldi
ld
lpm
add
YL,0x00
YH,0x10
ZL,0x00
ZH,0x20
r1,Y
r0,Z
r0,r1
; let Y point to data memory location 0x1000
;"
; let Z point to program memory location 0x2000
;"
; fetch data memory location contents
; fetch program memory location contents
; perform addition
37
▲
2.7.3 Subtract Instructions
The subtract instructions supported by the AVR are listed in Table 2.5.
RD, RR
SUB
This instruction subtracts the value in Rr from Rd and places the difference back in Rd. For
example,
sub
r1, r0
subtracts the value in r0 from that in r1 and places the difference in r1.
SUBI
RD,
K
This instruction subtracts the 8-bit constant k (0 # k # 255) from Rd and places the difference back in Rd. For example,
subi
r0, 10
subtracts 10 from r0 and places the result back to r0.
RD, RR
SBC
This instruction subtracts the contents of Rr and the C flag of the SREG register from Rd
and places the difference back in Rd. For example,
sbc
r0, r10
subtracts the value in r10 and the C flag of the SREG register from r0 and places the difference
in r0.
SBCI
RD,
K
This instruction subtracts the constant k (0 # K # 255) and the C flag of the SREG register
from Rd and places the result back to Rd. For example,
sbci
r0, 20
subtracts the value of 20 and the C flag of the SREG register from r0 and places the difference
back to r0.
SBIW
RD,
K
This instruction subtracts the constant k (0 # k # 63) from the register pair Rd+1:Rd and
places the difference in Rd+1:Rd. Rd can only be 24, 26, 28, or 30. For example,
sbiw
r24,30
subtracts the constant 30 from the register pair r25:r24 and places the difference in r25:r24.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
38
Chapter 2
■
Introduction to the AVR Microcontroller
Instruction
Description
Operation
sub Rd, Rr
Subtract without carry
Rd d [Rd]2[Rr]
subi Rd, k
Subtract immediate
Rd d [Rd] 2 k
sbc Rd, Rr
Subtract with carry
Rd d [Rd]2[Rr] 2 C
sbci Rd, k
Subtract immediate with carry
Rd d [Rd]2k 2 C
sbiw Rd, k
Subtract immediate from word
Rd + 1:Rd d [Rd + 1]:[Rd] 2 k
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 2.5
■
AVR addition Instructions
Example 2.4
▼
Write an instruction sequence to subtract 10 from the data memory location at 0x2000.
Solution: We have to use a pointer register to access the data memory location. The following
instruction sequence can perform the desired operation:
ldi
XL, 0x00
; use X to point to 0x2000
ldi
ld
sbi
st
XH, 0x20
r0, X
r0, 10
X, r0
;"
; get a copy of the data memory location at 0x2000
; subtract 10 from the copy
; store the result back to the data memory location at 0x2000
▲
Example 2.5
▼
Write a sequence of instructions to subtract 50 from data memory locations 0x2000~0x2001
and store the difference back to 0x2000˜0x2001.
Solution: The following instruction sequence performs the desired operation:
ldi
YL,0x00
; let Y point to data memory location 0x2000
ldi
ld
ldd
sbiw
st
std
YH,0x20
r24,Y
r25,Y11
r24,50
Y,r24
Y11,r25
;"
; fetch the low byte
; fetch the high byte
; perform the subtraction
; save the difference
;"
▲
2.8 Summary
The 8-bit AVR microcontroller has 32 CPU registers. These general-purpose registers can
be used as the source or destination operands of instructions. However, not every one of these
registers can be used as the source or destinations for some instructions. The AVR is not totally
orthogonal.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
2.9
■
Exercises
39
The AVR provides a rich instruction set to support high-level languages. The AVR addressing modes also simplify the access of complex data structures. The AVR has a version of the
ADD instruction that includes the C flag as one of the source operands, which enables multipleprecision addition operation. The AVR also has a version of the SUB instruction that includes
the C flag as one of source operands and hence is used to perform multiprecision subtraction
operation.
The arithmetic and logical operations can only be performed on operands in registers.
Memory operands must be loaded into a register before these operations can be performed.
2.9 Exercises
E2.1 Write an instruction sequence to swap the contents of registers r0 and r1. A third register
such as r2 or another can be used to facilitate the swap operation.
E2.2 Write an instruction sequence to swap the contents of data memory locations at 0x2000
and 0x2001.
E2.3 Write an instruction sequence to copy three bytes from data memory location at
0x1000~0x1002 to data memory locations at 0x2000~0x2002, respectively.
E2.4 Write an instruction sequence to store 1, 3, and 5 at data memory locations at 0x2000,
0x2005, and 0x200A, respectively.
E2.5 Write a sequence of instructions to add 5 to data memory locations at 0x2000, 0x2001, and
0x2002, respectively.
E2.6 Write a sequence of instructions to subtract 10 from data memory locations at 0x2000,
0x2005, and 0x200A, respectively.
E2.7 Write a sequence of instructions to add the three numbers stored in data memory locations at 0x2000, 0x2001, and 0x2002 and store the sum at data memory location at 0x2010.
E2.8 Write an instruction sequence to add 35 to the two-byte value stored at data memory locations 0x2000˜0x2001.
E2.9 Write an instruction sequence to output the value 0xAA to PORTC.
E2.10 Write a sequence of instructions to copy the three bytes from program memory locations
0x2000~0x2002 to data memory locations at 0x2000~0x2002, respectively.
E2.11 Write an instruction sequence to add the two 8-bit numbers stored in program memory
at 0x1000 and 0x1005 together and leave the sum in the data memory location at 0x2000.
E2.12 Write an instruction sequence to swap the 16-bit value stored in data memory location at
0x2000~0x2001 with the 16-bit value stored in the data memory at 0x2020~0x2021.
E2.13 Write an instruction sequence to subtract the value stored at data memory location
0x2000 from the sum of the values stored at data memory locations 0x2010 and 0x2011 and
leave the difference in r0.
E2.14 Write an instruction sequence to subtract the sum of data memory locations at 0x2000
and 0x2001 from the sum of the data memory locations at 0x2010 and 0x2011 and leave the
difference at data memory location 0x2020.
E2.15 Write an instruction sequence to add the 16-bit value stored at data memory locations
0x2000~0x2001 and the 16-bit value stored at program memory locations 0x2010~0x2011 and
store the sum at data memory locations 0x2020~0x2021.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3
AVR Assembly Language
Programming
3.1 Objectives
After completing this chapter, you will be able to
• Use AVR assembler directives to define
constants, reserve memory locations, define
macros, set location counter, and so on.
• Write assembly programs to perform
arithmetic and logic operations.
• Write program loops in assembly language.
• Write an assembly program to perform block
data transfer from program memory to data
memory.
• Write an assembly program to perform block
data transfer from data memory to data
memory.
• Use logical instructions to manipulation a bit
or bit field of a register or I/O pins.
• Write program loops to create time delays.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
42
Chapter 3
■
AVR Assembly Language Programming
3.2 AVR Assembly Language Program Structure
An AVR assembly language program consists of statements that may be assembly instructions, assembler directives, or comments. A statement may have up to four fields. Therefore, an
AVR assembly program statement may take one of the following four forms:
1. [label:] directive [arguments] [comment]
2. [label:] instruction [operands] [comment]
3. Comment
4. Empty line
Items placed in braces ([]) are optional. There are no restrictions with respect to column placement of labels, directives, comments, or instructions. The AVR assembler is not case sensitive.
3.2.1 Label Field
This field is optional and, when present, serves one of the following functions:
•
•
To identify a location in program memory
To identify a location in data memory
A label must begin with a letter (a-z or A-Z), a question mark (?), or an underscore (_) and
is followed by zero or more letters, digits, and special characters (including a dollar sign ($),
question mark (?), and underscore (_)). A label must be terminated by a colon (:) character.
Example 3.1
▼
Give a few examples of valid and invalid labels.
Solution: Labels in the following instructions and directives are valid:
loop:
true:
_ibuf:
lights:
ldi
mov
.byte
.db
r10,100
r1,r0
20
0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B
Labels in the following instructions are invalid:
,too
3 three
f two:
.byte
add
and
5
r3,r5
r10,r23
// , is an illegal character
// label starts with 3 and not terminates with a column
// label contains a space character
▲
3.2.2 Operation Field
This field may be an AVR instruction mnemonic or an assembler directive.
Example 3.2
▼
Give a few examples of operation fields.
Solution:
.def
inc
count = r10
r5
// .def is the operation field
// inc is the operation field
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.3
■
43
Expressions
cp
ldi
r1,r2
r2,0x40
// cp is the operation field
// ldi is the operation field
▲
3.2.3 Operand Field
This field follows the operation field and is separated from the operation field by at
least one space. An assembly instruction may have zero, one, or two operands. The data
definition assembler directive, for example, DB and DW, can have any number of operands.
An operand may be a constant, a register, or a memory location. A constant is formed by
using an expression, whereas a memory location is specified using one of the AVR addressing modes.
Example 3.3
▼
Give a few examples of operand fields.
Solution:
.dseg
.db
ldi
ldi
first:
10,11,16,18
r27,first
r28,first+2
// no operand
// 10, 11, 16, and 18 are operand field
// both r27 and first are operand field
// both r28 and first+2 are operand field
▲
3.2.4 Comment Field
The programmer may use this field to explain the function or operation of an instruction
(or assembler directive) or a block of instructions (or assembler directives). A comment may
have one of the following forms:
; [Text]
// this is a comment line
/* this is also a comment and may span multiple lines */
3.3 Expressions
Expressions are needed to form the operand field of an instruction or assembler directive.
An expression may consist of operands, operators, and functions. All expressions are internally
32 bits.
3.3.1 Operands
The following operands may be used in forming expressions in an AVR assembly statement:
•
User defined labels that are given the value of the location counter at the place
they appear
•
•
•
•
User defined variables defined by the set directive
User defined constants defined by the equ directive
Integer constants, which can be given in binary, hexadecimal, or decimal format
The current value of the program counter
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
44
■
Chapter 3
AVR Assembly Language Programming
3.3.2 Functions
The AVR assembler provides the following functions for forming constants:
•
Low(expression). This function returns the low byte (least significant byte) of the
given expression.
•
•
•
•
High(expression). This function returns the second byte of the given expression.
•
Lwrd(expression). This function returns the lower word (bit 0 to 15) of the given
expression.
•
Hwrd(expression). This function returns the higher word (bit 16 to 31) of the given
expression.
•
•
•
•
•
Page(expression). This function returns bit 16 to 21 of the given expression.
•
q7(expression). This function converts a fractional floating-point expression to a
form suitable for the fmul/fmuls/fmulsu instructions. (sign + 7-bit fraction)
•
q15(expression). This function converts a fractional floating-point expression to the
form returned by the fmul/fmuls/fmulsu instructions. (sign+15-bit fraction)
•
•
abs(expression). This function returns the absolute value of the expression.
•
STRLEN(string) returns the length of a string constant, in bytes.
Byte2(expression). This function is the same as high.
Byte3(expression). This function returns the third byte of the given expression.
Byte4(expression). This function returns the fourth byte (most significant byte) of
the given expression.
Exp2(expression). This function returns 2**expression.
Log2(expression). This function returns the integer part of log2(expression).
Int(expression). This function truncates a floating-point expression to an integer.
Frac(expression). This function extracts the fractional part of a floating-point
expression.
DEFINED(symbol). Returns true if symbol is previously defined using .equ/.set/
.def directives. Normally used in conjunction with .if directives (.if defined(foo)),
but may be used in any context. It differs from other functions in that parentheses
around its argument are not required, and that it only makes sense to use a single
symbol as argument.
Example 3.4
▼
Write a sequence of instructions that use AVR assembler functions to place the value represented by the label ibuf into the register pair r26 and r27.
Solution:
ldi
ldi
r 26,low(ibuf)
r27,high(ibuf)
; r26 also can be written as XL
; r27 also can be written as XH
▲
3.3.3 Operators
The AVR assembler supports a number of operators. The user can use them to form expressions in their assembly programs. These operators are listed in Table 3.1.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.3
Symbol
■
45
Expressions
Operation
Description
Example
!
Logical NOT
This operator returns 1 if the expression is zero.
!0xF0
∼
Bitwise NOT
This operator toggles every bit of the expression.
~0x0F
-
Unary minus
This operator negates the given expression.
-2
∗
Multiplication
This operator returns the product of two operands.
label*2
/
Division
This operator returns the integral quotient.
label/2
+
Addition
This operator returns the sum of operands.
c1 + c2
-
Subtraction
This operator returns the difference of two operands.
c1 - c2
V
Shift left
This operators returns the left expression shifted left a number of times
given by the right expression.
1V4
W
Shift right
This operator returns the left expression shifted right a number of
times given by the right expression.
c1 W c2
6
Less than
This operator returns 1 if the signed expression to the left is less than
the signed expression to the right.
bmask* (c1 6 c2) + 1
6=
Less or equal
This operator returns 1 if the signed expression to the left is less or
equal to the signed expression to the right.
bmask* (c16= c2) = 1
7
Greater than
This operator returns 1 if the signed expression to the left is greater
than the signed expression to the right.
bmask* (c1 7 c2) + 1
7=
Greater or equal
This operator returns 1 if the signed expression to the left is greater
than or equal to the signed expression to the right.
bmask* (c1 7= c2) + 1
==
Equal
This operator returns 1 if the signed expression to the left is equal to
the signed expression to the right.
bmask* (c1 = = c2) + 1
!=
Not equal
This operator returns 1 if the signed expression to the left is not equal
to the signed expression to the right.
.set flag = (c1 != c2)
&
Bitwise AND
This operator returns the bitwise AND of two expressions.
(c1 & c2)
∧
Bitwise XOR
This operators returns the bitwise XOR of two expressions.
c1 ^ c2
|
Bitwise OR
This operator returns the bitwise OR of two expressions.
c1 | c2
||
Logical OR
This operator returns 1 if one or both expressions are nonzero.
c1 || c2
&&
Logical AND
This operator returns 1 if both expressions are nonzero.
c1 && c2
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.1
■
Operators supported by the AVR assembler
3.3.4 Formats of Constants
The AVR assembler accepts numbers represented in binary, octal, decimal, and hexadecimal.
Both the decimal and hexadecimal bases have been used in Chapter 2 and the previous sections
of this chapter.
B I N A R Y C O N S TA N T S
There are four possible formats for representing a binary constant:
1. Adding a lowercase b as the suffix to a binary value. For example, 1010b, 10101011b,
and so on.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
46
Chapter 3
■
AVR Assembly Language Programming
2. Adding an uppercase B as the suffix to a binary value. For example, 1010B, 10101111B,
and so on.
3. Adding a lowercase b as the prefix to a single-quoted binary number. For example,
b'101011', b'01011101', and so on.
4. Adding an uppercase B as the prefix to a single-quoted binary number. For example,
B'1110111', B'10110110', and so on.
O C TA L C O N S TA N T S
1. Adding a lowercase q as the suffix to an octal value. For example, 1234q, 1234Q,
and so on.
2. Adding an uppercase Q as the suffix to an octal value. For example, 1347Q, 4371Q,
and so on.
3. Adding a lowercase q as the prefix to a single-quoted binary number. For example,
q'1224', q'432105', and so on.
4. Adding an uppercase Q as the prefix to a single-quoted binary number. For example,
Q'1177', Q'7654321', and so on.
D E C I M A L C O N S TA N T S
1. Adding neither suffix nor prefix to the decimal value. For example, 1234, -1, and so
on. This is the default format.
2. Adding a lowercase d as the prefix to a single-quoted decimal value. For example,
d'2345', d'334456', and so on.
3. Adding an uppercase D as the prefix to a single-quoted decimal value. For example,
D'2356', D'9843210', and so on.
H E X A D E C I M A L C O N S TA N T S
1. Adding a lowercase h as the suffix to a hexadecimal value that is preceded by a 0.
For example, 0ABCDEh, 023450h, and so on.
2. Adding an uppercase H as the suffix to a hexadecimal value that is preceded by a 0.
For example, 0A8B30H, 0CDEF0031H, and so on.
3. Adding a 0x pair as the prefix to a hexadecimal value. For example, 0x1234, 0xFFFC,
and so on.
4. Adding a lowercase h as the prefix to a single-quoted hexadecimal value. For example,
h'3344', h'ABCDEF00', and so on.
5. Adding an uppercase H as the prefix to a single-quoted hexadecimal value. For
example, H'6543', H'FFFC', and so on.
3.4 Memory Class
The AVR microcontroller has separate program memory and data memory. In addition,
some of the AVR devices also have on-chip EEPROM. To distinguish the type of memory space
being accessed, the AVR assembler divides the memory into three classes: code memory, data
memory, and EEPROM memory. A segment of space in one of these spaces is referred to as
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.5
■
47
Assembler Directives
data segment, program segment, or EEPROM segment. The AVR assembler provides assembler
directives for specifying the type of memory segment being accessed. A location counter is
assigned to each segment during the assembly process so that the assembler knows where to
place the next code or data byte.
3.5 Assembler Directives
The Atmel AVR assembler supports a number of directives. The directives are not translated into machine code. Instead, they are used to adjust the location of the program in
memory, define macros, initialize memory, and so on. The set of directives supported by
the Atmel AVR assembler is listed in Table 3.2. All directives must be preceded by a period
character.
Directive
Description
byte
Reserve byte
cseg
Code segment
db
Define constant byte(s)
def
Define a symbolic name to a register
device
Define the device to assemble for
dseg
Data segment
dw
Define constant word(s)
endmacro
End macro
equ
Set a symbol equal to an expression
eseg
EEPROM segment
exit
Exit from file
include
Read source from the specified file
list
Turn on listfile generation
listmac
Turn on macro expansion
macro
Begin macro
nolist
Turn off listfile generation
org
Set location counter
set
Set a symbol to an expression
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.2
■
AVR assembler directives
3.5.1 The BYTE Directive
This directive is used to reserve memory spaces in the SRAM. The user can add a label to
the left of this directive so that he or she can use the label to refer to the reserved memory locations. This directive can only be used with the data segment. The syntax of this directive is as
follows:
[label:]
.byte
expression
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
48
Chapter 3
■
AVR Assembly Language Programming
Example 3.5
▼
Use the byte directive to reserve 20 bytes in data memory space and write a sequence of
instructions to load the first byte of this buffer into register r2.
Solution:
buf:
.dseg
.byte
…
.cseg
ldi
ldi
ld
20
; start a new data segment
; reserve 20 bytes
XL,low(buf)
XH,high(buf)
r2,X
; start a new code segment
; load X register low
; load X register high
; load the byte pointed by X to r2
▲
3.5.2 The CSEG Directive
This directive defines the start of a code segment. An assembly file may consist of several
code segments, which are concatenated into one code segment when being assembled. The
location counter associated with each code segment is a word counter. The org directive can
then be used to place code and constants at specific locations in the program memory. This
directive does not take any parameters. The syntax of this directive is
.cseg
3.5.3 The DB Directive
This directive initializes program memory or EEPROM with 8-bit values. The syntax of
this directive is
[label:]
.db
expressionlist
Example 3.6
▼
Use the db directive to define an array of 8-bit elements 1, 2, …, 10 and a string “Happy
birthday!”.
Solution: The array is defined as follows:
array:
.db
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
The string is defined as follows:
string:
.db
“Happy birthday!”,0
; terminate the string with a NULL (ASCII code is 0) character
▲
3.5.4 The DEF Directive
This directive allows the user to use a symbol to refer to a register. Using a symbol to refer
to a register makes the program more readable. The syntax of this directive is
.def
symbol = register
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.5
■
49
Assembler Directives
Example 3.7
▼
Use the def directive to redefine register r4 as index.
Solution:
.def
index = r4
▲
3.5.5 The DEVICE Directive
The user uses this directive to tell the assembler which device the code is to be executed
on. If this directive is used, a warning is issued if an instruction not supported by the specified
device occurs in the code. If the size of the code segment or EEPROM segment is larger than
that supported by the specified device, a warning is issued. If the device directive is not use, it is
assumed that all instructions are supported and that there are no restrictions on memory sizes.
The syntax of this directive is
.device
device_name
For example, the following statement tells the assembler that the code is to be executed on
the XMega128A1:
.device
ATXMega128A1
3.5.6 The DSEG Directive
This directive defines the start of a new data segment. An assembler file may consist of
several data segments, which are concatenated into one data segment when assembled. A data
segment normally consists of byte directives (and labels). The syntax of this directive is
.dseg
The following two directives start a new data segment and reserve 20 bytes for an array:
obuf:
.dseg
.byte
20
3.5.7 The DW Directive
This directive initializes program memory or EEPROM with 16-bit values. The syntax of
this directive is
[label:]
.dw
expressionlist
; label is optional
Example 3.8
▼
Give an example of the use of the dw directive.
Solution: An example of the use of the dw directive is as follows:
constArr:
.cseg
.dw
0, 0xFFFF, 0x7FFF, 65536
▲
3.5.8 The MACRO and ENDMACRO Directives
A macro is a name assigned to a group of instructions or directives. There are situations
in which the same sequence of instructions must be included in several places. This sequence
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
50
Chapter 3
■
AVR Assembly Language Programming
of instructions may operate on different parameters. By placing this sequence of instructions
in a macro, the instruction sequence need be typed only once. After defining the macro, the
programmer can place the macro name in places where the same sequence of instructions has
to be executed. The macro capability not only makes the programmer more productive but also
makes the program more readable.
The keyword macro starts a new macro definition, whereas the keyword endm terminates
the macro definition. A macro may refer to as many parameters as needed. A parameter of the
macro is referred to by using the @ character. The parameters of a macro are referred to as @0,
@1, @2, and so on. The syntax of macro and endmacro is
.macro
…
…
.endmacro
macroname
The following macro subtracts a 16-bit immediate value from two registers:
.macro
subi
sbci
.endmacro
sub16I
@0,low(@2)
@1,high(@2)
; @0 and @2 are the 0th and 2nd macro parameter
; @1 is the 1st macro parameter
To subtract the 16-bit value 0x1234 from registers r17:r16, invoke the following statement
(r16 holds lower byte):
sub16I
r16,r17, 0x1234
The following macro loads the address of a memory location into the X, Y, or Z register:
.macro
ldi
ldi
.endmacro
setPointer
@0,low(@2)
@1,high(@2)
For example, the following macro call loads the address of the data memory location represented by the label array into X:
setPointer
XL,XH,array
; XL and XH refer to register r26 and r27, respectively
3.5.9 The EQU Directive
The equ directive assigns a value to a label. This label can then be used in later expressions.
A label assigned to a value by the equ directive is a constant and cannot be changed or redefined. The syntax of the equ directive is
.equ
label = expression
Example 3.9
▼
Give a few examples of the use of the equ directive.
Solution:
.equ
.equ
.equ
TRUE = 1
FALSE = 0
NN = 100
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.5
■
51
Assembler Directives
3.5.10 The ESEG Directive
This directive defines the start of an EEPROM segment. An assembly file may consist of
several EEPROM segments, which are concatenated into one EEPROM segment when assembled. An EEPROM segment has its own location counter. The org directive is used to place constants at specific locations in the EEPROM. The syntax of this directive is
.eseg
3.5.11 The EXIT Directive
The exit directive tells the assembler to stop assembling the file. Normally, the assembler
runs until the end of the assembly program file. If the exit directive appears in an assembly file,
then the assembler skips the remaining statements of the file. The syntax of the directive is
.exit
3.5.12 The INCLUDE Directive
This directive tells the assembler to start reading from a specified file. The assembler
processes the include file until the end of the file or the exit statement. The syntax of this
directive is
.include “filename”
The following statement inserts the iodefs.asm file into the program:
.include “iodefs.asm”
3.5.13 The LIST and NOLIST Directives
The assembler generates a listfile which is a combination of assembly source code,
addresses, and opcodes. Listfile generation is turned on by default. However, it can also be
turned off by using the nolist directive. The list directive tells the assembler to turn on listfile
generation. By using the list directive together with nolist directive, the programmer can generate listfile of selected parts of the assembly source code. The syntaxes of these two directives are
.list
.nolist
The following statements illustrate this idea:
.nolist
.include “macro.inc”
.include “const.def”
.list
; disable listfile generation
; the included files are not shown
; in the listfile
; re-enable listfile generation
3.5.14 The LISTMAC Directive
This directive tells the assembler that when a macro is called, the expansion of the macro
is to be shown on the listfile generated by the assembler. By default, only the macro-call statement is shown in the listfile. The syntax of this directive is
.listmac
3.5.15 The ORG Directive
This directive sets the active location counter to an absolute value. The value to set is
given as a parameter. When the org statement does not include an absolute value, the assembler sets the location counter to an appropriate default value. The default values of the code and
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
52
Chapter 3
■
AVR Assembly Language Programming
EEPROM location counters are zero, whereas the default value of the SRAM location counter
is 32 (because CPU registers occupy addresses 0 to 31). Note that the EEPROM and SRAM location counters count bytes whereas the program memory location counter counts words. The
syntax of this directive is
.org
expression
Example 3.10
▼
Use assembler directives to reserve 20 bytes in data memory starting from address 0x20.
Solution:
buffer:
.dseg
.org
.byte
0x20
20
▲
3.5.16 The Set Directive
This directive assigns a value to a label. This label can then be used in later expressions. A
label assigned to a value by the set directive can be changed later in the program. The syntax of
this directive is
.set
label = expression
Example 3.11
▼
Give a few examples of the use of the set directive.
Solution:
.set
.set
.cseg
clr
out
io_offset = 0x23
PORTA = io_offset + 2
r2
PORTA,r2
▲
3.6 AVR Assembly Program Template
The block of program memory starting from address 0 up to a certain location (device
dependent) is reserved for handling resets and interrupts. The AVR device that has the most
interrupt sources reserves 0xF6 words for this purpose. Other AVR devices with fewer interrupt
sources reserve fewer words for reset and interrupt handling. Two words are allocated to the
reset and each interrupt source. The user program should be stored after this block.
After power on reset, the AVR microcontroller starts to execute the program from address 0.
Because two words are not enough to handle reset, a common practice is to place a jmp instruction at the program memory location 0, to jump to the memory location for handling reset.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.7
■
53
Software Development Issue
When writing an AVR assembly program, we need to add the include file of the target microcontroller. This file contains the definitions of peripheral registers (also called I/O registers) and
bits of these registers. By including the MCU include file, we are able to use symbolic names to
access I/O registers and their bits.
After reserving space for handling reset and interrupts, an assembly program would look
like (using the AVR assembler)
.include
.org
jmp
…
org
…
start:
6xxx.inc7
0x00
start
; xxx is the AVR device name
0xF6
3.7 Software Development Issue
Experience tells us that developers spent much more time on software development than
hardware design during the development period of an embedded product. To become an effective software developer, we need to
•
•
•
•
•
Learn a systematic software development methodology.
Learn to develop the algorithm for problem solving.
Learn to develop reusable software.
Learn to use software tools to perform software debugging.
Follow a good programming style to make the program more readable and easier to
debug.
A complete discussion of issues involved in software development is beyond the scope of
this text. However, we discuss them here whenever it is possible.
Software development starts with problem definition. The problem presented by the
application must be fully understood before any program can be written. At the problem definition stage, the most critical thing is to get the programmer and the end user to agree upon what
needs to be done. To achieve this, asking questions is very important. For complex and expensive applications, a formal, written definition of the problem is formulated and agreed upon by
all parties.
Once the problem is known, the programmer can begin to lay out an overall plan for solving the problem. The plan is also called an algorithm. Informally, an algorithm is any welldefined computational procedure that takes some value or a set of values as input and produces
some value or a set of values as output. An algorithm is thus a sequence of computational steps
that transforms the input into the output. We can also view an algorithm as a tool for solving a
well-specified computational problem. The statement of the problem specifies in general terms
the desired input/output relationship. The algorithm describes a specific computational procedure for achieving that input/output relationship.
An algorithm is expressed in pseudocode that is very much like C or PASCAL. What separates pseudocode from “real” code is that in pseudocode, we employ whatever expressive
method is most clear and concise to specify a given algorithm. Sometimes, the clearest method
is English, so do not be surprised if you come across an English phrase or sentence embedded
within a section of “real” code.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
54
Chapter 3
■
AVR Assembly Language Programming
An algorithm provides not only the overall plan for solving the problem but also the documentation to the software to be developed. In the rest of this book, all algorithms are presented
in the following format:
Step 1
….
Step 2
….
An example of an algorithm that generates a 1 kHz waveform from the PORTE pin 0 is as
follows:
Step 1
Pull the pin 0 of PORTE to high.
Step 2
Wait for 0.5 ms.
Step 3
Pull the pin 0 of PORTE to low.
Step 4
Wait for 0.5 ms.
Step 5
Go to Step 1.
An earlier alternative for providing the overall plan for solving software problems was the
use of flowcharts. A flowchart shows the way a program operates. It illustrates the logic flow
of the program. Therefore, flowcharts can be a valuable aid in visualizing programs. Flowcharts
are used not only in computer programming but also in many other fields, such as business and
construction planning.
The flowchart symbols used in this book are shown in Figure 3.1. The start/stop symbol is
used at the beginning and the end of each program. When it is used at the beginning of a program, the word Start is written inside it. When it is used at the end of a program, it contains the
word Stop.
The operation box indicates what must be done at this point in the program execution. The
operation specified by the process box could be sending the contents of one general-purpose register to a peripheral register, setting a flag, and so on.
The I/O operation box is used to specify what data are to be read or displayed by the
microcontroller.
The decision box has a question to which the answer could be yes or no. When the answer
is yes, the computer takes one action. When the answer is no, the computer takes a different
action.
The subroutine box represents the start of a sequence of instructions that may be called
from many places within a program. The place that calls a subroutine should use an arrow to
specify the entrance connector of the subroutine, and the places to be returned from the subroutine should have a connector identical to the exit connector of the subroutine. The issues
related to subroutine are discussed in Chapter 5.
The on-page connector enables the flowchart to continue elsewhere on the same page.
The place where it is continued has the same label as the on-page connector. The off-page
connector allows the flowchart to continue on a different page. The place where the flowchart continues can be found by locating the matching off-page connector in the following
pages.
The normal flow of a flowchart is from top to bottom and from left to right. Any line
that does not follow this normal flow should have an arrowhead on it. When the program gets
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
55
Writing Programs to Perform Arithmetic
α
Start/Stop
Operation
Subprogram
Input or
output
β
Off-page connector
Decision
making
Yes
α
On-page connector
No
Figure 3.1
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
3.8
Flowchart symbols used in this book
complicated, the flowchart that documents the logic flow of the program also becomes difficult
to follow. This is the limitation of the flowchart. In this book, we mix the use of flowcharts and
the algorithm procedures to describe the solution to a problem.
After the programmer is satisfied with the algorithm or the flowchart, it is converted to
source code in one of the assembly or high-level languages. Each statement in the algorithm
(or each block of the flowchart) is converted to one or multiple assembly instructions or highlevel language statements. If an algorithmic step (or a block in the flowchart) requires many
assembly instructions or high-level language statements to implement, then it might be beneficial to either (1) convert this step (or block) into a subroutine and just call the subroutine, or
(2) further divide the algorithmic step (or flowchart block) into smaller steps (or blocks) so that
it can be coded with just a few assembly instructions or high-level language statements. This
process is referred to as top-down design with hierarchical refinement and is considered to be
the most efficient software development methodology.
The next major step is testing the program. Testing a program means testing for anomalies. The first test is for normal inputs that are always expected. If the result is what is
expected, then the borderline inputs are tested. The maximum and minimum values of the
input are tested. When the program passes this test, then illegal input values are tested. If
the algorithm includes several branches, then enough values must be used to exercise all of
the possible branches. This is to make sure that the program operates correctly under all possible circumstances.
In the rest of this book, most of the problems are well defined. Therefore, our focus is on
how to design the algorithm that solves the specified problem as well as how to convert the
algorithm into source code.
3.8 Writing Programs to Perform Arithmetic
In Chapter 2, we learned how to write instruction sequences to perform simple arithmetic. In
this chapter, we now learn how to write complete programs that can be simulated using the software simulator or executed using a hardware demo board. In this section and the rest of the chapter,
we use short programs that perform simple calculations to demonstrate how to write an assembly
program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
56
Chapter 3
■
AVR Assembly Language Programming
Example 3.12
▼
Write a program to add the 8-bit numbers stored at data memory locations 0x20 and 0x21,
and save the sum at data memory location 0x30.
Solution: The procedure to add the 8-bit numbers stored at two data memory locations is
as follows:
Step 1
Load the contents of the data memory location at 0x20 to a register (for example, R1).
Step 2
Load the contents of the data memory location 0x21 to another register (for example, R2).
Step 3
Add the contents of R1 to R2.
Step 4
Store the contents of R2 in the data memory location at 0x30.
The program that implements this algorithm is as follows:
start:
.include
.org
jmp
.org
lds
lds
add
sts
6xxxxxdef.inc7
0x00
start
0xF6
r1,0x20
r2,0x21
r2,r1
0x30,r2
; xxxxx represents one of the Mega or XMega MCU
; copy the contents of the data memory location at 0x20 to R1
; copy the contents of the data memory location at 0x21 to R2
; add two numbers together
; store the sum at 0x30
The first line of the program inserts the register and bit definitions for an AVR MCU.
Depending on the device being used, the user should include the appropriate include file (for
example, m2560def.inc).
▲
Example 3.13
▼
Write a program that adds 5 to data memory locations 0x21, 0x22, and 0x23, respectively.
Solution: The procedure to add 5 to 0x21 is as follows:
Step 1
Place 5 in register R16.
Step 2
Copy the contents of the data memory location in 0x21 to R1.
Step 3
Add R16 to R1.
Step 4
Store the contents of R1 in data memory location 0x21.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.8
■
Writing Programs to Perform Arithmetic
57
The assembly program that performs the specified operation is as follows:
start:
.include
.org
jmp
.org
ldi
lds
add
sts
lds
add
sts
lds
add
sts
6m1280def.inc7
0x00
start
0xF6
r16,5
r1,0x21
r1,r16
0x21,r1
r1,0x22
r1,r16
0x22,r1
r1,0x23
r1,r16
0x23,r1
;
; place 5 in R16
; copy the contents of the data memory location 0x21 to R1
; R1 6- R1 + 5
; store the sum at the data memory location 0x21
; load the contents of the data memory location 0x22 into R1
; add 5 to this copy
; save the sum back to data memory location 0x22
; load the contents of the data memory location 0x23 into R1
; add 5 to this copy
; save the sum back to data memory location 0x23
▲
3.8.1 The Carry/Borrow Flag
Bit 7 of the status register (SREG) register is the carry (C) flag. The C flag is affected by all of
the AVR addition and subtraction instructions. The sum of two 8-bit numbers may or may not
be held in an 8-bit register. For this reason, the AVR uses the C flag to hold the most significant
bit of the sum of two 8-bit numbers. For example, the execution of the following three instructions yields the sum of 0x131, and the C flag is set to 1:
ldi
ldi
add
r16,0x98
r17,0x99
r16,r17
When the sum of two 8-bit numbers can be held in an 8-bit register, the C flag is cleared
to 0. For example, the execution of the following three instructions sets the C flag to 0 because
the sum of 0x35 and 0x42 is 0x77:
ldi
ldi
add
r16,0x35
r17,0x42
r16,r17
In summary, the C flag is set to 1 or 0 during an addition depending on whether there is a
carry out.
3.8.2 Multiprecision Addition
When two numbers longer than 8 bits are to be added, the user must program the AVR
to add one byte at a time and proceed from the least significant byte (lsb) toward the most
significant byte (msb) with carry out included in all except the least significant byte addition.
Addition performed in this manner is referred to as multiprecision addition. Multiprecision
addition makes use of the carry flag in the SREG. The next example illustrates the procedure
of multiprecision addition. In this book, we store the lsb to msb of a multibyte number in
memory locations from low to higher addresses.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
58
Chapter 3
■
AVR Assembly Language Programming
Example 3.14
▼
Write a program to add two 4-byte numbers stored at num1~num1+3 and num2~num2+3,
respectively, in program memory. Save the sum at sum~sum+3 in data memory.
Solution: The addition should start from the lsb toward the msb. The carry bit must be included
in the addition in all except the lsb. The assembly program that adds two 4-byte numbers is as
follows:
.include
.dseg
.org
num1: .byte
num2: .byte
sum: .byte
.cseg
.org
jmp
.org
start: lds
lds
add
sts
lds
lds
adc
sts
lds
lds
adc
sts
lds
lds
adc
sts
// end of the program
6m2560def.inc7
0x200
; start from data memory location at 0x200 (set to 0x2000 for
; ATXMega MCUs)
4
4
4
0x00
start
0xF6
r0,num1
r1,num2
r0,r1
sum,r0
r0,num1+1
r1,num2+1
r0,r1
sum+1,r0
r0,num1+2
r1,num2+2
r0,r1
sum+2,r0
r0,num1+3
r1,num2+3
r0,r1
sum+3,r0
; fetch the lsb of num1
; fetch the lsb of num2
; add the lsbs of two numbers
; save the lsb of sum
; fetch the second lsb of num1
; fetch the second lsb of num2
; add two bytes together
; save the sum of second lsbs
; fetch the second msb of num1
; fetch the second msb of num2
; add two bytes together
; save the sum of second msbs
; fetch the msb of num1
; fetch the msb of num2
; add the msbs of two numbers
; save the msb of sum
▲
3.8.3 The C Flag and Subtraction
The C flag enables the AVR to borrow from the high byte to the low byte during a multiprecision subtraction. The C flag operates as follows during a subtraction:
•
The C flag is set to 1 when the subtrahend is larger than the minuend during a
subtraction.
•
The C flag is cleared to 0 when the subtrahend is equal to or smaller than the
minuend during a subtraction.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.8
■
59
Writing Programs to Perform Arithmetic
3.8.4 Multiprecision Subtraction
Multiprecision subtraction is the subtraction of numbers that are longer than one byte for
an 8-bit microcontroller. For the AVR, multiprecision subtraction is performed one byte at a
time from the lsb toward the msb with the C flag involved to take care of the required borrow.
The next example illustrates the process.
Example 3.15
▼
Write a program to subtract the four-byte number stored at 0x200~0x203 from the fourbyte number stored at 0x204~0x207 and save the difference at 0x210~0x213.
Solution: Subtraction proceeds from the lsb toward the msb.
.include
.dseg
.org
num1:
num2:
diff:
.byte
.byte
.byte
.cseg
.org
jmp
.org
start:
lds
lds
sub
sts
lds
lds
sbc
sts
lds
lds
sbc
sts
lds
lds
sbc
sts
// end of the program
6m2560def.inc7
0x200
; start from data memory location 200 (set to 0x2000 for
; ATXMega MCUs)
4
4
4
0x00
start
0xF6
r1,num1
r0,num2
r0,r1
diff,r0
r1,num1+1
r0,num2+1
r0,r1
diff+1,r0
r1,num1+2
r0,num2+2
r0,r1
diff+2,r0
r1,num1+3
r0,num2+3
r0,r1
diff+3,r0
; fetch the lsb of num1
; fetch the lsb of num2
; subtract the lsbs of two numbers
; save the lsb of difference
; fetch the msb of num1
; fetch the msb of num2
; subtract the msbs of two numbers
; save the msb of difference
▲
3.8.5 Multiplication and Division
The AVR provides three instructions (mul, muls, and mulsu) that can multiply two 8-bit
integers and three instructions (fmul, fmuls, and fmulsu) that can multiply two 8-bit fractions.
The products of these instructions are stored in the register pair r1:r0. These instructions are
listed in Table 3.3.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
60
■
Chapter 3
AVR Assembly Language Programming
Mnemonics
Description
Operation
Multiply unsigned
R1:R0 ← [Rd] 3 [Rr] (UU)(4)
Multiply signed
R1:R0 ← [Rd] 3 [Rr] (SS)(4)
mulsu Rd, Rr
Multiply signed with unsigned
R1:R0 ← [Rd] 3 [Rr] (SU)(4)
fmul Rd, Rr(3)
Fractional multiply unsigned
R1:R0 ← [Rd] 3 [Rr] 66 1 (UU)(4)
fmuls Rd, Rr
Fractional multiply signed
R1:R0 ← [Rd] 3 [Rr] 66 1 (SS)(4)
fmulsu Rd, Rr(3)
Fractional multiply signed with unsigned
R1:R0 ← [Rd] 3 [Rr] 66 1 (SU)(4)
(1)
mul Rd, Rr
muls Rd, Rr(2)
(3)
(3)
Note: 1. 0 # d # 31; 0 # r # 31
2. 16 # d # 31; 16 # r # 31
3. 16 # d # 23; 16 # r # 23
4. U: unsigned; S: signed
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.3
■
AVR multiply instructions
Example 3.16
▼
Write an instruction sequence to multiply the 8-bit unsigned integers stored at data memory locations 0x200 and 0x201 and save the product at data memory locations 0x202~0x203.
Place the lower and upper bytes in 0x202 and 0x203, respectively.
Solution: We have to place these two integers in two registers before the multiplication.
.include
.cseg
.org
jmp
.dseg
.org
num1:
.byte
num2:
.byte
prod:
.byte
.cseg
.org
start:
lds
lds
mul
sts
sts
// end of program
6m2560def.inc7
0x00
start
0x200
1
1
2
0xF6
r2,num1
r3,num2
r2,r3
prod,r0
prod+1,r1
; load the first number into r2
; load the second number into r3
; save the low byte of product
; save the high byte of product
▲
The fractional multiplication is often used in digital signal processing. Let (N.Q) denote
a fractional number with N binary digits to the left of the radix point, and Q binary digits
to the right of the radix point. A multiplication between two numbers in the formats (N1.
Q1) and (N2.Q2) results in the format ((N11N2).(Q11Q2)). For signal processing applications,
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.9
■
Accessing Data in Data and Program Memory
61
the format (1.7) is widely used for the inputs, resulting in a (2.14) format for the product. A left
shift is required for the high byte of the product to be in the same format as the inputs. The
FMUL instruction (also true for FMULS and FMULSU) incorporates the shift operation in the
same number of cycles as MUL.
The (1.7) format is most commonly used with signed numbers, whereas FMUL performs
an unsigned multiplication. This instruction is therefore most useful for calculating one of the
partial products when performing a signed multiplication with 16-bit inputs in the (1.15) format, yielding a result in the (1.31) format. Note: The result of the FMUL operation may suffer
from a 2’s complement overflow if interpreted as a number in the (1.15) format. The most significant bit of the multiplication before shifting must be taken into account, and is found in the
carry bit.
The AVR does not provide any divide instruction. The programmer must write a subroutine to implement this operation. We deal with this issue in Chapter 5.
3.9 Accessing Data in Data and Program Memory
When developing a program, the programmer must provide test data to find out whether
the program that he or she develops works correctly. The db and dw directives can be used to
define test data for testing the programs under development.
There are two steps for accessing data stored in the program memory:
Step 1
Place the address of data in program memory in the Z register.
Step 2
Execute an lpm or elpm instruction.
To access data in program memory, we need to use the Z register as a pointer to the data.
Because the location counter of program memory counts words instead of bytes, a label in
program memory represents a word address (= byte address,2). We have to multiply a word
address by 2 to translate it to a byte address. Multiplication by 2 can be performed by shifting a
number to the left by one position (num 66 1).
Example 3.17
▼
Write an instruction sequence to load the contents of the program memory location with
the label parray into register r1.
Solution:
ldi
ldi
lpm
r30,low (parray661) ; load the address of the specified program memory
r31,high (parray661) ; location into the register z
r1, z
; load memory contents into r1
The AVR can access a data memory location by specifying its address directly or via a
pointer. Using a pointer is more efficient when the program must access many memory locations or the whole array.
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
62
Chapter 3
■
AVR Assembly Language Programming
Example 3.18
▼
Write an instruction sequence to load the contents of the program memory location with
the label parray and store it in the data memory location with the label obuf.
Solution: The following instruction sequence fetches the specified program memory contents
and then stores it at the specified data memory location:
ldi
ldi
lpm
sts
r30,low (parray661)
r31,high (parray661)
r0, z
obuf, r0
If a pointer to the data memory is desired, then the following instruction sequence should
be used:
ldi
ldi
lpm
ldi
ldi
st
ZL,low (parray661)
ZH, high (parray661)
r0, z
XL, low (obuf)
XH, high (obuf)
x, r0
; set up register z to point to program memory location
; at parray
; set up register x to point to obuf
; set up register x to point to obuf
; store r0 in the data memory location pointed to by x
▲
3.10 Writing Program Loops
Microcontrollers are good at performing repetitive operations. To command a microcontroller to perform a repetitive operation, the user must write a program loop. There are
two types of program loops: a finite loop and an infinite loop. A finite loop is a sequence of
instructions that are executed only a finite number of times whereas an infinite loop is one in
which the microcontroller stays forever.
3.10.1 The Infinite Loop
The AVR provides four unconditional jump instructions (listed in Table 3.4) that can be
used to implement infinite loop. The distance for the rjmp instruction is 2 kW (forward or
backward). The jump distance for the jmp instruction is 4 MW. An infinite loop has the following format:
forever:
…
…
rjmp
forever
Mnemonics
; rjmp can be replaced by one of the other jump instructions
Description
Operation
PC ← [PC] 1 k 1 1
rjmp k
Relative jump
ijmp
Indirect jump to (Z)
PC(15:0) ← [Z], PC(21:16) ← 0
eijmp
Extended indirect jump to (Z)
PC(15:0) ← [Z], PC(21:16) ← EIND
jmp k
Jump
PC(15:0) ← k
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.4
■
AVR unconditional jump instructions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.10
■
63
Writing Program Loops
The jump distance can be positive or negative depending on whether the jump direction
is backward or forward. In practice, the programmer simply uses a label to specify the jump
destination and let the assembler figure out the appropriate value to be placed in the machine
instruction.
A finite loop can be implemented by using one of the following three constructs:
•
•
•
For-loop
While-loop
Repeat-until loop
3.10.2 The For-Loop
The syntax of a for-loop is
For i = n1 to n2 do S or For i = n2 downto n1 do S
i ← i1
i ≤ i2
Yes
i←i+1
Figure 3.2a
S
■
No
For i = i1 to i2 Do S
(b)
i ← i2
i ≥ i1
Yes
i←i–1
Figure 3.2b
S
■
No
Source: Atmel Corporation, The Atmel AVR
Microcontroller
(a)
Source: Atmel Corporation, The Atmel AVR
Microcontroller
where i is the loop index, which runs from n1 to n2 or from n2 down to n1, depending on the
format used (n2 $ n1). The two alternatives for implementing the for-loop are shown in Figure 3.2.
For i = i2 to i1 Do S
The implementation of a for-loop requires the use of a compare instruction to set up the
branch condition, a conditional branch instruction to carry out the action of branch, and an
arithmetic instruction (such as inc or dec) to update the loop index variable. The compare and
conditional branch instructions provided by AVR are listed in Table 3.5 and Table 3.6. Among
them, the breq instruction along with the cp (compare) and the inc (or dec) instruction can be
used to implement the for-loop construct.
A for-loop can be implemented in the following manner:
floop:
exitloop:
.include
.equ
.equ
.def
…
ldi
cpi
breq
…
…
inc
rjmp
..
6m2560def.inc7
n1=1
; loop index lower bound
n2=30
; loop index upper bound
ii = r16
; use r16 for-loop index ii
ii, n1
ii, n2+1
exitloop
ii
floop
; initialize ii to n1
; set up loop exit condition
; branch if loop exit condition is met
; perform loop operation
; "
; update loop index
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
64
Chapter 3
■
AVR Assembly Language Programming
Mnemonics
Description
Operation
cpse Rd, Rr
Compare, skip if equal
If ([Rd] = = [Rr]) PC ← [PC] 1 2 or 3
cp Rd, Rr
Compare
[Rd] 2 [Rr], and update Z, C, N, V, S, H
cpc Rd, Rr
Compare with carry
[Rd] 2 [Rr]2 C, and update Z, C, N, V, S, H
cpi Rd, k
Compare with immediate
[Rd] 2 k, and update Z, C, N, V, S, H; 0 # k # 255
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.5
■
Mnemonics
AVR compare instructions
Description
Operation
sbrc Rr, b
Skip if bit in register cleared
If (Rr(b) = = 0) PC ← [PC] 1 2 or 3
sbrs Rr, b
Skip if bit in register set
If (Rr(b) = = 1) PC ← [PC] 1 2 or 3
sbic A, b
Skip if bit in I/O register cleared
If (I/O(A, b) = = 0) PC ← [PC] 1 2 or 3
sbis A, b
Skip if bit in I/O register set
If (I/O(A, b) = = 1) PC ← [PC] 1 2 or 3
brbs s, k
Branch if status flag set
If (SREG(s) = = 1) then PC ← [PC] 1 k 1 1
brbc s, k
Branch if status flag cleared
If (SREG(s) = = 0) then PC ← [PC] 1 k 1 1
breq k
Branch if equal
If (Z = = 1) then PC ← [PC] 1 k 1 1
brne k
Branch if not equal
If (Z = = 0) then PC ← [PC] 1 k 1 1
brcs k
Branch if carry set
If (C = = 1) then PC ← [PC] 1 k 1 1
brcc k
Branch if carry cleared
If (C = = 0) then PC ← [PC] 1 k 1 1
brsh k
Branch if same or higher
If (C = = 0) then PC ← [PC] 1 k 1 1
brlo k
Branch if lower
If (C = = 1) then PC ← [PC] 1 k 1 1
brmi k
Branch if minus
If (N = = 1) then PC ← [PC] 1 k 1 1
brpl k
Branch if plus
If (N = = 0) then PC ← [PC] 1 k 1 1
brge k
Branch if greater or equal, signed
If (N { V = = 0) then PC ← [PC] 1 k 1 1
brlt k
Branch if less than signed
If (N { V = = 1) then PC ← [PC] 1 k 1 1
brhs k
Branch if half carry set
If (H = = 1) then PC ← [PC] 1 k 1 1
brhc k
Branch if half carry cleared
If (H = = 0) then PC ← [PC] 1 k 1 1
brts k
Branch if T flag set
If (T = = 1) then PC ← [PC] 1 k 1 1
brtc k
Branch if T flag cleared
If (T = = 0) then PC ← [PC] 1 k 1 1
brvs k
Branch if V flag set
If (V = = 1) then PC ← [PC] 1 k 1 1
brvc k
Branch if V flag cleared
If (V = = 0) then PC ← [PC] 1 k 1 1
brie k
Branch if interrupt enabled
If (I = = 1) then PC ← [PC] 1 k 1 1
brid k
Branch if interrupt disabled
If (I = = 0) then PC ← [PC] 1 k 1 1
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.6
■
AVR conditional branch instructions
Example 3.19
▼
Write a program that uses a for-loop to add all the integers from 1 to 100.
Solution: Let i, sum, n1, and n2 refer to loop index, sum, the lower limit, and the upper limit,
then the algorithm for adding all integers from 1 to 100 is as follows:
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.10
■
65
Writing Program Loops
Step 1
i ← n1; sum ← 0
Step 2
if (i 7 n2) then stop; else sum ← sum + i.
Step 3
i ← i + 1; go to Step 2.
The program is as follows:
.include
.equ
.equ
.dseg
.org
sum:
.byte
.def
.def
.def
.cseg
.org
jmp
.org
start:
ldi
ldi
ldi
ldi
loop:
cpi
breq
add
adc
inc
rjmp
done:
sts
sts
rjmp
// end of program
6m2560def.inc7
n1 = 1
n2 = 100
0x200
2
ii
= r16
sumHi = r19
sumLo = r18
0x00
start
0xF6
ii,n1
sumHi,0
sumLo,0
r25,0
ii,n2+1
done
sumLo,ii
sumHi,r25
ii
loop
sum,sumLo
sum+1,sumHi
done
; initialize ii to n1
; initialize sum to 0
; "
; place 0 in r25 for use in the for-loop
; check for-loop index limit
; "
; add ii to the low byte of sum
; add carry to high byte (r25 holds 0)
; save the sum in data memory
; "
As shown in this program, the loop-index test is done at the start of the loop. The last instruction of the loop is a rjmp instruction that causes the program flow to move to the start of
the loop.
▲
3.10.3 The While-Loop
The syntax of a while-loop is as follows:
WHILE C DO S
Whenever a while-loop construct is executed, the logical expression C is evaluated first.
If it yields a false value, statement S is not executed. The action of a while-loop construct is
illustrated in Figure 3.3.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
66
Chapter 3
■
AVR Assembly Language Programming
Initialize C
True Execute S and
update C
C
False
Exit
Figure 3.3
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The flow-control part of a while-loop can be implemented by using one of the conditional
branch instructions shown in Table 3.6. The branch decision may be based on the value of a flag
bit in the status register, a bit in the CPU register, or a bit in an I/O register.
The WHILE ... DO construct
Example 3.20
▼
Write a program to count the number of elements of an array of 8-bit integers that are a
multiple of 4.
Solution: The algorithm for finding the number of elements that are divisible by 4 is as follows:
Use cnt to keep track of the number of elements that are divisible by 4 and use ptr as the
pointer to the array element. A number with bit 1 and bit 0 equal to 00 is divisible by 4.
Step 1
cnt ← 0; ptr ← array; lpcnt ← array count; use the Z register to point to the first element
of the array.
Step 2
If (lpcnt = = 0), then exit.
Step 3
Fetch the array element pointed by ptr.
Step 4
If bit 1 and bit 0 of the fetched element are 00, add 1 to cnt.
Step 5
ptr ← ptr +1; lpcnt = lpcnt - 1.
Step 6
Go to Step 2.
The following program counts the number of array elements that are divisible by 4:
.include
.def
.def
.equ
.cseg
.org
rjmp
6m2560def.inc7
count = r16
lpcnt = r17
NN
= 30
; array count
0x00
start
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.10
■
67
Writing Program Loops
.org
ldi
ldi
ldi
ldi
loop:
cpi
breq
lpm
andi
brne
inc
next:
dec
rjmp
done:
rjmp
array:
.db
.db
.db
// end of program
start:
0xF6
ZL,low(array661)
; use Z to point to the array element
ZH,high(array661)
; "
count,0
; initialize element count to 0
lpcnt,NN
; initialize loop count to NN
lpcnt,0
done
r18,z+
; fetch one array element
r18,0x03
; check bit 1 and 0
next
; bit 1 and 0 are not 00, check next element
count
; increment element count when bit 1,0 = 00
lpcnt
; decrement loop count
loop
done
11,12,13,14,15,16,17,18,19,20
21,22,23,24,25,26,27,28,29,30
31,32,33,34,35,36,37,38,39,40
The first four instructions in Table 3.6 are often used to wait for the I/O operations to complete before continuing other operations. For example, the following instruction sequence waits
until the A/D conversion is completed before collecting the A/D result:
wADC:
lds
sbrs
rjmp
…
r16,ADCSRS
r16,ADIF
wADC
; make a copy of the A/D control and status register
; skip the next instruction if ADIF bit (bit 4) is set
; ADIF bit is not set, so jump back to check again
; collect A/D conversion result
▲
3.10.4 The Repeat-Until Loop
The repeat-S-until-C looping construct is used more often to perform some operation for a certain number of times. The following instruction sequence performs a certain operation N times:
loop:
.equ
.def
…
ldi
…
…
inc
cpi
brne
N
= 20
lpcnt = r16
lpcnt,0
lpcnt
lpcnt,N
loop
; increment loop count
; compare loop count with N
; loop count not equal to N, continue
The same loop can also be implemented using the following template:
loop:
.equ
.def
…
ldi
…
…
dec
brne
N
= 20
lpcnt = r16
lpcnt,N
lpcnt,N
loop
; perform the desired operation
; "
; decrement loop count
; loop count not zero, continue
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
68
Chapter 3
■
AVR Assembly Language Programming
Example 3.21
▼
Write a program to find the maximum element of an array of N 8-bit elements using the
repeat-S-until-C looping construct.
Solution: We use the variable j as the array index and also as the loop count and use the variable
maxVal to hold the array maximum. The logic flow of the program is shown in Figure 3.4.
The assembly program that finds the maximum element of an array of N 8-bit elements is
as follows:
Start
maxVal ← array[0]
j←1
No
Yes
maxVal ← array[j]
j←j+1
No
j = N?
Yes
Stop
Figure 3.4
start:
loop:
.include
.equ
.def
.def
.def
.cseg
.org
rjmp
.org
ldi
ldi
ldi
lpm
lpm
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
maxVal < array[j] ?
Logic flow of Example 3.21
6m2560def.inc7
NN
= 30
j
= r16
maxVal = r17
tmp
= r18
0x00
start
0xF6
ZL,low(array661)
ZH,high(array661)
j,0
maxVal,z+
tmp,z+
; total array count
; array index
; maximum array element
; temporary buffer
; set up array pointer
; "
; set array[0] as maximum
; fetch the next array element and move
; pointer
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.10
■
69
Writing Program Loops
cp
brlt
mov
next:
inc
cpi
brne
here:
rjmp
array:
.db
.db
.db
// end of program
tmp,maxVal
next
; branch if next array element is smaller
maxVal,tmp
; update the array max
j
j,NN-1
; check loop index
loop
here
; forever loop
11,12,13,14,15,16,17,18,19,20
21,22,23,24,25,26,27,28,29,30
31,92,33,34,35,67,40,50,52,80
▲
Example 3.22
▼
Given an array of N 8-bit elements, write a program to swap the first element with the last
element, swap the second element with the second-to-last element, and so on.
Solution: The major steps for swapping the array are as follows:
Step 1
Copy the array from program memory to data memory.
Step 2
Let the variable ptr1 (X register) point to the start of the array and let the variable ptr2
(Y register) point to the end of the array. Use lpcnt as the loop count, and set it to half of
the array count.
Step 3
Fetch the element (call it da) pointed by ptr1, and fetch the element (call it de) pointed to
by ptr2.
Step 4
Store da to the location pointed to by ptr2, and store de to the location pointed to by ptr1.
Increment ptr1 by 1, and decrement ptr2 by 1.
Step 5
Decrement lpcnt by 1.
Step 6
If (lpcnt = = 0) then stop; else go to Step 3.
The following program implements the algorithm described previously:
buf1:
.include
.equ
.dseg
.org
.byte
.def
.cseg
.org
rjmp
.org
6m2560def.inc7
NN=30
0x200
NN
lpcnt = r17
; buffer to hold the array
0x00
start
0xF6
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
70
Chapter 3
■
AVR Assembly Language Programming
start:
ldi
XL,low(buf1)
ldi
XH,high(buf1)
ldi
ZL,low(array661)
ldi
ZH,high(array661)
ldi
lpcnt,NN
cloop:
lpm
r0,z+
st
x+,r0
dec
lpcnt
brne
cloop
// swap operation start from here
ldi
XL,low(buf1)
ldi
XH,high(buf1)
ldi
YL,low(buf1+NN)
ldi
ldi
ld
ld
swloop:
YH,high(buf1+NN)
lpcnt,NN/2
r0,x
r1,-y
st
st
dec
brne
here:
rjmp
array:
.db
.db
.db
// end of program
; set up pointer to buf1
; "
; set up pointer to array
; "
; set up loop count to copy array
; loop to copy array to data memory
; "
; X points to the start of the array
; "
; Y points to the byte after the end of the
; array
; "
; loop count for swapping the array
; fetch an element from one side of the array
; fetch an element from other side of the
; array
; store at the other side of the array
; "
; decrement loop count
x+,r1
y,r0
lpcnt
swloop
here
11,12,13,14,15,16,17,18,19,20
21,22,23,24,25,26,27,28,29,30
31,32,33,34,35,36,37,38,39,40
▲
3.11 Shift and Rotate Instructions
The user may need to manipulate a bit field of a register. To perform this type of operation,
the user can use the group of instructions shown in Table 3.7. Any one of the 32 CPU registers
can be the operand of these instructions. All rotate and shift instructions involve the C flag in
the operation.
Mnemonics
Description
Operation
lsl Rd
Logical shift left
Rd(n 1 1) ← Rd(n), Rd(0) ← 0, C ← Rd(7), n = 0..6
lsr Rd
Logical shift right
Rd(n) ← Rd(n 1 1), Rd(7) ← 0, C ← Rd(0), n = 0..6
rol Rd
Rotate left through carry
Rd(n 1 1) ← Rd(n), Rd(0) ← C, C ← Rd(7), n = 0..6
ror Rd
Rotate right through carry
Rd(n) ← Rd(n 1 1), Rd(7) ← C, C ← Rd(0), n = 0..6
asr Rd
Arithmetic shift right
Rd(n) ← Rd(n 1 1), n = 0..6; Rd(7) ← Rd(7)
swap Rd
Swap nibbles
Rd(3..0) ↔ Rd(7..4)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.7
■
AVR shift and rotate instructions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.11
■
71
Shift and Rotate Instructions
Example 3.23
▼
Assume that the contents of register r1 and carry flag are 0x5D and 1, respectively. What are
the new values for r1 and C after the execution of each of the instructions listed in Table 3.7?
Solution: The new values of r1 and C after the execution of each instruction in Table 3.7 are as
follows:
(a) After executing the lsl r1 instruction, the contents of r1 and C are 0xBA and 0,
respectively (shown in Figure 3.5a).
C
Register r1
1
0
Before 1
1
0
1
1
1
0
0
After 0
1
0
1
1
1
0
1
0
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 3.5a
■
Execution result of lsl r1
(b) After executing the lsr r1 instruction, the contents of r1 and C are 0x2E and 1,
respectively (shown in Figure 3.5b).
C
Register r1
Before
0
1
0
1
1
1
0
1
1
0
0
1
0
1
1
1
0
1
0
After
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 3.5b
■
Execution result of lsl r1
(c) After executing the rol r1 instruction, the contents of r1 and C become 0xBB and 0,
respectively (shown in Figure 3.5c).
C
Before
After
0
Register r1
C
0
1
0
1
1
1
0
1
1
0
1
1
1
0
1
1
1
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 3.5c
■
Execution result of lsl r1
(d) After executing the ror r1 instruction, the contents of r1 and C become 0xAE and 1,
respectively (shown in Figure 3.5d).
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
72
Chapter 3
■
AVR Assembly Language Programming
C
Register r1
Before 1
0
1
0
1
1
1
0
1
After
1
0
1
0
1
1
1
0
C
1
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 3.5d
■
Execution result of lsl r1
(e) After executing the swap r1 instruction, the contents of r1 become 0xD5 and the
value of C does not change.
▲
A shift-right instruction can be used to divide a number by a power of 2 and a shift-left
instruction can be used to multiply a number by a power of 2. When a multibyte number is to
be multiplied or divided by a power of 2, we need to shift multiple bytes either to the left or to
the right. However, the AVR does not have an instruction that does this. Suppose the number
has k bytes and the least significant byte is stored at loc. The remaining bytes are located at loc
1 1, loc 1 2, …, loc 1 k 2 1, respectively, as shown in Figure 3.6.
loc
loc+1
loc+k–1
...
lsb
msb
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 3.6
■
k bytes to be shifted
The logical shift-one-bit-to-the-right operation to this multiple-byte number is performed
in the following manner:
•
Bit 7 of each byte receives bit 0 of its adjacent more significant byte (on
its immediate right) with the exception of the most significant byte, which
receives a 0.
•
Each byte is shifted to the right by one bit. Bit 0 of the least significant byte is
shifted out and lost.
The operation can therefore be implemented as follows:
Step 1
Shift the byte at loc + k - 1 to the right one place (using the lsr Rd instruction).
Step 2
Rotate the byte at loc + k - 2 to the right one place (using the ror Rd instruction).
Step 3
Repeat step 2 for the remaining bytes.
By repeating this procedure, the given k-byte number can be shifted to the right as many bits
as desired. Because we store the most significant byte in the location with the highest address,
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.11
■
73
Shift and Rotate Instructions
this right-shift operation is in the logical sense rather than in the spatial sense. The operation
to shift a multibyte number to the left should start from the lsb (leftmost byte) and rotate the
remaining bytes to the msb (rightmost byte).
Example 3.24
▼
Write a program to shift the 32-bit number stored at 0x200~0x203 in data memory to the
right four places.
Solution: The least significant to the most significant bytes are stored at 0x200~0x203. The
logical shift-right operation is performed from 0x203 to 0x200. The assembly program that performs the desired operation is as follows:
.include
.equ
.equ
.equ
.equ
.def
.dseg
.org
buf:
.byte
.cseg
.org
rjmp
.org
start:
ldi
ldi
ldi
ldi
sts
sts
sts
sts
ldi
srloop:
lsr
ror
ror
ror
dec
brne
sts
sts
sts
sts
nop
// end of program
6m2560def.inc7
bt3 = 0x79
bt2 = 0x86
bt1 = 0x53
bt0 = 0x42
lpcnt = r16
; msb of test data
;
;
; lsb of test data
0x200
4
; set to 0x2000 for XMega devices
; buffer to hold right-shift result
0x00
start
0xF6
r17,bt3
r18,bt2
r19,bt1
r20,bt0
buf+3,r17
buf+2,r18
buf+1,r19
buf,r20
lpcnt,4
r17
r18
r19
r20
lpcnt
srloop
buf+3,r17
buf+2,r18
buf+1,r19
buf,r20
; msb
; second to msb
; second to lsb
; lsb
; initialize msb in data memory
; initialize second to msb in data memory
; initialize second to lsb in data memory
; initialize lsb in data memory
; set up loop count
; shift the msb to the right one place
; rotate the second to msb to the right one place
; rotate the second to lsb to the right one place
; rotate the lsb to the right one place
; decrement loop count
; save the msb in data memory
; save the second to msb in data memory
; save the second to lsb in data memory
; save the lsb in data memory
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
74
Chapter 3
■
AVR Assembly Language Programming
3.12 Boolean Instructions
Boolean instructions can be used to change a few bits of output PORT pins. A summary of
the AVR Boolean instructions is given in Table 3.8.
Mnemonics
Description
Operation
and Rd, Rr
Logical AND
Rd ← [Rd] • [Rr]
andi Rd, k
Logical AND with immediate
Rd ← [Rd] • k
or Rd, Rr
Logical OR
Rd ← [Rd] ~ [Rr]
ori Rd, k
Logical OR with immediate
Rd ← [Rd] ~ k
eor Rd, Rr
Exclusive OR
Rd ← [Rd] { [Rr]
com Rd
One’s complement
Rd ← 0xFF - [Rd]
neg Rd
Two’s complement
Rd ← 0x00 - [Rd]
sbr Rd, k
Set bit (s) in register
Rd ← [Rd] ~ k
cbr Rd, k
Clear bit (s) in register
Rd ← [Rd] • (0xFF - k)
tst Rd
Test for zero or minus
Rd ← [Rd] • [Rd]
clr Rd
Clear register
Rd ← [Rd] { [Rd]
set Rd
Set register
Rd ← 0xFF
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.8
■
A summary of AVR Boolean instructions
The and instruction can be used to clear one or a few bits, and the or instruction can be
used to set one or a few bits within a byte. The exclusive or instruction can be used to toggle
(change from 0 to 1 and from 1 to 0) one or a few bits within a byte. For example, the instruction
sequence
in
andi
out
r16, PORTB
r16, 0x0F
PORTB,r16
; read PORTB (located at 0x05)
; clear the upper four bits
; store back to PORTB
clears the upper four bits of PORTB. This operation can also be performed by the following
instruction sequence:
in
cbr
out
r16,PORTB
r16,0xF0
PORTB,r16
; read PORTB
; clear the upper 4 bits
; store back to PORTB
The instruction sequence
in
ori
out
r16, PORTB
r16, 0x02
PORTB, r16
; read PORTB
; set bit 1 to 1
; store back to PORTB
sets the bit 1 of PORTB to 1. This operation can also be performed using the following instruction sequence:
in
sbr
out
r16,PORTB
r16,0x02
PORTB,r16
; read PORTB
; set bit 1 to 1
; store back to PORTB
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.13
■
75
Bit Manipulating Instructions
The instruction sequence
in
ldi
eor
out
r16, PORTB
r17, 0x0F
r16, r17
PORTB,r16
toggles the lower 4 bits of PORTB. The com instruction can be used if all the PORT pins have
to be toggled.
3.13 Bit Manipulating Instructions
The AVR also provides a group of bit manipulating instructions (listed in Table 3.9) that
allow the user to change the value of a bit or copy a bit from one register to another. These
instructions can be useful in performing control operations. The constants s and b in Table 3.9
specify the bit position to be manipulated.
Mnemonics
Description
Operation
bset s
Flag set
SREG(s) ← 1
bclr s
Flag clear
SREG(s) ← 0
sbi A, b
Set bit in I/O register
I/O(A, b) ← 1
cbi A, b
Clear bit in I/O register
I/O(A, b) ← 0
bst Rr, b
Bit store from register to T
T ← Rr(b)
bld Rr, b
Bit load from T to register
Rd(b) ← T
sec
Set carry
C←1
clc
Clear carry
C←0
sen
Set negative flag
N←1
cln
Clear negative flag
N←0
sez
Set zero flag
Z←1
clz
Clear zero flag
Z←0
sei
Enable global interrupt
I←1
cli
Disable global interrupt
I←0
ses
Set signed test flag
S←1
cls
Clear signed test flag
S←0
sev
Set 2’s complement overflow
V←1
clv
Clear 2’s complement overflow
V←0
set
Set T in SREG
T←1
clt
Clear T in SREG
T←0
seh
Set half carry flag in SREG
H←1
clh
Clear half carry flag in SREG
H←0
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 3.9
■
A summary of the AVR bit manipulation instructions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
76
Chapter 3
■
AVR Assembly Language Programming
The instruction
sbi
SPCR,SPE
; SPE is bit 6 of the SPCR register
sets the bit 6 of the SPCR register and enables the serial peripheral interface (SPI).
The instruction
cbi
SPCR,SPIE
; SPIE is the bit 7 of the SPCR register
clears the bit 7 (SPIE bit is the bit 7 of the SPCR register) and disables the SPI interrupt to the
MCU.
The sbi and cbi instructions may also be used to set or clear a bit in an I/O PORT data register, which can then pull the associated pin voltage to high or low. This capability is often used
to enable and disable the functioning of a peripheral chip.
3.14 Create Time Delay Using Program Loops
The AVR instruction execution is controlled by the CPU clock. This clock signal is often
generated by using an external crystal oscillator. One AVR instruction may take from one to
five CPU clock cycles to complete. The execution time of each AVR instruction can be found
in Appendix A.
There are many applications that require the generation of time delays. Program loops are
often used to create a certain amount of delay unless the time delay needs to be very accurate.
The creation of a time delay involves two steps:
Step 1
Select a sequence of instructions that take a certain number of CPU clock cycles to
execute.
Step 2
Repeat the instruction sequence for an appropriate number of times.
For example, the following instruction sequence takes 32 CPU clock cycles to execute:
loop0:
push
pop
push
pop
push
pop
push
pop
push
pop
push
pop
push
pop
nop
dec
brne
r0
r0
r0
r0
r0
r0
r0
r0
r0
r0
r0
r0
r0
r0
r21
loop0
; 2 CPU clock cycles
; 2 CPU clock cycles
; 1 CPU clock cycle
; 1 CPU clock cycle
; take 2 (1) CPU clock cycles when branch is taken (not taken)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.15
■
77
Summary
This instruction sequence can be shortened by using a program loop as follows:
loop0:
loopi:
ldi
push
pop
dec
brne
dec
brne
r20,4
r0
r0
r20
loopi
r21
loop0
; 1 cycle
; 2 clock cycles
; 2 clock cycles
; 1 CPU clock cycle
; 2 (1) cycle when branch is taken (not taken)
; 1 cycle
; 2 (1) cycle when branch is taken (not taken)
The created time delay is set by the CPU clock frequency. Suppose the CPU clock frequency
is 16 MHz; then the previous instruction sequence takes 2 µs to execute. To create a time delay
of 0.5 ms, we need to load 250 into the r21 register. The following instruction sequence creates
a time delay of 0.5 ms when the CPU clock frequency is 16 MHz:
loop0:
loopi:
ldi
ldi
push
pop
dec
brne
dec
brne
r21,250
r20,4
r0
r0
r20
loopi
r21
loop0
; set loop count to 250
; 1 cycle
; 2 clock cycles
; 2 clock cycles
; 1 CPU clock cycle
; 2 (1) cycle when branch is taken (not taken)
; 1 cycle
; 2 (1) cycle when branch is taken (not taken)
A longer time delay can be created by using a multilayer loop. For example, the following
instruction sequence can create a time delay of 100 ms:
loop1:
loop0:
loopi:
ldi
ldi
ldi
push
pop
dec
brne
dec
brne
dec
brne
r16,200
r21,250
r20,4
r0
r0
r20
loopi
r21
loop0
r16
loop1
; set external loop count to 200
; set loop count to 250
; 1 cycle
; 2 clock cycles
; 2 clock cycles
; 1 CPU clock cycle
; 2 (1) cycle when branch is taken (not taken)
; 1 cycle
; 2 (1) cycle when branch is taken (not taken)
The time delay created by using program loops is not accurate. Some overhead is required
to set up the loop count. For example, the one-layer loop has one clock cycle overhead, whereas
the two-layer loop has much more overhead.
Overhead = 1 CPU cycle + 200 * (1 + 1 + 2) = 801 CPU cycles = 50 µs (at 16 MHz CPU clock frequency)
3.15 Summary
An assembly language program consists of three types of statements: assembler directives,
assembly language instructions, and comments. An assembler directive tells the assembler how
to process subsequent assembly language instructions. Directives also provide a way for defining constants and reserving space for dynamic variables. A statement of an assembly program
consists of four fields: label, operation code, operands, and comment.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
78
Chapter 3
■
AVR Assembly Language Programming
Although the AVR can perform only 8-bit arithmetic operations, numbers that are longer
than 8 bits can still be added, subtracted, or multiplied by performing multiprecision arithmetic.
The multiprecision addition can be implemented by using the add-with-carry (adc) instruction,
and multiprecision subtraction can be performed by using the subtract-with-carry (sbc) instruction. To perform multiprecision multiplication, both the multiplicand and the multiplier must
be divided into 8-bit chunks. The next step is to generate partial products and align them properly before adding them together. A subroutine that performs multiprecision multiplication is
described in Chapter 5. Multiprecision division is performed by repeated shifting and subtraction method and also is detailed in Chapter 5.
Performing repetitive operations is the strength of a microcontroller and microprocessor.
For a computer to perform repetitive operations, we have to write program loops to tell the
computer what instruction sequence to repeat and how many times to repeat. Two components
are required in implementing a finite loop: one is the test of loop termination condition, and
the second is the change of program flow. The AVR and all microcontrollers provide instructions for both operations. The AVR also provides instructions for initializing and updating variables and loop indices.
The AVR instruction set includes many logical instructions, which may be useful for
implementing control and I/O applications.
Shift and rotate instructions are useful for bit field operations. They can also be used to
implement multiplication and division by a power of 2. All shift and rotate instructions can
operate on any of the 32 CPU registers. When required, we can write a sequence of instructions
to shift a number longer than 8 bits.
It is important to provide test data for the program being developed. A common method
is by using assembler directives such as db or dw to define numbers or strings to be tested in
program memory. If the program has to modify the test data, then you need to copy the test data
from program memory to data memory.
Time delays are useful in many applications. A time delay can be created by repeating a
sequence of instructions for a certain number of times. Depending on the length of the delay,
the programmer may need to use a multiple-layer program loop to create a time delay.
3.16 Exercises
E3.1 Write assembler directives to define the ASCII codes of letters a to z in program memory.
E3.2 Write assembler directives to define the ASCII codes of digits 0 to 9 in program memory
starting from address 0x1000.
E3.3 Invoke the setPointer macro defined in Section 3.5.8 to load the address 0x3000 into Y
register.
E3.4 Write a program to add the 16-bit numbers stored at data memory locations 0x210~0x211
and 0x220~0x221, respectively, and store the sum at 0x230~0x231.
E3.5 Write a program to add the 24-bit numbers stored at data memory locations 0x200~0x202
and 0x203~0x205, respectively, and store the sum at 0x206~0x208.
E3.6 Write a program to add the 32-bit numbers stored at data memory locations 0x200~0x203
and 0x204~0x207, respectively, and store the sum at 0x208~0x20B.
E3.7 Write a program to subtract the 16-bit number stored at 0x200~0x201 from the 16-bit
number stored at 0x202~0x203, and store the difference at 0x204~0x205.
E3.8 Write a program to subtract the 24-bit number stored at 0x200~0x202 from the 24-bit
number stored at 0x203~0x205 and store the difference at 0x206~0x208.
E3.9 Write a program to subtract the 32-bit number stored at 0x200~0x203 from the 32-bit
number stored at 0x204~0xx207 and store the difference at 0x208~0x20B.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
3.16
■
Exercises
79
E3.10 Write a program to find the total elements of an array of 8-bit integers that have bit
2, 3, and 4 set to 1. Use the repeat-until looping construct. Assume the array is in the program
memory.
E3.11 Write a program to swap the upper 4 bits with the lower 4 bits of every element of an
array of 8-bit integers. The initial array is stored in the program memory and you must copy
this array to the data memory for testing purpose.
E3.12 Write a program to find the total number of elements in an array of 8-bit integers that are
larger than 20. Use the for-loop looping construct.
E3.13 Write a program to find the total number of elements in an array of 8-bit integers that are
greater than 30 and less than 100. Use the for-loop looping construct.
E3.14 Write a program to find the total number of elements in an array of 8-bit integers that are
greater than 100 or less than 30. Use the repeat-until looping construct to implement the loop.
E3.15 Write a program to set the bit 7 and bit 0 of all the elements of an array to 1.
E3.16 Assume that the contents of register r0 and carry flag are 0x79 and 0, respectively. What
are the new values for r0 and C after the execution of each of the instructions listed in Table 3.7?
E3.17 Assume that the contents of the register r16 and carry flag are 0xA6 and 1, respectively.
What are the new values for r16 and C after the execution of each of the instructions listed in
Table 3.7?
E3.18 Write an instruction sequence to create a time delay of 1 second.
E3.19 Write a program to copy a block of memory locations from one area to another area in
data memory.
E3.20 Write a program to find the largest element, the smallest element, and their average of an
array of 8-bit elements. Store these three numbers in data memory starting from 0x200.
E3.21 What are the values stored in registers r1 and r0 after the execution of the instruction
mul r16, r17 if r16 and r17 originally contain the following values?
(a) 0x58 and 0x37
(b) 0x29 and 0x49
E3.22 Write a program to shift the 32-bit number stored at 0x200~0x203 in data memory to the
left four places. The msb to lsb are stored from 0x203 toward 0x200, respectively.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4
Hardware and Software
Development Tools
for the AVR
4.1 Objectives
After completing this chapter, you will be able to
• Understand the type of hardware
development tools available for learning AVR
microcontroller.
• Understand the type of software
development tools available for learning AVR
microcontroller programming.
• Use the AVR Studio IDE to enter, assemble,
and download programs onto a demo board for
execution.
• Use the AVR Studio IDE to debug AVR
assembly programs.
• Learn the strategy for program debugging.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
82
Chapter 4
■
Hardware and Software Development Tools for the AVR
4.2 Development Tools for the Atmel AVR
Microcontroller development tools are divided into two categories: hardware tools and
software tools. Hardware tools support device programming, program execution, and software
debugging, whereas software tools allow programs to be entered, assembled/compiled, linked,
and executed.
4.3 Hardware Development Tools
The microcontroller demo board, programmer, and debug adapter are the most useful hardware tools for learning the AVR MCU.
4.3.1 Choosing a Demo Board for Learning the AVR
What type of demo board is good for learning the AVR microcontroller? To answer this
question, we need to think about the I/O functions and the peripheral chips that we have to
deal with during the learning process. A semester-long course would be able to cover general
I/O PORTs, interrupts, timer functions, universal asynchronous receiver transmitter (UART)
PORT, serial peripheral interface (SPI), two-wire interface (TWI), A/D converter, and D/A converter. A demo board that provides one or two peripheral chips for learning each of these peripheral functions would be very desirable.
•
I/O PORT. The inexpensive dual-in-line package (DIP) switches are used to provide
input to the user program. The light-emitting diodes (LEDs) are inexpensive output
devices that are used to practice output function and validate the time delays
created by program loops or the timer function. Liquid crystal displays (LCDs) are
useful for displaying a large quantity of information. A demo board should at least
provide these three types of I/O devices.
•
Interrupt input. A demo board should add one or two debounced switches for
testing external interrupt sources. An interrupt pin is also used to perform
interrupt-driven input.
•
Timer functions. I/O pins related to timer functions must be made available to the
user.
•
UART PORT. By providing a 9-pin connector with the UART PORT, the demo
board can communicate with a PC via the COM PORT. This PORT has been useful
in providing users with keyboard input and terminal window output in the past.
However, almost all PCs have eliminated the COM PORT and the HyperTerminal
program. This feature will be harder to use in the future.
•
SPI interface. Semiconductor vendors have provided many peripheral chips with
the SPI interface. For example, D/A converter, A/D converter, shift register,
EEPROM, SRAM, real-time clock (RTC), digital temperature sensor, seven-segment
display driver, and so on. Having one or two peripheral chips with the SPI interface
on the demo board, to allow the user to practice SPI read and write operations,
would be helpful for learning the SPI function.
•
TWI (or I2C interface) interface. This interface allows the AVR to use two pins to
communicate with many peripheral chips. Like the SPI interface, semiconductor
vendors have provided a wide variety of peripheral chips with the TWI (or I2C)
interface. Examples include thermostat, A/D converter, D/A converter, real-time
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.3
■
83
Hardware Development Tools
clock, EEPROM, SRAM, and so on. Having one or two peripheral chips with the
TWI interface is very helpful for learning this function.
•
A/D converter. In order to test the on-chip A/D converter, the demo board should
provide at least a potentiometer. An additional temperature sensor or other sensors
such as humidity or barometric senor are very helpful for testing the A/D function.
•
D/A converter. Some AVR devices (XMega AVR MCUs) provide an on-chip D/A
converter. The demo board has to make the D/A output pins available to the user.
In addition to providing many peripheral chips and I/O devices to the user, the demo board
should also make all signal pins available to the user so that he or she can experiment with
other peripheral chips.
Some people may argue that using a bare kit that only makes I/O signals available to the
user forces the user to do more wiring and hence to learn more during the process. This argument may be true for those peripheral chips in the DIP package. However, many peripheral
chips are using the surface-mount package (difficult to handle), which might frustrate the user
during the learning process.
The demo board must also have a connector to connect to a debug adapter or programmer
so that the user can download the program onto the demo board for execution. A JTAG (joined
test action group) and ISP (in-system programming) connectors are required for this purpose.
4.3.2 The EasyAVR M1280 Demo Boards
© Cengage Learning 2014
This demo board is made by AVRVI (website at www.avrvi.com or www.enshop.avrvi.com).
A photograph of this demo board is shown in Figure 4.1.
Figure 4.1
■
The EasyAVR M1280 M1280 Demo Boards
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
84
Chapter 4
■
Hardware and Software Development Tools for the AVR
The EasyAVR provides the following features:
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Mega1280 MCU with 128 kB flash memory
On-board AVRISP MKII USB interface for on-chip programming
External ISP and JTAG interface debugging
UART 9-pin communication connector
74HC4060 variable frequency square wave output
Four 7-segment displays
8 LEDs
I2C real-time clock chip DS1337
Analog temperature sensor TC1047A
Digital temperature sensor TC72 with SPI interface
I2C EEPROM AT24C01
12-bit resolution MCP4922 DAC with SPI interface
Buzzer
CAN bus circuit with MCP2515 CAN controller
2 3 16 character LCD
4 3 4 keypad
PS/2 keyboard connector
Potentiometer
4 buttons
4.3.3 Stingray XMega Demo Board
The Stingray demo board is an XMega demo board from Xbit Inc. A photograph of the
Stingray is shown in Figure 4.2. The Stingray XMega demo board provides the following
features:
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Atmel ATXMega128A1 MCU
Onboard USB programmer
All pins routed to external female headers
Can be powered from USB, wall jack, or 9 V battery
2.048 V ADC reference voltage
16 MHz crystal capable of creating a 32 MHz system clock
8 slide switches
8 LEDs
4 debounced push buttons
16 3 2 character LCD
6-digit, 7-segment displays (driven by two 74HC595 shift registers)
Potentiometer (connected to the A/D converter input)
Analog temperature sensor MCP9700 (connected to the A/D converter)
UART 9-pin connector
JTAG and PDI connectors for program programming and debugging
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.3
■
85
Hardware Development Tools
Buzzer
Variable frequency outputs
I2C 8-kbit EEPROM 24AA08
I2C temperature sensor TCN75A
I2C real-time clock chip DS1337
CAN controller MCP2515 and CAN driver MCP2551
SPI EEPROM 25AA080D
Digital temperature sensor TC72
© Cengage Learning 2014
•
•
•
•
•
•
•
•
Figure 4.2
■
The Stingray XMega demo board from Xbit Inc.
4.3.4 Arduino Demo Kits
Arduino is an open-source electronics prototyping platform consisting of hardware and
software. Arduino provides several predesigned boards for the user to adapt to his or her
applications. Examples are Uno, Nano, Mega2560 (shown in Figure 4.3), Arduino Ethernet,
and so on. These boards are based on AVR MCUs. Arduino also has boards called shields
that can be mounted on top of the Arduino board to extend the functionality of Arduino to
control different devices, acquire data, and so forth. Motor shield and Ethernet shield are
examples. The hardware reference designs (CAD files) are available under an open-source
license; users are free to adapt them to their needs. These boards are bare kits and hence are
inexpensive.
The microcontroller on an Arduino board is programmed using the Arduino programming
language and the Arduino development environment. The Arduino development environment
provides a simple text editor for the user to enter the program (referred to as a sketch) in Arduino programming language. After the sketch is entered properly, the user can then upload it to
the Arduino board for execution. The Arduino development environment also provides a library
of functions to simplify the programming task for the user.
The Arduino environment does not have the debugging capabilities available in the AVR
Studio IDE. More information about Arduino can be found at www.arduino.cc. Books on how to
use and program the Arduino kits are available [5,6,7,8].
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 4
■
Hardware and Software Development Tools for the AVR
© Cengage Learning 2014
86
Figure 4.3
■
Arduino Mega2560 demo kit
4.3.5 Debug Adapters from Atmel
Atmel produces several debug adapters to support the software debugging of AVR applications: AVR Dragon, JTAGICE3, JTAGICE mkII, and AVR ONE!.
AV R D R A G O N
© Cengage Learning 2014
The AVR Dragon is an inexpensive debug adapter that programs and supports software
debugging for all AVR devices. A photograph of the AVR Dragon is shown in Figure 4.4. The
AVR Dragon allows the user to use four different interfaces (including JTAG, high-Voltage,
Parallel, and in-system programming (ISP)) to program the target AVR device and also supports
two debug interfaces (JTAG and debug Wire (dW)).
Figure 4.4
■
Atmel Dragon debug adapter
J TA G I C E 3
Shown in Figure 4.5, the JTAGICE3 is the newest debug adapter (introduced in June 2011)
from Atmel. This debug adapter supports the debugging of software for all 8-bit and 32-bit AVR
devices using the JTAG, aWire, SPI and PDI interfaces.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
87
Hardware Development Tools
© Cengage Learning 2014
4.3
Figure 4.5
J TA G I C E
■
Atmel JTAGICE 3 debug adapter
MKII
© Cengage Learning 2014
A photograph of JTAGICE mkII is shown in Figure 4.6. The JTAGICE mkII supports
programming and software debugging for all 8-bit and 32-bit AVR devices using five interfaces,
including the JTAG, PDI, debugWIRE, SPI, and aWire.
Figure 4.6
■
Atmel JTAGICE mkII debug adapter
AV R O N E !
AVR ONE! is the most expensive debug adapter from Atmel. It supports the device programming using the SPI, JTAG, PDI, and a Wire programming modes and debugging using the
debugWIRE, JTAG, PDI, and aWire interfaces for all 8-bit and 32-bit AVR devices. It also supports LiveDebug, which makes it possible to attach to a running target nonintrusively, and the
Nexus auxiliary interface for high-speed program, data, or ownership trace at up to 200 MHz in
either buffered or streaming mode. A photograph of AVR ONE! is shown in Figure 4.7.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 4
■
Hardware and Software Development Tools for the AVR
© Cengage Learning 2014
88
Figure 4.7
■
Atmel AVR ONE! debug adapter
4.4 Software Development Tools
To develop software to be run on an AVR demo board, we need a text editor to enter the
program, an assembler and compiler to assemble and compile the program, a linker to resolve
variables and subroutines cross-referencing and memory assignment, a simulator and a debugger to debug the software being developed. A project manager is also needed to coordinate the
overall debug activities. These pieces of software are often integrated into a single package
called integrated development environment (IDE). For example, the IAR Embedded Workbench
IDE provides an AVR assembler, a C compiler, a linker, a librarian, a simulator, a project manager, and debugging support for the Atmel JTAGICE mkII debug adapter.
Atmel provides a freeware AVR Studio IDE to support its customers in developing AVR
application software. The AVR Studio version 5 and later contain a project manager; an AVR
assembler; a C compiler; a linker; an AVR simulator; support for several debug adapters, including Dragon, JTAGICE3, JTAGICE mkII, and AVR One!; and support for many starter kits from
Atmel. With the AVR Studio, the user has an IDE that allows the user to use both the assembly and C languages to develop application software. This text uses the AVR Studio version 5
to enter and test all of the AVR assembly and C programs. The AVR Studio IDE version 4 and
WINAVR C compiler are also included in the complimentary CD for those who preferred not to
migrate to version 5.
4.5 Using the AVR Studio IDE
The procedure for developing a program includes the following major steps:
Step 1
Create a project.
Step 2
Enter the program.
Step 3
Assemble or compile (also called build) the project and eliminate syntax errors.
Step 4
Debug the program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.5
■
89
Using the AVR Studio IDE
4.5.1 Create a Project
Source: Atmel Corporation, The Atmel AVR Microcontroller
The AVR Studio is started by selecting StartãAll ProgramsãAtmel AVR toolsãAVR Studio
5.0 or clicking on its icon. The startup screen is shown in Figure 4.8. The startup screen displays
a few recent projects. The user can choose to work on a recent project by selecting it and clicking on Open Project… or start a new project by clicking on New Project… on the startup screen
in Figure 4.8. If the user clicks on New Project…, the screen changes to that in Figure 4.9.
Figure 4.8
■
AVR Studio startup screen
The user should click on AVR Assembler if he or she wants to develop a program in assembly language. The user should also enter the project name and specify the project location
(directory). The Solution name is forced to be identical to the project name. The screen changes
to that in Figure 4.10 after AVR Assembler is selected (the project name is set to tutor1).
After the user is satisfied with the project name and location, he or she should click on
OK; a pop up dialog appears for the user to select the target device, as shown in Figure 4.11.
After selecting the target device and clicking on OK, the screen changes to that seen in
Figure 4.12.
The window with the title “tutor1.asm” in Figure 4.12 is where the new program is
entered. The sizes of these windows may not be appropriate to work with. The user can resize
the windows before entering the program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 4
■
Hardware and Software Development Tools for the AVR
Source: Atmel Corporation, The Atmel AVR Microcontroller
90
■
AVR Studio screen after clicking on New Project in Figure 4.8
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.9
Figure 4.10
■
AVR IDE screen after creating a new assembler project
4.5.2 Enter the Program
In the following, we use a program that finds the total number of elements in an array of
8-bit numbers that are greater than 30 but smaller than 100 as an example to illustrate the program debug process. The screen after entering the program is shown in Figure 4.13.
4.5.3 Assemble (or build) the Project
To assemble (or build) the program, press Build menu and select Build Solution, as shown
in Figure 4.14. The user can also press the function key F7 to build the project.
There might be syntax or semantic errors during the assembling process. The AVR Studio outputs error messages corresponding to the errors. An example of two semantic errors
is shown in Figure 4.15. The error list indicates the error causes and the lines that contain
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
91
Using the AVR Studio IDE
Source: Atmel Corporation, The Atmel AVR Microcontroller
4.5
■
AVR Studio pop up dialog for device selection
Figure 4.12
■
AVR Studio screen after device is selected
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.11
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 4
■
Hardware and Software Development Tools for the AVR
Source: Atmel Corporation, The Atmel AVR Microcontroller
92
■
AVR Studio screen after entering an assembly program
Figure 4.14
■
Build project dialog
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Figure 4.13
the error. When the user clicks on the error message, the AVR Studio moves the cursor to the
program line that contains the error. The two lines in error use an invalid register as their destination. By changing the line .def lpcnt = r15 to .def lpcnt = r19 and changing .def count = r13 to
.def count = r20, the errors are fixed. The ldi Rd, k instruction requires Rd to be from r16 to r31.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
93
Using the AVR Studio IDE
Source: Atmel Corporation, The Atmel AVR Microcontroller
4.5
Figure 4.15
■
Project build with semantic errors
4.5.5 Program Execution and Debugging
The user can choose to use either the simulator (simulation) or the target hardware
(emulation; a debug adapter is needed). There are three methods to start program execution and
debugging in the AVR Studio, as shown in Figure 4.16.
1. Start debugging. In this method, the AVR Studio launches the debugging/emulation
tool, which immediately starts an emulation session. Your program is executed
immediately in this method. This method also can be selected by pressing the
function key F5.
2. Start debugging and break. The AVR Studio launches the debugging tool and starts
the simulation/emulation with a breakpoint set at the entry point of the produced
executable file. On encountering the breakpoint, the simulator suspends the program
run. This method is also selected by pressing the function key F10.
3. Start without debugging. AVR Studio launches the debugging tool, but not the
emulation session, which means that you can set up a breakpoint with ease
before the launch. Pressing the function key F5 and the CTRL key also starts this
method.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
94
Chapter 4
■
Hardware and Software Development Tools for the AVR
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.16
■
Methods for starting debugging and program execution
Source: Atmel Corporation, The Atmel AVR Microcontroller
The screen after the second method used is shown in Figure 4.17. A yellow arrow at the
left-hand side of the program window points to the instruction (jmp start) located at address x,
where instruction execution is to be started.
Figure 4.17
■
AVR Studio screen after the second debugging method is chosen
S E T U P W AT C H L I S T
The Watch window is used to watch the value changes of program variables during the
program execution process. The Watch window has the word Watch on its upper-left corner.
The Watch window is available only when the debug session has been started. A variable can
be added to the Watch window by pressing the right mouse button on the variable (lpcnt) and
selecting Add Watch, as shown in Figure 4.18. After this, the variable is added into the Watch
window, as shown in Figure 4.19.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
95
Using the AVR Studio IDE
Source: Atmel Corporation, The Atmel AVR Microcontroller
4.5
■
Screen for adding a variable (lpcnt) to the watch window
Figure 4.19
■
AVR Studio Watch window with two variables added
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.18
RESETTING
THE
MCU
Make sure that the target MCU is reset before running the program. The program counter
of the target MCU is forced to 0 after a reset. There are three methods to reset the MCU:
•
•
•
Press Debug and select Reset.
Press the Reset button, as shown in Figure 4.20.
Press the key combination of Shift+F5.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
96
Chapter 4
■
Hardware and Software Development Tools for the AVR
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.20
SETTING
A
■
Press Reset button to reset the MCU
BREAKPOINT
Source: Atmel Corporation, The Atmel AVR Microcontroller
A breakpoint is the address of an instruction where program execution stops. After we
select Start without debugging from the Debug menu, AVR Studio builds the project but does
not start the debug session. The user can set breakpoints in this mode and the start-debuggingand-break mode. A breakpoint is set by pressing the right mouse button on the instruction to be
set as a breakpoint and selecting BreakpointãInsert Breakpoint. After an instruction is set as a
breakpoint, a red circle is placed to the left side of the instruction. Multiple breakpoints can be
set during a debugging process. A screen with a breakpoint set is shown in Figure 4.21. When
a breakpoint is not desired, it can be disabled (by selecting BreakpointãDisable Breakpoint). A
disabled breakpoint (with a white circle) has no effect on program execution. When a disabled
breakpoint is needed again, it can be reenabled. When a breakpoint is not needed, it can be
deleted (by selecting BreakpointãDelete Breakpoint).
Figure 4.21
■
A breakpoint has a red circle at its lefthand side
AVR Studio 5 allows the user to modify the behavior of a breakpoint by setting its
properties:
•
Hit count. By setting the hit count, the user can force the program to stop when the
breakpoint is encountered for hit count times. Hit count is set by pressing the right
mouse button on the breakpoint and selecting BreakpointãHit count.
•
Condition. Condition is an expression that determines whether the breakpoint
is hit or skipped. When the debugger reaches the breakpoint, it evaluates the
condition. The breakpoint is hit only if the condition is satisfied. You can use a
condition with a location breakpoint to stop at a specified location only when a
certain condition is true.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.5
■
•
RUN
97
Using the AVR Studio IDE
TO
Action. Action specifies something that should occur when the breakpoint is hit.
By default, the debugger breaks execution, but you can choose to print a message or
run a Visual Studio macro instead.
CURSOR
Source: Atmel Corporation, The Atmel AVR Microcontroller
The Run-to-Cursor option is a quick way for running the program up to the instruction
at the mouse cursor and then stopping. When the program stops, the AVR Studio IDE updates
the values of all the CPU registers and the variables in the Watch Window. We use this method
to quickly find out if the program executes correctly up to the cursor position. This method is
much more efficient than using program breakpoints. This option can be exercised by pressing
the right mouse button on the instruction where the program is expected to stop. Press the cursor at the here: rjmp here instruction, as shown in Figure 4.22. When the program stops, the
value of count is 10 (shown in Figure 4.23) and is correct. This example program finds the total
number of elements that are between 30 and 100.
Figure 4.22
■
Execute “Run to Cursor” command
STEPPING OVER INSTRUCTIONS
Sometimes the programmer has to find out the effect of one or two instructions in order to
identify the source of errors. This option makes it possible. The AVR studio has three options
for stepping through the program:
•
Step into. This option causes the MCU to execute one instruction at a time. If
the instruction being stepped is a call instruction, then the MCU stops at the first
instruction of the subroutine.
•
Step over. If the instruction being stepped is not a call instruction, the MCU only
executes one instruction and stops. However, if the instruction being stepped is a
call instruction, then the MCU completes the execution of the whole subroutine
and stops at the instruction after the call instruction.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 4
■
Hardware and Software Development Tools for the AVR
Source: Atmel Corporation, The Atmel AVR Microcontroller
98
Figure 4.23
•
■
AVR Studio screen after executing “Run To Cursor” command
Step out. If the MCU is executing a subroutine, this command causes the MCU to
complete the execution of the current subroutine and return to the caller of this
subroutine. This command should not be executed if the user did not perform the
command Step into on a call instruction before.
4.6 Tips for Assembly Program Debugging
Assembly program errors can be classified into two categories:
• Syntax and semantic errors
• Logical errors
4.6.1 Syntax and Semantic Errors
Syntax and semantic errors are common for beginners. These errors can be divided into the
following categories:
•
Misspelling of instruction mnemonics. This type of error is highlighted by the
assembler (with a red dot) in the build window. For example, the build window
would look like Figure 4.24 if we change the brlo next instruction to drlo next. The
line number at which the error occurred is displayed in the Error List. The user
double clicks on the error message to be brought to the statement that contains the
error (shown in Figure 4.25).
•
Symbol not terminated with a colon character when it is defined. When a symbol is
not terminated with a colon character, it is treated as an error. By double-clicking
on the error message, the line that contains the symbol not terminated with a
colon is highlighted.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.6
■
Tips for Assembly Program Debugging
99
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Error list window contains error messages
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.24
■
The line with error is highlighted
Figure 4.26
■
An error caused by a missing operand
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.25
•
Missing operands. When an instruction does not have enough number of
operands, the assembler indicates it as “wrong number of operands.” Suppose we
delete the first operand of the cpi r16, lowVal+1 instruction, and the instruction is
changed to cpi lowVal+1. The AVR assembler generates the message, as shown in
Figure 4.26.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 4
■
Hardware and Software Development Tools for the AVR
Source: Atmel Corporation, The Atmel AVR Microcontroller
100
■
Error caused by invalid register
Figure 4.28
■
A syntax error caused by undefined symbol “countx”
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 4.27
•
Invalid register. Not all 32 CPU registers can be the operand of every instruction.
When the user specifies an illegal register for an instruction, the assembler outputs
an error message indicating that the instruction uses an invalid register. An
example is shown in Figure 4.27. Here, the user specified r10 as the destination
register for the andi instruction. However, the andi instruction can only accept a
register from r16 to r31 as its destination register.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.6
■
Tips for Assembly Program Debugging
•
101
Undefined Symbols. An undefined symbol is identified and displayed in the Build
Window. One example is shown in Figure 4.28, in which the symbol countx is
undefined.
As time goes on, the user gains experience and also memorizes the instruction mnemonics;
this type of error will reduce dramatically and even disappear.
4.6.2 Logical Errors
There are an infinite number of possible logical errors. Anything that can go wrong will
happen in assembly language programming; it is impossible to discuss all the possible errors.
However, we must have a strategy to quickly determine whether the program runs correctly
and locate any error quickly.
4.6.3 General Debug Strategy
The general debug strategy consists of three steps: (a) Determine whether the program runs
correctly, (2) locate any error, and (3) fix the error.
D E T E R M I N E W H E T H E R P R O G R A M R U N S C O R R E C T LY
The user can use the Run-to-Cursor feature to test the program. First, let the program run
until the last instruction in the program under the AVR Studio IDE. During this process, the
user must provide normal data, borderline data, and illegal data to test the program, as described
in Section 3.7.
L O C AT E
THE
ERROR
OF THE
PROGRAM
The programmer can locate the error by using the Run-to-Cursor feature of the IDE. Sometimes, single-stepping a few instructions may also help. By letting the program execute to the
suspected instruction using this feature and examining the value change in the Watch Window,
the programmer can quickly locate the program error. This step may have to be repeated several
times before the error is identified.
FIX
THE
ERROR
The programmer needs to know the type of error that occurred before he or she can fix
the error. Although it is impossible to enumerate all possible errors, a few common ones are
explained in the next section.
4.6.4 Common Program Logical Errors
• Forgetting initializing program variables. Program loop indices or repetition counts
and program variables must be initialized properly to obtain the correct result.
•
Using the same register for multiple variables at the same time. If we assign
variables count and lpcnt to the same register in the previous tutor program
example, the program loop never terminates.
•
Using the wrong instruction for a certain purpose. There are many possibilities for
this error. For example, using an addition or subtraction instruction that does not
involve carry would cause the result to be incorrect for multiple-byte addition and
subtraction operations.
•
Operand size mismatch. There are several possibilities for this error. One is
attempting to load a big number into a small variable. The other is attempting to
increment or decrement a multiple-byte variable using an instruction that only
operates on a single byte and hence leaves a part of the variable untouched.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
102
Chapter 4
■
Hardware and Software Development Tools for the AVR
•
Missing a return instruction in a subroutine or interrupt service routine. The last
instruction to be executed in a subroutine (to be discussed in Chapter 5) must be a
ret instruction so that the program control can return to the caller after it finishes all
the computation. Similarly, the last instruction to be executed in an interrupt service
routine must be a reti instruction so that the program control can be returned to the
interrupted program when the interrupt service routine finishes its execution.
•
Forgetting to pass parameters to the subroutine being called. It is obvious that a
subroutine cannot run correctly without the caller passing appropriate parameters
to it. This error did happen.
•
Incorrect program algorithm. An incorrect program algorithm rarely produces a
correct result.
4.7 Project File Structure
The AVR Studio IDE creates a directory of the project name under the selected directory. For example, the tutorial would cause a directory of the name tutor1 to be created under
c:\books\avr\programs\ch04. Under the tutor1 directory, an AVR Studio Solution file of the
name tutor1 and a directory of the name tutor1 are created. Under the directory c:\books\avr\
programs\ch04\tutor1\tutor1, you should see at least a Debug directory, the assembly program
file tutor1.asm, and the tutor1 assembler project file. If you have other assembly program
files to be included to this project, they should be stored in the c:\books\avr\prorgams\ch04\
tutor1\tutor1 directory. Assuming that you need to call the delay function delayby10ms in the
delays.asm file, then this file should be included there.
4.8 Summary
Development tools are indispensible for learning a microcontroller. Development tools
can be divided into two categories: software tools and hardware tools. Software development
tools include assembler, compiler, linker, librarian, simulator, and debugger. The assembler
and compiler convert source code into machine instructions. The linker resolves variable
cross-referencing and memory space assignment. The librarian allows the user to invoke the utility functions in the library provided by the compiler and put well-tested subroutines and functions (written by the user) into a library for future reuse. The simulator allows the user to execute
a program of certain instruction set without the actual hardware by performing the intended
operation for each instruction in the program and using the PC memory to hold the contents
of each program variable. The debugger is a program written to test the correctness of another
program. It may use either the simulator to execute the user program or execute the program
directly using the target hardware via a debug adapter. The debugger has the capability to set
breakpoints, single step, execute program until the cursor position, and then update the register
and memory contents. Most debuggers also allow the user to place certain program variables of
interest in a watch window (or watch list) so that the user can easily observe the program execution result. The assembler, compiler, linker, librarian, simulator, debugger, and project manager
are often integrated into a single software package called integrated development environment
(IDE). Atmel provides the AVR Studio IDE to its customers for free, to support program development for the AVR microcontroller. The AVR Studio IDE contains all of the software mentioned
previously. The AVR Studio IDE can be downloaded from the Atmel website at www.atmel.com.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
4.9
■
Lab Assignments
103
The most important hardware tools for learning microcontrollers are demo boards and
the debug adapter. Demo boards allow the user to test the program under development. Demo
boards are essential for testing experiments that involve peripheral chips and I/O devices.
A feature-rich demo board is very helpful for learning the AVR. Atmel provides four debug
adapters: the Dragon, JTAGICE3, JTAGICE mkII, and the AVR ONE!. The Dragon debug adapter
is least expensive, and there is no program size limit (there was a 32 kB program size limit when
the author started writing this text).
4.9 Lab Assignments
L4.1 The following program finds the number of elements that are greater than 100 or less
than 40, using the repeat-until looping construct to implement the loop:
6m2560def.inc7
; or ATXMega128A1def.inc
.include
.equ
NN = 40
.def
lpcnt = r16
.def
count = r17
.def
tmp1 = r18
.def
tmp2 = r19
.macro
setPointer
ldi
@0,low(@2)
ldi
@1,high(@2)
.endmacro
.cseg
.org
0x00
rjmp
start
.org
0xF6
start:
ldi
lpcnt,NN
; initialize ii to NN
clr
count
; initialize count to 0
ldi
tmp1,40
; values to be compared
ldi
tmp2,100
;"
setPointer ZL,ZH,(array<<1)
; use register Z as a pointer to the array
rploop:
lpm
r0,z+
; read the next array element
cp
r0,tmp1
; is the element smaller than 40?
brlt
yes
; if yes, then branch to check upper bound
cp
tmp2,r0
; is the number larger than 100?
brlt
yes
rjmp
next
yes:
inc
count
next:
dec
lpcnt
brne
rploop
done:
rjmp
done
array:
.db
10,41,12,13,14,15,16,17,18,19
.db
50,21,52,23,24,25,26,27,28,29
.db
30,31,32,33,34,35,36,37,38,39
.db
60,162,56,99,132,103,104,89,78,59
// end of program
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
104
Chapter 4
■
Hardware and Software Development Tools for the AVR
Perform the following operations:
(a) Create a new project and call it lab1.
(b) Create a new file (call it lab1.asm), and enter the previous program into this file. This
file is added into the project automatically.
(c) Make the project. Eliminate syntax errors if there are any.
(d) Connect the Dragon, JTAGICE 3, or JTAGICE mkII to the demo board and power up
the demo board.
(e) Download the program onto the demo board by selecting DebugãStart Debugging and
Break.
(f) Make sure the Watch window is open, and add count and lpcnt into the Watch
window.
(g) Reset the CPU.
(h) Press the right mouse button on the setPointer macro call and select Run to Cursor.
What are the contents of the Watch Window?
(i) Press the right mouse button on the last instruction of the program and select Run to
Cursor. What are the contents of the Watch Window?
L4.2 Write a program to count the total even numbers in an array of 8-bit elements.
Leave the count in the register r0. Use the AVR Studio IDE to enter, assemble, and execute the
program.
L4.3 Write a program to compute the average of the maximum and minimum numbers of
an array of 8-bit numbers. Use AVR Studio to enter, assemble, and execute the program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5
Advanced Assembly
Programming and
Subroutine Calls
5.1 Objectives
After completing this chapter, you will be able to
• Understand the issues related to subroutine
calls.
• Initialize the stack pointer and perform stack
operations.
• Write subroutines to create time delays.
• Explain and apply top-down-design with
hierarchical refinement software development
methodology.
• Write subroutines to multiply and divide
signed and unsigned 16-bit or larger numbers.
• Write a subroutine to determine whether a
number is a prime number.
• Perform program debugging that involves
subroutines.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
106
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
5.2 Introduction
It is not unusual that the same sequence of instructions has to be executed in several
places of the same program. Macros have been used so far as the solution to this issue. However, using the macro call duplicates the same sequence of instructions in places where
the macro is invoked and causes the program size to be bloated. Fortunately, all microprocessors and microcontrollers provide the subroutine mechanism that enables the program to
invoke the same sequence of instructions in many different places of the program without
duplicating it.
A subroutine is often written to perform operations based on the inputs provided by the
caller. The inputs provided by the caller are called incoming parameters. The caller of the subroutine often expects the subroutine to return certain results to it.
Subroutine calls cause program flow to change. In general, the processor executes a
subroutine-call instruction to change the program flow. When the subroutine-call instruction is
being executed, the processor performs at least the following two operations:
•
Saves the return address in the stack. Return address is the address of the
instruction that immediately follows the subroutine-call instruction.
•
Loads the starting address of the subroutine into the program counter.
After that, the processor control is transferred to the subroutine. When the processor finishes
execution of the subroutine, it returns to the instruction immediately after the subroutine-call
instruction. This is achieved by executing a return-from-subroutine (RET) instruction.
The subroutine-call and return-from-subroutine instructions work together to make the
subroutine mechanism work. The subroutine-call instruction saves the return address in the
stack data structure and at the same time changes program flow to the start of the subroutine.
The return-from-subroutine instruction fetches the return address from the stack, places it in
the program counter, and hence returns the program control to the instruction immediately
after the subroutine-call instruction.
It was mentioned in Section 3.7 that “top-down design with hierarchical refinement” is
the most popular software development methodology. The subroutine mechanism makes this
methodology possible.
In addition, it is important for the software developers to reuse the working program pieces
that they developed earlier in order to avoid duplicating the same work and improve productivity. Both the macro and subroutine mechanisms facilitate the reuse of software. Programmers
can collect common macros and subroutines into files and selectively include them into their
new programs to save the development time.
5.3 The Stack Data Structure
A stack is a data structure from which elements can be accessed only from its top. The
processor can add a new element to the stack by performing a push operation. To remove an element from the stack, the processor performs a pull (or pop) operation. Physically, a stack grows
from a high address toward lower addresses or from a low address toward higher addresses.
Depending upon the processor, the stack pointer points to the top element of the stack or to the
byte immediately above the top element of the stack.
The AVR stack grows from a high address toward lower addresses (shown in Figure 5.1)
and has a 16-bit stack pointer (SP) that points to the byte immediately above the top byte of
the stack. The memory space available for use by the stack is limited in a computer system.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.3
■
107
The Stack Data Structure
SP
Top byte
Low address
High address
Figure 5.1
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
There is always a danger of stack overflow and stack underflow. Stack overflow is a situation
in which the processor pushes data into the stack too many times so that the SP points to a
location outside the area allocated to the stack. Stack underflow is a situation in which the
processor pulls data from the stack too many times so that the SP points to an area below the
stack bottom.
The diagram of AVR stack
5.3.1 Initializing the Stack Pointer
The stack pointer must be initialized before the stack can be used. The stack data structure must be created inside the on-chip SRAM area. Different AVR devices may have different
sizes of on-chip SRAM. In the AVR device include file of the AVR Studio assembler, the last
byte of the on-chip SRAM is defined as RAMEND. This variable has a different value for different AVR devices. The user can load this value into the stack pointer and use it as its initial
value.
The stack pointer (SP) is implemented as two 8-bit registers (SPH and SPL) in the I/O
space for Mega devices. For XMega devices, SPL and SPH are referred to as CPU_SPL and
CPU_SPH, respectively. The user needs to use the IN and OUT instructions to access them.
The initialization of the AVR Mega stack pointer is usually done immediately after reset as
follows:
ldi
out
ldi
out
temp,low(RAMEND)
SPL,temp
temp,high(RAMEND)
SPH,temp
; temp is one of the registers from r16 to r31
; initialize the SP
; "
; "
The initialization of the XMega stack pointer is as follows:
ldi
out
ldi
out
temp,low(RAMEND)
CPU_SPL,temp
temp,high(RAMEND)
CPU_SPH,temp
; temp is one of the registers from r16 to r31
; initialize the SP
; "
; "
5.3.2 Instructions for Stack Operation
The AVR provides two instructions for stack operations. The push Rd instruction places
the contents of the Rd register at the location pointed to by the SP and then decrements SP
by 1. The pop Rd instruction increments SP by 1 and then copies the contents of the memory
location pointed to by the SP to the Rd register.
The push Rd instruction is mainly used to save the contents of a register in the stack,
whereas the pop Rd instruction is mainly used to restore the contents of a register from the
stack during the execution of a program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
108
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
5.4 An Example of Subroutine
A subroutine is a sequence of instructions that can be called from many places of a program. At the end of the subroutine, the program control returns to the instruction immediately
after the instruction that calls this subroutine. A sequence of instructions can be converted to
a subroutine by:
•
•
adding a label (name of the subroutine) to the first instruction of the sequence.
adding a ret instruction as the last instruction of the sequence.
For example, the following instruction sequence swaps the contents of register r16 and r17:
push
mov
r16
r16,r17
; save the contents of r16 in stack
; copy the contents of r17 to r16
pop
r17
; place the contents of r16 in r17
This instruction sequence can be converted into a subroutine as follows:
swapRegs:
push
mov
pop
ret
r16
r16,r17
r17
; save the contents of r16 in stack
; copy the contents of r17 to r16
; place the contents of r16 in r17
The instruction sequence that creates a 500 µs time delay (CPU clock is 16 MHz), described
in Section 3.14, can be converted into a subroutine as follows:
delay500us:
loop0:
loopi:
ldi
ldi
push
pop
dec
brne
dec
brne
ret
r21,250
r20,4
r0
r0
r20
loopi
r21
loop0
; adding a label to the first instruction
; set loop count to 250
; 1 cycle
; 2 clock cycles
; 2 clock cycles
; 1 CPU clock cycle
; 2 (1) cycle when branch is taken (not taken)
; 1 cycle
; 2 (1) cycle when branch is taken (not taken)
; to return to the caller
This subroutine is much more useful if it creates a time delay that is a multiple of 500 µs
and allows the caller to specify the multiple. The following version of the subroutine achieves
just that, and the multiple is passed in r16:
delayby500us:
ldi
loop0:
ldi
loopi:
push
pop
dec
brne
dec
brne
dec
brne
ret
;
r21,250
; set loop count to 250
r20,4
; 1 cycle
r0
; 2 clock cycles
r0
; 2 clock cycles
r20
; 1 CPU clock cycle
loopi
; 2 (1) cycle when branch is taken (not taken)
r21
; 1 cycle
loop0
; 2 (1) cycle when branch is taken (not taken)
r16
; decrement multiple count
delayby500us
; to return to the caller
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.5
■
Issues Related to Subroutine Calls
109
The caller needs to place the multiple in r16 before calling this subroutine. For example,
the following instruction sequence calls delayby500us to create a delay of 100ms:
ldi
call
r16,200
delayby500us
5.5 Issues Related to Subroutine Calls
There are three major issues related to subroutine calls: parameter passing, result returning, and local variable allocation.
5.5.1 Parameter Passing
The caller of the subroutine may pass parameters, using registers, stack, or global memory.
For the AVR, the programmer can use registers r0 to r31 to pass parameters to the subroutine.
Because most of the AVR instructions only operate on these registers, they are preferred for
passing parameters. The stack and on-chip data memory (global memory) also can be used to
pass parameters to the subroutine.
5.5.2 Local Variable Allocation and Deallocation
In addition to parameters passed to it, a subroutine may also need memory space (or
additional CPU registers) to hold temporary variables and results. These variables are useful
only during the execution of the subroutine and are called local variables because they are local
to the subroutine.
Theoretically, it is a perfect idea to allocate local variables in the stack, because local
variables come into being when the subroutine is entered and disappear when the subroutine
is exited as long as the subroutine allocates local variables at its entrance and deallocates local
variables before it returns to the caller. This can avoid the interference among subroutines
when a subroutine requires calling other subroutines. Allocating local variables in the stack has
an additional benefit: It allows the creation of re-entrant subroutines. A re-entrant subroutine
can call itself.
However, the fact that no AVR instruction can perform arithmetic or logical operation on
memory locations makes it a poor idea to assign local variables to data memory. Before an
operation can be performed, local variables must be loaded into CPU registers. After the operation, the result must be written back to the stack. This procedure is inefficient. A better idea is
to use CPU registers for local variables as much as possible. However, we must be careful not
to overwrite the registers that have been assigned to variables of the caller. This problem can be
avoided by saving registers used in the subroutine in the stack.
When a subroutine needs more space for local variables than can be supported by the CPU
registers, we must assign it to the stack. The programmer can use the following instruction
sequence to allocate k bytes in the stack for local variables for Mega devices:
in
in
sbiw
out
out
r28,SPL
r29,SPH
r28,k
SPL,r28
SPH,r29
; use CPU_SPL for XMega devices
; use CPU_SPH for XMega devices
; allocate k bytes in the stack (0 < k < 64)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
110
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
This instruction sequence can be converted to a macro as follows:
.macro
in
in
sbiw
out
out
.endmacro
allocStk
r28,SPL
r29,SPH
r28,@0
SPL,r28
SPH,r29
; use CPU_SPL for XMega devices
; use CPU_SPH for XMega devices
; allocate k bytes in the stack
The subroutine should deallocate the stack space used by local variables before returning
to the caller. The following instruction sequence deallocates k bytes of space from the stack for
Mega devices:
in
in
adiw
out
out
r28,SPL
r29,SPH
r28,k
SPL,r28
SPH,r29
; use CPU_SPL for XMega devices
; use CPU_SPH for XMega devices
; deallocate k bytes from the stack
This instruction sequence can be converted to a macro as follows:
.macro
in
in
adiw
out
out
.endmacro
deallocStk
r28,SPL
r29,SPH
r28,@0
SPL,r28
SPH,r29
; use CPU_SPL for XMega devices
; use CPU_SPH for XMega devices
; deallocate k bytes in the stack
When the caller of a subroutine has many parameters to be passed, it may also pass them in
the stack. The subroutine may save registers and allocate local variables in the stack. The region
in the stack that holds incoming parameters, return address, saved registers, and local variables
is referred to as the stack frame. A stack frame may look like the one shown in Figure 5.2.
Local variables
Saved registers
Return address
Incoming parameters
Figure 5.2
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
SP
Structure of the AVR stack frame
5.5.3 Result Returning
A subroutine may return its computation result in registers, stack, or global memory. For
the AVR, a subroutine can return its computation results using registers r0~r31, the space in
stack, or the on-chip data memory. The programmer can use the allocStk macro to reserve
space in stack for returning the result. This operation can be done by the caller or the callee
(subroutine being called). However, it takes the caller less effort to do (Why?).
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.5
■
111
Issues Related to Subroutine Calls
5.5.4 Accessing Local Variables in the Stack
The local variables allocated in the stack are accessed by using the data-indirect-withdisplacement addressing mode. Because the base address must be in Y or Z, we must transfer
the contents of SP to Y or Z. For example, the local variable locVark in Figure 5.3 is loaded into
register r0, using the following instruction sequence:
in
in
ldd
YL,SPL
YH,SPH
r0,Y1k
; use CPU_SPL for XMega devices
; use CPU_SPH for XMega devices
To store the contents of the r0 register in locVark in Figure 5.3, we use the following
instruction sequence:
in
in
std
YL,SPL
YH,SPH
Y1k,r0
; use CPU_SPL for XMega devices
; use CPU_SPH for XMega devices
n
k
3 2 1
locVar1
locVar2
locVar3
locVark
locVarn
Figure 5.3
■
SP
Source: Atmel Corporation, The Atmel
AVR Microcontroller
If we need to access local variables in the stack many times in a subroutine, we use either
the Y or Z register to point to the top of the stack.
Accessing local variables in the stack
5.5.5 Register Usage Issue
Because both the subroutine and the caller of the subroutine need to use CPU registers,
there might be interference. The interference must be avoided in order for programs to execute
correctly. Atmel does not have recommendation to the usage of AVR registers even though
many 32-bit microcontroller vendors do. The recommendations of register usage, parameter
passing, and result returning are part of the embedded-application binary interface (EABI) for
32-bit microcontrollers.
In the EABI of a 32-bit MCU, certain registers are reserved for parameter passing, certain
registers are reserved for returning results, certain registers (referred to as caller-saved registers)
are specified to be saved by the caller, and other registers (referred to as callee-saved registers)
are specified to be saved by the callee.
Caller-saved registers are saved by the caller before it calls a subroutine and it has the
concern that these registers may be modified by the subroutine. Callee-saved registers are saved
by the subroutine whenever it needs to modify these registers.
In this text, we follow the recommendation of the register usage shown in Table 5.1 for
assembly language programming.
5.5.6 Instructions for Subroutine Call
The AVR provides four subroutine-call instructions and one return instruction (listed in
Table 5.2) to support the subroutine-call mechanism. All of the subroutine-call instructions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
112
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
Name
∼
∼
r4 r7, r12 r15, r28, r29
r0∼r3, r8∼r11, r20, r21
r16∼r19, r30, r31
r22∼r27
Usage
Callee saved
Caller saved
Parameter passing
Result returning
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 5.1
■
Recommendation for register usage
push the return address onto the stack before transferring the program control to the subroutine. Depending upon the devices, the return address may be 2 or 3 bytes.
CALL k
This instruction calls a subroutine within the entire program memory. When this instruction is executed, the AVR processor places the constant k in the program counter (PC) and
also pushes the address of the next instruction onto the stack. After this, the program control
is transferred to the subroutine at address k. The constant k is a value between 0 and 216 2 1
for devices with a 16-bit PC and up to 128 kB of program memory. The constant k would
be a value between 0 and 222 2 1 for devices with a 22-bit PC and 8 MB program memory
maximum.
The following instruction sequence illustrates the use of this instruction:
chkVal:
error:
ldi
call
…
…
cpi
breq
…
ret
…
…
ret
r16,0x40
chkVal
; call a subroutine
r16,0x35
error
EICALL
This instruction calls a subroutine pointed to by the Z pointer register in the register file
and the EIND register in the I/O space. When this instruction is executed, the AVR processor
places the value held in Z into the lower 16 bits of the PC and places the value held in the EIND
register into the upper 6 bits of the PC, and transfers program control to that address. The AVR
also saves the return address in the stack.
The following instruction sequence calls the subroutine located at 0x201000:
ldi
out
ldi
ldi
eicall
r16,0x20
EIND,r16
r30,0x00
r31,0x10
; place 0x20 in EIND
; "
; place 0x1000 in Z
; "
; call the subroutine at 0x201000
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.5
■
113
Issues Related to Subroutine Calls
ICALL
This instruction calls the subroutine specified by the Z pointer register. For devices with
22-bit PC, the highest 6 bits of the PC (PC(21:16)) are forced to 0. The return address is pushed
onto the stack after the execution of this instruction. The following instruction sequence
illustrates the use of this instruction:
ldi
ldi
icall
ZL,low(subx)
ZH,high(subx)
; set up subroutine address in Z
; "
RCALL k
The range of constant k (an 11-bit value) is between 22048 and 2048. This instruction
allows a program to call a subroutine that is k words away from the rcall instruction. When
using this instruction, the programmer specifies the name of the subroutine to be called, and
the assembler figures out the actual distance of the subroutine to be called. The following
instruction sequence illustrates the use of this instruction:
bubble:
rcall
…
push
…
pop
ret
bubble
r12
r12
RET
This instruction returns from subroutine. Depending upon the device, the AVR processor
pops up the top two or three bytes from the stack and places the value onto the program counter, and the program control transfers to the new PC value. This instruction should be the last
instruction to be executed in a subroutine.
Instruction
Operation
call k
PC ← k; stack ← PC 1 2; SP ← SP 2 2 (devices with 16-bit PC)
SP ← SP 2 3 (devices with 22-bit PC)
eicall
PC(15:0) ← Z(15:0); PC(21:16) ← EIND; stack ← PC 1 1; SP ← SP 2 3
icall
PC(15:0) ← Z(15:0); PC(21:16) ← 0; (devices with 22-bit PC); stack ← PC 1 1;
SP ← SP22 (devices with 16-bit PC); SP ← SP 2 3 (devices with 22-bit PC)
rcall k
PC ← PC 1 K 1 1; stack ← PC 1 1; SP ← SP 2 2 (devices with 16-bit PC);
SP ← SP 2 3 (devices with 22-bit PC)
ret
PC(15:0) ← stack (devices with 16-bit PC); SP ← SP 1 2
PC(21:0) ← stack (devices with 22-bit PC); SP ← SP 1 3
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 5.2 Subroutine call instructions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
114
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
5.6 Writing Subroutines to Perform Multiprecision Arithmetic
The AVR provides no instructions for performing arithmetic on 16-bit or larger numbers. In
this section, we write subroutines that can perform 16-bit unsigned and signed multiplication
and division. An unsigned number is nonnegative, whereas a signed number may be positive,
zero, or negative. The most significant bit of a signed number is the signed bit. When the signed
bit is 1, the number is negative. Otherwise, it is either 0 or positive.
5.6.1 Writing Subroutines to Perform 16-Bit Unsigned Multiplication
To multiply two 16-bit unsigned numbers, the multiplier and the multiplicand must be
broken down into 8-bit chunks, and four 8-bit by 8-bit multiplications are performed. Suppose
that P and Q are two 16-bit unsigned numbers to be multiplied; they are broken down as
follows:
P 5 PHPL 5 PH 3 28 1 PL
Q 5 QHQL 5 QH 3 28 1 QL
where PH, PL, QH, and QL are the upper and lower bytes of P and Q, respectively. Four byte-tobyte multiplications are performed, and then the partial products are aligned and added together,
as shown in Figure 5.4. The procedure for adding these four partial products is as follows:
Step 1
Allocate four bytes to hold the product. Refer to these four bytes using the symbols PR, PR
1 1, PR 1 2, and PR 1 3, respectively.
Step 2
Compute the partial product PLQL and save it at locations (or registers) PR and
PR 1 1. Store the high byte of the product at PR 1 1 and low byte of the product at
PR, respectively.
Step 3
Compute the partial product PHQH and save it at locations PR 1 2 and PR 1 3. Store the
high byte of the product at PR 1 3 and the low byte of the product at PR 1 2, respectively.
Step 4
Compute the partial product PHQL and add it to the memory locations PR 1 1 and PR 1 2.
Add the carry flag to the memory location PR 1 3.
lsb
Partial product
PLQL
Partial product
PHQL
Partial product
PLQH
+
Partial product
PHQH
Address PR + 3 PR + 2 PR + 1
Figure 5.4
■
PR
Final product P × Q
Source: Atmel Corporation, The Atmel AVR Microcontroller
msb
16-bit by 16-bit multiplication
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
Writing Subroutines to Perform Multiprecision Arithmetic
115
Step 5
Compute the partial product PLQH and add it to the memory locations PR 1 1 and PR 1 2.
Add the carry flag to the memory location PR 1 3.
Example 5.1
▼
Write a subroutine to multiply two unsigned 16-bit integers passed in r16:r17 and r18:r19,
and return the product in r22, r23, r24, and r25. r17 and r19 hold the upper bytes of two numbers to be multiplied, and r25 down to r22 hold the most significant to the least significant
bytes of the product.
Solution: The assembly subroutine that implements the previous algorithm and its test program are as follows:
start:
forever:
.include
.equ
.equ
.equ
.equ
.def
.cseg
.org
rjmp
.org
ldi
out
ldi
out
ldi
ldi
ldi
ldi
call
rjmp
<ATXMega128A1def.inc>
num1H 5 0x37
; high byte of the first test data
num1L 5 0x32
; low byte of the first test data
num2H 5 0x41
; high byte of the second test data
num2L 5 0x48
; low byte of the second test data
temp 5 r16
0x00
start
0xF6
temp,low(RAMEND)
CPU_SPL,temp
temp,high(RAMEND)
CPU_SPH,temp
r16,num1L
r17,num1H
r18,num2L
r19,num2H
mul16U
forever
; temp is one of the registers from r16 to r25
; initialize the SP (use SPL for Mega devices)
; "
; (use SPH for Mega devices)
; pass the first number in r16~r17
; "
; pass the second number in r18~r19
; "
; ------------------------------------------------------------------------------------------------------------------; The next subroutine multiplies the 16-bit unsigned number contained in r16~r17
; and r18~r19 and returns the product in r25~r22.
; ------------------------------------------------------------------------------------------------------------------.def
p1 5 r22
.def
p2 5 r23
.def
p3 5 r24
.def
p4 5 r25
.def
pH 5 r17
.def
pL 5 r16
.def
qH 5 r19
.def
qL 5 r18
mul16U: mul
pL,qL
; generate partial product PL * QL
mov
p1,r0
mov
p2,r1
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
116
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
mul
mov
mov
mul
add
adc
ldi
adc
mul
add
adc
ldi
adc
ret
pH,qH
p3,r0
p4,r1
pL,qH
p2,r0
p3,r1
r20,0
p4,r20
pH,qL
p2,r0
p3,r1
r20,0
p4,r20
; generate partial product PH * QH
; generate partial product PL * QH
; generate partial product PH * QL
The multiplication of two numbers longer than 16 bits or two numbers of different lengths
can be performed using the same method.
▲
5.6.2 Writing a Subroutine to Perform 16-bit Signed Multiplication
Because the computer’s word length is limited, it is essentially performing modulus arithmetic when performing an arithmetic operation. For example, an 8-bit MCU drops (discards)
the part of the result that is equal to or larger than 28. A 16-bit MCU drops the part of the result
that is equal to or larger than 216. Adding 28 to the result of the arithmetic operation performed
by an 8-bit MCU has no effect on the result, because this value (28) cannot be kept in the arithmetic hardware of an 8-bit MCU. In summary, in an n-bit MCU, the result of any arithmetic
operation is equal to the remainder of the initial result divided by 2n (i.e., it is performing a
modulo-2n operation).
The multiplication of signed numbers requires the programmer to consider the signs of the
multiplier and the multiplicand. Let P and Q represent the magnitudes of two numbers. There
are four possible situations.
Case 1
Both operands are positive (op1 5 P, op2 5 Q). The product of these two operands can be
computed by using either the mul Rd,Rs instruction for 8-bit operands or the procedure described in Section 5.6.1 for 16-bit and longer operands.
Case 2
The first operand is negative (op1 5 2P), whereas the second operand is positive (op2 5 Q).
The first operand op1 is represented in two’s complement of P (28 – P if P is 8-bit, 216 – P if P is
16-bit, etc.). The product of two n-bit operands 2P and Q can be rewritten as follows:
2P 3 Q 5 (2n 2 P) 3 Q 5 (2n 3 Q) 2 P 3 Q 5 22n 2 P 3 Q 1 2n 3 Q
3
3
➀
➁
The value 22n is added to the above expression. Because the MCU is performing a modulo2 arithmetic in this case, adding the value of 22n makes no difference to the result. Item 1 is
the two’s complement of the number 2P 3 Q and is the correct product. Part 2 is an extra term
and should be eliminated from the product. This extra term can be eliminated by subtracting
op2 from the upper half of the product of 2P and Q.
2n
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
117
Writing Subroutines to Perform Multiprecision Arithmetic
Case 3
The first operand is positive (op1 5 P), but the second operand is negative (op2 5 2Q).
Similar to Case 2, the product of two n-bit operands P and 2Q can be rewritten as follows:
P 3 (2 Q) 5 P 3 (2n 2 Q) 5 (2n 3 P) 2 P 3 Q 5 22n 2 P 3 Q 1 2n 3 P
3
3
➀
➁
The value of 22n is added to the expression, and it makes no difference to the result for the
same reason as in Case 2. Again, the first term is the correct product, which is represented as
the two’s complement of 2P 3 Q. The second term of the product is an extra term and can be
eliminated by subtracting op1 from the upper half of the product of P and 2Q.
Case 4
Both operands are negative (op1 5 2P, op2 5 2Q). The product of two n-bit operands 2P
and 2Q can be rewritten as follows:
(2P) 3 (2Q) 5 (2n 2 P) 3 (2n 2 Q) 5 22n 2 2n 3 P 2 2n 3 Q 1 P 3 Q
5 P 3 Q 1 22n 2 2n 3 P 1 22n 2 2n 3 Q
5 P 3 Q 1 2n 3 (2n 2 P) 1 2n 3 (2n 2 Q)
3
3
3
➀
➁
➂
2n
The value of 2 is added to the expression. It makes no difference to the result for the same
reason as in Case 2. The first term is the product of –P and –Q. The second term and the third
term are extra terms and must be eliminated. The second term is eliminated by subtracting
op1 from the upper half of the product, whereas the third term is eliminated by subtracting op2
from the upper half of the product.
By combining these four situations, we conclude that the signed n-bit multiplication can
be implemented by the following algorithm:
Step 1
Multiply two operands (that is, compute op1 3 op2) disregarding their signs.
Step 2
If op1 is negative, then subtract op2 from the upper half of the product.
Step 3
If op2 is negative, then subtract op1 from the upper half of the product.
Example 5.2
▼
Write a subroutine that can multiply two 16-bit signed integers. The multiplier and multiplicand are passed to this subroutine in r16:r17 and r18:r19, respectively. The product is
returned in registers r22~r25, with the most significant byte stored in r25 and the least significant byte restored in r22, respectively.
Solution: This subroutine may call the mul16u subroutine to perform unsigned 16-bit multiplication. The subroutine and its test program are as follows:
.include <ATXMega128A1def.inc>
.equ
num1H 5 0x97
.equ
num1L 5 0x76
.equ
num2H 5 0x41
.equ
num2L 5 0x48
.def
temp5r16
; high byte of the first test data
; low byte of the first test data
; high byte of the second test data
; low byte of the second test data
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
118
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
.cseg
.org
0x00
rjmp
start
.org
0xF6
start:
ldi
temp,low(RAMEND)
; temp is one of the registers from r16 to r25
out
CPU_SPL,temp
; initialize the SP
ldi
temp,high(RAMEND)
; "
out
CPU_SPH,temp
ldi
r16,num1L
; pass the first number in r16~r17
ldi
r17,num1H
; "
ldi
r18,num2L
; pass the second number in r18~r19
ldi
r19,num2H
; "
call
mul16s
forever:
rjmp
forever
;--------------------------------------------------------------------------------------------------------------------; The next subroutine multiplies the 16-bit signed numbers held in r16~r17 and
; r18~r19 and returns the product in r25~r22.
; -------------------------------------------------------------------------------------------------------------------mul16s:
call
mul16U
; multiply two numbers disregarding their signs
sbrs
r17,7
; check the sign bit of the first number
rjmp
chk2
sub
r24,r18
sbc
r25,r19
chk2:
sbrs
r19,7
; check the sign bit of the second number
rjmp
doneMs
sub
r24,r16
sbc
r25,r17
doneMs:
ret
; ------------------------------------------------------------------------------------------------------------------; Include MUL16U here
; -------------------------------------------------------------------------------------------------------------------
▲
5.6.3 Writing Subroutines to Perform Unsigned Multiprecision Division
The AVR does not provide any divide instruction. The division operation must be implemented in macros or subroutines. One of the most widely used division methods is the
repeated-shift-and-subtract method. This method assumes the use of three n-bit registers, R, Q, and S.
The repeated-shift-and-subtract algorithm consists of two phases.
I N I T I A L I Z AT I O N P H A S E
Place 0, dividend, and divisor in registers R, Q, and S, respectively
SHIFT-AND-SUBTRACT PHASE
Repeat:
Step 1
Shift the register pair R and Q to the left one place.
Step 2
Subtract S from R, and place the difference back to R if the difference is non-negative.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
Writing Subroutines to Perform Multiprecision Arithmetic
119
Step 3
Set the least significant bit of Q to 1 if the result in Step 2 is non-negative. Otherwise, set
the least significant bit of Q to 0
for n times.
Example 5.3
▼
Write a subroutine that can divide an unsigned 16-bit integer into another 16-bit unsigned
integer. The dividend and divisor are passed in r16:r17 and r18:r19, respectively. Remainder and
quotient are to be returned in register pairs r22:r23 and r24:r25, respectively.
Solution: The assembly subroutine that implements the 16-bit unsigned division and its test
program are as follows:
.include
<ATXMega128A1def.inc>
.equ
num1H 5 0xFA
; high byte of the first test data
.equ
num1L 5 0x00
; low byte of the first test data
.equ
num2H 5 0x00
; high byte of the second test data
.equ
num2L 5 0x50
; low byte of the second test data
.def
temp 5 r16
.cseg
.org
0x00
rjmp
start
.org
0xF6
start:
ldi
temp,low(RAMEND)
; initialize the SP
out
CPU_SPL,temp
; "
ldi
temp,high(RAMEND)
; "
out
CPU_SPH,temp
; "
ldi
r16,num1L
; pass the dividend in r16~r17
ldi
r17,num1H
; "
ldi
r18,num2L
; pass the divisor in r18~r19
ldi
r19,num2H
; "
call
div16U
forever:
nop
rjmp
forever
;----------------------------------------------------------------------------------------------------------------------------; The next subroutine divides the 16-bit unsigned numbers contained in r18~r19 into the 16-bit
; unsigned number contained in r16~r17 and returns the quotient in r25~r24 and
; the remainder in r23~r22.
; ----------------------------------------------------------------------------------------------------------------------------.def
lpcnt 5 r20
.def
tmpL 5 r0
.def
tmpH 5 r1
div16U:
ldi
lpcnt,16
; set up divide iteration count
movw
r24,r16
; place dividend in Q register
clr
r23
; load 0 in R register
clr
r22
; "
dvloop:
lsl
r24
; shift R:Q to the left one place
rol
r25
; "
rol
r22
; "
rol
r23
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
120
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
movw
sub
sbc
brmi
movw
ori
rjmp
less:
andi
nxtb:
dec
brne
ret
// end of program
tmpL,r22
tmpL,r18
tmpH,r19
less
r22,tmpL
r24,0x01
nxtb
r24,0xFE
lpcnt
dvloop
; save R in temporary registers
; compute R 2 S
; "
; branch if divisor is larger
; save the difference in R
; set the lsb of Q to 1
; set the lsb of Q to 0
▲
5.6.4 Converting an Internal Binary Number into a BCD String
A binary number in the computer memory cannot be directly output to an output device. It
must be converted into a BCD string before being output. A BCD string uses the ASCII code to
represent each decimal digit. For example, the binary number 110101102 is converted to a threebyte string 0x32 0x31 0x34 before being output. After being output to a monitor screen or an
LCD, the string appears as the decimal value 214. For easy processing, a BCD string is usually
terminated by a NULL character (ASCII code is 0).
Example 5.4
▼
Write a subroutine to convert a 16-bit signed integer into a string of BCD digits, and save
the conversion result in a data memory buffer pointed to by the Z register. The string is terminated by a NULL character. The high and low bytes of the number to be converted are passed in
r16 and r17, respectively.
Solution: An unsigned binary number can be converted into a BCD string by executing an
algorithm that performs repeated division by 10 until the quotient becomes zero. Adding 0x30
to the remainder converts the remainder to its ASCII code. This process generates a string that
is reversed. It can be converted back to the right order by pushing it into the stack and then
popping it out. Let xx, quo, rem, and ptr represent the number to be converted, quotient of the
division process, remainder of the division process, and the pointer to the buffer to hold the resultant string, respectively. The procedure is as follows.
Step 1
Push 0 into stack.
Step 2
quo ← xx/10; rem ← xx mod 10
Step 3
Stack ← rem 1 0x30
Step 4
If quo ≠ 0, xx ← quo and go to Step 2; otherwise, go to Step 5.
Step 5
Pop the string out of the stack and store it in the buffer.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
Writing Subroutines to Perform Multiprecision Arithmetic
121
A negative number should be converted into its two’s complement representation before
being processed by the previous algorithm. After conversion, a negative number is preceded by
a minus sign.
The assembly program that implements this algorithm is as follows:
.include
<ATXMega128A1def.inc>
.equ
numH 5 0xE6
; high byte of the test data (-6601)
.equ
numL 5 0x37
; low byte of the test data
.dseg
.org
0x2000
; change to 0x200 for Mega devices
buf:
.byte
20
.cseg
.org
0x00
rjmp
start
.org
0xF6
start:
ldi
r16,low(RAMEND)
; temp is one of the registers from r16 to r25
out
CPU_SPL,r16
; initialize the SP (use SPL for Mega devices)
ldi
r16,high(RAMEND)
; "
out
CPU_SPH,r16
; "(use SPH for Mega devices)
ldi
r16,numL
; place the number in r16~r17
ldi
r17,numH
; "
ldi
ZL,low(buf)
; place the buffer address in Z
ldi
ZH,high(buf)
; "
call
bin2bcd
forever:
nop
rjmp
forever
; -------------------------------------------------------------------------------------------------------------------------; The following subroutine converts the 16-bit binary number held in r17~r16 into an
; ASCII BCD string and stores the string in a buffer pointed to by the Z register.
; -------------------------------------------------------------------------------------------------------------------------.def
sign 5 r12
; initialize sign flag to positive
.equ
NULL 5 0
; ASCII code of NULL character
bin2bcd:
clr
r12
; initialize the sign to positive
push
r12
; push a NULL character in the stack
sbrs
r17,7
; is the given number negative?
rjmp
normal
inc
sign
; change the sign to negative
com
r16
; compute the magnitude of the number
com
r17
; "
movw
r26,r16
; "
adiw
r26,1
; "
movw
r16,r26
; "
normal:
ldi
r18,10
; prepare to divide the number by 10
ldi
r19,0
; "
call
div16U
ldi
r26,0x30
; convert the remainder digit to ASCII
add
r22,r26
; "
push
r22
; save the character in the stack
sbiw
r24,0
; is the quotient 0?
breq
popSt
; quotient is zero, pop string out and save
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
122
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
movw
r16,r24
; quotient not zero, continue the divide
rjmp
normal
; loop
popSt:
sbrs
sign,0
; check the sign of the given number
rjmp
toRev
; do nothing if positive
ldi
r17,’-’
; push a minus sign character into stack if negative
push
r17
; "
toRev:
clr
r0
popLp:
pop
r1
cp
r1,r0
; is it a NULL character?
breq
exit
st
z1,r1
rjmp
popLp
exit:
st
z,r0
; terminate the string with a NULL character
ret
;--------------------------------------------------------------------------------------------------------------------; Include the div16U subroutine here.
; -------------------------------------------------------------------------------------------------------------------// end of program
▲
5.6.5 Signed Division Operation
The one complication for signed division is that we must also set the sign of the remainder.
This equation must always hold for division:
Dividend 5 Quotient 3 Divisor 1 Remainder
Our common sense requires that the magnitude of the quotient to be the same as long as
the magnitudes of the dividends are the same and the magnitudes of the divisors are the same.
We can determine the sign of the remainder on the basis of this principle. To illustrate, let’s use
(±41) ÷ (±7) as an example. The first situation is simple.
41 ÷ 7: Quotient 5 15, Remainder 5 16
If we change the sign of the dividend, the quotient must be changed as well.
241 ÷ 7: Quotient 5 25
Rewriting our basic formula to find the remainder; we have
Remainder 5 Dividend 2 Quotient 3 Divisor
5 241 2 (25 3 7) 5 241 1 35 5 26
If we change the sign of the divisor and keep the sign of dividend unchanged,
41 ÷ (27): Quotient 5 25
Remainder 5 41 2 (25 3 27) 5 41 2 35 5 6
If we change the signs of both the dividend and the divisor,
241 ÷ 27: Quotient 5 5
Remainder 5 241 2 (5 3 27) 5 241 135 5 26
From this discussion, we conclude that the correctly signed division algorithm negates the
quotient if the signs of the operands are opposite and makes the sign of the nonzero remainder
match that of the dividend. The signed division subroutine is straightforward and hence is left as an
exercise.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
123
Writing Subroutines to Perform Multiprecision Arithmetic
5.6.6 Finding the Square Root
There are several methods available for finding the square root of a number q. One of the
methods is based on successive approximation shown in Figure 5.5. The square root of a 2n-bit
number is n bits long. The successive approximation method computes the square root of a
32-bit integer in the following manner:
Step 1
sar ← 0; mask ← 0x8000; lpcnt ← 16; temp ← 0
Step 2
temp ← sar OR mask
Step 3
If ((temp ** 2) ≤ num) sar ← temp;
Step 4
mask ← mask srl 1 (shift right logically one place);
Step 5
lpcnt ← lpcnt 2 1
Step 6
If (lpcnt 55 0) stop; else go to step 2.
Start
SAR[i] ← 1
i ← i–1
SAR * SAR > num?
yes
SAR[i] ← 0
no
no
i = 0?
yes
Stop
Source: Atmel Corporation, The Atmel AVR Microcontroller
SAR[n–1, ..., 0] ← 0
i ← n–1
Figure 5.5 ■ Successive-approximation method for
finding square root
Example 5.5
▼
Write a subroutine to implement the square root algorithm. This subroutine must be able
to find the square root of a 32-bit unsigned integer. The parameter q (for which we want to find
the square root) is passed in r19~r16, and the square root is returned in r22~r23.
Solution: Four local variables are needed for implementing the square root algorithm:
•
•
mask: set a bit in the SAR register to be 1
sar: successive approximation register
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
124
Chapter 5
•
•
■
Advanced Assembly Programming and Subroutine Calls
temp: the value of (mask OR sar)
lpcnt: number of loop iterations to be performed
These local variables are assigned to the following CPU registers:
•
•
•
•
mask: r12~r13
sar: r8~r9
temp: r10~r11
lpcnt: r20
SP
q4 q3 q2 q1
r16
r17
r18
r19
r28
r29
r12
r13
Return address
Figure 5.6
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Several registers are saved in the stack due to the need for computation; the resultant stack is
shown in Figure 5.6.
Stack frame for Example 5.5
The subroutine that computes the square root of a 32-bit integer and its test program is as
follows:
.include
buf:
start:
.equ
.equ
.equ
.equ
.dseg
.org
.byte
.cseg
.org
rjmp
.org
ldi
out
ldi
out
ldi
ldi
<ATXMega128A1def.inc>
; test data for findSqRoot32
num4 5 0x01
; msb of the test data
num3 5 0x3E
; 3nd byte of the test data
num2 5 0x42
; 2rd byte of the test data
num1 5 0x91
; lsb of the test data
0x2000
20
0x00
start
0xF6
r16,low(RAMEND)
CPU_SPL,r16
r16,high(RAMEND)
CPU_SPH,r16
r16,num1
r17,num2
; initialize the SP
; "
; "
; "
; place the number in r16~r19
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
Writing Subroutines to Perform Multiprecision Arithmetic
forever:
ldi
ldi
call
nop
rjmp
r18,num3
r19,num4
SqRoot32
125
; "
; "
; compute the square root
forever
; -----------------------------------------------------------------------------------------------------------------; The following subroutine computes the square root of a 32-bit integer contained
; in r19~r16 and returns the result in r22~r23.
; ------------------------------------------------------------------------------------------------------------------
SqRoot32:
sqLoop:
.equ
.equ
.equ
.equ
.def
.def
.def
.def
.def
.def
.def
push
push
push
push
push
push
push
push
ldi
clr
movw
clr
clr
ldi
in
in
movw
or
or
movw
movw
push
call
pop
ldd
sub
ldd
sbc
q1
51
q2
52
q3
53
q4
54
maskH 5 r13
maskL 5 r12
sarH 5 r9
sarL 5 r8
tmpH 5 r11
tmpL 5 r10
lpcnt 5 r20
r13
r12
r29
r28
r19
r18
r17
r16
r21,0x80
r20
maskL,r20
sarH
sarL
lpcnt,16
r28,CPU_SPL
r29,CPU_SPH
tmpL,sarL
tmpL,maskL
tmpH,maskH
r16,tmpL
r18,tmpL
lpcnt
mul16U
lpcnt
r0,Y1q1
r0,r22
r0,Y1q2
r0,r23
; save Y register
; "
; save a copy of the number of which square root is to be
; computed in the stack
; "
; "
; initialize mask to 0x8000
; "
; "
; initialize sar to 0
; "
; initialize loop count to 16
; use Y to point to the byte above the top
; of the stack
;
; guess the kth bit is 1
; "
; compute the sar * sar
; "
; "
; compare sar*sar with q
; "
; "
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
126
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
ldd
r0,Y1q3
; "
sbc
r0,r24
; "
ldd
r0,Y1q4
; "
sbc
r0,r25
; "
brsh
yes
; branch if q >5 sar * sar
rjmp
nxtb
yes:
or
sarL,maskL
; keep the guess when it is correct
or
sarH,maskH
; "
nxtb:
lsr
maskH
ror
maskL
dec
lpcnt
brne
sqLoop
movw
r22,sarL
; transfer the square root to r22~r23
pop
r16
pop
r17
pop
r18
pop
r19
pop
r28
pop
r29
pop
r12
pop
r13
ret
; --------------------------------------------------------------------------------------------------------------; include mul16U subroutine here
; --------------------------------------------------------------------------------------------------------------// end of program
▲
If a given number has an exact square root, this subroutine finds it. If the given number does
not have an exact integer square root, then the number returned by the subroutine may not be
the closest approximation. The algorithm in Figure 5.5 computes a sar that satisfies the relationship sar * sar Ä q. This may have the undesirable effect that the computed sar value may not
be as close to the real square root as is the value of sar 1 1. However, this can be fixed easily by
comparing the following two expressions:
1. (sar + 1)2 – q
2. q – sar2
If the first expression is smaller, then (sar 1 1) is a better choice. Otherwise, we should choose
sar as the approximation to the real square root. This is left as an exercise problem. The subroutine that finds the square root of a 16-bit unsigned integer can be written in the same way and is
made into a file (SqRoot16.asm) so that it can be reused in the next example.
5.6.7 Prime Test Subroutine
Testing whether a number is a prime number may not be very useful for embedded applications. However, it can serve as a good example for software reuse.
The most efficient method for testing whether a number is a prime number is to divide the
number by all the prime numbers from 2 to its integral square root. Because the prime numbers
from 2 to the square root of the given number are not available, we are satisfied with dividing
the given number by all the integers from 2 to its integral square root.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.6
■
Writing Subroutines to Perform Multiprecision Arithmetic
127
The algorithm for testing whether a number is a prime number is as follows:
Step 1
Let num, k, and isprime represent the number to be tested, the loop index, and the flag to
indicate if num is a prime number.
Step 2
isprime ← 0; tlimit ← square root of num;
Step 3
for k 5 2 to tlimit do
if ((num % k) 55 0) then return;
isprime ← 1;
return;
The following example implements this algorithm.
Example 5.6
▼
Write a subroutine that can determine whether an unsigned 16-bit integer is a prime
number.
Solution: The subroutine that determines whether a number is a prime and its test program is
as follows:
.include <ATXMega128A1def.inc>
start:
cntLoop:
again:
.equ
.equ
.equ
.cseg
.org
rjmp
.org
ldi
out
ldi
out
ldi
ldi
call
nop
rjmp
SPL 5 CPU_SPL
SPH 5 CPU_SPH
tstDat 5 7919
; comment this line for AVR Mega devices
; comment this line for AVR Mega devices
0x00
start
0xF6
r20,low(RAMEND)
SPL,r20
r20,high(RAMEND)
SPH,r20
r16,low(tstDat)
r17,high(tstDat)
prime16
again
; ----------------------------------------------------------------------------------------------------------------------; The next subroutine determines whether an unsigned 16-bit integer is a prime number.
; The 16-bit number is passed in r16~r17 and the result (0 or 1) is returned in r22.
; ----------------------------------------------------------------------------------------------------------------------.def
.def
tLimit 5 r3
tstDiv 5 r21
; limit of test divide
; number to test divide r16~r17
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
128
Chapter 5
■
prime16:
eq2or3:
normal:
tdLoop:
notP:
isP:
Advanced Assembly Programming and Subroutine Calls
cpi
brne
cpi
brhs
cpi
brhs
ldi
ret
ldi
ret
call
mov
ldi
mov
clr
push
push
call
pop
pop
cpi
breq
cp
breq
inc
rjmp
ldi
ret
ldi
ret
.include
.include
r17,0
normal
r16,4
normal
r16,2
eq2or3
r22,0
; is upper byte 0?
; upper byte not 0, continue
; is the number greater than 3?
; yes, continue
; is the number less than 2?
; yes, 2 and 3 are prime numbers
; 1 or 0 are not prime numbers
r22,1
; 2 and 3 are prime numbers
SqRoot16
tLimit,r22
tstDiv,2
r18,tstDiv
r19
tLimit
tstDiv
div16U
tstDiv
tLimit
r22,0
notP
tstDiv,tLimit
isP
tstDiv
tdLoop
r22,0
; derive the test divide limit
; save the test divide limit
; start the test divide number from 2
; divide the number by tstDiv
; is the remainder 0?
; have we tested all numbers up to tLimit?
; if yes, then the number is a prime
; test divide the next higher number
r22,1
"div16U.asm"
"SqRoot16.asm"
; insert the subroutine that performs 16-bit division
; insert the subroutine that finds the square root of 16-bit
; unsigned integer
//End of program
▲
5.7 Subroutines with Local Variables in Stack
Only subroutines that require many local variables need to utilize the stack to assign local
variables. Subroutines that deal with multiple large numbers simultaneously (say, 32-bit numbers) are in this category and may take advantage of the stack to meet the need of computation.
The two examples provided in this section do not need to assign local variables to the stack.
They are written to demonstrate how to assign local variables in the stack and how to access
them during the course of subroutine execution.
5.7.1 Subroutine to Convert a BCD String to a Binary Number
Unlike numeric data, text data are encoded in ASCII code. Text data may also represent
numbers. For example, the ASCII string 32333435363716 represents the decimal value 234567.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.7
■
Subroutines with Local Variables in Stack
129
In order to allow the MCU to manipulate text data that represent numeric values, we need to
convert them into binary values.
The subroutine that performs the conversion also needs to perform error checking to make
sure that the text data contains no invalid characters. The subroutine should use a flag to
indicate whether the return value is valid or invalid.
To get an idea how to convert a BCD string into binary value, let’s use a two-digit decimal value 36 as an example. The value of 36 is encoded as a two-byte ASCII string 0x3336.
The ten’s digit can be extracted by subtracting 0x30 from the first byte of the string, whereas
the one’s digit can be extracted by subtracting 0x30 from the second byte of the string as
follows:
Ten’s digit 5 0x33 2 0x30 5 3
One’s digit 5 0x36 2 0x30 5 6
These two bytes can be combined by multiplying the ten’s digit by 10 and then adding the
ones to the product. The following code converts the ASCII string into binary value:
string:
ldi
ldi
lpm
subi
ldi
mul
lpm
subi
add
ZL,low(string << 1)
ZH,high(string << 1)
r20,z1
r20,0x30
r21,10
r20,r21
r20,z
r20,0x30
r0,r20
.db
"36",0
; use Z to point to the BCD string
; "
; fetch the first byte
; extract the ten’s digit
; multiply ten’s digit by 10
; product is in r1:r0
; fetch second byte
; extract one’s digit
; add to the product of ten’s digit x 10
; the upper byte (r1) of the product is zero
This idea can be extended to handle longer BCD strings. The subroutine that performs
the conversion also needs to perform error checking to make sure that the text data contains
no invalid characters. The subroutine should use a flag to indicate whether the return value is
valid or invalid.
Let in_ptr, sign, error, and value represent the pointer to the BCD string, sign flag, error flag,
and the number (4 bytes) represented by the BCD string. The algorithm of the subroutine is as
follows:
Step 1
sign ← 0; error ← 0; value ← 0;
Step 2
If the character pointed to by in_ptr is the minus sign, then
sign ← 1; in_ptr ← in_ptr 1 1
Step 3
If the character pointed to by in_ptr is the NULL character,
then go to step 4.
else if the character is not a BCD digit (i.e., m[in_ptr] > 0x39 or m[in_ptr] < 0x30), then:
error ← 1;
go to step 4;
else:
value ← value 3 10 1 m[in_ptr] - 0x30;
in_ptr ← in_ptr 1 1;
go to step 3;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
130
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
Step 4
If sign 5 1 and error 5 0, then
number ← two’s complement of number;
else
stop;
Example 5.7
Write a subroutine that can convert a BCD ASCII string to a binary number. The ASCII
string represents a number in the range of 2231~231 2 1. A pointer to the string is passed to this
subroutine in Z. The converted binary number is returned in registers r22~r25.
5 4 3 2 1
Figure 5.7
■
SP
sign
t1
t2
t3
t4
r27
r28
r29
retAddr
Source: Atmel Corporation, The Atmel AVR
Microcontroller
▼
Stack frame for Example 5.7
Solution: In this example, the subroutine allocates local variables in the stack as shown in Figure 5.7.
Registers r22~r25 are used to return the value represented by the BCD string. The expression of value 3 10 is evaluated by computing the partial products, aligning them properly, and
accumulate them using local variables t4~t1 as illustrated in Figure 5.8. v1~v4 are the lsb~msb
of value. Because the size limit of the number represented by the BCD string, the product of v4
and 10 is no larger than one byte.
t3
t2
t1
v1 x 10
v2 x 10
v3 x 10
v4 x 10
+
msb
Isb
Source: Atmel Corporation, The Atmel AVR
Microcontroller
t4
Figure 5.8 ■ Partial product accumulation used to
convert from BCD string to binary value
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.7
■
Subroutines with Local Variables in Stack
start:
againC:
BCDStr:
131
.include <ATXMega128A1def.inc>
.macro allocStk
in
r28,CPU_SPL
in
r29,CPU_SPH
sbiw
r28,@0
out
CPU_SPL,r28
out
CPU_SPH,r29
.endmacro
.macro deallocStk
in
r28,CPU_SPL
in
r29,CPU_SPH
adiw
r28,@0
out
CPU_SPL,r28
out
CPU_SPH,r29
.endmacro
.cseg
.org
0x00
rjmp
start
.org
0xF6
ldi
r20,low(RAMEND)
out
CPU_SPL,r20
ldi
r20,high(RAMEND)
out
CPU_SPH,r20
ldi
r30,low(BCDStr<<1)
ldi
r31,high(BCDStr<<1)
call
bcd2bin32
; convert to binary
rjmp
againC
.db
"9367200",0,0
; ------------------------------------------------------------------------------------------------------------------------------------; The next subroutine converts a BCD string to a 32-bit binary number that the BCD string represents.
; The string is pointed to by the Y register and the converted value is returned in r22~r25 (v1~v4).
; --------------------------------------------------------------------------------------------------------------------------------------
bcd2bin32:
.equ
.equ
.equ
.equ
.equ
.def
.def
.def
.def
.def
.def
push
push
push
allocStk 5
in
in
sign 5 1
t1 5 2
t2 5 3
t3 5 4
t4 5 5
newC 5 r20
ten 5 r21
v1 5 r22
v2 5 r23
v3 5 r24
v4 5 r25
r29
r28
r27
YL,CPU_SPL
YH,CPU_SPH
; distance from top of stack for temporary storage
; "
; "
; "
; used to hold the current character
; used to hold the value of 10
; registers to hold the value to be returned
; "
; "
; "
; allocate 5 bytes for local variables
; let Y point to the byte above stack top
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
132
Chapter 5
rloop:
chkErr:
■
Advanced Assembly Programming and Subroutine Calls
clr
clr
clr
clr
clr
std
ldi
lpm
cpi
brne
ldi
std
lpm
lpm
cpi
brne
rjmp
cpi
brlo
cpi
brsh
ldi
sub
mul
std
std
mul
std
std
mul
ldd
add
std
ldd
adc
std
ldd
clr
adc
std
mul
ldd
add
std
ldd
add
mov
clr
ldd
v1
v2
v3
v4
r0
Y1sign,r0
ten,10
newC,z
newC,'-'
rloop
newC,1
Y1sign,newC
newC,z1
newC,z1
newC,0
chkErr
doneBCD2B
newC,0x30
illegal
newC,0x3A
illegal
r27,0x30
newC,r27
v1,ten
Y1t1,r0
Y1t2,r1
v3,ten
Y1t3,r0
Y1t4,r1
v2,ten
r2,Y1t2
r0,r2
Y1t2,r0
r2,Y1t3
r2,r1
Y1t3,r2
r2,Y1t4
r1
r2,r1
Y1t4,r2
v4,ten
r2,Y1t4
r0,r2
Y1t4,r0
r0,Y1t1
r0,newC
v1,r0
r1
r0,Y1t2
; initialize the value to be returned to 0
; "
; "
; "
; initialize the sign to positive
; place 10 in register r21
; set sign to minus
; move pointer to the next character
; read one BCD character from string and move pointer
; reach the end of string?
; convert current character to its decimal value
; performed by generating partial products,
; aligned properly, added together
; "
; "
; "
; "
; "
; "
; "
; "
; "
; "
; "
; "
; "
; "
; "
; the product of 10 and v4 is only one byte
; "
; "
; "
; add the current character value to slots stack t1~t4
; and then save the result in v1~v4
; "
; "
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.7
■
133
Subroutines with Local Variables in Stack
adc
mov
ldd
adc
mov
ldd
adc
mov
rjmp
doneBCD2B: ldi
rjmp
illegal:
ldi
toRet:
ldd
sbrs
rjmp
com
com
com
com
movw
adiw
movw
ldi
adc
adc
skip:
deallocStk 5
pop
pop
pop
ret
// End of program
r0,r1
v2,r0
r0,Y1t3
r0,r1
v3,r0
r0,Y1t4
r0,r1
v4,r0
rloopç
r26,0
toRet
r26,1
r28,Y1sign
r28,0
skip
v1
v2
v3
v4
r28,v1
r28,1
v1,r28
r28,0
v3,r28
v4,r28
;
;
;
;
;
;
;
;
"
"
"
"
"
"
"
"
; set error flag to 0 (no error)
; set error flag to 1 (with error)
; skip if bit 0 (sign bit) of r28 is 1
; no need to find 2’s complement if positive
; the given number is negative; so find its
; two’s complement
; "
; "
; add 1 to the 1’s complement of v4~v1
; "
; "
; "
; "
; "
r27
r28
r29
▲
5.7.2 Bubble Sort
Sorting is among the most common ingredients of programming, and many sorting methods are being used. Sorting makes many efficient search methods possible. The bubble sort is
a simple, widely known, but inefficient, sorting method. Many other more efficient sorting
methods require the use of recursive subroutine calls, which fall outside the scope of this book.
The basic idea underlying the bubble sort is to go through the array or file sequentially
several times. Each iteration consists of comparing each element in the array or file with its
successor (x[i] with x[i11]) and interchanging them if they are not in proper order (either ascending or descending). Consider the following array:
157 13 35 9 98 810 120 54 10 30
Suppose we want to sort this array in ascending order. The following comparisons are made
in the first iteration:
x[0] with x[1] (157 and 13) interchange
x[1] with x[2] (157 with 35) interchange
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
134
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
x[2] with x[3] (157 with 9) interchange
x[3] with x[4] (157 with 98) interchange
x[4] with x[5] (157 with 810) no interchange
x[5] with x[6] (810 with 120) interchange
x[6] with x[7] (810 with 54) interchange
x[7] with x[8] (810 with 10) interchange
x[8] with x[9] (810 with 30) interchange
Thus, after the first iteration, the array is in the order
13 35 9 98 157 120 54 10 30 810
Notice that after this first iteration, the largest element (in this case, 810) is in its proper
position within the array. In general, x[n 2 i] is in its proper position after iteration i. The
method is called the bubble sort because each number slowly bubbles up to its proper position.
After the second iteration the array is in the order
13 9 35 98 120 54 10 30 157 810
Notice that 157 is now in the second-highest position. Because each iteration places a new
element into its proper position, an array or a file of n elements requires no more than n – 1
iterations. The complete set of iterations is as follows:
Iteration
0 (original array)
1
2
3
4
5
6
7
8
9
157 13 35 9 98 810 120 54 10 30
13 35 9 98 157 120 54 10 30 810
13 9 35 98 120 54 10 30 157 810
9 13 35 98 54 10 30 120 157 810
9 13 35 54 10 30 98 120 157 810
9 13 35 10 30 54 98 120 157 810
9 13 10 30 35 54 98 120 157 810
9 10 13 30 35 54 98 120 157 810
9 10 13 30 35 54 98 120 157 810
9 10 13 30 35 54 98 120 157 810
There are some obvious improvements to the foregoing method:
•
First, because all elements in positions greater than or equal to n 2 i are already
in proper position after iteration i, they need not be considered in succeeding
iterations. Thus, in the first iteration, n 2 1, comparisons are made; on the second
iteration, n 2 2, comparisons are made; and on the (n 2 1)th iteration, only one
comparison is made (between x[0] and x[1]). Therefore, the process is sped up as it
proceeds through successive iterations.
•
Second, although we have shown that n 2 1 iterations are sufficient to sort an array
or a file of size n, in the preceding sample array of 10 elements, the array was sorted
after the seventh iteration, making the last two iterations unnecessary. To eliminate
unnecessary iterations, we must be able to detect the fact that the array is already
sorted. An array is sorted if no swaps are made in an iteration. By keeping a record
of whether any swaps are made in a given iteration, it can be determined whether
any further iteration is necessary. The logic flow of the bubble sort algorithm is
illustrated in Figure 5.9. The following example implements the bubble sort as a
subroutine:
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.7
■
135
Subroutines with Local Variables in Stack
Start
iteration ← N–1
sorted ← 1
inner ← iteration
i←0
array[i] > array[i+1]?
no
yes
swap array[i] & array[i+1]
sorted ← 0
no
inner = 0?
yes
sorted = 1?
no
Iteration ← iteration–1
no
iteration = 0?
yes
Stop
Figure 5.9
■
yes
Source: Atmel Corporation, The Atmel AVR Microcontroller
inner ← inner–1
i←i+1
Logic flow of bubble sort
Example 5.8
▼
Write a subroutine to implement the bubble sort algorithm and a sequence of instructions
along with a set of test data for testing this subroutine. Use an array that consists of n 8-bit unsigned integers for testing purposes.
Solution: The bubble sort subroutine has several local variables:
•
•
•
Sorted: flag to indicate whether the array is in order after an iteration
Inner: number of comparisons that remain to be performed in the current iteration
Iteration: number of iterations that remain to be performed
The stack frame of the bubble sort subroutine is shown in Figure 5.10.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
SP
3 2 1
Figure 5.10
sorted
iCnt
eCnt
r28
r29
ret_addr
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
136
Stack frame for bubble sort subroutine
The bubble sort subroutine and its test program are as follows:
array:
start:
cpLoop:
.include
.equ
.equ
.macro
in
in
sbiw
out
out
.endmacro
.macro
in
in
adiw
out
out
.endmacro
.equ
.def
.dseg
.org
.byte
.cseg
.org
rjmp
.org
ldi
out
ldi
out
ldi
ldi
ldi
ldi
ldi
lpm
<ATXMega128A1def.inc>
SPL 5 CPU_SPL
; commented for Mega devices
SPH 5 CPU_SPH
; "
allocSt k
; this macro allocate space for local variables
r28,SPL
r29,SPH
r28,@0
SPL,r28
SPH,r29
deallocStk
r28,SPL
r29,SPH
r28,@0
SPL,r28
SPH,r29
; this macro deallocates space used by local variables
NN 5 30
lpcnt 5 r21
0x2000
40
0x00
start
0xF6
r20,low(RAMEND)
SPL,r20
r20,high(RAMEND)
SPH,r20
ZL,low(xarr<<1)
ZH,high(xarr<<1)
XL,low(array)
XH,high(array)
lpcnt,NN
r0,z1
; initialize stack pointer
; "
; "
; "
; set up pointer to the array in program memory
; "
; set up pointer to the buffer array in data memory
; "
; set up loop count
; copy the array from program memory to data memory
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.7
■
137
Subroutines with Local Variables in Stack
again:
st
dec
brne
ldi
ldi
ldi
call
nop
rjmp
x1,r0
lpcnt
cpLoop
r16,low(array)
r17,high(array)
r18,NN
bubble
; so that it can be sorted
; "
; "
; pass array pointer
; "
; pass array count
again
; -----------------------------------------------------------------------------------------------------------------; The next subroutine uses bubble sort algorithm to sort an array in data memory.
; The array count is passed in r18 and the pointer to the array is passed in r16~r17.
; All array elements are nonnegative.
; -------------------------------------------------------------------------------------------------------------------
bubble:
eLoop:
iloop:
next:
.equ
.equ
.equ
.equ
push
push
allocStk
in
in
dec
std
ldd
std
movw
ldi
std
ld
ldd
cp
brlo
st
std
ldi
std
adiw
ldd
dec
std
brne
ldd
cpi
breq
ldd
dec
eCnt 5 3
iCnt 5 2
sorted 5 1
true 5 1
YH
YL
3
YL,SPL
YH,SPH
r18
Y1eCnt,r18
r18,Y1eCnt
Y1iCnt,r18
ZL,r16
r20,1
Y1sorted,r20
r8,z
r9,z11
r8,r9
next
z,r9
z11,r8
r20,0
Y1sorted,r20
ZL,1
r20,Y1iCnt
r20
Y1iCnt,r20
iloop
r20,Y1sorted
r20,true
done
r20,Y1eCnt
r20
; iteration count offset from TOS
; inner count offset from TOS
; array is already sorted flag offset from TOS
; allocate 3 bytes for local variables
; set Y point to the byte above the top of stack
; "
; initialize iteration count to NN - 1
; "
; set up inner loop count
; "
; place array base address in Z
; set flag to indicate array is sorted
; "
; get array[i]
; get array[i11]
; compare array[i] with array[i11]
; swap array[i] with array[i11]
; "
; indicate array not sorted
; "
; increment array pointer by 1
; decrement inner loop count
; "
; "
; continue if inner loop count is not 0
; check array sorted flag
; "
; stop if sorted flag is true (1)
; decrement iteration loop count
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
138
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
std
brne
done:
deallocStk 3
pop
pop
ret
xarr:
.db
.db
.db
// End of program
Y1eCnt,r20
eLoop
; "
YL
YH
12,91,20,33,45,72,24,19,17,101
11,92,21,34,44,71,25,18,16,131
41,43,49,50,99,79,89,98,37,59
▲
5.8 Summary
Often, the same sequence of instructions has to be executed in several places in a program. The programmer can place this sequence of instructions in a macro or a subroutine. Both
the subroutine and macro can be invoked in many places within a program. The differences
between a macro and a subroutine are as follows:
Similarities
•
Both the macro and subroutine can be invoked from many different places within a
program.
•
•
Parameters may be passed when a macro or subroutine is invoked.
•
Both the macro and subroutine reduce the amount of typing necessary when they
are invoked more than once in a program.
Both create reusable code. A macro can be defined once and included in many
programs that can use it; so can a subroutine.
Differences:
•
A macro is invoked by entering the macro name and parameters, whereas a
subroutine is invoked by executing a call instruction.
•
A macro call does not need the saving and restoring of return address and hence
runs faster than its equivalent in the subroutine format.
•
Each time a macro is invoked, a copy of the instructions contained in the macro
definition is inserted into the program. However, no such code duplication is made
in a subroutine call.
The subroutine mechanism makes the “top-down design with hierarchical refinement”
methodology easy to implement. In addition to creating reusable code, the subroutine mechanism enables the user to breakdown a difficult problem into smaller and manageable program
units. A complicated problem then becomes easier to solve.
To implement the subroutine mechanism, the AVR provides subroutine-call instructions
rcall, icall, eicall, and call, and return instruction ret. The subroutine mechanism also requires
the return address to be saved and restored. This is achieved by providing the stack data structure. The AVR MCU allows the user to implement a stack using the on-chip data memory.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.9
■
Exercises
139
The 16-bit stack pointer (SP) points to the byte above the top byte of this stack. The user can
push data into the stack and pop data out of the stack.
When making subroutine calls, the caller may need to pass certain values required by the
subroutine for performing the intended operation. After the computation is completed, the
subroutine returns the result back to the caller. Incoming parameters may be passed in registers, data memory (global memory), or the stack. The computation result may be returned in
registers, data memory (global memory), or the stack. The subroutine also may need temporary
variables for computation purpose. These temporary variables are called local variables and
should be allocated in the stack to avoid interference among subroutines. However, for the
following two reasons the programmer should assign local variables to registers as much as
possible:
•
•
The AVR instruction set can perform arithmetic and logic operations only on registers.
The AVR has many CPU registers to be assigned to local variables.
The programmer should follow certain rules in using registers to pass parameters to subroutine, assigning local variables to registers, and using registers to return computation results.
This text follows the register usage recommendation specified in Table 5.1.
The AVR provides only 8-bit by 8-bit multiplication instructions. However, the programmer can write subroutines to implement multiprecision multiplication and division operations,
as demonstrated in this chapter.
5.9 Exercises
E5.1 Write a subroutine that can create a time delay that is a multiple of 1 ms. The multiple is
passed in register r16, assuming that the CPU clock is 16 MHz.
E5.2 Write a subroutine that can create a time delay that is a multiple of 10 ms. The multiple is
passed in r16, assuming that the CPU clock is 16 MHz.
E5.3 Write a subroutine that can divide a 16-bit signed integer into another 16-bit signed integer. The dividend and divisor are passed in registers r16~r17 and r18~r19, respectively. The
quotient and remainder are returned in r24~r25 and r22~r23, respectively.
E5.4 Write a subroutine that can divide a 32-bit unsigned integer into another 32-bit unsigned
integer. The dividend is passed in registers r16~r19, and the divisor is passed in the stack. The
quotient is returned in registers r22~r25, and the remainder is returned in registers r16~r19.
E5.5 Write a subroutine that can divide a 32-bit signed integer into another 32-bit signed integer. The dividend is passed in registers r16~r19, and the divisor is passed in the stack. The
quotient is returned in registers r22~r25, and the remainder is returned in registers r16~r19.
E5.6 Write a subroutine to find the number of elements in an array that are a multiple of 5.
The pointer to the array is passed in r30~r31, whereas the array count is passed in r16. The
array has no more than 255 16-bit unsigned integers. The subroutine returns the result in
register r22.
E5.7 Write a subroutine to find the greatest common divisor of two 16-bit unsigned integers.
Two integers are passed in registers r16~r17 and r18~r19, respectively. The gcd is returned in
registers r22~r23.
E5.8 Write a subroutine to test whether a four-digit decimal number has the following property: The square of the sum of the upper half and the lower half of the given number is equal
to the original number. The number to be tested is passed in r16~r17, and the result (0 or 1) is
returned in register r22.
E5.9 Write a program to find out all the four-digit decimal numbers (1000 to 9999) that have the
property specified in problem E5.8.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
140
Chapter 5
■
Advanced Assembly Programming and Subroutine Calls
E5.10 Write a subroutine to test whether a four-digit decimal number has the following property: The sum of the square of the upper half and the square of the lower half of the given number is equal to the original number. The number to be tested is passed in r16~r17, and the result
(0 or 1) is returned in register r22.
E5.11 Write a program to find out all the four-digit decimal numbers (1000 to 9999) that have
the property specified in problem E5.10.
E5.12 Write a subroutine to test whether a 3-digit decimal integer has the property: Let d2, d1,
and d0 be the hundreds, tens, and ones digit. d23 1 d13 1 d03 5 original number. Write a program
to call this function and find out all the 3-digit numbers that have this property.
E5.13 Write a subroutine to implement selection sort and write a main program to test it.
The selection sort method works like this if the array is to be sorted in descending order: You
are given an array of 8-bit integer values. Search through the array, find the largest value, and
exchange it with the value stored in the first array location. Next, find the second largest value
in the array, and exchange it with the value stored in second array location. Repeat the same
process until the end of the array is reached.
Assume that the array is stored in data memory. Write an instruction sequence to test this
subroutine. This instruction sequence should copy a test array in program memory to the data
memory and then call the subroutine to sort the array. The array count and starting address are
passed in registers r16 and r30~r31, respectively.
E5.14 Write a program to call the prime16 subroutine in Example 5.6 to find out all the prime
numbers between 8000 and 9999, and store them in data memory.
E5.15 Write a subroutine to convert an 8-bit binary number to two hexadecimal digits, with
each digit encoded in ASCII code. Also write a main program to test this subroutine.
5.10 Lab Assignments
L5.1 BINARY SEARCH SUBROUTINE
Searching is a frequently performed operation. When an array is not sorted, the search program may need to compare every element of the array. When an array or a file is sorted, searching can be performed much faster. Several efficient searching algorithms have been invented
for a sorted array. The binary search algorithm is one of the most efficient search algorithms in
use. Suppose the sorted array (in ascending order) has N elements and is stored in memory locations starting at the label arr. Let max and min represent the highest and lowest range of array
indices to be searched, and the variable mean represent the average of max and min. The idea of
a binary search algorithm is to divide the sorted array into three parts.
•
•
•
The upper half: the portion of the array with indices ranging from mean 1 1 to max.
The middle element: the element with index equal to mean.
The lower half: the portion of the array with indices ranging from min to mean 2 1.
The binary search algorithm compares the key with the middle element and takes one of
the following actions on the basis of the comparison result:
•
•
If the key equals the middle element, then stop.
•
If the key is smaller than the middle element, then the key can be found only in
the lower half of the array. The search is continued in the lower half.
If the key is larger than the middle element, then the key can be found only in the
upper half of the array. The search is continued in the upper half.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
5.10
■
Lab Assignments
141
Write a subroutine to implement the binary search algorithm and write a test program
(including a sorted array as test data) to test the subroutine. The search result is returned in
register r22. When the key is found, a 1 is returned. Otherwise, a 0 is returned.
L5.2 BINARY
TO
HEX ASCII CONVERSION
Write a subroutine to convert a 16-bit binary number into four hexadecimal digits. Each
of these hexadecimal digits is represented in the ASCII code. The 16-bit number to be converted are passed in r17~r16 (r17 holds the upper 8 bits), and the result is returned in r25~r22
(from most significant digit to least significant digit). Also write a main program to test this
subroutine.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6
C Language Programming
6.1 Objectives
After completing this chapter, you will be able to
• Explain the overall structure of a C language
program.
• Use appropriate operators to perform desired
operations in the C language.
• Understand the basic data types and expressions
of the C language.
• Write program loops in the C language.
• Write functions and make function calls in
the C language.
• Use arrays and pointers for data manipulation.
• Perform basic I/O operations in the C language.
• Use C statements to manipulate bit and bit
fields of a variable.
• Learn the naming convention of AVR registers
and bits.
• Use the AVR Studio IDE to enter, compile,
and debug C programs.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
144
Chapter 6
■
C Language Programming
6.2 Introduction to C
The purpose of this chapter is to provide a review to the C language and also an introduction to using the C language to program the AVR peripheral functions. To benefit from this
chapter readers are expected to have taken a course in C or another high-level language before
reading it.
This chapter provides a summary of the C language constructs that are commonly used
in embedded system programming. In addition to summarizing the C language features,
this chapter also illustrates the naming convention for registers and bits, the data structure
used in describing the AVR peripheral registers, bit masks, bit group masks, and so on.
A tutorial on using the AVR Studio IDE in developing and debugging C programs is also
provided.
The C language is quickly replacing the assembly language in every embedded application
because it has several advantages over the assembly language. The most important one is that
it allows the user to work on program logic at a level much higher than that of the assembly
language, and thus programming productivity is greatly improved.
A C program, whatever its size, consists of functions and variables. A function contains
statements that specify the operations to be performed. The types of statements in a function
could be a declaration, assignment, function call, control, or null. A variable stores a value
to be used during the computation. The main() function is required in every C program and
is the one to which control is passed when the program is executed. A simple C program is
as follows.
(1) #include ,avr\io.h.
(2) void main (void)
(3) {
(4)
char ax, bx, cx;
(5)
DDRA
5 0xFF;
(6)
ax
5 6;
(7)
bx
5 9;
(8)
cx
5 ax 1 bx;
(9)
PORTA
5 cx;
(10)
while(1);
(11) }
/* declare three variables */
// configure PORTA for output
// assign 6 to variable ax
// assign 9 to variable bx
// assign the sum of ax and bx to cx
// output cx to PORTA
// stay in an infinite loop
The first line of the program causes the specified file to be included in this program. This
line appears at the beginning of every C program for the Atmel AVR MCU. When using the AVR
Studio IDE to create a project, the user must specify the target MCU. After that, the header file
that contains the definitions of all special function registers (peripheral control, data, and status
registers) and bits will be inserted into the program so that the user can use symbolic names to
refer to them.
The second line main() is where program execution begins. The opening brace on the third
line marks the start of the main() function’s code. Every C program must have one, and only
one, main() function. Program execution is also ended with the main() function. The fourth
line declares three variables (ax, bx, and cx) of character type. In C language, a variable must be
declared before it can be used.
The fifth line assigns 0xFF to the DDRA register that configures the PORTA pins for output.
The sixth and seventh lines assign a value to a variable. The eighth line adds ax and bx together
and assigns the sum to the variable cx.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.3
■
Types, Operators, and Expressions
145
The ninth line assigns the value of cx to PORTA pins which might be driving LEDs or
seven-segment displays, and so on. The tenth line is an infinite loop that causes the processor to stay at this statement forever. The closing brace in the last line ends the main()
function.
Comments can be added to the C statements to explain the purpose or the operations performed by the statements. A single line comment may start with /* (line 4) or // (line 5 to 10)
and is terminated by */ (line 4) or a space character (line 5 to 10). A multiple line comment can
only be started with the /* character pair and terminated with the */ character pair.
6.3 Types, Operators, and Expressions
Variables and constants are the basic objects manipulated in a program. Variables must be
declared before they can be used. A variable declaration must include the name and type of the
variable and may optionally provide its initial value. A variable name may start with a letter
(A through Z or a through z) or an underscore character followed by zero or more letters, digits,
or underscore characters. Variable names cannot contain arithmetic signs, dots, apostrophes,
C keywords, or special symbols such as @, #, ?, and so on. Adding the underscore character (_)
may sometimes improve the readability of long variables. Don’t begin variable names with an
underscore, however, because library routines often use such names. C language is case sensitive. Uppercase and lowercase letters are distinct.
6.3.1 Data Types
There are only a few basic data types in C: void, char, int, float, and double. A variable of type void represents nothing. The type void is used most commonly with functions,
which can indicate that the function does not return any value or does not have incoming
parameters. A variable of type char can hold a single byte of data (signed). A variable of type
int is an (signed) integer, which is normally the natural size (word length) for a particular
machine. The type float refers to a 32-bit, single-precision, floating-point number. The type
double represents a 64-bit, double-precision, floating-point number. In addition, there are a
number of qualifiers that can be applied to these basic types. Short and long apply to integers. These two qualifiers will modify the lengths of integers. An integer variable is 16-bit
by default for many C compilers for 8- or 16-bit microcontrollers. However, the int type is
32 bit for 32-bit or higher microcontrollers. The modifier short does not change the length
of an integer for these compilers. The modifier long doubles a 16-bit integer to 32 bits.
The keyword unsigned should be used if the variables are never negative, to improve the
efficiency of the generated code.
6.3.2 Variable Declarations
All variables must be declared before their use. A declaration specifies a type and contains
a list of one or more variables of that type, as in
int
char
i, j, k;
cx, cy;
A variable may also be initialized when it is declared, as in
int
i 5 0;
char echo 5 ‘y’;
// the ASCII code of letter y is assigned to variable echo.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
146
Chapter 6
■
C Language Programming
6.3.3 Constants
There are four kinds of constants: characters, integers, floating-point numbers, and strings.
A character constant is an integer written as one character within single quotes, such as ‘x.’
A character constant is represented by the ASCII code of the character. A string constant is a
sequence of zero or more characters surrounded by double quotes, as in
“XMega128A1 is a microcontroller made by Atmel.”
or
“”
/* an empty string */
Each individual character in the string is represented by its ASCII code.
An integer constant such as 3241 is an int. A long constant is written with a terminal l (el)
or L, as in 44332211L. The constant characters listed in Table 6.1 are predefined in C language
(can be embedded in a string):
Character
Meaning
Character
Meaning
\a
Alert (bell) character
\\
Backspace
\b
Backspace
\?
Question mark
\f
Formfeed
\’
Single quote
\n
Newline
\”
Double quote
\r
Carriage return
\ooo
Octal number
\t
Horizontal tab
\xhh
Hexadecimal number
\v
Vertical tab
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.1
■
Escaped characters in C
As in assembly language, a number in C can be specified in different bases. The method to
specify the base of a number is to add a prefix to the number. The prefixes for different bases are
listed in Table 6.2.
Base
Prefix
Decimal
None
Binary
Example
1357
0b
0b10010010
Octal
0
04523
Hexadecimal
0x
0x345
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.2
■
Number base prefixes
6.3.4 Arithmetic Operators
The arithmetic operators supported in C are listed in Table 6.3.
The expression
a%b
produces the remainder when a is divided by b. The % operator cannot be applied to a float or
double. The / operator performs a division and truncates the quotient to an integer when both
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.3
■
147
Types, Operators, and Expressions
Symbol
Operation
Example
1
Add and unary plus
3 1 5; 14
2
Subtract and unary minus
60 2 13; 210
*
Multiply
a*b
/
Divide
100 / 13
Modulus
300 % 19
11
Increment
11y; y11
22
Decrement
22ptr; ptr22
%
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.3
■
Arithmetic operators in C
operands are integers. The 11 operator adds 1 to the operand, and the 22 operator subtracts
1 from the operand. Depending on whether the 11 (or 22) operator appears before or after the
variable it applies to, the increment (decrement) operation is performed before or after it is used
in the expression. For example, in the next statement
xx 5 11yy;
the variable yy is incremented before it is assigned to xx. In the expression
abc 5 3 1 yy11;
the sum of 3 and the variable yy is assigned to the variable abc, and then yy is incremented by 1.
Example 6.1
▼
What value will be assigned to ax for the following statement?
ax 5 230 / 11;
Solution: The integral part of 230/11 is 11. Therefore, ax receives 11 after the previous statement
is executed.
▲
Example 6.2
▼
What value will be assigned to bx for the following statement?
bx 5 435 % 25;
Solution: The remainder of 435/25 is 10. Therefore, bx receives 10 after the previous statement
is executed.
▲
Example 6.3
▼
Assume that ak is a four-digit (decimal) integer. Write a few C statements to separate ak
into two parts, and assign the upper two digits to the variable ax and the lower two digits to the
variable bx.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
148
Chapter 6
■
C Language Programming
Solution: A four-digit value d3d2d1d0 can be written as
d3d2d1d0 5 d3d2 3 100 1 d1d0
where d 3, d 2, d 1, and d 0 are the thousands, hundreds, tens, and ones digit of the number,
respectively.
Therefore, we can divide a four-digit integer by dividing 100 into that number. The following
two statements perform the desired operation:
ax 5 ak /100;
bx 5 ak % 100;
▲
6.3.5 Bitwise Operators
C provides six operators (listed in Table 6.4) for bit manipulations; these operators may be
applied only to integral operands, which are char, short, int, and long, whether they are signed
or unsigned.
Symbol
Operation
Example
&
AND
ax & bx
|
OR
ax | 0x0F
^
XOR
ax ^ 0xAA
|
NOT
|ax
..
Right shift
ax .. 2
,,
Left shift
bx ,, 4
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.4
■
Bitwise logic operators in C
The & operator is often used to clear one or more bits to zero. For example, the statement
P1 5 P1 & 0xBD;
/* variable P1 is 8 bits */
clears bits 6 and 1 of P1 to 0. The | operator is often used to set one or more bits to 1. For example,
the statement
P2 5 P2 | 0x40;
/* variable P2 is 8 bits */
sets the bit 6 of P2 to 1. The XOR operator can be used to toggle a bit. For example, the statement
abc 5 abc ^ 0xF0;
/* abc is of type char */
toggles the upper four bits of the variable abc. The .. operator shifts the involved operand to
the right for the specified number of places. For example,
xyz 5 abc .. 3;
shifts the variable abc to the right three places and assigns the result to the variable xyz. The ,,
operator shifts the involved operand to the left for the specified number of places. For example,
xyz 5 xyz ,, 4;
shifts the variable xyz to the left four places. The assignment operator 5 is often combined with
the operator when the destination operand is the same as one of the source operand. For example,
PTP 5 PTP & 0xBD;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.3
■
149
Types, Operators, and Expressions
can be rewritten as
PTP &5 0xBD;
The statement
P2 5 P2 | 0x40;
can be rewritten as
P2 |5 0x40;
6.3.6 Relational and Logical Operators
Relational operators are used in expressions to compare the values of two operands. If the
result of the comparison is true, then the value of the expression is 1. Otherwise, the value of
the expression is zero. The relational and logical operators are listed in Table 6.5.
Symbol
Operation
equal to
55
Example
ax 55 bx
!5
not equal to
ax !5 10
.
greater than
ax .60
greater than or equal to
ax .5 20
less than
ax ,40
less than or equal to
ax ,5 80
.5
,
,5
&&
and
(ax . 3) && (bx , 10)
||
or
(ax 55 0) || (bx !5 3)
!
not (one’s complement)
!ax
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.5
■
Relational and logical operators in C
Some examples of relational and logical operators are
if (!(PORTD & 0x80))
statement1;
if (i . 0 && i , 10)
statement2;
if (a1 55 a2)
statement3;
/* if bit 7 is 0, then execute statement1 */
/* if 0 , i , 10 then execute statement2 */
/* if a1 equals a2 then execute statement3 */
6.3.7 Precedence of Operators
Precedence refers to the order in which operators are processed. The C language maintains a precedence for all operators, as shown in Table 6.6. Operators at the same level are
evaluated from left to right. A few examples that illustrate the precedence of operators are
listed in Table 6.7.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
150
Chapter 6
■
C Language Programming
Precedence
Operator
Highest
Lowest
Associativity
() [] S .
left to right
! | 11 22 2 * & (type) sizeof
right to left
*/%
left to right
12
left to right
,, ..
left to right
, ,5 . .5
left to right
55 !5
left to right
&
left to right
^
left to right
|
left to right
&&
left to right
||
left to right
?:
right to left
5 15 25 *5 /5 %5 &5 ^5 |5 ,,5 ..5
right to left
‘
left to right
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.6
■
Table of precedence of operators
Expression
Result
15 2 2 * 7
1
(13 2 4) * 5
45
(0x20 | 0x01) !50x01
1
Note
* has higher precedence than 2
0x20 | 0x01 !50x01
0x20
!5 has higher precedence than |
1 ,, 3 1 1
16
1 has higher precedence than ,,
(1 ,, 3) 1 1
9
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.7
■
Examples of operator precedence
6.4 Control Flow
The control-flow statements specify the order in which computations are performed. In the
C language, the semicolon is a statement terminator. Braces, { and }, are used to group declarations and statements together into a compound statement or block, so that they are syntactically equivalent to a single statement.
6.4.1 If Statement
The if statement is a conditional statement. The statement associated with the if statement is executed based upon the outcome of a condition. If the condition evaluates to nonzero,
the statement is executed. Otherwise, it is skipped.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.4
■
Control Flow
151
The syntax of the if statement is
if (expression)
statement;
An example of an if-statement is
if (a . b)
sum 15 2;
The value of sum will be incremented by 2 if the variable a is greater than the variable b.
6.4.2 If-Else Statement
The if-else statement handles conditions where a program requires one statement to be
executed if a condition is nonzero and a different statement if the condition is zero.
The syntax of an if-else statement is
if (expression)
statement1
else
statement2
The expression is evaluated. If it is true (nonzero), statement1 is executed. If it is false,
statement2 is executed. Here is an example of the if-else statement:
if (a !5 0)
r 5 b;
else
r 5 c;
The if-else statement can be replaced by the ?: operator. The statement
r 5 (a !5 0)? b : c;
is equivalent to the previous if-else statement.
6.4.3 Multiway Conditional Statement
A multiway decision can be expressed as a cascaded series of if-else statements. Such a
series looks like
if (expression1)
statement1
else if (expression2)
statement2
else if (expression3)
statement3
…
else
statementn
An example of a three-way decision is
if (abc . 0) return 5;
else if (abc 55 0) return 0;
else return 25;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
152
Chapter 6
■
C Language Programming
6.4.4 Switch Statement
The switch statement is a multiway decision based on the value of a control expression.
The syntax of the switch statement is
switch (expression) {
case const_expr1:
statement1;
break;
case const_expr2:
statement2;
break;
…
default:
statementn;
}
As an example, consider the following program fragment:
switch (level) {
case 1:
pay 5 10;
break;
case 2:
pay 5 20;
break;
case 3:
pay 5 30;
break;
case 4:
pay 5 40;
break;
case 5:
pay 5 50;
break;
default:
pay 5 0;
}
The variable pay receives a value that is equal to level 3 10. The keyword break forces the
program flow to drop out of the switch statement so that only the statements under the corresponding case-labels are executed. If any break statement is missing, then all of the statements
from that case-label until the next break statement within the same switch statement will be
executed.
6.4.5 For-Loop Statement
The syntax of a for-loop statement is
for (expr1; expr2; expr3)
statement;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.4
■
Control Flow
153
where expr1 and expr3 are assignments or function calls, and expr2 is a relational expression.
For example, the following for loop computes the sum of the squares of integers from 1 to 9.
sum 5 0;
for (i 5 1; i , 10; i11)
sum 5 sum 1 i * i;
The following for loop prints out the first 10 odd integers.
for (i 5 1; i , 20; i11)
if (i % 2) printf(“%d “, i);
6.4.6 While Statement
When an expression is nonzero, the while loop repeats a statement or block of code. The
value of the expression is checked prior to each execution of the statement. The syntax of a while
statement is
while (expression)
statement;
The expression is evaluated. If it is nonzero (true), the statement is executed and expression is
reevaluated. This cycle continues until the expression becomes zero (false), at which point
execution resumes after the statement. The statement may be a NULL statement. A NULL statement does nothing and is represented by a semicolon. Consider the program fragment:
intCnt 5 5;
while (intCnt);
The CPU will stay in the while-loop until the variable intCnt becomes zero. In microcontroller
applications, the decrement of intCnt is often triggered by external events, such as interrupts.
6.4.7 Do-While Statement
The while and for loops test the termination condition at the beginning of the statement.
By contrast, the do-while statement tests the termination condition at the end of the statement; the body of the statement is executed at least once. The syntax of the statement is
do
statement
while (expression);
The following do-while statement initializes the array elements to its position in the array.
int k 5 0;
do
array[k] 5 k;
while (k , 20);
6.4.8 Goto Statement
Execution of a goto statement causes control to be transferred directly to the labeled statement, which must be located in the same function as the goto statement. The use of the goto
statement interrupts the normal sequential flow of a program and thus makes it harder to follow and decipher. For this reason, the use of goto is not considered good programming style, so
it is recommended that you do not use it in your program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
154
Chapter 6
■
C Language Programming
The syntax of the goto statement is
goto label
An example of the use of a goto statement is
if (x . 100)
goto
fatal_error;
…
fatal_error:
printf(“Variable x is out of bound!\n);
6.5 Input and Output
Input and output facilities are not part of the C language itself. However, input and output
are very important in applications. The ANSI standard defines a set of library functions that
must be included so that they can exist in a compatible form on any system where C exists.
Some of the functions deal with file input and output. Others deal with text input and output.
In this section, we will look at four input and output functions.
1. int getchar ( ). This function returns a character when it is called. The following
program fragment returns a character and assigns it to the variable xch.
char xch;
xch 5 getchar ();
2. int putchar (int). This function outputs a character on the standard output device. The
following statement outputs the letter a from the standard output device.
putchar (‘a’);
3. int puts (const char *s). This function outputs the string pointed to by s on the
standard output device. The following statement outputs the string “Learning
microcontroller is fun!” from the standard output device.
puts (“Learning microcontroller is fun!\n”);
4. int printf (formatting string, arg1, arg2, …, argn). This function converts, formats,
and prints its arguments on the standard output under the control of a formatting
string. arg1, arg2, …, argn are arguments that represent the individual output data items.
The arguments can be written as constants, single variable or array names, or more
complex expressions. The formatting string is composed of individual groups of
characters, with one character group associated with each output data item. The
character group corresponding to a data item must start with %. In its simplest form,
an individual character group consists of a percent sign followed by a conversion
character, indicating the type of the corresponding data item.
Multiple character groups can be contiguous or separated by other characters, including
white-space characters. These “other” characters are simply transferred directly to the output
device where they are displayed. A subset of the more frequently used conversion characters
is listed in Table 6.8. Between the % character and the conversion character there may be, in
order:
•
•
A minus sign, which specifies left adjustment of the converted argument.
•
A period, which separates the field width from precision.
A number that specifies the minimum field width. The converted argument will
be printed in a field at least this wide. If necessary, it will be padded on the left (or
right, if left adjustment is called for) to make up the field width.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.6
■
155
Functions and Program Structure
•
A number for the precision, which specifies the maximum number of characters to
be printed from a string, the number of digits after the decimal point of a floatingpoint value, or the minimum number of digits for an integer.
•
An h if the integer is to be printed as short, or l (letter el) if as long.
Several valid printf calls are given next.
printf (“this is a challenging course! \n”);
printf (“%d %d %d”, x1, x2, x3);
printf (“Today’s temperature is %4.1d \n”, temp);
Conversion
character
// outputs only a string
/* outputs variables x1, x2, x3 using a minimal number of
digits with one space separating each value */
/* display the string Today’s temperature is followed by
the value of temp. Display one fractional digit and use at
least four digits for the value. */
Meaning
c
Data item is displayed as a single character .
d
Data item is displayed as a signed decimal number .
e
Data item is displayed as a floating-point value with an exponent.
f
Data item is displayed as a floating-point value without an exponent.
g
Data item is displayed as a floating-point value using either e-type or f-type conversion,
depending on value; trailing zeros, trailing decimal point will not be displayed.
i
Data item is displayed as a signed decimal integer.
o
Data item is displayed as an octal integer ,without a leading zero.
s
Data item is displayed as a string.
u
Data item is displayed as an unsigned decimal integer.
x
Data item is displayed as a hexadecimal integer, without the leading 0x.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.8
■
Commonly used conversion characters for data output
By default, functions putchar, puts, and printf output data to the computer monitor via the
UART PORT, whereas the getchar function receives data entered from the computer keyboard
via the UART PORT. The UART PORT is discussed in Chapter 13. Most embedded systems are
not connected to the PC, and hence users cannot use these functions to perform I/O. However,
these functions can be very helpful during the program development stage because most developers are using PC as a development platform.
6.6 Functions and Program Structure
Every C program consists of one or more functions. If a program consists of multiple functions, their definitions cannot be embedded within another. The same function can be called
from several different places within a program. Generally, a function will process information
passed to it from the calling portion of the program and return a single value. Information is
passed to the function via special identifiers called arguments (also called parameters) and
returned via the return statement. Some functions, however, accept information but do not
return anything (for example, the library function printf). There are also functions that do not
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
156
Chapter 6
■
C Language Programming
receive or return any values. Their purpose is to modularize the program, that is, make it more
readable and easier to develop.
The syntax of a function definition is
return_type function_name (declarations of arguments)
{
declarations and statements
}
The declaration of an argument in the function definition consists of two parts: the type
and the name of the variable. The return type of a function is void if it does not return any value
to the caller. An example of a function that converts a lowercase letter to an uppercase letter is
char lower2upper (char cx)
{
if (cx .5 ‘a’ && cx ,5 ‘z’) return (cx 2 (‘a’ 2 ‘A’));
else return cx;
}
A character is represented by its ASCII code. A letter is in lowercase if its ASCII code is
between 97 (0x61) and 122 (0x7A). To convert a letter from lowercase to uppercase, subtract its
ASCII code by the difference of the ASCII codes of letters a and A.
Example 6.4
▼
Write a function to find the closest integral square root of a 16-bit unsigned integer.
Solution: The successive approximation method is one of the methods for finding the closest
integral square root of an integer. This method is also used in performing analog-to-digital conversion. The logic flow of this method is illustrated in Figure 5.5. The SAR register is used to
accumulate the result.
The square root found in Figure 5.5 tends to be smaller than the true square root. The integer closest to the true square root could be [SAR] (the contents of the SAR register) or [SAR] 1 1.
To find the closest approximation to the true square root, we need to compare the values of
(y 2 [SAR]2) and (([SAR] 1 1)2 2 y), where y is the integer for which the square root is to be found.
The C function that finds the closest integral square root of a 16-bit integer is as follows:
unsigned int sqroot (unsigned int y)
{
unsigned int i, k, mask, test;
k 5 0;
mask 5 0x80;
for (i 5 0; i , 8; i11) {
test 5 k | mask;
if ((test * test) ,5 y)
k 5 test;
mask 5 mask .. 1;
}
if ((y 2 k * k) , ((k11) * (k11) 2 y))
return k;
else return (k11);
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.6
■
Functions and Program Structure
157
6.6.1 Function Prototype
A function cannot be called before it has been defined. This dilemma is solved by using the
function prototype statement. The syntax for a function prototype statement is as follows.
return_type function_name (declarations of arguments);
For example, the statement
char test_prime (int a);
before main() is a function prototype statement. This statement indicates that the function test_prime has an integer incoming argument and returns a signed character value to
the caller.
6.6.2 Writing a C Program with Multiple Functions
To call a function, simply write the name of the function and replace the argument declarations by actual arguments or values and terminate it with a semicolon.
Example 6.5
▼
Write a program to find out the number of prime numbers between 100 and 1000.
Solution: The most efficient method to find out whether a number is prime is to divide the
given number by all the prime numbers between 2 and its square root. If none of them can
divide the given number, then it is a prime number. However, we don’t have all the prime numbers at hand; we will be satisfied by dividing the given number by all the numbers from 2 to its
square root.
#include ,avr\io.h.
char test_prime (unsigned int k);
unsigned int sqroot (unsigned int y);
void main (void)
{
unsigned int i, prime_count;
prime_count 5 0;
for (i 5 100; i ,5 1000; i11) {
if (test_prime(i))
prime_count 11;
}
while(1);
}
// ---------------------------------------------------------------------------------------------------------------------------// The following function tests if k is a prime. It returns a 1 if it is; otherwise, it returns a 0
// ---------------------------------------------------------------------------------------------------------------------------char test_prime (unsigned int k)
{
unsigned int i;
char limit;
if (k 5 5 0 || k 5 5 1) return 0; // 0 and 1 are not prime numbers
else if (k 5 5 2 || k 5 5 3)
// 2 and 3 are prime numbers
return 1;
limit 5 sqroot(k);
// use the square root as prime test limit
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
158
Chapter 6
■
C Language Programming
for (i 5 2; i ,5 limit; i11)
if ((k % i) 5 5 0) return 0; // divisible?
return 1;
}
// ---------------------------------------------------------------------------------------------------------------------------// include sqroot (unsigned int y) here
// ----------------------------------------------------------------------------------------------------------------------------
▲
6.7 Pointers, Arrays, Structures, Unions, and Type Definition
A pointer holds the address of a variable. It is closely related to arrays, structures, and unions.
An array is a collection of data of the same type. A structure is a collection of data that may have
the same or different data types. A union is a variable that may hold (at different times) objects of
different types and sizes. A pointer can be used to access an array, a structure, and a union.
6.7.1 Pointers and Addresses
A pointer is a variable that holds the address of another variable. Pointers are used
frequently in C, as they have a number of useful applications. For example, pointers can
be used to pass information back and forth between a function and its reference (calling)
point. In particular, pointers provide a way to return multiple data items from a function
via function arguments. Pointers also permit references to other functions to be specified as
arguments to a given function. This has the effect of passing functions as arguments to the
given function.
Pointers are also closely associated with arrays and therefore provide an alternative way to
access individual array elements. The syntax for declaring a pointer type is
type_name *pointer_name;
For example,
int *ax;
declares that the variable ax is a pointer to an integer, and
char *cp;
declares that the variable cp is a pointer to a character.
To access the value pointed to by a pointer, use the dereferencing operator *. For example,
int a, *b;
…
a 5 *b;
// b is a pointer to int type
assigns the value pointed to by b to variable a.
We can assign the address of a variable to a pointer by using the unary operator &. The following example shows how to declare a pointer and how to use & and *:
int
int
ip
y
x, y;
*ip;
5 &x;
5 *ip;
// ip is a pointer to an integer
// assigns the address of the variable x to ip
// y gets the value of x
Arithmetic can be performed on pointer variables. If ptr is a pointer to some element of an
array, then p++ increments p to point to the next element, and p += k increments it to point k elements beyond where it currently does.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.7
■
Pointers, Arrays, Structures, Unions, and Type Definition
159
6.7.2 Arrays
Many applications require the processing of multiple data items that have common characteristics (e.g., a set of numerical data, represented by x1, x2, …, xn). In such situations, it is more
convenient to place data items into an array, where they will all share the same name. The
individual data items can be characters, integers, floating-point numbers, and so on. They must
all be of the same type and the same storage class.
Each array element is referred to by specifying the array name followed by one or more
subscripts, with each subscript enclosed in brackets. Each subscript must be expressed as a
nonnegative integer. Thus, the elements of an n-element array x are x[0], x[1], …, x[n 2 1]. The
number of subscripts determines the dimensionality of the array. For example, x[i] refers to an
element of a one-dimensional array. Similarly, y[i][j] refers to an element of a two-dimensional
array. Higher-dimensional arrays can be formed by adding additional subscripts in the same
manner. However, higher-dimensional arrays are not used very often in 8- and 16-bit microcontroller applications. In general, a one-dimensional array can be expressed as
data-type array_name[expression];
A two-dimensional array is defined as
data-type array_name[expr1][expr2];
An array can be initialized when it is defined. This is a technique used in table lookup,
which can speed up the computation process.
Example 6.6
▼
Write the bubble sort function to sort an array of integers.
Solution: The basic idea of bubble sort is to go through several iterations of the array sequentially, with each iteration placing one element in its right position. An iteration consists of
comparing each element in the array with its successor (x[i] with x[i11]) and interchanging
them if they are not in proper order (either ascending or descending).
For an array with N elements, N 2 1 comparisons are performed during the first iteration.
As more and more iterations are performed, more and more elements would be moved to their
right positions. Fewer comparisons are needed in the later iterations. In the worse case, N 2 1
iterations are needed, and only one comparison is made during the last iteration.
The bubble sort program can be made more efficient by keeping track of whether swap
operations have been performed. If no swap is made in an iteration, then the array is already
sorted, and the process should be stopped. The function that implements this idea is as
follows:
void swap (char *px, char *py);
void bubble (char a[ ], char n)
// n is the array count
{
char i, j;
char inorder;
// array in order flag
for (i 5 0; i < n 2 1; i11){ // up to n 2 1 iterations are performed
inorder 5 1; // assume array is in order at the start of a new iteration
for (j 5 0; j < n 2 i 2 1; j11)
if (a[j] > a[j11]){ // are two adjacent elements not in order?
swap (&a[j], &a[j11]);
inorder = 0;
// array not in order
}
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
160
Chapter 6
■
C Language Programming
if (inorder) // array is in order, there is no need to continue.
break;
}
}
void swap (char *px, char *py)
{
char temp;
temp 5 *px;
*px 5 *py;
*py 5 temp;
}
▲
6.7.3 Pointers and Arrays
In C, there is a strong relationship between pointers and arrays. Any operation that can be
achieved by array subscripting can also be done with pointers. The pointer version in general
will be faster but somewhat harder to understand. For example, the statement
int ax[20];
defines an array ax of 20 integral numbers. The notation ax[i] refers to the ith element of the
array. If ip is a pointer to an integer, declared as
int *ip;
then the assignment
ip 5 &ax[0];
makes ip contain the address of ax[0]. Now the statement
x 5 *ip;
will copy the contents of ax[0] into x. If ip points to ax[0], then ip11 points to ax[1], and ip1i
points to ax[i], etc.
6.7.4 Passing Arrays to a Function
An array name can be used as an argument to a function, thus permitting the entire array to
be passed to the function. To pass an array to a function, the array name must appear by itself,
without brackets or subscripts, as an actual argument within the function call. When declaring
a one-dimensional array as a formal argument, the array name is written with a pair of empty
square brackets. The size of the array is not specified within the formal argument declaration.
If the array is two-dimensional, then there should be two pairs of brackets following the array
name, with the first pair of brackets empty and the second pair of brackets containing the column size.
The following program outline illustrates the passing of an array from the main portion of
the program to a function.
int average (int n, int arr[]);
void main ( )
{
int n, avg;
// variable declaration
int arr[50];
// array definition
…
avg 5 average(n, arr); // function call
…
}
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.7
■
Pointers, Arrays, Structures, Unions, and Type Definition
int average (int k, int brr[])
{
…
}
161
// function definition
Within main, we see a call to the function average. This function call contains two actual
arguments—the integer variable n and the one-dimensional integer array arr. Note that arr
appears as an ordinary variable within the function call. In the first line of the function definition, we see two formal arguments, k and brr. The formal argument declarations establish k as
an integer variable and brr as a one-dimensional integer array. Note that the size of brr is not
defined in the function definition. As formal parameters in a function definition,
int brr[];
and
int *brr;
are equivalent.
6.7.5 Initializing Arrays
C allows initialization of arrays. Standard data-type arrays may be initialized in a straightforward manner. The syntax for initializing an array is
array_declarator 5 { value-list };
The following statement shows a five-element integer array initialization:
int i[5] 5 {10, 20, 30, 40, 50};
The element i[0] has the value of 10, and the element i[4] has the value of 50.
The following statement shows a two-dimensional array initialization:
dispTab[6][2] 5 {{0x30,0xDF},{0x6D,0xEF},{0x79,0xF7},
{0x33,0xFB},{0x5B,0xFD},{0x5F,0xFE}};
A string (character array) can be initialized in two ways. One method is to make a list of
each individual character, such as
char strgx[5] 5 {‘w’, ‘x’, ‘y’, ‘z’, 0};
The second method is to use a string constant
char myname [6] 5 “huang”;
A NULL character is automatically appended at the end of “huang.” When initializing an
entire array, the array size (which is one more than the actual length) must be included, for example
char prompt [24] 5 “Please enter an integer:”;
Most C compilers allow the user to declare an initialized array without specifying the array
size. The C compiler will figure out the array size when it compiles the program. For example,
the following statement is legal:
char myName[] 5 “John Adam”;
Another way to declare this string is
char *myName 5 “John Adam”;
6.7.6 Structures
A structure is a group of related variables that can be accessed through a common name.
Each item within a structure has its own data type, which can be different from the other data
items. The syntax of a structure declaration is
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
162
Chapter 6
■
C Language Programming
struct struct_name {
type1 member1;
type2 member2;
…
};
/* struct_name is optional */
The struct_name is optional and, if it exists, defines a structure tag. A struct declaration
defines a type. The right brace that terminates the list of members may be followed by a list of
variables, just as for any basic type. The following example is for a card catalog in a library.
struct catalog_tag {
char author [40];
char title [40];
char pub [40];
unsigned int date;
unsigned char rev;
} card;
Here, the variable card is of type catalog_tag.
A structure definition that is not followed by a list of variables reserves no storage; it
merely describes a template or the shape of a structure. If the declaration is tagged (i.e., has a
name), however, the tag can be used later in definitions of instances of the structure. For example, suppose we have the following structure declaration.
struct point {
int x;
int y;
};
We can then define a variable pt of type point as follows:
struct point pt;
A member of a particular structure is referred to in an expression by a construction of the form
structure-name.member
or
structure-pointer-.member
The structure member operator “.” connects the structure name and the member name. As an
example, the square of the distance of a point to the origin can be computed as follows.
long integer sq_distance;
…
sq_distance 5 pt.x * pt.x 1 pt.y * pt.y;
y
Radius
Center
x
Figure 6.1
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
Structures can be nested. One representation of a circle consists of the center and radius, as
shown in Figure 6.1.
A circle
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.7
■
Pointers, Arrays, Structures, Unions, and Type Definition
163
This circle can be defined as
struct circle {
struct
unsigned
};
point
int
center;
radius;
6.7.7 Unions
A union is a variable that may hold (at different times) objects of different types and sizes,
with the compiler keeping track of size and alignment requirements. Unions provide a way to
manipulate different kinds of data in a single area of storage without embedding any machinedependent information in the program. The syntax of the union is as follows:
union union_name {
type-name1
element1;
type-name2
element2;
…
type-namen
elementn;
};
The field union_name is optional. When it exists, it is called a union-tag. One can declare
a union variable at the same time one declares a union type. The union variable name should
be placed after the right brace }. In order to represent the current temperature using both the
integer and the string, we can use the following declaration:
union u_tag {
int i;
char c[4];
} temp;
Four characters must be allocated to accommodate the larger of the two types. Integer type
is good for internal computation, whereas string type is suitable for output. Of course, some
conversion may be needed before making a certain kind of interpretation. Using this method,
the variable temp can be interpreted as an integer or a string, depending on the purpose. Syntactically, members of a union are accessed as
union-name.member
or
union-pointer → member
just as for structures.
6.7.8 The typedef Statement
The C language provides a capability that enables you to assign an alternate name to a data
type. This is done with a statement known as typedef. The statement
typedef int Counter;
defines the name Counter to be equivalent to the C data type int. Variables can subsequently be
declared to be of type Counter, as in the following statement:
Counter j, n;
The C compiler treats the declaration of the variables j and n, shown in the preceding statement, as normal integer variables. The main advantage of the use of typedef in this case is the
added readability it lends to the definition of the variables. It is clear from the definition of j and
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
164
Chapter 6
■
C Language Programming
n what the intended purpose of these variables is in the program. Declaring them to be of type
int in the traditional fashion would not have made the intended use of these variables at all
clear. Of course, choosing more meaningful variable names would have helped as well.
The following typedef statement defines a type name StringPtr to be a character pointer:
typedef char *StringPtr;
Variables subsequently declared to be of type StringPtr, as in
StringPtr buffer1, buffer2;
are treated as character pointers by the C compiler.
The statements
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long int uint32_t;
enable the user to use uint8_t, uint16_t, and uint32_t to declare unsigned 8-bit, 16-bit, and
32-bit integer variables.
A typedef statement can reuse the previously defined type. For example, the following three
statements reuse the previously defined types:
typedef volatile uint8_t register8_t;
typedef volatile uint16_t register16_t;
typedef volatile uint32_t register32_t;
Atmel uses these three statements to define 8-bit, 16-bit, and 32-bit I/O registers in the
header file for the C language for the AVR microcontroller.
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type was being declared.
2. Where the name of the declared variable would normally appear, substitute the new
type name.
3. In front of everything, place the keyword typedef.
As an example of this procedure, to define a type called Date to be a structure containing
three integer numbers called month, day, and year, write out the structure definition, substituting
the name Date where the variable name would normally appear (before the last semicolon).
Before everything, place the keyword typedef:
typedef struct {
int
month;
int
day;
int
year;
} Date;
With this typedef in place, we can subsequently declare variables to be of type Date, as in
Date birthdays[100];
This defines birthdays to be an array containing 100 Date structures.
6.7.9 Enumerated Data Types
This data type allows the user to define a variable and specify the valid values that could be
stored into that variable.
An enumerated data type definition is initiated by the keyword enum. Immediately following this keyword is the name of the enumerated data type, followed by a list of identifiers
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.8
■
Miscellaneous Items
165
(enclosed by a set of curly braces) that defines the permissible values that can be assigned to the
type. For example, the statement
enum primaryColor {red, yellow, blue};
defines a data type primaryColor. Variables declared to be of this data type can be assigned the
value red, yellow, and blue inside the program, and no other values.
To declare a variable to be of type enum primaryColor, you again use the keyword enum, followed by the enumerated type name, followed by the variable list. So the statement
enum primaryColor myColor, gregsColor;
defines two variables myColor and gregsColor to be of type primaryColor. The only permissible values
that can be assigned to these variables are the names red, yellow, and blue. So the following statements are valid:
myColor 5 red;
if (gregsColor 5 5 yellow)
…
6.8 Miscellaneous Items
6.8.1 Automatic/External/Static/Volatile
A variable defined inside a function is an internal variable of that function. These variables are called automatic, because they come into existence when the function is entered and
disappear when it is left. Internal variables are equivalent to local variables in assembly language. External variables are defined outside of any function and thus are available potentially
to many functions. Because external variables are globally accessible, they provide an alternative to functional arguments and return values for communicating data between functions.
Any function may access an external variable by referring to it by name (if the name has been
declared somewhere). External variables are also useful when two functions must share some
data, yet neither calls the other.
The use of static with a local variable declaration inside a block or a function causes the
variable to maintain its value between entrances to the block or function. Internal static variables are local to a particular function just as automatic variables are, but unlike automatic
variables, they remain in existence rather than coming and going each time the function is
activated. When a variable is declared static outside of all functions, its scope is limited to the
file that contains the definition. A function can also be declared as static. When a function is
declared as static, it becomes invisible outside of the file that defines the function.
A volatile variable has a value that can be changed by something other than user code.
A typical example is an input PORT or a timer register. These variables must be declared as
volatile so the compiler makes no assumptions on their values while performing optimizations.
The keyword volatile prevents the compiler from removing apparently redundant references
through the pointer. For example, the PORTC data register may be defined as follows:
#define PORTC (*(volatile PORT_t *) 0x0640)
6.8.2 Scope Rules
The functions and external variables that make up a C program need not all be compiled at
the same time; the source text of the program may be kept in several files, and previously compiled routines may be loaded from libraries.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
166
Chapter 6
■
C Language Programming
The scope of a name is the part of the program within which the name can be used.
For a variable declared at the beginning of a function, the scope is the function in which
the name is declared. Local (internal) variables of the same name in different functions are
unrelated.
The scope of an external variable or a function lasts from the point at which it is declared
to the end of the file being compiled. Consider the following program segment:
…
void f1 (…)
{
…
}
int a, b, c;
void f2 (…)
{
…
}
Variables a, b, and c are accessible to function f2 but not to f1.
When a C program is split into several files, it is convenient to put all global variables into
one file so that they can be accessed by functions in different files. Functions residing in different files that have to access global variables must declare them as external variables. In addition, the prototypes of certain functions can be placed in one file so that they can be called by
functions in other files. The following example is a skeletal outline of a two-file C program that
makes use of external variables:
In file1:
extern int xy;
extern long arr[];
void main (void)
{
…
}
void foo (int abc) { … }
long soo (void) { … }
In file2:
int xy;
long arr[100];
6.8.3 Type Casting
Type casting causes the program to treat a variable of one type as though it contains data of
another type. The format for type casting is
(type) variable
For example, the following expression converts the variable kk to a long integer.
int kk;
…
(long) kk
Type casting can avoid many errors caused by size mismatch among operands. For example,
in the program segment
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.8
■
Miscellaneous Items
167
long result;
int y1, y2;
…
result 5 y1 * y2;
the product of variables y1 and y2 will be truncated to 16 bits if it is larger than 216 2 1. Then
the variable result will receive an incorrect value. To fix the error, use type casting to force y1
and y2 to long integer, as follows.
result 5 ((long) y1) * ((long) y2);
This technique is used in several examples in this text.
Another example of the use of type casting is in the pointer type. Sometimes you must
treat the contents of a structure-type variable as a string. The most convenient way to do it is
to recast the pointer to a structure-type variable into a pointer to a string (character type). For
the declarations
struct personal {
char name [10];
char addr [20];
char sub1[5];
char sub2[5];
char sub3[5];
char sub4[5];
} ptr1;
char *cp;
we can use the following statement to treat the variable ptr1 as a string:
cp 5 (char *) &ptr1;
6.8.4 Pointer to Functions
In C, a function itself is not a variable, but it is possible to define pointers to functions,
which can be assigned, placed in arrays, passed to functions, returned by functions, and
so on. When working with pointers to functions, the C compiler needs to know not only
that the pointer variable points to a function, but also the type of value returned by that
function, as well as the number and types of its arguments. To declare a variable funcPtr to
be of type “pointer to function that returns an int and that takes one int argument,” the
declaration
int (*funcPtr) (int kx);
can be written. The parentheses around *funcPtr are required because otherwise the C compiler treats the preceding statement as the declaration of a function called funcPtr that returns
a pointer to an int (because the function call operator () has higher precedence than the pointer
indirection operator *).
To set a function pointer pointing to a specific function, we simply assign the name of the
function to it. Let primeTest be a function that returns an int and that takes an int argument; the
statement
funcPtr 5 primeTest;
stores a pointer to this function inside the function pointer variable funcPtr. Writing a function name without a subsequent set of parentheses is treated in an analogous way to writing
an array name without a subscript. The C compiler automatically produces a pointer to the
specifi ed function. An ampersand is permitted in front of the function name, but it’s not
required.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
168
Chapter 6
■
C Language Programming
If the primeTest function has not been previously defined in the program, it is necessary to
declare the function before the preceding assignment can be made. So, a statement such as
int primeTest (int kx);
is needed before a pointer to this function can be assigned to the variable funcPtr.
We can call the function that is indirectly referenced through a pointer variable by applying the function call operator to the pointer, listing any arguments to the function inside the
parentheses. For example,
result 5 funcPtr (ax);
calls the function pointed to by funcPtr, passing the argument ax and storing the returned value
in the variable result.
One common application for pointers to functions is in passing them as arguments to other
functions. The standard C library uses this, for example, in the function qsort, which performs
a “quicksort” on an array of data elements. This function takes as one of its arguments a pointer
to a function that is called whenever qsort needs to compare two elements in the array being
sorted. In this manner, qsort can be used to sort arrays of any type, as the actual comparison of
any two elements in the array is made by a user-supplied function, and not by the qsort function
itself. Another common application for function pointers is to create what is known as dispatch
tables. We can’t store functions themselves inside the elements of an array. However, it is valid
to store function pointers in an array. By doing this, we can create tables that contain pointers
to functions to be called. For example, we may create a table for processing different commands
that will be entered by a user. Each entry in the table could contain both command name and
a pointer to a function, to call to process that particular command. Now, whenever the user
enters a command, the program can look up the command inside the table and invoke the corresponding function to handle it.
6.9 The C Preprocessor
The preprocessor is a part of the C compilation process that recognizes special statements
that might be interspersed throughout a C program. As its name implies, the preprocessor
actually analyzes these statements before analysis of the C program takes place. Preprocessor
statements are identified by the presence of a pound sign, #, which must be the first nonspace
character on the line. As you will see, preprocessor statements have a syntax that is slightly
different from that of normal C statements.
6.9.1 The #define Statement
One of the primary uses of the #define statement is to assign symbolic names to program
constants. The preprocessor statement
#define
TENms 10000
defines the name TENms and makes it equivalent to the value of 10,000. The name TENms
can subsequently be used anywhere in the program where the constant 10,000 could be used.
Whenever this name appears, its defined value of 10,000 is automatically substituted into the
program by the preprocessor. For example, you might have the following C statement that uses
the defined name TENms:
counter 5 counter 1 TENms;
This statement adds the value of 10,000 to the variable counter.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.9
■
The C Preprocessor
169
Suppose you have the following two #define statements:
#define
#define
AND
OR
&&
||
Then you can write expressions such as
if (x . 0 AND x , 10)
…
and
if (y 5 5 0 OR y 5 5 value)
…
You can even include a #define statement for the equality test:
#define EQUAL 5 5
and then write the statement
if (y EQUAL 0 OR y EQUAL value)
…
The #define statement can appear anywhere in the program, but the name must be defined
before it is used. A definition for a name can include more than a simple constant value. It can
include an expression, simple or complicated.
A macro (from the Greek µάĸpo for “big” or “far”) in computer science is a rule or pattern
that specifies how a certain input sequence (often a sequence of characters) should be mapped
to an output sequence (also often a sequence of characters) according to a defined procedure.
The mapping process that instantiates a macro into a specific output sequence is known as
macro expansion.
The #define statement can also be used to define macro definition, which would enable the
user to make macro substitution in his or her program. For example, the statement
#define SQUARE(x) x * x
enables the user to subsequently write statements, such as
yy 5 SQUARE(v);
to assign the value of v2 to yy. The argument v can be of type int, type long, or type float, and the
same macro can be used. However, this macro definition does have a pitfall. For example, the
following statement
yy 5 SQUARE(v 1 1)
will be evaluated as
yy 5 v 1 1 * v 1 1;
which would not produce the expected result. This problem can be resolved by changing the
macro definition to
#define SQUARE (x) ((x) * (x))
With this modification, previous invocation of the SQUARE macro will become
yy 5 ((v 1 1) * (v 1 1));
and is correct.
6.9.2 The ## Operator
This operator is used in macro definitions to join two tokens (a token can be a character or a string) together. It is preceded (or followed) by the name or a parameter to the macro.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
170
Chapter 6
■
C Language Programming
The preprocessor takes the actual argument to the macro that is supplied when the macro is invoked
and creates a single token out of that argument and whatever token follows (or precedes) the ##.
For example, with the statements
#define _WORDREGISTER(regname) \
union \
{\
register16_t regname; \
struct \
{\
register8_t regname ## L; \
register8_t regname ## H; \
}; \
}
and
_WORDREGISTER(CH0RES);
the user can use CH0RES to access the 16-bit I/O register CH0RES as one unit or use CH0RESH
and CH0RESL to access the high and low bytes of the same I/O register individually.
With the statements
#define _DWORDREGISTER(regname) \
union \
{\
register32_t regname; \
struct \
{\
register8_t regname ## 0; \
register8_t regname ## 1; \
register8_t regname ## 2; \
register8_t regname ## 3; \
}; \
}
and
_DWORDREGISTER(CAL);
the user can use the name CAL to access the 32-bit register as one unit or use CAL0, CAL1,
CAL2, and CAL3 to access its individual bytes (CAL0 is the least significant byte and CAL3 is
the most significant byte).
6.9.3 The #include Statement
After you have programmed in C for a while, you will find yourself developing your set of
macros that you will want to use in each of your programs. But instead of having to type these
macros into each new program you write, the preprocessor enables you to collect all your
definitions into a separate file and then include them in your program, using the #include
statement. These files normally end with the characters .h and are referred to as header or
include files.
Microcontroller programming deals with the registers and bits of peripheral modules.
Each register is assigned with an address. It is desirable to refer to them using symbolic names
rather than addresses. The association of addresses with register names is done with #define
statements and is needed by all of the programs. Therefore, they are collected in one or multiple
header files and then included by all of the programs.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.9
■
171
The C Preprocessor
When dealing with a large programming project, the chief designer often breaks the project into multiple files and assigns each individual file or several files to one programmer. The
main function is contained in one of the program files and needs to call functions in other files.
In addition to writing the function definitions, each individual programmer has to provide a
header file that contains the prototype definitions of all functions contained in the program
file. The chief designer includes these header files in the main program file and also includes
all the program files in the project. The IDE will then be able to combine all program files into
one executable code by invoking the linker. Many C programs in later chapters follow this
approach.
6.9.4 Conditional Compilation
The C preprocessor offers a feature known as conditional compilation. Conditional compilation is often used to create one program that can be compiled to run on different computer systems. It is often used to switch on or off various statements in the program, such as debugging
statements that print out the values of various variables or trace the flow of program execution.
THE #IFDEF, #ENDIF, #ELSE, #IFNDEF, #IF,
AND
# E L I F S TAT E M E N T S
The #ifdef statement causes the subsequent statements to be executed if the specified symbol is defined. The #ifndef statement causes the subsequent statements to be executed if the
specified symbol is not defined. The #if preprocessor statement offers a more general way of
controlling conditional compilation. The #if statement can be used to test whether a constant
expression evaluates to nonzero. If the result of the expression is nonzero, subsequent lines up
to a #else , #elif, or #endif are processed; otherwise, they are skipped.
The following statements define the symbol _JBLEN to be 24 if the symbol _AVR_3_BYTE_PC_
is previously defined and is nonzero:
#if defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__
#define _JBLEN 24
#else
#define _JBLEN 23
#endif
The following statements define a pointer to the void type if it has not been defined before:
#ifndef __ptr_t
#define __ptr_t void *
#endif
When using the Atmel AVR Studio IDE to develop C programs for the AVR devices, the user
needs to add the #include <avr\io.h> statement at the start of his or her C program, and specifies
the target device during the project creation process. After specifying an appropriate device, the
corresponding symbol will be defined and known to the IDE, and it causes the appropriate header
files to be included. This is achieved by having the following statements in the io.h header file:
if defined (__AVR_ATMega2560__)
#include ,avr/iom2560.h.
…
…
#elif defined (__AVR_ATXMega128A1__)
#include ,avr/iox128a1.h.
…
#endif
The AVR Studio uses this method to allow the user to use symbolic names to refer to I/O registers and their individual bits.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
172
Chapter 6
■
C Language Programming
6.10 Using the AVR Studio C Compiler
Like any other microcontroller, the ATMEL AVR is composed of several basic building blocks:
An AVR CPU core, SRAM, Flash, EEPROM, I/O PORTs, and a number of peripheral modules.
These building blocks are called module types. An AVR device may have one or more instances of
a given module type. All instances of a module type have the same features and functions.
Some module types can be a subset of other module types. These inherit a subset of the
features (and registers) of the super type; all inherited features are fully compatible. This applies
to timers, I/O PORTs, and so on. For the timer type, the subset means that it simply has fewer
compare and capture channels than a full timer module. Similarly, an I/O PORT may have less
than eight pins.
A module type can be a “PORT,” whereas the module instance is, for example, PORTA, where
the suffix “A” indicates the instance label. For simplicity, module instance will be referred to as
a module throughout this text, unless there is a need to differentiate.
Each module has a number of registers that contain control or status bits. All modules of
a given type contain the same set of registers, and all these registers contain the same set of
control and status bits. The relationship among the module type, module, register, and bits is
illustrated in Figure 6.2.
Module type
MODULE0
Register
Bit 7
MODULEn
Figure 6.2
■
Register
Source: Atmel Corporation, The Atmel AVR Microcontroller
Bit 0
Module type, instances, registers, and bits
Each module has a fixed base address in the I/O memory map, and all registers contained in
the module have fixed offset addresses relative to the module base address. This way each register will not only have an absolute address in the I/O memory space, but also a relative address
defined by its offset. The register offset addresses are equal for all instances of a module type,
simplifying the task of writing drivers that can be used for all modules of a specific type. The
description of this section is based on the practice of the gcc compiler.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.10
■
173
Using the AVR Studio C Compiler
6.10.1 AVR Peripheral Register Naming Convention
The AVR peripheral registers can be divided into control, status, and data registers, and
their naming reflects that. A general-purpose control register of the module is named CTRL. If a
module has multiple control registers, then they are differentiated by using a suffix character.
In this case, the control registers would be named CTRLA, CTRLB, CTRLC, and so on. This also applies
to the STATUS register.
For registers having a specific function, the register name would reflect this functionality.
For example, a control register that controls the interrupt level of a module is named INTCTRL.
Because the AVR data bus width is 8 bits, larger registers are implemented using several
8-bit registers. For a 16-bit register, the high and low bytes are accessed by appending H and
L, respectively, to the register name. For example, the 16-bit Timer/Counter count register is
named CNT. The two bytes are named CNTL and CNTH.
For a register larger than 16 bits, the bytes are numbered from the least significant byte. For
example, the 32-bit ADC calibration register is named CAL. The four bytes are named CAL0,
CAL1, CAL2, and CAL3 (from the least to the most significant byte).
Most C compilers offer automatic handling of access to multibyte registers. In that case,
the name CNT, without an H or L suffix, could be used to perform a 16-bit access to the Timer/
Counter count register. This is also the case for 32-bit registers.
6.10.2 AVR Peripheral Register Bit Naming Convention
Register bits can have an individual function or be part of a bit group that has a joint function. An individual bit could be a bit that enables a module, for example, the ADC enable bit. A
bit group can consist of two or more bits that jointly select a specific configuration of the module
that they belong to. An n-bit group offers up to 2n selections. The two bits that control the ADC
resolution are an example of a bit group. These two bits offer the selections shown in Table 6.9.
Resolution [1:0]
Group configuration
00
Description
12BIT
12-bit result, right justified
01
Reserved
10
8BIT
8-bit result, right justified
11
LEFT12BIT
12-bit result, left justified
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.9
■
ADC conversion result resolution
Bits that are part of a group will always have a number suffix. Bits that are not part of a
bit group will never have a number suffix. A Timer/Counter control register D has two groups,
EVACT and EVSEL (shown in Table 6.10). The bits in these groups have a number suffix,
whereas the EVDLY bit, which is not part of a bit group, has no number suffix.
Bit group
EVACT
-
EVSEL
Bit name
EVACT2
EVACT1
EVACT0
EVDLY
EVSEL3
EVSEL2
EVSEL1
EVSEL0
Bit number
7
6
5
4
3
2
1
0
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.10
■
Bits groups and bit names for bits in Timer/Counter control register D—CTRLD
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
174
Chapter 6
■
C Language Programming
6.10.3 Accessing AVR Mega Device Peripheral Registers in C
For Mega devices, the gcc compiler uses the #define statement to associate every peripheral
register with its I/O address or memory address. This approach allows the user to use a symbolic name to access the peripheral register. For example,
SPCR 5 0x50;
assigns 0x50 to the control register of the SPI module. The effect of this assignment is discussed
in Chapter 14.
PORTA 5 0x53;
outputs the value 0x53 to the PORTA pins.
temp 5 PINA;
reads the values of PORTA pins and stores them in the variable temp.
To facilitate the access of bits of peripheral registers, Atmel assigns the position number
to the symbolic name of each implemented bit of the peripheral register. For example, the
iomxx0_1.h file contains the following definitions for the SPCR register:
#define
#define
#define
#define
#define
#define
#define
#define
SPIE
SPE
DORD
MSTR
CPOL
CPH
SPR1
SPR0
7
6
5
4
3
2
1
0
// bit position 7
// bit position 6
// bit position 5
// bit position 4
// bit position 3
// bit position 2
// bit position 1
// bit position 0
The user can enable the SPI module by setting the SPE bit, using the following statement:
SPCR
|5 1 ,, SPE;
The user can disable SPI interrupt by clearing the SPIE bit, using the following statement:
SPCR
&5 ~(1 ,, SPIE);
// AND the SPCR register with 0x7F
6.10.4 Accessing AVR XMega Device Peripheral Registers in C
Gcc deals with the XMega devices differently from the Mega devices in the following
manner:
•
Defining a structured data type for each type of module (ADC, UART, PMIC, etc).
This data type contains all of the registers in the module
•
Declaring a variable of the defined data type for each instance of the module
For example, Atmel defined the PMIC_t data type for the programmable multiple-level
interrupt controller as follows:
typedef struct PMIC_struct {
unsigned char STATUS;
unsigned char INTPRI;
unsigned char CTRL;
} PMIC_t;
// status register
// interrupt priority register
// control register
After this, the PMIC module is declared (in iox128a1.h) as follows:
#define PMIC (*(PMIC_t *) 0x00A0) // Programmable Interrupt Controller
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.10
■
175
Using the AVR Studio C Compiler
The STATUS register of the PMIC module is located at the address of 0x00A0. With this
definition, the user can access the CTRL register by appending the period character ‘.’ and the
string “CTRL” to the word PMIC. For example,
PMIC.CTRL 5 0x85;
enables the high-priority interrupts, disables medium-priority interrupts, and enables the lowpriority interrupts in the round-robin manner.
temp 5 PMIC.STATUS;
reads the STATUS register and saves it in the variable temp.
The AVR Studio C compiler also allows the user to access any register without using the module struct. To refer to register directly, concatenate the module instance name, an underscore, and
the register name. The same naming convention is used when programming in assembly language.
For example, to use the STATUS register of the PMIC module, use the name PMIC_STATUS.
This approach is referred to as the flattened approach. The AVR assembler uses the flattened
approach to access peripheral registers.
To deal with the bits of a peripheral register of an XMega device, the user has the choice of
using either the bit position value or bit mask. Bit positions are not recommended for most tasks.
The relationship between a bit position and its corresponding bit mask is shown in Table 6.11.
The AVR Studio C compiler defines a symbolic name for each bit position and its corresponding bit mask of a peripheral register so that the user can use the symbolic names to refer
to them, to perform the desired bit field manipulation operation. For example, the bit 7 of the
PMIC control register is the round-robin scheduling enable (RREN) bit. The AVR Studio C compiler defines the bit mask and bit position for it as follows:
Bit position
7
6
5
4
3
2
1
0
Bit mask
0x80
0x40
0x20
0x10
0x08
0x04
0x02
0x01
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 6.11
■
Bit positions and bit masks
#define PMIC_RREN_bm
#define PMIC_RREN_bp
0x80
7
// round-robin priority enable bit mask
// round-robin priority enable bit position
With this definition, the user can set and clear the RREN bit, using the following
statements:
PMIC.CTRL |5 PMIC_RREN_bm;
PMIC.CTRL &5 ~PMIC_RREN_bm;
// enable round-robin interrupt priority
// disable round-robin interrupt priority
Many peripheral functions are controlled by a group of bits. The control register D of a
16-bit timer (timer 0 and 1) and the bit group EVACT are shown in Figure 6.3.
The AVR Studio C compiler defines three constants for each bit group:
• Bit group position: This constant specifies the lowest bit position of the group. For
example, the group position for the EVACT group is 5.
• Bit group mask: This constant allows the user to clear the group so that further
operation on the group can be performed easily. For example, the group mask for
the EVACT group is 0xE0.
• Bit group configurations: Because there are seven possible settings for the EVACT bit
group, the AVR Studio C compiler defines seven constants corresponding to them.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 6
■
C Language Programming
7
6
5
EVACT[2:0]
4
3
2
1
0
EVSEL[3:0]
EVDLY
EVACT[2:0]
Group configuration
000
001
010
011
100
101
110
111
OFF
CAPT
UPDOWN
QDEC
RESTART
FRQ
PW
Event action
None
Input capture
Externally controlled up/down count
Quadrature decode
Restart waveform period
Frequency capture
Pulse width capture
Reserved
Source: Atmel Corporation, The Atmel AVR Microcontroller
176
Figure 6.3 ■ Timer control register D and the group configuration
of EVACT bit group
The header file of an XMega device includes the following statements to define the EVACT
bit group:
#define
#define
TC0_EVACT_gm
TC0_EVACT_gp
0xE0
5
/* Event Action group mask. */
/* Event Action group position. */
The AVR Studio C compiler uses enumeration type to define all the possible configurations
for each bit group. The configuration definition for the EVACT group is as follows:
/* Event Action */
typedef enum TC_EVACT_enum
{
TC_EVACT_OFF_gc
TC_EVACT_CAPT_gc
TC_EVACT_UPDOWN_gc
TC_EVACT_QDEC_gc
TC_EVACT_RESTART_gc
TC_EVACT_FRW_gc
TC_EVACT_PW_gc
} TC_EVACT_t;
5 (0x00,,5), /* No Event Action */
5 (0x01,,5), /* Input Capture */
5 (0x02,,5), /* Externally Controlled Up/Down Count */
5 (0x03,,5), /* Quadrature Decode */
5 (0x04,,5), /* Restart */
5 (0x05,,5), /* Frequency Capture */
5 (0x06,,5), /* Pulse-width Capture */
The bit group mask is primarily intended to clear the old configuration of a bit group before
writing a new value. To set a bit group to certain configuration, the user should take the following two steps:
Step 1
Clear the bit group using the group mask.
Step 2
Set the bit group to the desired configuration by ORing the control register with an
appropriate configuration value.
For example, the following statement configures the Timer/Counter C0 to input capture
mode:
TCC0.CTRLD 5 (TCC0.CTRLD & ~(TC_EVACT_gm)) | TC_EVACT_CAPT_gc;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.11
■
Using the AVR Studio IDE to Develop C Programs
177
6.11 Using the AVR Studio IDE to Develop C Programs
The procedure for developing C programs, using the AVR Studio IDE, includes the following steps:
Step 1
Create a new project to manage the programming task.
Step 2
Enter C functions in one or multiple files.
Step 3
Add C files into the project.
Step 4
Compile (also called build) the project and eliminate syntax and semantic errors of all the
C programs.
Step 5
Execute and debug the project.
6.11.1 Create a New Project
Source: Atmel Corporation, The Atmel AVR Microcontroller
The AVR Studio IDE can be started by clicking on its icon on the PC monitor screen. The
AVR Studio IDE can be started by clicking on its icon. The startup screen of AVR Studio is
shown in Figure 6.4. Because we want to create a new project, click the New Project button (on
the middle left in Figure 6.4). The screen will change to that in Figure 6.5.
The next step is to select Installed Template, enter project name, and select project
location. Click AVR GCC in the box under Installed Templates, set project location to an
Figure 6.4
■
AVR Studio startup screen
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 6
■
C Language Programming
Source: Atmel Corporation, The Atmel AVR Microcontroller
178
Figure 6.5
■
AVR Studio screen after clicking on New Project on the start page
Source: Atmel Corporation, The Atmel AVR Microcontroller
appropriate directory (c:\books\avr\programs\ch06 in this tutorial), and enter an appropriate project
name (e.g., ctutor1). The screen will change to that in Figure 6.6. Check the box Create
directory for solution if it is unchecked. Click OK when you are satisfied with the name.
Click the C option under AVR GCC inside the Recent Templates window. If you deal with
the user demo board, then you should select User Boards under AVR GCC. When you are
satisfied with the names that you entered, click OK and a dialog box will appear to allow you
to select the target device as shown in Figure 6.7.
Figure 6.6 ■ AVR Studio screen for selecting installed templates, entering project name,
and selecting project location
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
Using the AVR Studio IDE to Develop C Programs
179
Source: Atmel Corporation, The Atmel AVR Microcontroller
6.11
Figure 6.7
■
AVR Studio pop up dialog for device selection
Source: Atmel Corporation, The Atmel AVR Microcontroller
Select a device (ATXMega128A1 in this tutorial) and then click OK and the screen will change
to that in Figure 6.8.
Figure 6.8
■
AVR Studio screen after a new project has been created
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
180
Chapter 6
■
C Language Programming
AVR Studio version 5 is based on Microsoft Visual Studio and hence the application development process is organized into projects and solutions. A solution is a logic folder that contains references to all the source files contained in your project, all the included libraries and all
the built executables. A solution allows a seamless reuse of code and an easy automation of the
build process for complex application.
6.11.2 Entering C Programs in AVR Studio IDE
The AVRStudio IDE creates a default source file with the name of ctutor1.c under <project_
dir>\projectName\projectName as shown in Figure 6.8 (c:\books\avrFinal\programs\ch06\ctutor1\ctutor1 in
this example). This C file contains the main function. Click ctutor1.c inside the Solution explorer window
if the ctutor1.c file is not open (on the left) yet. Unless the project directory already has a file with
the same name, the ctutor1.c file would be an empty file. The programmer should enter his or her
main function using this file. The programmer should enter the following program to ctutor.c for
this tutorial:
#include ,avr\io.h.
unsigned int prim_num[6]; // array to hold the prime numbers
#define yes 1
#define no 0
char isprime(unsigned int x);
unsigned char sqroot(unsigned int y);
void main (void)
{
unsigned int i, count;
unsigned int testnum;
// number to be tested
i 5 2; // index of array prim_num for holding the first found prime number
testnum 5 9999; // first number to be tested for prime under 10000
count 5 3; // number of primes less than 10000 to be found
while (count){
if(isprime(testnum)){ // if the number to be tested is prime, then save it
prim_num[i] 5 testnum;
i--;
count--;
}
testnum -5 2;
}
testnum 5 10001; // first number to be tested for prime number above 10000
count 5 3;
i
5 3; // index for array prim_num to hold the first prime number above 10000
while (count){
if(isprime(testnum)){
prim_num[i] 5 testnum;
i11;
count--;
}
testnum 15 2;
}
while(1);
}
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.11
■
Using the AVR Studio IDE to Develop C Programs
181
//------------------------------------------------------------------------------------------------------------------------------------// This function tests whether the unsigned integer k is a prime number.
//------------------------------------------------------------------------------------------------------------------------------------char isprime (unsigned int k)
{
int i;
char limit;
if (k , 2) return 0;
else if(k , 4)
return 1;
limit 5 sqroot(k); // use the square root as prime test limit
for (i 5 2; i ,5 limit; i11)
if ((k % i) 5 5 0) return 0; // divisible?
return 1;
}
//------------------------------------------------------------------------------------------------------------------------------------// This function finds the closest integral square root of the unsigned integer y.
//------------------------------------------------------------------------------------------------------------------------------------unsigned char sqroot (unsigned int y)
{
unsigned int i, sar, mask, test;
sar 5 0;
mask 5 0x80;
for (i 5 0; i , 8; i11) {
test 5 sar | mask;
if ((test * test) ,5 y)
sar 5 test;
mask 5 mask .. 1;
}
if ((y 2 sar * sar) , ((sar11) * (sar11) 2 y))
return sar;
else return (sar11);
}
This program finds the three prime numbers closest to 10,000 but smaller than 10,000 and
the three prime numbers closest to 10,000 but greater than 10,000. The screen after entering the
program is shown in Figure 6.9.
6.11.3 Add C Files into the Project
The user can also add existing files to a project. To add a new or an existing file to the
project, the user should press the right-mouse button on the string “ctutor1” on the Solution
Explorer window and select the Add New item… or Add existing item… option as shown in
Figure 6.10. After that, the user can use the file browser to select the appropriate files to be
added to the project. If the user selects the Add New item… option, then the dialog as shown
in Figure 6.11 will appear to allow the user to enter a new C file or header file. The user should
enter the file name and click Add to add the new file.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 6
■
C Language Programming
Source: Atmel Corporation, The Atmel AVR Microcontroller
182
■
AVR screen after entering a C program
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 6.9
Figure 6.10 ■ Screen for adding new item or existing item
to the project
6.11.4 Compile (or Build) the Project
To compile (or build) the project, press the Build menu and select Build Solution as shown
in Figure 6.12. The user also can press the F7 function key instead.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
Using the AVR Studio IDE to Develop C Programs
183
Source: Atmel Corporation, The Atmel AVR Microcontroller
6.11
■
AVR Studio dialog for adding a new C file or Include file
Figure 6.12
■
AVR Studio screen for building the project
Source: Atmel Corporation, The Atmel
AVR Microcontroller
Figure 6.11
If there are syntax errors, the AVR Studio C compiler will indicate them as shown in
Figure 6.13. By clicking on the error message, the mouse cursor will be moved to the statement
where the error is located. One example is shown in Figure 6.14 (tetnum undefined). The user
can then fix the error and recompile the program. This process should be repeated until all of
the errors have been removed.
6.11.5 Execute and Debug the Project
The user can choose to use either the simulator (simulation) or the target hardware (emulation, a debug adapter is needed). There are three methods to start program execution and debugging in the AVR Studio as shown in Figure 6.15:
1. Start debugging. In this method, the AVR Studio launches the debugging/emulation
tool, which immediately starts an emulation session. Your program is executed
immediately in this method. Pressing the function key F5 also can start this method.
This method can be used to find out whether a program works in certain hardware.
When this option is selected, a pop up dialog will appear to allow the user to select
debug tool as shown in Figure 6.16. After the user selects the debug tool, AVR Studio
will immediately start the debugging session and execute the program.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 6
■
C Language Programming
Source: Atmel Corporation, The Atmel AVR Microcontroller
184
■
Example of AVR Studio error messages
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 6.13
Source: Atmel Corporation,
The Atmel AVR Microcontroller
Figure 6.14 ■ The mouse cursor moved to the statement with error after clicking on
error message
Figure 6.15
■
Start to debug the project
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.11
■
Using the AVR Studio IDE to Develop C Programs
185
2. Start debugging and break. The AVR Studio launches the debugging tool and starts the
simulation/emulation session with a breakpoint set at the entry point of the produced
executable file. On encountering the breakpoint the simulator/debugger will suspend the
program run. Pressing function key F10 also can start this method. This method provides
many debugging options (for example, set breakpoints, run-to-cursor, add variables to the
watch list) to the user. Like the first debug option, this option also will cause the AVR
Studio to put out a pop up dialog for the user to select the debug tool (shown in Figure
6.16). After the user selects the debug tool, the screen will change to that in Figure 6.17.
A yellow arrow points to the first executable statement of the main function.
Source: Atmel Corporation, The Atmel AVR Microcontroller
3. Start without debugging. AVR Studio launches the debugging tool, but not the
emulation session, which means that you can set up a breakpoint with ease before the
launch. Pressing the function key F5 and the CTRL key also can start this method.
■
AVR Studio popup dialog for selecting debug tool
Figure 6.17
■
AVR Studio screen after Start Debugging and Break option is performed
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 6.16
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
186
Chapter 6
SET
UP
■
C Language Programming
W AT C H L I S T
Source: Atmel Corporation, The Atmel AVR Microcontroller
The Watch window is an AVR Studio IDE window in which the user can place program
variables and watch their value changes during the course of program execution. This feature
is a good help during the debugging process. The Watch window in Figure 6.17 is empty. Only
global variables can be placed in the Watch window. The array variable prim_num[] is declared as
a global variable. To place the variable prim_num in the Watch window, press the right-mouse
button on the variable and select Add Watch as shown in Figure 6.18. After this, the variable
prim_num will appear in the Watch window. Since prim_num is an array, there is a + sign to its
left. The user can click the + sign and display every element of the array prim_num. The Watch
window after expanding the prim_num array is shown in Figure 6.19.
■
Add prim_num into the Watch Window
Figure 6.19
■
Watch Window with expanded array prim_num []
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Figure 6.18
RUN
TO
CURSOR
A convenient feature for debugging is to let the program execute to a certain statement and
watch the variable changes in the Watch window. In Figure 6.20, we let the program execute
until the statement testnum 5 10001;. After releasing the mouse button, the AVR MCU starts
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.11
■
Using the AVR Studio IDE to Develop C Programs
187
Source: Atmel Corporation, The Atmel AVR Microcontroller
program execution, and the Watch window changes to that in Figure 6.21. The first three elements of the prim_num[] have been generated and displayed in the decimal format by default.
You can change the display format to hexadecimal by pressing the right-mouse button on the
variable name prim_num in the Watch window and selecting Hexadecimal Display, as shown
in Figure 6.22. This will cause all values to be displayed in the hexadecimal format, as shown
in Figure 6.23.
■
Use the “Run to Cursor” feature to watch program variables change
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 6.20
Figure 6.21 ■ Watch window after program is executed until the statement
“testnum 5 10001;”
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 6
■
C Language Programming
Source: Atmel Corporation, The Atmel AVR Microcontroller
188
■
Display all values in Watch Window in hexadecimal format
Figure 6.23
■
Display all values in Watch Window in hex format
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Figure 6.22
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Next execute the Run to Cursor feature at the while (1); statement, and all the prime numbers will be generated, as shown in Figure 6.24.
Figure 6.24
■
Program execution result
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.11
■
Using the AVR Studio IDE to Develop C Programs
189
OTHER COMMANDS
There are other debug commands that are useful to program debugging. For example:
1. Reset.This command will force the AVR Studio to start program execution from
the first statement of the main function. When this command is executed, the AVR
Studio IDE places the mouse cursor at the first executable statement in the main
function and waits for further commands.
2. Toggle Breakpoint. A breakpoint is a statement at which program execution is going
to stop. After setting a breakpoint, the user can start program execution by pressing
function key F5. When reaching the breakpoint, the AVR Studio will stop and update
the contents of all windows of the AVR Studio. The programmer can figure out
whether the program execution is correct up to the breakpoint.
3. Step into, Step over, and Step out. These commands allow the user to execute one
statement at a time and examine the execution result, and hence are useful for
checking whether a specific statement correctly performs the desired operation.
This ends the tutorial. AVR Studio version 5 is still under active development at the time of
this writing. Some of the features may not work properly yet.
Example 6.7
▼
Write a program to find all the four-digit decimal numbers that have the following property: The square of the sum of the upper and lower halves of the given number is equal to the original number.
Solution: The upper and lower halves of a four-digit number can be separated by dividing the
given number by 100. The following program finds all the four-digit decimal numbers that have
the specified property and saves them in an array:
#include <avr\io.h>
unsigned int xarr[10];
char test(unsigned int k);
void main (void)
{
unsigned int k;
unsigned char i;
i 5 0;
// used as index of xarr[]
for (k 5 1000; k , 10000; k11){
if (test(k) 5 5 1){ // Does the current array element has the specified property?
xarr[i] 5 k; // Yes, save it.
i11;
// increment the index
}
}
while(1);
}
char test(unsigned int k)
{
unsigned int xa, xb, xc;
xa 5 k / 100;
// calculate the upper two digits of the number
xb 5 k % 100;
// find the lower two digits of the number
xc 5 xa 1 xb;
// add the upper and lower two digits of the number
if ((xc * xc) 5 5 k) // calculate the square of the sum
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
190
Chapter 6
■
C Language Programming
return 1;
else
return 0;
}
The three numbers having this feature are 2025, 3025, and 9801.
▲
6.12 Multiple-File Project
It is common for a real-world application to have multiple files. There are two reasons for this:
1. Code reuse. After developing applications for some time, the developer will
accumulate certain number of reusable programs. By reusing the previously verified
programs, the programmer can reduce the application development time.
2. Divide and Conquer. Applications are often very complicated. However, there is
always a deadline for the application software. Missing deadline often means penalty
or even losing business. In order not to miss the deadline, the project manager divides
a complex project into several smaller and manageable subprojects and assigns each
subproject to one developer. A subproject may be written as a single-file or multiplefile program. After each subproject has been written and tested, the whole project can
be built by combining all the subprojects together.
In the following we will use the circuit shown in Figure 14.10 to illustrate the setup of a
multiple-file project. We would like to use the circuit shown in Figure 14.10 to display the following patterns repeatedly, with each row displayed for 600 ms:
012345
123456
234567
345678
456789
567890
678901
789012
890123
901234
The circuit in Figure 14.10 uses the time-multiplexing technique to display six digits. The first
74HC595 shift register drives the seven-segment pattern to be displayed, whereas the second
74HC595 selects a display to be lighted. Both shift registers have the SPI interface. These six displays are lighted in turn from left to right, with each display turned on for 1 ms and then turned
off. Because this application is related to timing, we need to call a function to create a time delay of
1 ms. We have a delays_xmega.c file that contains a function called delayby1ms(), which will create
a delay that is a multiple of 1 ms. The delays_xmega.c file also contains functions for several other
time delays. The prototypes of these delay functions are stored in the header file delays_xmega.h.
We also need to set up the system clock source. For this purpose, we create a file called
sysClock_xmega.c (to be discussed in Chapter 7) for the XMega device. The function setCPUClockto32Mwith16MCrystal() sets the CPU clock to 32 MHz, using an external 16-MHz crystal. The header file associated with sysClock_xmega.c is sysClock_xmega.h.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.12
■
Multiple-File Project
191
We create a project called sevenSegDisplay, which would contain a file with the same name
to hold the main function and several other required functions as follows:
#include ,avr\io.h.
#include “sysClock_xmega.h”
#include “delays_xmega.h”
#define d0
0xFC
// seven-segment pattern of 0
#define d1
0x60
// seven-segment pattern of 1
#define d2
0xDA
// seven-segment pattern of 2
#define d3
0xF2
// seven-segment pattern of 3
#define d4
0x66
// seven-segment pattern of 4
#define d5
0xB6
// seven-segment pattern of 5
#define d6
0xBE
// seven-segment pattern of 6
#define d7
0xE0
// seven-segment pattern of 7
#define d8
0xFE
// seven-segment pattern of 8
#define d9
0xF6
// seven-segment pattern of 9
#define S0 0x7F
// value to allow only display #0 to be turned on
#define S1 0xBF
// value to allow only display #1 to be turned on
#define S2 0xDF
// value to allow only display #2 to be turned on
#define S3 0xEF
// value to allow only display #3 to be turned on
#define S4 0xF7
// value to allow only display #4 to be turned on
#define S5 0xFB
// value to allow only display #4 to be turned on
void initSPIx(void);
void putcSPID_Xmaster(unsigned char cx);
void main (void)
{
unsigned char dispTab[10][12] 5
{{S0,d0,S1,d1,S2,d2,S3,d3,S4,d4,S5,d5},
{S0,d1,S1,d2,S2,d3,S3,d4,S4,d5,S5,d6},
{S0,d2,S1,d3,S2,d4,S3,d5,S4,d6,S5,d7},
{S0,d3,S1,d4,S2,d5,S3,d6,S4,d7,S5,d8},
{S0,d4,S1,d5,S2,d6,S3,d7,S4,d8,S5,d9},
{S0,d5,S1,d6,S2,d7,S3,d8,S4,d9,S5,d0},
{S0,d6,S1,d7,S2,d8,S3,d9,S4,d0,S5,d1},
{S0,d7,S1,d8,S2,d9,S3,d0,S4,d1,S5,d2},
{S0,d8,S1,d9,S2,d0,S3,d1,S4,d2,S5,d3},
{S0,d9,S1,d0,S2,d1,S3,d2,S4,d3,S5,d4}};
unsigned char ix, iy, k;
setclkCPUto32Mwith16MCrystal();
initSPIx();
while(1) {
for (ix 5 0; ix , 10; ix11){ // there are ten different patterns
for (k 5 0; k , 100; k11){ // each row lasts for 600 ms
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
192
Chapter 6
■
C Language Programming
for (iy 5 0; iy , 12; iy 15 2){ // time-multiplex six digits
putcSPID_Xmaster(dispTab[ix][iy]); // send out digit select value
putcSPID_Xmaster(dispTab[ix][iy11]); // send out seven-segment pattern
PORTD.OUT &5 0xE7; // transfer data from shift register to output latch
PORTD.OUT |5 0x18; // within the 74HC595
delayby1ms(1); // wait for 1 ms
}
}
}
}
}
// ------------------------------------------------------------------------------------------------------------------// This function enables SPI module to master mode, set SCK to idle low, shift
// data MSB first on the rising edge of SCK, and set data shift rate to 4 MHz.
// ------------------------------------------------------------------------------------------------------------------void initSPIx(void)
{
PORTD.DIR 5 0xBF; // configure MOSI, SCK for output, MISO for input
SPID.CTRL 5 0xF1; // enable master mode, SCK idle low, sample data on rising edge, 4 MHz
SPID.INTCTRL 5 0;
}
// -----------------------------------------------------------------------------------------------------------// The SPI master of the XMega device associated with PORTD calls this function
// to send a character to an SPI slave.
// -----------------------------------------------------------------------------------------------------------void putcSPID_Xmaster(unsigned char cx)
{
char tmp;
SPID.DATA 5 cx;
// write data to SPI data register
while(!(SPID.STATUS & SPI_IF_bm));
// wait for data byte to be shifted out
tmp 5 SPID.DATA;
// clear the IF flag
}
Assuming that we create this project under the c:\books\avrFinal\programs\ch06 directory, then
the following directories will be created:
1. c:\books\avrFinal\programs\ch06\sevenSegDisplay—project directory
2. c:\books\avrFinal\programs\ch06\sevenSegDisplay\sevenSegDisplay—solution directory
We should place the sysClock_xmega.h and delays_xmega.h header files under the solution
directory because we use the following two statements to include these two header files to the
project:
#include
#include
“sysClock_xmega.h”
“delays_xmega.h”
Both the sysClock_xmega.c and delays_xmega.c files must be included to this project. After
the sevenSegDisplay project is created, we should see the screen, as shown in Figure 6.25.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
193
Summary
Source: Atmel Corporation, The Atmel AVR Microcontroller
6.13
Figure 6.25
■
AVR Studio screen for the sevenSegDisplay project
6.13 Summary
A C program consists of one or more functions and variables. The main( ) function is
required in every C program. It is the entry point of a C program. A function contains statements that specify the operations to be performed. The types of statements in a function could
be declaration, assignment, function call, control, and NULL.
A variable stores a value to be used during the computation. A variable must be declared
before it can be used. The declaration of a variable consists of the name and the type of the variable. There are four basic data types in C: int, char, float, and double. Several qualifiers can be
added to the variable declarations. They are short, long, signed, and unsigned.
Constants are often needed in forming a statement. There are four types of constants: integers, characters, floating-point numbers, and strings.
There are seven arithmetic operators: 1, 2, *, /, %, 11, and 2 2. There are six bitwise
operators: &, |, ˆ, ~, .., and ,,. Bitwise operators can be applied only to integers. Relational operators are used in control statements. They are 5 5, !5, ., .5, ,, ,5, &&, ||,
and !.
The control-flow statements specify the order in which computations are performed.
Control-flow statements include if-else statement, multi-way conditional statement, switch
statement, for-loop statement, while statement, and do-while statement.
Every C program consists of one or more functions. The definition of a function cannot
be embedded within another function. The same function can be called from several different
places within a program. Generally, a function will process information passed to it from the
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
194
Chapter 6
■
C Language Programming
calling statement of the program and return a single value. Information is passed to a function via special identifiers called arguments (also called parameters) and returned via the return
statement. Some functions, however, accept information but do not return anything (for example, the library function printf).
A pointer holds the address of a variable. Pointers can be used to pass information back
and forth between a function and its reference (calling) point. In particular, pointers provide a
way to return multiple data items from a function via function arguments. Pointers also permit
references to other functions to be specified as arguments to a given function. Two operators are
related with pointers: * and &. The * operator returns the value of the variable pointed to by the
pointer. The & operator returns the address of a variable.
Data items that have common characteristics are placed in an array. An array may be onedimensional or multidimensional. The dimension of an array is specified by the number of
square bracket pairs [] following the array name. An array name can be used as an argument to
a function, thus permitting the entire array to be passed to the function. To pass an array to a
function, the array name must appear by itself, without brackets or subscripts. An alternative
way to pass arrays to a function is to use pointers.
A variable defined inside a function is an internal variable of that function. External variables are defined outside of any function and are thus potentially available to many functions.
The scope of a name is the part of the program within which the name can be used. The scope
of an external variable or a function lasts from the point at which it is declared to the end of the
file being compiled.
In C language, parallel I/O is performed by an assignment statement. An input operation is
performed by making the PORT data register as one of the source operands, whereas an output
operation is performed by making the PORT data register as the destination of a statement.
The header file in C language is used mainly to hold constant definitions (registers and bits
are in this category), macros, functional prototype declarations, and type definition. It is not
meant to hold program files. The register and bit definitions contained in the header file allows
the user to use symbolic names to refer to registers and bits, which would improve the readability of the program.
6.14 Exercises
E6.1 What is the value of ax/bx, assuming that ax 5 93 and bx 5 19?
E6.2 What is the value of ax % bx, assuming that ax 5 93 and bx 5 23?
E6.3 What is the value of ax ^ bx, assuming that ax 5 0x93 and bx 5 7D?
E6.4 What are the values of ax ,, 2 and ax .. 2, assuming that ax 5 0xD7?
E6.5 What is the value of ax & bx, assuming that ax 5 0xB6 and bx 5 0xED?
E6.6 Write a program to find the median of an array of 8-bit unsigned integers. When the array
has an even number of elements, the median is defined as the average of the middle two elements. Otherwise, it is defined as the middle element of the array. You need to sort the array in
order to find the median.
E6.7 Write a program to find the mode of the array of 8-bit unsigned integers. The mode is the
element that occurs most frequently.
E6.8 Write a function to test whether a given number is a multiple of 8. A 1 is returned if the
given number is a multiple of 8. Otherwise, a 0 is returned. The number to be tested is an integer and is an argument to this function.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
6.15
■
Lab Assignments
195
E6.9 Write a function that finds the greatest common divisor (GCD) of two unsigned integers
m and n.
E6.10 What is a function prototype? What is the difference between a function prototype and
function definition?
E6.11 Write a switch statement that will examine the value of an integer variable yy and assign
one of the following values to the variable dd, depending on the value of yy:
(a) 15, if yy 5 5 1
(b) 25, if yy 5 5 2
(c) 35, if yy 5 5 3
(d) 45, if yy 5 5 4
(e) 55, if yy 5 5 5
E6.12 Write a function that converts a lowercase letter to uppercase.
E6.13 Write a function that swaps the first element of the array with the last element, swaps
the second element of the array with the second to last element, and so on.
E6.14 Write a function that swaps the first row of a matrix with the last row, swaps the second
row of the matrix with the second-to-last row, and so on.
E6.15 Write a loop to compute the sum of the squares of the first 100 odd integers.
E6.16 An Armstrong number is a number of n digits that is equal to the sum of each digit raised
to the nth power. For example, 153 (which has three decimal digits) equals 131 53 1 33. Write
a function to test whether a three-digit number is an Armstrong number and a test program to
store all three-digit Armstrong numbers in an array.
E6.17 Write a function to test whether a four-digit decimal number is an Armstrong number
and a main program to find all four-digit Armstrong numbers and store them in an array.
E6.18 Write a program to find the first five numbers that when divided by 2, 3, 4, 5, or 6 leave a
remainder of 1, and when divided by 7, have no remainder.
E6.19 Write a function that tests whether a four-digit decimal number has the property that
the sum of the squares of the upper and lower halves equals the original number. The function
returns a 1 if a given number has this property. Otherwise, it returns a 0.
E6.20 Write a function that can convert a NULL-terminated string that represents a decimal
number into a binary number. Assume that the string represents a signed binary number no
larger than 16-bit.
E6.21 Write a function that can convert a binary number into a NULL-terminated BCD string
that represents the given binary number.
6.15 Lab Assignments
L6.1 Write a program that finds four prime numbers that are closest to but less than 20,000 and
four prime numbers that are closest to but higher than 30,000.
L6.2 Write a program to find the first five numbers that when divided by 2, 3, 4, 5, and 6 leave a
remainder of 1, and when divided by 7, have no remainder.
L6.3 Write a function and a test program to find all the 3-digit decimal Armstrong numbers and
store them in an array.
L6.4 Write a function and a test program to find all the 4-digit decimal Armstrong numbers and
store them in an array.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7
System Clock Configuration
7.1 Objectives
After completing this chapter, you will be able to
• Understand the importance of the system clock
generation.
• Understand the possible system clock generation
options.
• Understand the Mega device clock circuit module.
• Be able to configure the Mega system clock signal
by programming the fuse map.
• Understand the XMega device clock circuit
module.
• Be able to configure the XMega system clock by
programming the appropriate registers.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
198
Chapter 7
■
System Clock Configuration
7.2 Overview of System Clock Generation
Time delays are needed to achieve the desired effects of I/O operations. Examples include
LED flashing, time-multiplexing of multiple seven-segment displays, keeping track of time of
day, siren generation, song playing, LCD write operation, stepper motor driving, keypad and
keyboard debouncing, EEPROM and flash memory internal write operation, and so on. Without
accurate time delays, these operations cannot be performed properly and correctly. Time delay
creation is based upon an accurate system clock frequency.
Devices such as ceramic resonators, crystal oscillators, and RC circuits (on-chip or off-chip)
have been used to generate a system clock. Among them, the crystal oscillator has the tightest
frequency tolerance and should be used in any system requiring accurate timing. When timing
accuracy is not critical, either a ceramic resonator or an RC circuit can be used.
The clock signal required by the MCU must be a square waveform. However, the waveform
generated from a ceramic oscillator, a crystal oscillator, or an RC circuit is not a square wave
and must be squared up before it can be used by the MCU. Because this circuit is indispensible,
all MCUs have incorporated it on a chip.
The frequency of the crystal oscillator may not be the same as the on-chip system clock.
The MCU may include a circuit to multiply or divide the frequency of the oscillator. Frequency
division is achieved by using a countdown counter. However, frequency multiplication must be
performed by a phase-lock loop (PLL). The PLL is a circuit technique that can not only stabilize
but also multiply the clock frequency. Many of the latest MCUs (including the XMega AVR)
have incorporated a PLL circuit on the chip.
In addition to the CPU, every peripheral module in the MCU also requires a clock signal
to function. To satisfy this demand, the MCU includes a complicated circuit to generate clock
signals and distribute them to every peripheral module.
7.3 The Clock System of the AVR Mega Devices
The clock distribution of the AVR Mega devices is shown in Figure 7.1. The CPU clock
(clkCPU) is routed to parts of the system concerned with the AVR core operation. Examples of
such module are general-purpose registers, the status registers, and data memory. The I/O clock
(clkI/O) is used by the majority of the I/O modules, like timer/counters, SPI, and USART. The
I/O clock is also used by the external interrupt module. The flash clock (clkFLASH) controls the
operation of the flash memory interface. The asynchronous clock (clkASY) allows the asynchronous timer/counter to be clocked directly from an external clock or an external 32 kHz clock
crystal. The ADC clock (clkADC) provides an operation clock required by the ADC module.
7.3.1 Clock Sources
The clock sources available to the Mega devices are listed in Table 7.1. The user selects the
clock source by programming the CKSEL fuse bits (via the AVR Studio IDE).
The low-power crystal oscillator or the full-swing crystal oscillator should be connected to
the XTAL1 (input) and XTAL2 (output) pins. The low-power crystal oscillator has reduced voltage swing on the XTAL2 output, is not capable of driving other clock inputs, and may be more
susceptible to noisy environment. The full-swing crystal oscillator can drive other clock input
and should be used in a noisy environment. A typical crystal oscillator circuit connection is
shown in Figure 7.2. The recommended values for C1 and C2 are from 12 to 22 pF. When a lowpower crystal oscillator with frequency in the range of 8 to 16 MHz is used, the bit 3 to 1 of the
CKSEL fuses should be set to 111. When a full-swing crystal oscillator with a frequency in the
range of 0.4 to 16 MHz is used, the bit 3 to 1 of the CKSEL fuses should be set to 011.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.3
■
199
The Clock System of the AVR Mega Devices
Asynchronous
timer/counter
General I/O
modules
ADC
RAM
CPU core
Flash and
EEPROM
clkADC
clkI/O
AVR clock
Control unit
clkASY
clkCPU
clkFLASH
Reset logic
Watchdog
timer
System clock
prescaler
Watchdog
oscillator
Clock
multiplexer
Timer/Counter
oscillator
Figure 7.1
■
External clock
Crystal
oscillator
Low-frequency
crystal oscillator
Calibrated RC
oscillator
Source: Atmel Corporation, The Atmel AVR Microcontroller
Source clock
AVR Mega device clock distribution
Device clocking option
Low-power crystal oscillator
CKSEL[3:0]
1111–1000
Full-swing crystal oscillator
0111–0110
Low-frequency crystal oscillator
0101–0100
Internal 128 kHz RC oscillator
0011
Calibrated internal RC oscillator
0010
External clock
0000
Reserved
0001
Note: For all fuses, “1” means unprogrammed, whereas “0” means
programmed
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 7.1
■
Mega device clocking options select
7.3.2 Default Clock Source
A Mega device is shipped with a calibrated internal RC oscillator at 8.0 MHz and with the
CKDIV8 fuse programmed (value is 0), resulting in a 1.0 MHz system clock. The startup time is
set to maximum and the time-out period enabled.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
200
Chapter 7
■
System Clock Configuration
XTAL2
C1
XTAL1
Figure 7.2
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
C2
Crystal oscillator connections
7.3.3 External Clock
An external clock source (a square wave with a stable frequency) can be used to generate
clock signals required by all the modules. When an external clock source is used, it is connected to the XTAL1 pin, and the XTAL2 pin is left unconnected.
7.3.4 Watchdog Oscillator
The Watchdog timer is a circuit that is used to detect software errors (to be detailed in
Chapter 9). The clock source of the Watchdog timer is derived from the on-chip 128 kHz RC
oscillator.
7.3.5 Low-Frequency Oscillator
The Mega device can use a 32.768 kHz watch oscillator as its clock source. The crystal
should be connected as shown in Figure 7.2.
7.3.6 Timer/Counter Oscillator
The Mega device can operate its timer/counter2 from an external 32.768 kHz watch crystal
or an external clock source. This crystal should be connected to the TOSC1 (input) and TOSC2
(output) pins. The circuit connection method is identical to that in Figure 7.2.
7.3.7 System Clock Prescaler
7
6
5
4
CLKPCE
—
—
—
R/W
R
R
R
3
2
1
0
CLKPS3 CLKPS2 CLKPS1 CLKPS0
R/W
R/W
R/W
R/W
CLKPCE: Clock prescaler change enable
This bit must be written to 1 to enable change of CLKPS bits. The CLKPCE
bit is only updated when the other bits in CLKPR are simultaneously to 0.
CLKPCE is cleared by hardware four cycles after it is written or when CLKPS
bits are written.
CLKPS3~0: Clock prescaler selects 3~0
These bits define division factor between the selected clock source and the
internal system clock, as shown in Table 7.2.
Figure 7.3
■
Reset value
= 0x0x
Source: Atmel Corporation, The Atmel AVR Microcontroller
In Figure 7.1, the clock source selected by the clock multiplexer is further divided by the
system clock prescaler. The possible prescaling factor is chosen by the CLKPR register. The
contents of the CLKPR register are shown in Figure 7.3.
Clock prescale register (CLKPR)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.3
■
201
The Clock System of the AVR Mega Devices
CLKPS[3∼0]
Clock division factor
0000
1
0001
2
0010
4
0011
8
0100
16
0101
32
0110
64
0111
128
1000
256
1001∼1111
Reserved
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 7.2
■
Mega device clock prescaler select
The CKDIV8 fuse determines the initial value of the CLKPS bits. If the CKDIV8 fuse is
unprogrammed (value is 1), the CLKPS bits resets to 0000. If the CKDIV8 fuse is programmed,
CLKPS bits are reset to 0011, giving a division factor of 8 at startup. Any value can be written
to the CLKPS bits regardless of the CKDIV8 fuse setting. The application software must ensure
that a sufficient division factor is chosen if the selected clock source has a higher frequency
than the maximum frequency of the device at the present operating conditions.
The procedure to change the CKDIV8 fuse after creating a new project (when using the
AVR Studio) is as follows:
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Step 1
Select toolsãAVR Programming… from the AVR Studio IDE window menu, as shown
in Figure 7.4. A pop-up dialog appears, as shown in Figure 7.5, which allows the user to
choose the programming tool, device, and interface.
Figure 7.4
■
Prepare to change CKDIV8 fuse
Step 2
Choose the programmer (e.g., JTAGICE mkII), device (e.g., the Mega2560 on the STK600),
and programming interface (JTAG); click Apply and Fuses, and the screen changes to that
in Figure 7.6. The ATMega2560 demo kit without external crystal oscillator is used in
this example. In Figure 7.6, the Mega2560 uses an internal RC oscillator to generate the
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
202
Chapter 7
■
System Clock Configuration
Source: Atmel Corporation, The Atmel AVR Microcontroller
system clock and has 6 clock cycles of startup time. The last fuse is SUT_CKSEL, which
allows the user to select the appropriate system clock source and the startup time. The
user clicks the downward arrow to the right of SUT_CKSEL to bring up all the options for
the clock source, as shown in Figure 7.7.
■
AVR Programming popup dialog
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 7.5
Figure 7.6
■
Default setting of the fuses (CKDIV8 is not programmed)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
203
The Clock System of the AVR Mega Devices
Source: Atmel Corporation, The Atmel AVR Microcontroller
7.3
Figure 7.7
■
All possible clock sources and startup times
Source: Atmel Corporation, The Atmel AVR Microcontroller
Step 3
Figure 7.6 shows that the CKDIV8 is not programmed (without a ∨ character in the square
of the value column). If we want to use the internal RC oscillator to generate clkCPU, then
we should unprogram the CKDIV8 fuse. Make the change to the right of CKDIV8 and
click Program, and the screen reflects the new values.
Figure 7.8
■
The fuse map for the EasyAVR1280M demo board
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
204
Chapter 7
■
System Clock Configuration
The fuse map of the EasyAVR1280M demo board is shown in Figure 7.8. The Mega
device outputs the system clock on the CLKO pin. To enable the output, the CKOUT fuse
in Figure 7.7 and Figure 7.8 should be programmed. The CLKO signal is used to drive other
circuitry on the system. The EasyAVR1280M demo kit uses an external 7.3728 MHz crystal
oscillator to generate the system clock.
7.4 Clock System of the XMega Devices
The XMega device generates clock signals for internal operation from a large number of
sources. The clock system, clock sources and clock distribution for the XMega device are
illustrated in Figure 7.9. The XMega device utilizes a phase-locked loop (PLL) and prescalers to
generate a wide range of clock frequencies. To stabilize the clock frequency, the XMega clock
system implements a digital frequency locked loop (DFLL) that performs automatic run-time
calibration to the internal oscillators. A crystal oscillator failure monitor can be enabled to
issue a nonmaskable interrupt and switch to the internal oscillator if the external oscillator
fails. Interrupts and interrupt handling are discussed in Chapter 9.
Real time
counter
Peripherals
Non-volatile
memory
AVR CPU
RAM
clkCPU
clkPER
clkPER2
clkPER4
clkRTC
System clock
prescalers
Brown-out
detection
Watchdog
timer
clkSYS
System clock multiplexer
DIV4
32 kHz
Int. ULP
32.768 kHz
Int. Osc.
2 MHz
Int. Osc.
32 MHz
Int. Osc.
XTAL
32 kHz
XTAL1
XTAL2
■
TOSC1
TOSC2
Figure 7.9
XTAL
0.4–16
MHz
External
clock
Source: Atmel Corporation, The Atmel AVR Microcontroller
PLL
XMega device clock system, clock sources, and distribution
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.4
■
Clock System of the XMega Devices
205
After reset, the XMega device starts operation using the 2 MHz internal oscillator. During
normal operation, the system clock source and prescalers can be changed from software at
any time.
7.4.1 Internal Oscillators
The XMega device has four internal oscillators that serve different purposes, as described
below.
32
KHZ
U LT R A - L O W - P O W E R O S C I L L AT O R
This oscillator provides an approximate 32 kHz clock and employs a built-in prescaler providing both a 32 kHz output and a 1 kHz output. It is automatically enabled or disabled when
used as the clock source of any part of the device. It is used as the clock source for the Watchdog timer and Brown-out detection circuitry. It can also be chosen as the clock source of the
real-time counter (RTC).
32.768
KHZ
C A L I B R AT E D I N T E R N A L O S C I L L AT O R
This RC oscillator provides a 32.768 kHz clock. A factory-calibrated value is written to
the 32.768 kHz oscillator calibration register (OSC.RC32KCAL) during reset to ensure that the
oscillator is running within its specification. The calibration register can also be written into
from software for run-time calibration of the oscillator frequency. This oscillator employs a
built-in prescaler to provide both a 32.768 kHz output and a 1.024 kHz output.
3 2 M H Z R U N - T I M E C A L I B R AT E D I N T E R N A L O S C I L L AT O R
This RC oscillator provides an approximate 32 MHz clock. The oscillator employs a DFLL
that can be enabled for automatic run-time calibration of the oscillator. A factory-calibrated
value is written to the 32 MHz DFLL calibration registers (DFLLRC32M.CALA and DFLLRC32M.CALB) during reset to ensure that the oscillator is running within its specification.
The calibration registers can also be written from software for manual run-time calibration of
the oscillator.
2 M H Z R U N - T I M E C A L I B R AT E D I N T E R N A L O S C I L L AT O R
This oscillator provides a 2 MHz clock. Like the 32 MHz oscillator, it also utilizes the
DFLL for automatic run-time calibration. A factory-calibrated value is written into the 2 MHz
DFLL calibration registers (DFLLRC2M.CALA and DFLLRC2M.CALB) during reset to ensure
that the oscillator is running within its specification. The calibration register can also be written from software for manual run-time calibration of the oscillator.
7.4.2 External Clock Sources
The XTAL1 and XTAL2 pins are used to drive an external oscillator, either a quartz crystal
or a ceramic resonator. The TOSC1 and TOSC2 pins are dedicated to driving a 32 kHz crystal
oscillator. The crystal oscillator connection is shown in Figure 7.2.
0 . 4 ~ 1 6 M H Z C R Y S TA L O S C I L L AT O R
This oscillator operates in four different modes (programmed via the XOSCCTRL register),
optimized for different frequency ranges, all within 0.4∼16 MHz.
EXTERNAL CLOCK INPUT
When an external clock signal is chosen to generate system clocks, it should be connected
to the XTAL1 pin. In this mode, XTAL2 is used as a general-purpose I/O pin.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
206
Chapter 7
■
System Clock Configuration
3 2 K H Z C R Y S TA L O S C I L L AT O R
A 32 kHz crystal oscillator can be connected between the TOSC1 and TOSC2 pins by
enabling a dedicated low-frequency oscillator input circuit.
7.4.3 System Clock Selection and Prescalers
All the calibrated internal oscillators, the external clock sources, and the PLL output can
be used as the system clock source. The system clock source is selectable from software and
can be changed during normal operation. A clock source must be enabled and stable before it
can be selected as the source of the system clock. The enabling or disabling of the PLL, external
oscillator, and internal oscillators is controlled by the oscillator control register (OSC.CTRL).
The status of each of these clock sources is recorded in the oscillator status register (OSC.
STATUS). The contents of OSC.CTRL and OSC.STATUS registers are shown in Figure 7.10 and
Figure 7.11, respectively. The selection of external oscillator is controlled by the external oscillator control register (OSC.XOSCCTRL) shown in Figure 7.12.
The system clock is fed into a prescaler block that can divide the clock signal by a factor
from 1 to 2048 before it is routed to the CPU and peripherals. The prescaler settings are changed
from software during normal operation. The first stage, prescaler A, can divide by a factor from
1 to 512. The prescalers B and C can be individually configured to either pass the clock through
or divide it by a factor from 1 to 4. The prescaler guarantees that derived clocks are always
in phase and that no glitches or intermediate frequencies occur when changing the prescaler
setting.
The system clock selection and prescaler circuit is shown in Figure 7.13, where it is shown
that the XMega peripheral modules may run at twice (clkPER2) or four times (clkPER4) the CPU
clock frequency. The system clock selection (via the CLK.CTRL register) and prescaler registers
(via the CLK.PSCTRL register) are protected by the configuration change protection mechanism, employing a timed write procedure (write 0xD8 into CPU_CCP and then write into one
of these two registers within four clock cycles) for changing the system clock and prescaler
settings.
6
5
4
3
—
—
PLLEN
XOSCEN
2
1
RC32KEN RC32MEN
0
RC2MEN
Reset value
= 0 x 01
R
R
R
R/W
R/W
R/W
R/W
R/W
PLLEN: PLL enable
0 = PLL disabled
1 = PLL enabled. The PLL must be configured with the desired multiplication factor
and input source before it is enabled.
XOSCEN: External oscillator enable
Setting this bit enables the external clock source selected by the XOSCCTRL register. The
contents of the XOSCCTRL register are shown in Figure 7.12.
RC32KEN: 32 kHz internal RC oscillator enable
Setting this bit enables the 32 kHz internal RC oscillator.
RC32MEN: 32 MHz internal RC oscillator enable
Setting this bit enables the 32 MHz internal RC oscillator.
RC2MEN: 2 MHz internal RC oscillator enable
Setting this bit enables the 2 MHz internal RC oscillator. By default, the 2 MHz internal
RC oscillator is enabled and this bit is set.
Figure 7.10
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
—
XMega oscillator control register (OSC.CTRL)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
207
Clock System of the XMega Devices
7
6
5
4
—
—
—
PLLRDY
3
2
1
0
XOSCRDY RC32KRDY RC32MRDY RC2MRDY
Reset value
= 0x00
R
R
R
R
R
R
R
R
PLLRDY: PLL Ready
0 = PLL is not locked on to the selected frequency.
1 = PLL has locked on to the selected frequency and is ready to be used as system clock
source.
XOSCRDY: External oscillator ready
0 = External clock source is not stable.
1 = External clock source is stable and ready to be used as the system clock source.
RC32KRDY: 32 kHz internal RC oscillator ready
0 = The 32 kHz internal oscillator is not stable yet.
1 = The 32 kHz internal oscillator is stable and ready to be used as the system clock
source.
RC32MRDY: 32 MHz internal RC oscillator ready
0 = The 32 MHz internal RC oscillator is not stable yet.
1 = The 32 MHz internal RC oscillator is stable and ready to be used.
RC2MRDY: 2 MHz internal RC oscillator ready
0 = The 2 MHz internal RC oscillator is not stable yet.
1 = The 2 MHz internal RC oscillator is stable and ready to be used.
■
Figure 7.11
7
XMega oscillator status register (OSC.STATUS)
6
FRQRANGE[1:0]
5
4
X32KLPM
—
3
2
1
0
XOSCSEL[3:0]
Reset value
= 0x00
R/W
R/W
R/W
R
R/W
R/W
R/W
R/W
FRQRANGE: Crystal oscillator frequency range select
See Table 6.14
X32KLPM: Crystal oscillator 32 kHz low power mode
0 = 32 kHz crystal oscillator operates in normal power mode.
1 = 32 kHz crystal oscillator operates in low power mode (reduce the swing on the
TOSC2 pin).
XOSCSEL[3:0]: Crystal oscillator selection
See Table 6.15
■
Figure 7.12
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
7.4
XMega XOSC control register (OSC.XOSCCTRL)
FRQRANGE[1:0]
Group
configuration
00
04TO2
Frequency range
0.4 MHz ∼ 2 MHz
01
2TO9
2 MHz ∼ 9 MHz
10
9TO12
11
12TO16
9 MHz ∼ 12 MHz
12 MHz ∼ 16 MHz
Recommended range for C1
and C2 (pF)
100
15
15
10
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 7.3
■
Oscillator frequency range selection
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
208
Chapter 7
■
System Clock Configuration
XOSCSEL[3:0]
Group configuration
Selected clock source
0000
EXTCK
External clock
6 CLK
0010
32KHZ
16k CLK
0011
XTAL_256CLK(1)
32 kHz TOSC
0.4∼16 MHz XTAL
(2)
0111
XTAL_1KCLK
1011
XTAL_16KCLK
Startup time
256 CLK
0.4∼16 MHz XTAL
1K CLK
0.4∼16 MHz XTAL
16K CLK
Notes: 1. This option should only be used when frequency stability at start-up is not important for
the application. This option is not suitable for crystal.
2. This option is intended for use with ceramic resonators and will ensure frequency
stability at start-up. It can also be used when the frequency stability at start-up is not
important for the application.
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
External oscillator selection and startup time
Internal 32 kHz Osc.
Internal 2 MHz Osc.
Internal 32 MHz Osc.
ClkSYS
XOSC
Prescaler A
1, 2, 4, …, 512
ClkCPU
Prescaler C
1, 2
Prescaler B
1, 2, 4
ClkPER
Internal PLL
ClkPER2
ClkPER4
■
XMega system clock selection and prescalers
7
6
—
—
5
4
3
—
—
—
R
R
R
R
SCLKSEL[2:0]: System clock selection
R
2
1
0
SCLKSEL[2:0]
R/W
R/W
R/W
SCLKSEL[2:0]
Group configuration
Description
000
001
010
011
100
101-111
RC2MHz
RC32MHz
RC32KHz
XOSC
PLL
—
2-MHz internal RC oscillator
32-MHz internal RC oscillator
32-kHz internal oscillator
External oscillator or clock
Phase locked loop
Reserved
Figure 7.14
■
Reset value
= 0x00
Source: Atmel Corporation,
The Atmel AVR Microcontroller
Figure 7.13
Source: Atmel Corporation, The Atmel
AVR Microcontroller
Table 7.4
XMega system clock control register (CLK.CTRL)
The selection of the system clock source is controlled by the system clock control register
(CLK.CTRL) in the CLK module. The contents of the CLK.CTRL register are shown in Figure 7.14.
The selection of prescaler factors is controlled by the system clock prescaler register (CLK.
PSCTRL) shown in Figure 7.15. The user can lock the setting of the clock source and prescaler
by setting the bit 0 of the clock system lock register (CLK.LOCK) shown in Figure 7.16.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.4
■
209
Clock System of the XMega Devices
7
6
5
4
—
2
3
1
0
PSBCDIV[1:0]
PSADIV[4:0]
R
R/W
R/W
R/W
R/W
PSADIV[4:0]: Prescaler A division factor
See Table 7.5
PSBDIV[1:0]: Prescaler B and C division factor
See Table 7.6
R/W
R/W
Reset value
= 0x00
R/W
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Figure 7.15
XMega system clock prescaler register (CLK.PSCTRL)
PSADIV[4:0]
Group
configuration
Description
00000
1
No division
00001
2
Divide by 2
00011
4
Divide by 4
00101
8
Divide by 8
00111
16
Divide by 16
01001
32
Divide by 32
01011
64
Divide by 64
01101
128
Divide by 128
01111
256
Divide by 256
10001
512
Divide by 512
others
–
Reserved
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 7.5
■
Prescaler A division factor
PSBCDIV[1:0]
Group configuration
Prescaler B division
Prescaler C division
00
1_1
No division
No division
01
1_2
No division
Divide by 2
10
4_1
Divide by 4
No division
11
2_2
Divide by 2
Divide by 2
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 7.6
■
Prescaler B and C division factor
7.4.4 PLL Circuit
The XMega clock system has a PLL circuit that can multiply the frequency of the incoming
clock signal by 1 to 31. It allows the user to use a low frequency crystal oscillator to generate
higher frequency system clocks.
Four different reference clock sources can be chosen as input to the PLL:
•
•
2 MHz internal oscillator
32 MHz internal oscillator divided by 4
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 7
■
System Clock Configuration
7
6
5
4
3
2
—
—
—
—
—
—
1
—
LOCK
0
R
R
R
R
R
R
R
R/W
Reset value
= 0x00
LOCK: Clock system lock
When this bit is written to 1, the CTRL and PSCTRL registers cannot be changed, and
the system clock selection and prescaler settings is protected against all further updates
until after the next reset. This bit is protected by the configuration change protection
mechanism. The user must write the value 0xD8 into the CCP register before he or she
can change this register.
Figure 7.16
•
•
■
Source: Atmel Corporation, The Atmel
AVR Microcontroller
210
XMega clock system lock register (CLK.LOCK)
0.4 MHz to 16 MHz crystal oscillator
External clock
To enable the PLL the following procedure must be followed:
1. Enable clock reference source.
2. Set the multiplication factor and select clock reference for the PLL.
3. Wait until the clock reference source is stable.
4. Enable PLL.
The clock source selection and the setting of multiplication factor for PLL are controlled
by the PLL control register (OSC.PLLCTRL). The contents of the OSC.PLLCTRL register are
shown in Figure 7.17.
6
PLLSRC[1:0]
R/W
R/W
5
4
3
R
2
1
0
R/W
R/W
PLLFAC[4:0]
—
R/W
R/W
R/W
PLLSRC[1:0]: Clock source
PLLSRC[1:0]
Group configuration
PLL input source
00
01
10
11
RC2M
—
RC32M
XOSC
2 MHz internal RC oscillator
Reserved
32 MHz internal RC oscillator
External clock source(1)
Note: 32 kHz cannot be selected as source for the PLL. An external clock must have a
frequency no lower than 0.4 MHz.
PLLFAC[4:0]: Multiplication factor
This field can be from 1 to 31. The output frequency from the PLL should be in a
range from 10 MHz to 200 MHz.
Figure 7.17
■
Reset value
= 0x00
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
XMega PLL control register (OSC.PLLCTRL)
7.4.5 DFLL 2 MHz and DFLL 32 MHz
The XMega device provides two built-in DFLLs to improve the accuracy of the 2 MHz and
32 MHz internal oscillator. The DFLL compares the oscillator frequency with a more accurate
reference clock to do automatic run-time calibration of the oscillator. The choices for the reference clocks include these:
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.4
■
211
Clock System of the XMega Devices
•
•
32 kHz calibrated internal oscillator
32 kHz crystal oscillator connected to the TOSC pins
The DFLLs divide the reference clock by 32 to derive a 1 kHz reference. The reference
clock is individually selected for each DFLL, as shown in Figure 7.18. The DFLL must be
enabled to function. If the internal oscillator runs too fast or too slow, the DFLL decrements
or increments the corresponding DFLL calibration register value by 1 to adjust the oscillator
frequency slightly. When the DFLL is enabled, the DFLL calibration register cannot be written
from software.
32 kHz crystal osc.
32 kHz internal osc.
DFLL
2 MHz Int. osc
DFLL
32 MHz Int. osc
Figure 7.18
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
TOSC1
TOSC2
DFLL reference clock selection
The DFLL for 32 MHz and 2 MHz internal oscillators belongs to the DFLLRC32M and
DFLLRC2M modules, respectively. Each module has the same set of registers:
•
•
•
•
•
•
DFLL control register (CTRL)
Calibration register A (CALA)
Calibration register B (CALB)
Oscillator compare register 0 (COMP0)
Oscillator compare register 1 (COMP1)
Oscillator compare register 2 (COMP2)
Setting the bit 0 of the CTRL register (DFLLRC32M.CTRL or DFLLRC2M.CTRL) enables
the DFLL and auto-calibration of the internal oscillator (32 MHz or 2 MHz). The CALA and
CALB registers hold the 13 bits of the DFLL calibration value that is used for automatic runtime calibration the internal oscillator. The contents of the CALA and CALB registers are
shown in Figure 7.19.
COMP0, COMP1, and COMP2 represent the low, middle, and high bytes of the COMP
register that holds the oscillator compare value. During reset, COMP is loaded with the default
value representing the ideal relationship between oscillator frequency and the 1.024 kHz reference clock. It is possible to write these bits from software and then enable the oscillator to tune
to a frequency different from its normal frequency. These bits can only be written when the
DFLL is disabled. The contents of COMP0∼COMP2 are shown in Figure 7.20.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
System Clock Configuration
7
6
5
3
4
2
1
0
Reset value
= 0x40
CALL[6:0]
COMP0
R
R/W
R/W
R/W
R/W
R/W
R/W
CALL[6:0]: DFLL calibration bits 6~0
These 7 bits are set to its middle value after reset.
7
6
5
4
3
2
1
R/W
0
Reset value
= 0b00xxxxxx
CALH[12:7]
COMP1
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
CALH[12:7]: DFLH calibration bits 12~7
These 6 bits are the most significant bits of the calibration register. When
the DFLL is disabled, the 13-bit calibration register can be written in the
software.
■
Figure 7.19
7
XMega calibration registers A and B (CALA, CALB)
6
5
4
COMP0
R/W
R/W
R/W
7
6
5
COMP1
COMP2
3
2
1
0
Reset value
= 0x00
COMP[7:0]
R/W
R/W
R/W
R/W
4
3
2
1
R/W
R/W
R/W
2
1
R/W
0
Reset value
= 0x00
COMP[15:8]
R/W
Source: Atmel Corporation, The Atmel AVR Microcontroller
Chapter 7
R/W
R/W
R/W
7
6
5
4
3
—
—
—
—
—
R
R
R
R
R
R/W
0
Reset value
= 0x00
COMP[19:16]
R/W
R/W
R/W
Source: Atmel Corporation, The Atmel AVR
Microcontroller
212
Figure 7.20 ■ XMega oscillator compare register 0, 1, and 2 (COMP0,
COMP1, and COMP2)
7
6
5
4
3
2
—
—
—
—
—
—
R
R
R
R
R
R
1
0
RC32MCREF RC2MCREF
R/W
Reset value
= 0x00
R/W
RC32MCREF: 32 MHz calibration reference
0 = Internal 32.768 kHz internal RC oscillator is used as calibration source of 32 MHz DFLL.
1 = External 32.768 kHz crystal oscillator is used as calibration source of 32 MHz DFLL.
RC2MCREF: 2 MHz calibration reference
0 = Internal 32.768 kHz internal RC oscillator is used as calibration source of 2 MHz DFLL.
1 = External 32.768 kHz crystal oscillator is used as calibration source of 2 MHz DFLL.
Figure 7.21
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The reference clock sources used by the 32 MHz and 2 MHz DFLL are selected by the DFLL
control register (OSC.DFLLCTRL) in the OSC module. The contents of the OSC.DFLLCTRL
register are shown in Figure 7.21.
XMega DFLL control register (OSC.DFLLCTRL)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.4
■
213
Clock System of the XMega Devices
The procedure for enabling a DFLL is as follows:
1. Select internal or external clock reference with the DFLL’s control bit in the DFLL
control register (OSC.DFLLCTRL).
2. Set the DFLL enable bit (ENABLE) in the control register (DFLLRC32M.CTRL or
DFLLRC2M.CTRL) to 1, to enable the DFLL.
3. The calibration process starts immediately.
7.4.6 External Oscillator Failure Detector
When using an external crystal or external clock source, there is always a slight probability
of the source failure. As a safety precaution, the XMega clock system has an external oscillator
failure detector that monitors the external clock source and reacts if it stops.
If the external source is selected as the main system clock source and it fails, the failure
detector switches to the internal 2 MHz RC oscillator and issues a nonmaskable interrupt. If
the external source is enabled but is not selected as the main system clock source, the external
source is only disabled, but the nonmaskable interrupt is still issued.
The external failure detector must be enabled. To avoid accidental enabling, the user must
follow a special sequence required to enable it. The procedure is as follows:
1. Load the protected I/O register signature (0×D8) into the CPU.CCP register.
2. Set the failure detection enable bit (XOSCFDEN) in the external oscillator failure
detection register (OSC.XOSCFAIL) to logic one.
3. The failure detector is now enabled until the next system reset.
Example 7.1
▼
Write a subroutine to use a 16 MHz external oscillator to generate a 32 MHz clkCPU.
Solution: One way to generate a 32 MHz clkCPU is to use the PLL to multiply the 16 MHz by 2
and set the prescalers A, B, and C to 1, 1, and 1.
setCPUClkto32Mwith16MCrystal:
; select 16-MHz crystal as external clock source
waitXOSC:
waitPLL:
ldi
sts
lds
ori
sts
lds
sbrs
rjmp
ldi
sts
lds
ori
sts
lds
sbrs
tmp1,0xCB
OSC_XOSCCTRL,tmp1
tmp2,OSC_CTRL
tmp2,OSC_XOSCEN_bm
OSC_CTRL,tmp2
tmp1,OSC_STATUS
tmp1,OSC_XOSCRDY_bp
waitXOSC
tmp1,0xC2
OSC_PLLCTRL,tmp1
tmp1,OSC_CTRL
tmp1,OSC_PLLEN_bm
OSC_CTRL,tmp1
tmp1,OSC_STATUS
tmp1,OSC_PLLRDY_bp;
; select external crystal with fre_range=12∼16MHz,
; startup time=16k CLKs
; enable external clock source
;"
;"
; check bit position for the skip instruction
; jump if external crystal oscillator is not ready
; select XOSC as source to PLL and set multiplying
; factor of PLL to 2
; enable PLL
;"
;"
; wait until PLL is ready
;"
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
214
Chapter 7
■
System Clock Configuration
rjmp
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ret
waitPLL
tmp1,0xD8
CPU_CCP,tmp1
tmp1,0x04
CLK_CTRL,tmp1
tmp1,0xD8
CPU_CCP,tmp1
tmp1,0
CLK_PSCTRL,tmp1
;"
; allow write into protected register
;"
; select PLL to generate system clock
;"
; allow write into protected register
;"
; set system clock prescale factor A,B,C
; to 0,0,0
The C language version of the function is as follows:
void setCPUClkto32Mwith16MCrystal(void)
{
OSC.XOSCCTRL = 0xCB;
// select 16-MHz external crystal as clock source
OSC.CTRL |= OSC_XOSCEN_bm;
// enable XOSC
while(!(OSC.STATUS & OSC_XOSCRDY_bm)); // wait until XOSC is ready
OSC.PLLCTRL = 0xC2;
// use XOSC as input to PLL, set multiplying factor to 2
OSC.CTRL |= OSC_PLLEN_bm; // enable PLL
while(!(OSC.STATUS & OSC_PLLRDY_bm)); // wait until PLL is ready
CCP = 0xD8;
// allow write into protected register
CLK.CTRL = 0x04; // select PLL to generate system clocks
CCP = 0xD8;
// allow write into protected register
CLK.PSCTRL = 0;
// set prescaler A,B,C to 1,1,1
}
▲
Example 7.2
▼
Write a subroutine to use the internal 32 MHz oscillator to generate a 32 MHz clkCPU.
Solution: The subroutine that selects the 32 MHz internal oscillator to generate the system clock, enable DFLL auto-calibration, and set the system clock prescaler to 1,1,1
is as follows:
; ---------------------------------------------------------------------------------------------------------------------; This subroutine uses the 32-MHz internal oscillator to generate a 32-MHz ClkCPU.
; ---------------------------------------------------------------------------------------------------------------------setCPUClkto32Mwith32MIntOsc:
lds
ori
sts
wait32MIntOSC:
lds
sbrs
rjmp
ldi
sts
ldi
r16,OSC_CTRL
r16,OSC_RC32MEN_bm
OSC_CTRL,r16
; enable 32-MHz internal oscillator
;"
;"
r16,OSC_STATUS
r16,OSC_RC32MRDY_bp
wait32MIntOsc
r16,0xD8
CPU_CCP,r16
r16,0x01
; wait until 32-MHz oscillator is ready
;"
;"
; allow configuration to change
;"
; use 32-MHz internal oscillator to generate
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7.5
■
215
Summary
sts
ldi
sts
ldi
sts
lds
ori
sts
lds
ori
sts
ret
CLK_CTRL,r16
r16,0xD8
CPU_CCP,r16
r16,0
CLK_PSCTRL,r16
r16,OSC_DFLLCTRL
r16,OSC_RC32MCREF_bm
OSC_DFLLCTRL,r16
r16,DFLLRC32M_CTRL
r16,0x01
DFLLRC32M_CTRL,r16
; system clock
; allow configuration to change
;"
; set system clock prescaler A, B, and C to 1,1,1
;"
; use external 32.768-kHz crystal to
; calibrate the 32-MHz internal oscillator
;"
; enable DFLL
;"
;"
The C language version of the function is as follows:
void setCPUClkto32Mwith32MIntOsc (void)
{
OSC.CTRL |= OSC_RC32MEN_bm;
// enable internal 32-MHz oscillator
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
// wait until 32-MHz is ready
CCP = 0xD8;
// allow configuration to change
CLK.CTRL = 1;
// use internal 32-MHz oscillator to generate system clock
CCP = 0xD8;
// allow configuration to change
CLK.PSCTRL= 0;
// set system clock prescaler A, B, C to 1,1,1
OSC.DFLLCTRL = 0x00;
// use external 32.768-kHz oscillator to auto-calibrate 32-MHz DFLL
DFLLRC32M.CTRL |= 0x01;
// enable 32-MHz DFLL
}
▲
7.5 Summary
We have learned that a clock signal is needed to synchronize and pace the instruction execution in Chapter 1. We also have learned how to create time delays using program loops in
Chapter 3. In addition to the CPU, all peripheral modules also need clock signals to control
their operations.
The embedded system designer has the choice of using a ceramic resonator, a crystal oscillator, or an RC circuit (on-chip or off-chip) to generate the system clock. The system clock is a
periodic square wave with roughly 50% duty cycle. The output signal from a ceramic resonator, a crystal oscillator, or an RC circuit is not a square wave and must be squared up before it
can be used. In addition, the frequency of the output of a ceramic resonator or a crystal oscillator need not be the same as the system clock. Circuit techniques are used to multiply the
frequency of the clock signal generated by the ceramic resonator, the crystal oscillator, or an
RC circuit. All MCUs include a clock module to configure the clock input source properly and
distribute the generated clock signals to all of the modules that need them.
Both the Mega and XMega provide on-chip RC oscillators as possible sources for the system clock. These on-chip oscillators can be calibrated to become more accurate. A Mega device
relies on fuse programming to select the clock generation method. However, the XMega clock
generation is completely controlled by the software program. The XMega’s clock system also
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
216
Chapter 7
■
System Clock Configuration
includes a PLL circuit that can multiply the chosen clock signal’s frequency so that a higher
frequency clock signal can be generated from an internal RC or external crystal oscillator with
a lower frequency.
7.6 Exercises
E7.1 What is the default system clock source of the Mega device after reset, and what is the
default frequency of clkCPU?
E7.2 What is the default system clock source for the XMega devices after reset?
E7.3 Write an assembly subroutine to use an 8 MHz external oscillator to generate a 32 MHz
clkCPU for the XMega device.
E7.4 Write a C function to use an 8 MHz external oscillator to generate a 32 MHz clkCPU for the
XMega device.
E7.5 Write an assembly subroutine that uses the internal 2 MHz oscillator to generate system
clocks so that the frequency of clkCPU is 32 MHz.
E7.6 Write a C function that uses the internal 2 MHz oscillator to generate system clocks so
that the frequency of clkCPU is 32 MHz.
E7.7 Write an assembly subroutine that uses the external 4 MHz crystal to directly generate
the clkSYS and configure the prescaler properly so that clkCPU frequency is set to 32 MHz.
E7.8 Write a C function that uses the external 8 MHz crystal oscillator to directly generate the
clkSYS and configure the prescaler properly so that clkCPU frequency is set to 32 MHz.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8
Parallel I/O
8.1 Objectives
After completing this chapter, you will be able to
• Explain the I/O addressing issue.
• Explain I/O synchronization methods.
• Verify voltage compatibility when interfacing a
microcontroller with peripheral devices.
• Verify current compatibility when driving
peripheral devices.
• Turn LEDs on and off.
• Input data from the DIP switches.
• Use seven-segment displays to display decimal
numbers and a small set of English letters.
• Use the I/O pin to generate waveform and make
sound.
• Write programs to generate waveforms using a
D/A converter
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
218
Chapter 8
■
Parallel I/O
8.2 I/O Introduction to I/O PORTs
The term PORT is often used with I/O functions. An I/O PORT consists of a group
of pins (often eight) and a set of registers including data registers (or latch), data direction
register, and control register(s) (optional). An I/O PORT is often bidirectional in the sense
that it can output and input data at different times. The directions of I/O pins are established
by programming the data direction register. The data register (or latch) allows the I/O pins
to maintain their voltage levels if the application program does not change them. Some I/O
PORTs may have more sophisticated functions and hence require one or more control registers for their configuration.
The I/O PORT allows the user to interface with I/O devices, such as dual-inline-package
(DIP) switches, keypads, keyboards, light-emitting diodes (LEDs), seven-segment displays, liquid crystal displays (LCDs), stepper motors, D/A converters, and so on. I/O devices
are also called peripheral devices in the sense that they are outside the core of a computer
system.
8.2.1 I/O Addressing Issue
When performing I/O operations, the CPU deals directly with the I/O PORT registers. This
involves two issues:
•
Address space. This issue is related to the question of whether I/O devices
should be treated the same as memory devices, that is, whether the I/O registers
should occupy the same address space (some people like to call it memory space)
as the memory devices (SRAM, DRAM, EEPROM, or flash memory) or have
a separate address space. Both approaches have been used by microprocessor
and microcontroller vendors. The current trend is for I/O devices and memory
components to share the same address space.
•
Addressing Modes and Instructions. I/O devices may have their own addressing
modes and instruction set or share the same addressing modes and instruction set
with the memory devices.
The AVR Mega devices have a dedicated I/O space that contains 64 locations (bytes) from
0x20 to 0x5F. These 64 bytes hold control registers, stack pointer, and other I/O registers. The
user accesses these registers, using the I/O instructions listed in Table 8.1. These I/O registers are also accessed as data space locations, using LD/LDS/LDD and ST/STS/STD instructions. For those Mega devices (Mega640/1280/1281/2560/2561) with more than 64 I/O registers,
an extended I/O space that spans from 0x60 to 0x1FF is added. I/O registers located in this
range are only accessed using the LD/LDS/LDD and ST/STS/STD instructions. The user can
use direct, indirect with displacement, indirect, indirect with pre-decrement, and indirect with
post-increment addressing modes to specify an I/O register.
For the XMega devices, all I/O registers reside in the lowest 4096 addresses of the data
memory. This is referred to as the I/O memory space. The lowest 64 addresses are accessed
directly using the I/O instructions listed in Table 8.1, or as the data space locations from 0x00 to
0x3F. The rest is the extended I/O memory space, ranging from 0x40 to 0x0FFF. I/O registers
here must be accessed as data space locations, using load (LD/LDS/LDD) and store (ST/STS/
STD) instructions.
Atmel assigns a symbolic name to each I/O register so that the user can use it to access
any I/O register. Using the symbolic name to refer to an I/O register makes your program more
readable.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.2
■
219
I/O Introduction to I/O PORTs
Mnemonic
Description
Operation
in Rd, A
Input from I/O location
Rd ← I/O(A)
out A, Rr
Output to I/O location
I/O(A)1 ← Rr
sbic A, b
Skip if bit in I/O register is zero
If(I/O(A, b)2 5 0) then PC d PC 1 2 or 3
sbis A, b
Skip if bit in I/O register is one
If(I/O(A, b)2 5 1) then PC d PC 1 2 or 3
sbi A, b
Set bit in I/O register
I/O(A, b)2 ← 1
cbi A, b
Clear bit in I/O register
I/O(A, b)2 ← 0
1
Notes: 1. I/O(A) refers to I/O space at address A.
2. I/O(A, b) refers to bit b of the I/O register at address A (0x00 to 0x1F).
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.1
■
AVR I/O Instructions
8.2.2 I/O Synchronization
As described in Section 1.5, microprocessors either cannot provide the current required by
the peripheral devices or operate at a voltage level different from those of peripheral devices.
Therefore, they usually communicate with peripheral devices via interface chips. For the microcontroller, the functions of most of these interface chips and the CPU are built into the same
chip. When transferring data in the parallel format (multiple bits at a time), the microcontroller
reads and writes data through the parallel PORT. When transferring data in the serial format
(one bit in one clock cycle), the microcontroller reads and writes data through the serial interface such as a universal synchronous asynchronous receiver and transceiver (USART), serial
peripheral interface (SPI), inter-integrated circuit (I2C), or controller area network (CAN).
Because data transfers go through the interface chip (or logic for the MCU), the synchronization issue occurs in two places. One is between the processor and the interface chip (or logic
for the MCU). The other is between the interface chip (or logic for the MCU) and the peripheral
devices.
8.2.3 Synchronization Issue for Parallel PORTs
The design of parallel PORTs of today’s microcontrollers (including the AVR Mega and
XMega) is to allow the data written into the data register to appear on the output pins directly
and allow the read operation from the data register to obtain the instantaneous voltage levels
on the input PORT pins. There is no concern about the synchronization issue. This is quite different from the era of microprocessors. To perform an I/O operation, the microprocessor needs
to make sure that interface chip for the input device has new data before it reads it or that
the interface chip for the output device can handle new data before it sends new data to it.
This is achieved by either polling or interrupt. The interface chip is designed to have status
flags to indicate whether it has new data or can accept new data for output. The interface chip
may use a strobe signal or handshake signals to achieve synchronization between the interface
chip and the peripheral device. This type of synchronization is no longer needed in today’s
microcontrollers.
8.2.4 Synchronization Issue for Serial Interface
For the serial interface, the data transfer rate between the processor and the interface logic
is much faster than that between the interface logic and the peripheral device. The processor
needs to make sure that there is new data in the interface logic (usually held in a data register)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
220
Chapter 8
■
Parallel I/O
before reading it. It also has to make sure that the interface logic can handle more data before
sending new data to it. This is achieved by using either the polling or the interrupt method to
make sure that the new I/O operation can be started.
The synchronization between the interface logic and the peripheral device is achieved by
following certain data transfer protocols. For example, the interface logic and the peripheral
device use the same clock signal to synchronize data transfer in the synchronous protocol. The
SPI and I2C module use this approach. For data transfers that use asynchronous protocol, both
the transmitter and receiver agree on a common data transfer rate, and the receiver uses a sampling clock signal with a frequency that is a multiple (16, 32, or 64) of the data rate to detect the
incoming data. This is used in the USART module.
8.3 I/O Pin Driving Circuit Structure
The internal logic values of the microcontroller drive the I/O pins through driving circuits.
There are several possible driving circuit configurations: totem pole, bus keeper, wired-OR, and
wire-AND.
8.3.1 Totem Pole
DIRn
Pn
OUTn
INn
Figure 8.1
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The totem-pole circuit configuration is illustrated in Figure 8.1. When a pin is configured
for totem pole (push–pull), the pin is driven high or low, according to the corresponding bit
setting in the OUT register. In this configuration, there is no current limitation for sink or
source other than what the pin is capable of. If the pin is configured for input, the pin floats
if no external pulling circuit (pull-up or pull-down) is connected. The input circuit (driver of
the INn signal) is a Schmidt trigger circuit that can square up the slow-rising input signal to a
sharp-rising output signal.
Totem pole block diagram
There are two variations for the totem-pole driving circuit. One version has a pull-down
circuit, whereas the other version has a pull-up.
TOTEM POLE
WITH
PULL-DOWN
The circuit of this version of the totem pole is shown in Figure 8.2. The pin Pn is configured for input or output, depending on whether the DIRn signal is driven to 0 or 1. The
pull-down resistor is enabled when the pin is configured for input. The nth bit (INn) of the IN
register holds the instantaneous values of the I/O pin Pn. When the Pn pin is configured for
input and is not driven, it is pulled to low by the RPD resistor.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
221
I/O Pin Driving Circuit Structure
DIRn
Pn
OUTn
RPD
INn
Figure 8.2
TOTEM POLE
WITH
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
8.3
Totem pole with pull-down
PULL-UP
DIRn
RPU
Pn
OUTn
INn
Figure 8.3
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
The circuit of this version of totem pole is shown in Figure 8.3. When the pin is configured
for input, the pull-up resistor is enabled. The rectangle containing the word RPU is the pull-up
resistor. When the input pin is not driven, the voltage at the input pin is pulled up to high by
the RPU resistor.
Totem pole with pull-up (on input)
8.3.2 Bus Keeper
The bus-keeper configuration is shown in Figure 8.4. When the I/O pin driver circuit is configured to bus-keeper mode, it provides a weak bus keeper that keeps the pin at its logic level
when the pin is no longer driven to any logic state. If the last level on the pin/bus was 1, the bus
keeper uses the internal pull resistor to keep the bus high. If the last logic level on the pin/bus
was 0, the bus keeper uses the internal pull resistor to keep the bus low. The bus keeper’s weak
output produces the same logical level as the last output level. It acts as a pull-up if the last
level was 1, and pull-down if the last level was 0.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
222
Chapter 8
■
Parallel I/O
Pn
OUTn
INn
Figure 8.4
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
DIRn
Totem pole with bus keeper
8.3.3 Wired-OR
OUTn
Pn
RPD
INn
Figure 8.5
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The circuit for the wired-OR configuration is shown in Figure 8.5. With the wired-OR configuration, the pin is driven high when the corresponding bit in the OUT register is written to 1.
When a bit of the OUT register is set to 0, the corresponding pin is not driven and can be pulled
low with the internal or an external pull-resistor. An internal pull-down is shown in Figure 8.5.
Wire-OR with optional pull-down
8.3.4 Wired-AND
The circuit of the wired-AND configuration is shown in Figure 8.6. With the wired-AND
configuration, the Pn pin is driven low when the corresponding bit in the OUT register is written to 0. When OUTn is set to 1, the Pn pin is released, allowing the pin to be pulled high with
the internal or an external pull-up resistor. If an internal pull-up resistor is used, this is also
active if the pin is set as input.
8.4 Electrical Characteristic Consideration for I/O Interfacing
Most embedded systems require the use of logic chips, peripheral devices in addition to
the microcontroller, to perform their function. Because these chips may use different types of
integrated circuit (IC) technologies, there is a concern that the resultant embedded system may
not function properly.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
223
Electrical Characteristic Consideration for I/O Interfacing
INn
RPU
Pn
OUTn
Figure 8.6
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
8.4
Wire-AND with optional pull-up
The major concern in interfacing IC chips that are made with different technologies is whether they are electrically compatible. There are two issues involved in electrical
compatibility:
•
Voltage-level compatibility. Is the high output level of an IC chip high enough
to be considered as a high for the input of another IC chip? Is the low output
level of an IC chip low enough to be considered as a low for the input of another
IC chip?
•
Current drive capability. Does the output of an IC chip have enough current to
drive its load? Can the output circuit of an IC chip sink the currents of its load?
Signal timing is also an important factor for making sure that the digital circuit functions
correctly. The main concern about timing is whether the signal from one chip becomes valid
early enough to be used by other chips. This is a timing compatibility issue. When the operating frequency becomes very high, the transmission line effect and ground bounce effect must be
considered too. However, we are not dealing with high-frequency systems in this text, so these
two issues are not discussed.
8.4.1 Voltage-Level Compatibility
There are many IC technologies in use today. Some of them are bipolar; others are unipolar. A bipolar IC technology has both the electron and hole currents in any moment. However,
in a unipolar IC technology, the current in any part of the circuit is either the electron current or the hole current. The unipolar CMOS technology is the dominant IC technology in
use today.
The voltage-level compatibility issue arises because IC technologies differ in the following
four voltages:
•
Input high voltage (VIH). This is the voltage level that is treated as a logic 1 when
applied to the input of a digital circuit.
•
Input low voltage (VIL). This is the voltage level that is treated as a logic 0 when
applied to the input of a digital circuit.
•
•
This is the voltage level when a digital circuit outputs a logic 1.
Output low voltage (VOL). This is the voltage level when a digital circuit outputs a
logic 0.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
224
■
Chapter 8
Parallel I/O
In order for the digital circuit X to be able to drive circuit Y correctly, the following conditions must be satisfied:
•
VOHX ê VIHY (the output high voltage of circuit X must be higher than or equal to
the input high voltage of circuit Y). The difference between VOH and VIH of the same
technology is referred to as the noise margin high (NMH).
•
VOLX Ä VILY (the output low voltage of circuit X must be lower than or equal to the
input low voltage of circuit Y). The difference between VIL and VOL of the same
technology is referred to as the noise margin low (NML).
The input and output voltage levels of a few popular logic families are listed in Table 8.2,
from which one can draw the following conclusions:
•
There is no problem using the CMOS logic chip to drive the bipolar logic chip at
the same power supply level.
•
The AVR Mega has no problem driving the CMOS logic chip and being driven by
the CMOS logic chip at the same power supply level.
•
The BiCMOS logic is not suitable for driving the AVR Mega and other CMOS logic
chips at the same power supply level.
•
The bipolar logic ICs are not suitable for driving the CMOS logic ICs or the AVR
microcontroller at the same power supply level.
Logic family
3
AVR Mega
AVR XMega6
S4
LS4
4
VDD
VIH
VOH
VIL
VOL
5V
3.0 V
4.2 V
1.5 V
0.9 V
2.4,3.6 V
0.7 VCC
VCC2 0.3 V7
0.3 VCC
0.45 V8
5V
2V
3.0,3.4 V1
0.8 V
0.4,0.5 V2
5V
2V
3.0,3.4 V1
0.8 V
0.4,0.5 V2
1
AS
5V
2V
3.0,3.4 V
0.8 V
0.35 V
F4
5V
2V
3.4 V
0.8 V
0.3 V
HC
3
5V
3.5 V
4.9 V
1.5 V
0.1 V
3
5V
3.5 V
4.9 V
1.5 V
0.1 V
ACT3
5V
2V
4.9 V
0.8 V
0.1 V
5
5V
2V
3V
0.8 V
0.55 V
BCT5
5V
2V
3.3 V
0.8 V
0.42 V
5
5V
2V
2.4 V
0.8 V
0.55 V
HCT
ABT
FCT
Notes: 1. VOH value will get lower when output current is larger.
2. VOL value will get higher when output current is larger. The VOL values of different logic gates are slightly
different.
3. AVR Mega, XMega, HC, HCT, and ACT are based on the CMOS technology.
4. S, LS, AS, and F logic families are based on the bipolar technology.
5. ABT, BCT, and FCT use the BiCMOS technology.
6. XMega MCU can operate with VCC from 2.4~3.6 V or 1.6~2.4 V.
7. This is a typical value.
8. This is also a typical value.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.2
■
Input and output voltage levels of common logic families
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.4
■
Electrical Characteristic Consideration for I/O Interfacing
225
The CMOS is the most widely used semiconductor technology. The power supply of the
CMOS technology can be in a wide range. As a result, the VIH and VIL are not a single value.
However, we can use 0.7 VCC and 0.3 VCC (VCC is the power supply) as an estimate of the
VIH and VIL.
8.4.2 Current Drive Capability
A microcontroller needs to drive other peripheral I/O devices in an embedded system. The
second electrical compatibility issue is whether the microcontroller can supply (when the output voltage is high, also called source) or sink (when the output voltage is low) the current
needed by the I/O devices that it interfaces with. Depending upon the voltage level of an output
pin, the current may flow out from (supply the current) or into (sink the current) the pin. The
designer must make sure that the following two requirements are satisfied:
•
Each I/O pin can supply (flowing out from the pin) and sink (flowing into the pin)
the current needed by the I/O devices that it interfaces with. For example, each of
the AVR Mega device I/O pins can source and sink 40 mA.
•
The total current required to drive I/O devices does not exceed the maximum
current rating of the microcontroller. For example, the total DC current that an
AVR Mega device can supply is 200 mA.
Each logic chip has the following four currents that are involved in the current drive
calculation:
•
Input high current (IIH). This is the input current (flowing into the input pin) when
the input voltage is high.
•
Input low current (IIL). This is the input current (flowing out of the input pin) when
the input voltage is low.
•
Output high current (IOH). This is the output current (flowing out of the output pin)
when the output voltage is high.
•
Output low current (IOL). This is the output current (flowing into the output pin)
when the output voltage is low.
The current capabilities of several common logic families and the AVR Mega and XMega
devices are listed in Table 8.3. In the CMOS technology, the gate terminal (one of the three
terminals in an N- or P-transistor) draws a significant current only when they are being charged
up toward VCC or pulled down toward GND level. After that, the gate terminal draws only leakage currents. Bipolar technology is different from the CMOS technology in that a DC current
always flows into or out of the base terminal of the transistor of a bipolar logic chip.
To determine whether a pin can supply and sink currents to all the peripheral pins that it
drives directly, the designer needs to check the following two requirements:
1. The IOH of an I/O pin of the microcontroller is equal to or greater than the sum
of currents flowing into all peripheral pins that are connected directly to the
microcontroller I/O pins.
2. The IOL of an I/O pin of the microcontroller is equal to or greater than the sum
of currents flowing out of all peripheral pins that are connected directly to the
microcontroller I/O pins.
In addition, the designer must also make sure that the total current needed to drive the
peripheral signal pins does not exceed the total current that the microcontroller can supply.
One question that arises here is what should be done if an I/O pin cannot supply (or
sink) the current needed to drive the peripheral pins? A simple solution is to add buffer chips
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
226
Chapter 8
■
Parallel I/O
Logic family
VCC
IIH
IIL
IOH
IOL
5V
1 µA
1 µA
40 mA
40 mA4
AVR XMega
2.4,3.6 V
1 µA
1 µA
20 mA
20 mA5
S
5V
50 µA
1.0 mA
15 mA
24 mA
AVR Mega
23
LS
5V
20 µA
0.2 mA
15 mA
24 mA
AS
5V
20 µA
1 mA
15 mA
64 mA
F
5V
20 µA
1 mA
15 mA
64 mA
HC3
5V
1 µA
1 µA
25 mA
25 mA
3
HCT
5V
1 µA
1 µA
25 mA
25 mA
ACT3
5V
1 µA
1 µA
24 mA
24 mA
3
ABT
5V
1 µA
1 µA
32 mA
64 mA
BCT
5V
20 µA
1 mA
15 mA
64 mA
3
5V
1 µA
1 µA
15 mA
64 mA
FCT
Notes: 1. Values are based on the 74xx244 of Texas Instrument (xx is the
technology name).
2. The total supply currents of AVR Mega and XMega are 200 mA and
200 mA.
3. The values for IIH and IIL are maximum input leakage currents.
4. The AVR Mega power supply has ranges 1.8,2.4 V and 2.4,5.5 V.
5. The AVR XMega power supply has two ranges 1.6,2.4 V and 2.4,3.6 V.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.3
■
Current capabilities of common logic families1
(for example, 74ABT244) that can supply enough current between the microcontroller and the
peripheral chips. This technique is widely used in microcontroller applications and is illustrated in several examples in this chapter.
8.4.3 Timing Compatibility
D
thd
Q
D
tsu
CLK
CLK
Q
(a)
Figure 8.7
■
(b)
Source: Atmel Corporation, The Atmel
AVR Microcontroller
If an I/O pin is driving a peripheral pin that does not contain latches or flip-flops, then timing is not an issue. A latch or flip-flop usually has a control signal or clock signal to control the
latching of an input signal. As illustrated in Figure 8.7, the D input to the D flip-flop must be
valid for tsu ns before the rising edge of the CLK signal and remain valid for at least thd ns after the
rising edge of the CLK signal in order for its value to be correctly copied to the output signal Q.
The timing parameters tsu and thd are referred to as the setup and hold time requirements of the
D flip-flop and its latching timing requirement
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.5
■
227
Overview of the AVR Mega Parallel PORTs
D flip-flop. The main timing consideration is that the setup- and hold-time requirements for all
latches and flip-flops in a digital system must be satisfied in order for the system to work correctly. A signal may pass through several intermediate chips before it is used by the final latch
or flip-flop. The time delays of all intermediate devices must be added when considering the
timing analysis. Timing requirement analysis can be very complicated and is best illustrated
using examples.
8.5 Overview of the AVR Mega Parallel PORTs
Source: Atmel Corporation, The Atmel AVR
Microcontroller
An AVR Mega MCU may have up to 11 parallel PORTs (PORTA, PORTB, …, PORTL [there
is no PORTI]). Each PORT has true read-modify-write functionality; that is, the user can change
the direction or value of any individual pin without affecting other pins by using the SBI or CBI
instruction. Each PORT has symmetrical drive characteristics with both high sink and source
capability. The pin driver is strong enough to drive an LED display directly. All PORT pins have
individually selectable pull-up resistors with a supply-voltage invariant resistance. All I/O pins
have protection diodes to both VCC and Ground, as indicated in Figure 8.8, to prevent the chip
from being damaged by static.
RPU
Pxn
Logic
Figure 8.8
■
I/O pin protection diodes
Three I/O memory locations are allocated for each PORT, one each for the data register (PORTx),
data direction register (DDRx), and the PORT input register (PINx). The letter x represents one
of the letters in {A, B, C, D, E, F, G, H, J, K, and L}. The contents of these three registers are
shown in Figures 8.9 through 8.11. The PINx register is read-only, whereas PORTx and DDRx
are read/writable. However, writing a 1 to a bit in the PINx register causes the corresponding bit
in the PORTx register to toggle. In addition, the pull-up resistors of all pins of all PORTs can be
disabled by setting the PUD bit in the MCUCR register.
7
6
5
4
3
2
1
0
PORTx7
PORTx6
PORTx5
PORTx4
PORTx3
PORTx2
PORTx1
PORTx0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 8.9
■
PORTx data register (PORTx, x 5 A, B, C, D, E, F, G, H, J, K, or L)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
228
Chapter 8
■
Parallel I/O
7
6
5
4
3
2
1
0
DDx7
DDx6
DDx5
DDx4
DDx3
DDx2
DDx1
DDx0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 8.10
■
PORTx data direction register (DDRx, x 5 A, B, C, D, E, F, G, H, J, K, or L)
7
6
5
4
3
2
1
0
PINx7
PINx6
PINx5
PINx4
PINx3
PINx2
PINx1
PINx0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= NA
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 8.11
■
PORTx input pins register (PINx, x 5 A, B, C, D, E, F, G, H, J, K, or L)
8.5.1 Configuring the Mega I/O Pins
The DDxn bit in the DDRx register selects the direction of the Pxn pin. The Pxn pin is configured as an output if the DDxn bit in the DDRx register is 1. If the DDxn bit is cleared to 0, the Pxn
pin is configured as an input.
If the PORTxn bit of the PORTx register is written to 1 when the pin is configured for input, the
pull-up resistor is activated. By writing a 0 to the PORTxn bit or configuring the pin for output,
the pull-up resistor is disabled. The PORT pins are tri-stated when reset condition becomes
active, even if no clocks are running.
If the PORTxn bit is written to 1 when the associated pin is configured for output, the Pxn
pin is driven high. If the PORTxn bit is written to 0 when the Pxn pin is configured for output,
the Pxn pin is driven low.
8.5.2 Toggling the Mega I/O Pin
An I/O pin can be toggled by writing a 1 to the PINxn bit, independent of the value of the
DDRxn bit of the DDRx register. The SBI instruction can be used to perform this operation.
8.5.3 Reading the Pin Value
Independent of the setting of the data direction bit DDxn, the PORT pin can be read
through the PINxn bit of the PINx register.
Example 8.1
▼
Write a sequence of instructions and C statements to configure PORTD for output and output the value 0x49 to it.
Solution: The following instructions perform the specified operations:
.include
…
ldi
out
ldi
out
,m2560def.inc.
; or include file of other Mega devices
r16,0xFF
DDRD,r16
r16,0x49
PORTD,r16
; configure PORTD for output
; "
; output the value 0x49 to PORTD
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.5
■
Overview of the AVR Mega Parallel PORTs
229
The following C statements perform the same operations:
#include
…
DDRD
PORTD
,avr\io.h.
5 0xFF;
5 0x49;
▲
Example 8.2
▼
Write a sequence of instructions and C statements to configure PORTB for input, read the
value of PORTB, and save it in data memory location at 0x1000.
Solution: The following instructions perform the specified operations:
.include
…
clr
out
in
st
,m2560def.inc.
r16
DDRB,r16
r17,PINB
0x1000,r17
; configure PORTB for input
; "
; read the current PORTB value
; store the value of PORTB in memory location at 0x1000
The following C statements perform the same operations:
#include ,avr\io.h.
…
char
*ptr;
ptr
5 0x1000;
…
DDRB
5 0x00;
*ptr
5 PINB;
// use ptr to point to memory location at 0x1000
// configure PORTB for input
// read PORTB value and store it in memory location at 0x1000
▲
8.5.4 Unconnected Pins
If some pins are unused, it is recommended to ensure that these pins have a defined level.
Even though most of the digital inputs are disabled in the deep sleep modes, floating inputs
should be avoided, to reduce current consumption in all other modes where the digital inputs
are enabled (reset, active mode, and idle mode).
The simplest method to ensure a defined level of an unused pin is to enable the internal
pull-up. In this case, the pull-up is disabled during reset. If low power consumption during reset
is important, it is recommended to use an external pull-up or pull-down. Connecting unused
pins directly to VCC or GND is not recommended because this may cause excessive currents if
the pin is accidentally configured as an output.
8.5.5 Alternate PORT Functions
Most PORT pins have alternate functions in addition to being general digital I/Os. The
alternate pin functions for each PORT are listed in Tables 8.4 through 8.15.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
230
Chapter 8
■
Parallel I/O
PORT pin
Alternate function
PA7
AD7 (external memory interface address and data bit 7)
PA6
AD6 (external memory interface address and data bit 6)
PA5
AD5 (external memory interface address and data bit 5)
PA4
AD4 (external memory interface address and data bit 4)
PA3
AD3 (external memory interface address and data bit 3)
PA2
AD2 (external memory interface address and data bit 2)
PA1
AD1 (external memory interface address and data bit 1)
PA0
AD0 (external memory interface address and data bit 0)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.4
■
PORTA pins alternate functions
PORT pin
Alternate function
PB7
OC0A/OC1C/PCINT7 (output compare and PWM output A for Timer/Counter0, output compare
and PWM output C for Timer/Counter 1 or pin change interrupt 7)
PB6
OC1B/PCINT6 (output compare and PWM output B for Timer/Counter1 or pin change interrupt 6)
PB5
OC1A/PCINT5 (output compare and PWM output A for Timer/Counter1 or pin change interrupt 5)
PB4
OC2A/PCINT4 (output compare and PWM output A for Timer/Counter2 or pin change interrupt 4
PB3
MISO/PCINT3 (SPI bus master input/slave output or pin change interrupt 3)
PB2
MOSI/PCINT2 (SPI bus master output/slave input or pin change interrupt 2)
PB1
SCK/PCINT1 (SPI bus serial clock or pin change interrupt 1)
PB0
SS/PCINT0 (SPI slave select input or pin change interrupt 0)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.5
■
PORTB pins alternate functions
PORT pin
Alternate function
PC7
A15 (External memory interface address bit 15)
PC6
A14 (External memory interface address bit 14)
PC5
A13 (External memory interface address bit 13)
PC4
A12 (External memory interface address bit 12)
PC3
A11 (External memory interface address bit 11)
PC2
A10 (External memory interface address bit 10)
PC1
A9 (External memory interface address bit 9)
PC0
A8 (External memory interface address bit 8)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.6
■
PORTC pins alternate functions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.5
■
Overview of the AVR Mega Parallel PORTs
PORT pin
231
Alternate function
PD7
T0 (Timer/Counter0 clock input)
PD6
T1 (Timer/Counter1 clock input)
PD5
XCK1 (USART1 external clock input/output)
PD4
ICP1 (Timer/Counter1 input capture trigger)
PD3
INT3/TXD1 (External interrupt 3 input or USART1 transmit pin)
PD2
INT2/RXD1 (External interrupt 2 input or USART1 receive pin)
PD1
INT1/SDA (External interrupt 1 input or TWI serial data)
PD0
INT0/SCL (External interrupt 0 input or TWI serial clock)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.7
■
PORTD pins alternate functions
PORT pin
Alternate function
PE7
INT7/ICP3/CLKO (External interrupt 7 input, Timer/Counter3 input capture trigger or divided
system clock
PE6
INT6/T3 (External interrupt 6 input or Timer/Counter3 clock input)
PE5
INT5/OC3C (External interrupt 5 input or output compare and PWM output C for Timer/Counter3)
PE4
INT4/OC3B (External interrupt 4 input or output compare and PWM output B for Timer/Counter3)
PE3
AIN1/OC3A (Analog comparator negative input 1 or output compare and PWM output A for
Timer/Counter3)
PE2
AIN0/XCK0 (Analog comparator positive input 0 or USART0 external clock)
PE1
PDO/TXD0 (Programming data output or USART0 transmit pin)
PE0
PDI/RXD0/PCINT8 (Programming data input, USART0 receive pin or pin change interrupt 8)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.8
■
PORTE pins alternate functions
PORT pin
Alternate function
PF7
ADC7/TDI (ADC input channel 7 or JTAG test data input)
PF6
ADC6/TDO (ADC input channel 6 or JTAG test data output)
PF5
ADC5/TMS (ADC input channel 5 or JTAG test mode select)
PF4
ADC4/TCK (ADC input channel 4 or JTAG test clock)
PF3
ADC3 (ADC input channel 3)
PF2
ADC2 (ADC input channel 2)
PF1
ADC1 (ADC input channel 1)
PF0
ADC0 (ADC input channel 0)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.9
■
PORTF pins alternate functions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
232
Chapter 8
■
Parallel I/O
PORT pin
Alternate function
PG5
OC0B (output compare and PWM output B for
Timer/Counter0)
PG4
TOSC1 (RTC oscillator Timer/Counter 2)
PG3
TOSC2 (RTC oscillator Timer/Counter 2)
PG2
ALE (Address latch enable to external memory)
PG1
RD (Read strobe to external memory)
PG0
WR (Write strobe to external memory)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.10
■
PORTG pins alternate functions
PORT pin
Alternate function
PH7
T4 (Timer/Counter4 clock input)
PH6
OC2B (Output compare and PWM output B for
Timer/Counter2)
PH5
OC4C (Output compare and PWM output C for
Timer/Counter4)
PH4
OC4B (Output compare and PWM output B for
Timer/Counter4)
PH3
OC4A (Output compare and PWM output A for
Timer/Counter4)
PH2
XCK2 (USART2 external clock)
PH1
TXD2 (USART2 transmit pin)
PH0
RXD2 (USART2 receive pin)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.11
PORT pin
■
PORTH pins alternate functions
Alternate function
PJ7
--
PJ6
PCINT15 (Pin change interrupt 15)
PJ5
PCINT14 (Pin change interrupt 14)
PJ4
PCINT13 (Pin change interrupt 13)
PJ3
PCINT12 (Pin change interrupt 12)
PJ2
XCK3/PCINT11 (USART3 external clock or pin change
interrupt 11)
PJ1
TXD3/PCINT10 (USART3 transmit pin or pin change
interrupt 10)
PJ0
RXD3/PCINT9 (USART3 receive pin or pin change
interrupt 9)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.12
■
PORTJ pins alternate functions
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.6
■
233
Overview of AVR XMega Parallel PORTs
PORT pin
Alternate function
PK7
ADC15/PCINT23 (ADC input channel 15 or pin change interrupt 23)
PK6
ADC14/PCINT22 (ADC input channel 14 or pin change interrupt 22)
PK5
ADC13/PCINT21 (ADC input channel 13 or pin change interrupt 21)
PK4
ADC12/PCINT20 (ADC input channel 12 or pin change interrupt 20)
PK3
ADC11/PCINT19 (ADC input channel 11 or pin change interrupt 19)
PK2
ADC10/PCINT18 (ADC input channel 10 or pin change interrupt 18)
PK1
ADC9/PCINT17 (ADC input channel 9 or pin change interrupt 17)
PK0
ADC8/PCINT16 (ADC input channel 8 or pin change interrupt 16)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.13
■
PORTK pins alternate functions
PORT pin
Alternate function
PL7
--
PL6
--
PL5
OC5C (Output compare and PWM output C for Timer/Counter5)
PL4
OC5B (Output compare and PWM output B for Timer/Counter5)
PL3
OC5A (Output compare and PWM output A for Timer/Counter5)
PL2
T5 (Timer/Counter5 clock input)
PL1
ICP5 (Timer/Counter5 input capture trigger)
PL0
ICP4 (Timer/Counter4 input capture trigger)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.14
■
PORTL pins alternate functions
8.6 Overview of AVR XMega Parallel PORTs
An XMega MCU may have up to 14 parallel PORTs (A, B, C, D, E, F, H, J, K, L, M, N, P, Q,
and R). Most PORTs have eight pins. A few of them have less than 8 pins. Each pin can be configured as input or output with highly configurable driver and pull settings. The register naming
of XMega AVR in C has been discussed in Section 6.10. Each PORT also implements several
functions including interrupts, synchronous/asynchronous input sensing, and asynchronous
wake-up signaling, which are discussed in Chapter 9.
The output driver and pull setting of each pin can be configured to one of the following:
•
•
•
•
•
•
•
Totem pole
Totem pole with pull-up
Totem pole with pull-down
Wired-OR
Wired-AND
Bus keeper
Inverted I/O
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
234
Chapter 8
■
Parallel I/O
Like the AVR Mega, each I/O PORT of the AVR XMega has one data direction register
(DIR), one data output register (OUT), and one data input (IN) register. In addition, each pin has
a pin configuration (PINnCTRL) register for additional pin configuration. The contents of the
PINnCTRL register are shown in Figure 8.12.
7
6
SRLEN
INVEN
5
R/W
R/W
4
3
2
OPC[2:0]
R/W
R/W
1
0
Reset value
= 0x00
ISC[2:0]
R/W
R/W
R/W
R/W
SRLEN: Slew rate limit enable
0 = Disable slew rate limit
1 = Enable slew rate limit on pin n
INVEN: Inverted I/O enable
0 = Disable inverting output and input on pin n
1 = Enable inverting output and input on pin n
OPC[2:0]
Group configuration
Output configuration
Pull configuration
000
001
010
011
100
101
110
111
TOTEM
BUSKEEPER
PULLDOWN
PULLUP
WIREDOR
WIREDAND
WIREDORPULL
WIREDANDPULL
Totem pole
Totem pole
Totem pole
Totem pole
Wired OR
Wire AND
Wired OR
Wired AND
(N/A)
Bus keeper
Pull-down (on input)
Pull-up (on input)
(N/A)
(N/A)
Pull-down
Pull-up
ISC[2:0]: Input sense configuration
ISC[2:0]
Group configuration
Description
000
001
010
011
100
101
110
111
BOTHEDGES
RISING
FALLING
LEVEL
Sense both edges
Sense rising edge
Sense falling edge
Sense low level
Reserved
Reserved
Reserved
Input buffer disabled
Figure 8.12
INPUT_DISABLE
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
OPC[2:0]: Output and pull configuration
Pin n configuration register (PORTx.PINnCTRL)
8.6.1 Setting the Direction of PORT Pins
The direction of XMega AVR PORT pins is controlled through the DIR register. A PORT
pin n is configured for output if the DIRn bit in the DIR register is 1. If the DIRn bit is 0, the
PORT pin is configured for input.
For example, the following instruction configures the upper four pins of PORTD for output
and the lower four pins for input:
ldi
sts
r16,0xF0
PORTD_DIR,r16
The following C statement performs the same configuration:
PORTD.DIR
5 0xF0;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.6
■
Overview of AVR XMega Parallel PORTs
235
The DIR register can be accessed directly, or manipulated through the strobe registers
DIRSET, DIRCLR, and DIRTGL. Writing a bit mask (with certain bit positions set to 1) to the
DIRSET register causes that bit mask to be set in the DIR register. Writing a bit mask to
the DIRCLR register causes that bit mask to be cleared in the DIR register. Writing a bit mask
to the DIRTGL register causes the bits in the mask to be toggled in the DIR register.
For example, the following sequence of instructions causes the odd bits of the DIR register
to be set to 1 and hence configures the odd pins of PORTD for output:
ldi
sts
r16,0xAA
PORTD_DIRSET,r16
The sequence of instructions
ldi
sts
r16,0x59
PORTD_DIRCLR,r16
causes bits 6, 4, 3, and 0 of the DIR register of PORTD to be cleared to 0 and hence configures
the pin 6, 4, 3, and 0 of PORTD for input.
The sequence of instructions
ldi
sts
r16,0x39
PORTD_DIRTGL,r16
causes bits 5, 4, 3, and 0 of the DIR register of PORTD to be toggled (from input to output and
vice versa) and hence change the direction of these four pins.
8.6.2 Controlling the Output Value of PORT Pins
The output value of a PORT pin is controlled through the OUT register. The direction of
the PORT pin must be set to output for the corresponding OUT register bit to have any effect.
The OUT register can either be accessed directly, or manipulated through the strobe registers
OUTSET, OUTCLR, and OUTTGL. Writing a bit mask to the OUTSET register causes that
bit mask to be set in the OUT register. Writing a bit mask to the OUTCLR register causes the
bits in the mask to be cleared in the OUT register. Writing a bit mask to the OUTTGL register
causes the bits in the mask to be toggled in the OUT register.
8.6.3 Reading the Logic State of PORT Pins
The logic state of a PORT pin can be obtained by reading the IN register. The current
logic state of the PORT pin n can be read through the INn bit, regardless of the setting of the
direction bit.
8.6.4 Pin Configuration
Each I/O pin has its own configuration register named PINnCTRL (shown in Figure 8.12),
where n signifies the pin number. Through these registers, a number of parameters can be configured on a pin-by-pin basis. These parameters are explained in the following paragraphs:
O U T P U T / P U L L C O N F I G U R AT I O N
The output/pull configuration bits are used to configure the output driver behavior and the
pull configuration. Table 8.15 shows a parametric overview of the possible configurations.
In the Totem pole configuration of Table 8.15, the output is driven to VCC or GND as
commanded by the corresponding bit in the OUT register. In the Wired-OR configuration, writing a 1 to the OUTn bit causes the pin n to be driven to VCC. Writing a 0 to the OUTn bit releases
the pin, allowing the pin to be pulled to GND with an internal or external pull-down resistor.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
236
Chapter 8
■
Parallel I/O
Symbol
Output configuration
PORT_OPC_TOTEM_gc
Pull configuration
Totem pole
(N/A)
PORT_OPC_BUSKEEPER_gc
Totem pole
Bus keeper on input and output
PORT_OPC_PULLDOWN_gc
Totem pole
Pull-down on input
PORT_OPC_PULLUP_gc
Totem pole
Pull-up on input
PORT_OPC_WIREDOR_gc
Wired_OR
(N/A)
PORT_OPC_WIREDAND_gc
Wired_AND
(N/A)
PORT_OPC_WIREDORPULL_gc
Wired_OR
Pull-down
PORT_OPC_WIREDANDPULL_gc
Wired_AND
Pull-up
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.15
■
XMega I/O pin output/pull configuration
In the Wired-AND configuration, writing a 0 to the OUTn bit causes the pin n to be driven to
GND. Writing a 1 to the OUTn bit releases the pin, allowing the pin to be pulled to VCC with an
internal or external pull-up resistor.
The bus keeper on input and output configuration of Table 8.15 provides a weak bus keeper
that keeps the pin at the same logic level when the pin is not driven to any logic state. The
pull-down configuration enables the internal pull-down resistor for the pin. The pull-up configuration enables the internal pull-up resistor for the pin.
I N P U T / S E N S E C O N F I G U R AT I O N
The input/sense configuration bit controls the input sensing and digital input buffer of the
I/O pin. The possible input/sense configurations are listed in Table 8.16. Four sense configurations are available, and they affect how interrupts and events are generated from the pin. A pin can
sense the rising edge, the falling edge, either edges, or the low level. Note that sensing on the high
level can be achieved by setting the “Inverted I/O” bit in the PINnCTRL register. If the pin is used
to generate events and the sense setting is set to low level, the pin is transparent to the event system, meaning that the level on the pin is directly connected to the event line. Setting the input/
sense field to Digital input buffer disabled disables the digital input buffer on the pin. This can be
used to reduce power consumption when the pin is unused, or used only for analog functions. The
corresponding bit in the IN register always reads “0” when the digital input buffer is disabled.
Symbol
Configuration
PORT_ISC_BOTHEDGES_gc
Sense both edges
PORT_ISC_RISING_gc
Sense rising edge
PORT_ISC_FALLING_gc
Sense falling edge
PORT_ISC_LEVEL_gc
Sense low level (transparent for events)
PORT_ISC_INPUT_DISABLE_gc
Digital input buffer disabled
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.16
■
XMega I/O pin input/sense configuration
INVERSION
The “Inverted I/O” bit in the PINnCTRL registers controls the polarity of the pin. If this bit is
written to 0, all input and output logic is not inverted. Setting the “Inverted I/O” bit for a pin inverts
the input/output signal for any peripheral module overriding the pin. As an example, it is possible
to invert a PWM output signal from a timer/counter module simply by setting the “Inverted I/O”
bit. This can be useful for easy switching between active high and active low driving.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.6
■
Overview of AVR XMega Parallel PORTs
237
S L E W R AT E
The slew rate determines how fast a signal can rise toward the maximum and fall to the
minimum level. Slew rate control can be enabled for all I/O pins individually. Enabling the slew
rate limiter typically increases the rise/fall time by 50–150%, depending on voltage, temperature, and load.
8.6.5 Multipin Configuration
Configuring I/O pins via the PINnCTRL register would be inefficient because this register only
configures one pin at a time. To increase efficiency, the AVR XMega allows the user to configure all I/O pins of the same PORT that require the same configuration at once, using a process
called multipin configuration process. This process consists of the following steps:
Step 1
Write a bit pattern matching the pins to be configured to the MPCMASK register in the
PORTCFG module.
Step 2
Write the value of configuration to one of the PINnCTRL registers of that PORT. The
PINnCTRL register to be written into need not be any one targeted by the MPCMASK register.
When a pin configuration is written to one of the PINnCTRL registers of that PORT,
that value is written to all the PINnCTRL registers of the pins matching the bit pattern in
the MPCMASK register. It is not necessary to write to one of the registers that are targeted
by the PINMASK register. If the bit mask in PINMASK does not target the register that
is written to, the register remains unchanged. Note that it is important that the multipin
configuration not be interrupted by a task that writes to a PINnCTRL register. If the
MPCMASK register is already written, an interrupt is executed, and the interrupt service
routine (ISR) writes to any PINnCTRL register, pins belonging to a different I/O PORT
than intended are configured. The recommended solution is to store and then disable the
global interrupt flag before doing a multipin configuration and restore the global interrupt
flag after the configuration has been written.
Example 8.3
▼
Write an instruction sequence to configure pins 0~3 on PORTC for Wired-OR with pulldown operation, and sense the rising edge.
Solution:
ldi
sts
ldi
sts
r16,0x0F
PORTCFG_MPCMASK,r16
r16,0x31
PORTC_PIN0CTRL,r16
; configure pins 0~3 simultaneously
; "
; configure output to Wired-OR, input sense the rising edge
; "
The same configuration is achieved by the following C statements:
PORTCFG.MPCMASK 5 0x0F;
PORTC.PIN0CTRL 5 0x31;
// apply the same configuration to pins 0~3
// output Wired-OR with pull down
▲
8.6.6 Virtual PORTs
The I/O instructions in the AVR instruction set can only operate on addresses that are
within the AVR I/O space. Using these instructions instead of their data space equivalents is
both faster and consumes less program memory. All I/O PORT registers on the XMega have
addresses outside the I/O space.
The solution to this is to use the virtual PORTs. Up to four of the I/O PORTs can be mapped
into virtual PORTs that have registers in the I/O space. The virtual PORTs make the DIR, OUT,
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
238
Chapter 8
■
Parallel I/O
IN, and INTFLAGS registers of the desired I/O PORT available in the I/O space. The other less used
I/O PORT registers are still available through the regular PORT module registers. The module
names for virtual PORTs are VPORT0, VPORT1, VPORT2, and VPORT3, respectively.
Registers VPCTRLA and VPCTRLB are used to map I/O PORTs to virtual PORTs. The contents of these two registers are shown in Figure 8.13 and Figure 8.14. These two registers belong
to the PORTCFG module.
7
6
5
4
3
VP1MAP[3:0]
R/W
R/W
2
1
0
Reset value
= 0x00
VP0MAP[3:0]
R/W
R/W
R/W
R/W
R/W
R/W
Note: VP1MAP[3:0] and VP0MAP[3:0] mapping are shown in Table 8.17.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 8.13
7
■
Virtual PORT-map control register A (VPCTRLA)
6
5
4
3
VP3MAP[3:0]
R/W
R/W
2
1
0
Reset value
= 0x00
VP2MAP[3:0]
R/W
R/W
R/W
R/W
R/W
R/W
Note: VP3MAP[3:0] and VP2MAP[3:0] mapping are shown in Table 8.17.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 8.14
■
Virtual PORT-map control register B (VPCTRLB)
VPnMAP[3:0]
Group configuration
Description
0000
PORTA
PORTA mapped to virtual PORTN
0001
PORTB
PORTB mapped to virtual PORTN
0010
PORTC
PORTC mapped to virtual PORTN
0011
PORTD
PORTD mapped to virtual PORTN
0100
PORTE
PORTE mapped to virtual PORTN
0101
PORTF
PORTF mapped to virtual PORTN
0110
PORTG
PORTG mapped to virtual PORTN
0111
PORTH
PORTH mapped to virtual PORTN
1000
PORTJ
PORTJ mapped to virtual PORTN
1001
PORTK
PORTK mapped to virtual PORTN
1010
PORTL
PORTL mapped to virtual PORTN
1011
PORTM
PORTM mapped to virtual PORTN
1100
PORTN
PORTN mapped to virtual PORTN
1101
PORTP
PORTP mapped to virtual PORTN
1110
PORTQ
PORTQ mapped to virtual PORTN
1111
PORTR
PORTR mapped to virtual PORTN
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.17
■
Virtual PORT mapping
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.7
■
239
Simple I/O Devices
Example 8.4
▼
Write a program to map PORTC to virtual PORT0, and PORTD to virtual PORT1; configure VPORT0 for input and VPORT1 for output; read data from VPORT0; and output it
to VPORT1.
Solution: The following instruction sequence performs the specified operation:
ldi
sts
ldi
out
ldi
out
in
out
r16,0x32
PORTCFG_VPCTRLA,r16
r16,0
VPORT0_DIR,r16
r16,0xFF
VPORT1_DIR,r16
r16,VPORT0_IN
VPORT1_OUT,r16
; map PORTC and D to VPORT0 and VPORT1, respectively
; "
; configure VPORT0 for input
; "
; configure VPORT1 for output
; "
; read from VPORT0
; output it to VPORT1
The following sequence of C statements performs the same operation:
PORTCFG.VPCTRLA5 0x32;
VPORT0.DIR
5 0;
VPORT1.DIR
5 0xFF;
VPORT1.OUT
5 VPORT0.IN;
// map PORTC and D to VPORT0 and VPORT1
// configure VPORT0 for input
// configure VPORT1 for output
// read from VPORT0 and output to VPORT1
▲
8.6.7 Alternate PORT Functions of XMega
Most PORT pins have alternate pin functions in addition to being a general-purpose I/O
pin. When an alternate function is enabled, it might override the normal PORT pin function or
pin value. This happens when other peripherals that require pins are enabled or configured to
use pins. A summary of alternate PORT functions for the XMega64A1/128A1/192A1/256A1/38
4A1 is given in Appendix E.
8.7 Simple I/O Devices
Many embedded systems only require simple input/output devices such as switches, lightemitting diodes, keypads, and seven-segment displays, to interface with the user.
8.7.1 Interfacing with LEDs
The LED is often used to indicate the system operation mode—whether power is turned
on, whether system operation is normal, and so on. An LED can illuminate when it is forward
biased and has sufficient current flowing through it. The current required to light an LED may
range from a few to more than 10 mA. The forward voltage drop across the LED can range from
about 1.6 V to more than 2.2 V.
Figure 8.15 suggests three methods for interfacing with LEDs. Methods (a) and (b) are recommended for use with LEDs that need only 1 or 2 mA to produce enough brightness. The
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
240
Chapter 8
■
Parallel I/O
VDD
VDD
PORT
pin
R1
R2
PORT
pin
(a) Positive direct drive
Figure 8.15
■
R3
PORT
pin
(b) Inverse direct drive
(c) Buffered drive
Source: Atmel Corporation, The Atmel AVR
Microcontroller
circuit (c) is recommended for use with LEDs that need larger current to light. Resistors R1, R2,
and R3 are referred to as current-limiting resistors because they set the magnitude of the current flowing through the LED.
Circuit for driving an LED
Example 8.5
▼
Use the AVR Mega PORTK to drive eight LEDs and output the value 0x58 to PORTK. Show
the circuit connection and give an instruction sequence to perform the desired operation.
Solution: The circuit shown in Figure 8.16 can be used to drive eight LEDs.
ldi
out
ldi
sts
r16,0xFF
DDRK,r16
r16,0x58
PORTK,r16
; configure PORTK for output
; "
; output the value 0x58 to LEDs
; "
The following C statements perform the same operation:
DDRK 5 0xFF;
PORTK 5 0x58;
// use PORTK.DIR instead of DDRK for XMega
// use PORTK.OUT instead of PORTK for XMega
Mega2560
1kΩ
Source: Atmel Corporation, The Atmel AVR Microcontroller
PK7
PK6
PK5
PK4
PK3
PK2
PK1
PK0
Figure 8.16
■
Circuit connection for Example 8.5
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.7
■
241
Simple I/O Devices
Example 8.6
▼
Replace the Mega2560 MCU in Figure 8.16 with the XMega128A1, and also change PORTK
to PORTC. Write an assembly program to turn on one LED at a time for 100 ms from top to bottom and then from bottom to top. Repeat this pattern forever.
Solution: The values to turn on one LED at a time from top-to-bottom and then from bottomto-top should be placed in an array (ledArr). Let ptr and j be the pointer to the LED pattern array
and the loop index, respectively. The algorithm of this program is as follows:
Step 1
j ← 0; ptr ← ledArr;
Step 2
Read the value pointed to by ptr and output it to PORTK.
Step 3
Increment j and move ptr.
Step 4
Wait for 100 ms.
Step 5
If (j 5 5 array count)
Goto Step 1
Else
Goto Step 2
The assembly program that implements this algorithm is as follows:
start:
again:
loop:
.include ,ATXMega128A1def.inc.
.equ
NN
5 16
.def
j
5 r17
.def
temp
5 r18
.cseg
.org
0x00
rjmp
start
.org
0xF6
ldi
r16,low(RAMEND)
sts
CPU_SPL,r16
ldi
r16,high(RAMEND)
sts
CPU_SPH,r16
call
setCPUclkto32Mwith16MCrystal
ldi
temp,0xFF
sts
PORTC_DIR,temp
ldi
ZL,low(ledArr,,1)
ldi
ZH,high(ledArr,,1)
ldi
j,0
lpm
temp,z1
sts
PORTC_OUT,temp
ldi
r16,2
rcall
delayby100ms
inc
j
cpi
j,NN
brne
loop
rjmp
again
.include “sysClock_XMega.asm”
; array count
; loop index
; temporary storage
; set up stack pointer
; "
; "
; "
; set up system clock
; configure PORTC for output
; "
; set up pointer to LED pattern array
; "
; read one LED pattern
; output to LED
; wait for 200 ms
; "
; test end of LED pattern array
; "
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
242
Chapter 8
■
Parallel I/O
delayby100ms:
push
loop2:
ldi
loop1:
ldi
loop0:
ldi
loopi:
push
pop
dec
brne
dec
brne
dec
brne
dec
brne
pop
ret
ledArr:
.db
.db
r28
r28,200
r21,250
r20,4
r0
r0
r20
loopi
r21
loop0
r28
loop1
r16
loop2
r28
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
The C language version of the program is as follows:
#include ,avr/io.h.
#include “delays_XMega.h”
// include delays_XMega.c to this project
#include “sysClock_XMega.h”
// include sysClock_XMega.c to this project
#define NN
16
char ledArr[NN] 5 {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int main(void)
{
int j;
PORTC.DIR 5 0xFF; // configure PORTC for output
setCPUclkto32Mwith16MCrystal(); // set CPU clock to 32 MHz
while(1) {
for(j 5 0; j , NN; j11){
PORTC.OUT 5 ledArr[j]; // output the LED pattern
delayby100ms(1);
}
}
}
▲
8.7.2 Interfacing with Seven-Segment Displays
Seven-segment displays are often used when the embedded system product needs to display
only a few digits. Seven-segment displays are mainly used to display decimal digits and a small
subset of letters.
Although an AVR MCU has enough current to drive a seven-segment display, it is not
advisable to do so when an AVR-based embedded product needs to drive many other I/O
devices. In Figure 8.17, PORTK drives a common-cathode seven-segment display through the
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.7
■
243
Simple I/O Devices
buffer chip SN74LV244 from TI. The SN74LV244 can operate with a power supply ranging
from 2 V to 5.5 V. Assume that both the Mega2560 and the SN74LV244 use a 5 V power
supply. Both the Mega2560 and the SN74LV244 are implemented in CMOS technology and
hence are compatible in voltage levels. The high output voltage of the SN74LV244 is 5 V. The
segment current is 3.2 mA (5 (5 – 1.8)V/1 kV), assuming that the voltage drop of the sevensegment display is 1.8 V.
Mega2560
1 kΩ
g
b
c
d
Common cathode
Figure 8.17
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
a
a
b f
c
d
e e
f
g
SN74LV244
PK6
PK5
PK4
PK3
PK2
PK1
PK0
Driving a single seven-segment display
To display decimal digits 0 to 9, appropriate values must be sent to PORTK in Figure 8.17.
The light patterns corresponding to 10 decimal digits are shown in Table 8.18. The numbers in
Table 8.18 require that segments a~g be connected from the second most significant pin (PK6)
to the least significant pin (PK0) of PORTK. The SN74LV244 can source and sink up to 35 mA
continuously. The maximum current that needs to be sourced and sunk by the SN74LV244 is
22.4 mA (5 7 * 3.2 mA) and hence is within its capacity.
Segments
Decimal
digit
a
b
c
d
e
f
g
Corresponding
hex number
0
1
1
1
1
1
1
0
0x7E
1
0
1
1
0
0
0
0
0x30
2
1
1
0
1
1
0
1
0x6D
3
1
1
1
1
0
0
1
0x79
4
0
1
1
0
0
1
1
0x33
5
1
0
1
1
0
1
1
0x5B
6
1
0
1
1
1
1
1
0x5F
7
1
1
1
0
0
0
0
0x70
8
1
1
1
1
1
1
1
0x7F
9
1
1
1
1
0
1
1
0x7B
Note: Segments a through g are connected to the second most significant through
least significant I/O pins.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8.18
■
Decimal to seven-segment decoder
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
244
Chapter 8
■
Parallel I/O
When an application is required to display multiple decimal digits, the time-multiplexing
technique is often used. An example of the circuit that displays six decimal digits (for the
XMega128A1) is shown in Figure 8.18. PORTA outputs the segment pattern, whereas PORTB
outputs the digit select signals. Whenever a PORTB pin is driven low, the driven display is
lighted because its common cathode pin has been driven low.
In the time-multiplexing technique, each display is lighted in turn briefly (for example, 1
ms) and then turned off. When one display is lighted, all other displays are turned off. Within 1
second, each seven-segment display is lighted and then turned off many times. Because of the
persistence of vision, the six displays appear to be lighted simultaneously.
PA5
PA0
g
SN74LV244A
VDD
XMega128A1
Figure 8.18
■
PB5
1A1
1Y1
PB4
1A2
1Y2
PB3
1A3
1Y3
PB2
1A4
1Y4
PB1
2A1
2Y1
PB0
2A2
2Y2
OE1
OE2
3.3 V
. . .
g
Common
cathode
Common
cathode
Common
cathode
Imax = 24.4 mA
PA6
. . .
. . .
.
.
. g
a
b
Imax = 24.4 mA
SN74LV244
a
b
Imax = 24.4 mA
.
.
430 Ω .
#0
#4
a
b
.
.
.
Source: Atmel Corporation, The Atmel AVR Microcontroller
#5
430 Ω
PORTA and PORTB together drive six seven-segment displays (XMega128A1)
To implement the time-multiplexing technique, we need a delay subroutine (or function).
A delay subroutine (or function) can be implemented by program loops (Chapter 3) or timer
function (Chapters 11 and 12).
Example 8.7
▼
Write a program to display 123456 on the six 7-segment displays shown in Figure 8.18
assuming that the XMega device has a 32 MHz CPU clock.
Solution: The digits 1, 2, 3, 4, 5, and 6 are displayed on seven-segment displays #5, #4, …, and
#0, respectively. The values to be output to PORTA_OUT and PORTB_OUT to display one digit
at a time are shown in Table 8.19.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.7
■
245
Simple I/O Devices
Seven-segment
display
Displayed
BCD digit
PORTA_OUT
PORTB_OUT
#5
1
0x30
0xDF
#4
2
0x6D
0xEF
#3
3
0x79
0xF7
#2
4
0x33
0xFB
#1
5
0x5B
0xFD
#0
6
0x5F
0xFE
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Table 8.19
Table of display patterns for Example 7.7
This table can be created by the following assembler directives:
disTab:
db
db
0x30,0xDF,0x6D,0xEF,0x79,0xF7
0x33,0xFB,0x5B,0xFD,0x5F,0xFE
The program logic of this example is shown in Figure 8.19.
Start
PORTA_OUT ← *ptr
PORTB_OUT ← *(ptr+1)
ptr ← ptr + 2
Wait for 1 ms
No
Reach the end
of table?
Yes
Figure 8.19
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Ptr ← Address of display table
Time-multiplexing seven-segment display algorithm
The program that implements this algorithm is as follows:
.include ,ATXMega128A1def.inc.
.def
temp 5 r16
.equ
NN 5 12
.def
j 5 r17
.cseg
.org
0x00
rjmp
start
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
246
Chapter 8
start:
again:
loop:
disTab:
■
Parallel I/O
.org
0xF6
ldi
temp,low(RAMEND)
; temp is r16
out
CPU_SPL,temp
; initialize the SP (use SPL for Mega devices)
ldi
temp,high(RAMEND)
; "
out
CPU_SPH,temp
; (use SPH for Mega devices)
call
setCPUclkto32Mwith16MCrystal
ldi
temp,0xFF
sts
PORTA_DIR,temp
; configure PORTA for output
sts
PORTB_DIR,temp
; configure PORTB for output
ldi
ZL,low(disTab ,, 1)
; set up pointer to seven-segment display pattern array
ldi
ZH,high(disTab ,, 1)
; "
ldi
j,0
; initialize loop index
lpm
temp,z1
; read segment pattern
sts
PORTA_OUT,temp
; output segment pattern
lpm
temp,z1
; read digit select value
sts
PORTB_OUT,temp
; output digit select value
ldi
r16,1
; wait for 1 ms
rcall
delayby1ms
; "
inc
j
inc
j
cpi
j,NN
; reach the end of the segment pattern array?
brne
loop
rjmp
again
.include “delays_XMega.asm”
.include “sysClock_XMega.asm”
ret
.db
0x30,0xDF,0x6D,0xEF,0x79,0xF7
.db
0x33,0xFB,0x5B,0xFD,0x5F,0xFE
The C language version of the program is as follows:
#include ,avr\io.h.
#include “sysClock_XMega.h”
// include sysClock_XMega.c into the project
#include “delays_XMega.h”
// include delays_XMega.c into the project
char dispTab[6][2] 5 {{0x30,0xDF},{0x6D,0xEF},{0x79,0xF7},
{0x33,0xFB},{0x5B,0xFD},{0x5F,0xFE}};
void main (void)
{
unsigned char j;
setCPUclkto32Mwith16MCrystal();
PORTA.DIR 5 0xFF;
// configure PORTA for output
PORTB.DIR 5 0xFF;
// configure PORTB for output
while(1) {
for(j 5 0; j , 6; j11){
PORTA.OUT 5 dispTab[j][0]; // output segment pattern
PORTB.OUT 5 dispTab[j][1]; // output digit select
delayby1ms(1); // wait for 1 ms
}
}
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.7
■
247
Simple I/O Devices
8.7.3 Generating a Digital Waveform Using an I/O Pin
A periodic digital waveform can be generated by manipulating I/O voltage level and inserting an appropriate delay (equal to half of the waveform period) between the two voltage levels.
For example, a 500 Hz periodic square wave can be generated from the PH7 pin, using the following algorithm:
Step 1
Configure the PH7 pin for output.
Step 2
Pull the PH7 pin to high.
Step 3
Wait for 1 ms.
Step 4
Pull the PH7 pin to low.
Step 5
Wait for 1 ms.
Step 6
Go to Step 2.
Example 8.8
▼
Write a program to generate a 500 Hz periodic square waveform from the PH7 pin of the
XMega device assuming that the XMega device has a 32 MHz CPU clock.
Solution: The following instruction sequence implements the algorithm described previously:
start:
forever:
.include
.def
.cseg
.org
rjmp
.org
ldi
out
ldi
out
call
lds
ori
sts
lds
ori
sts
ldi
call
lds
andi
sts
,ATXMega128A1def.inc.
temp 5 r16
0x00
start
0xF6
temp,low(RAMEND)
CPU_SPL,temp
temp,high(RAMEND)
CPU_SPH,temp
setCPUclkto32Mwith16Mcrystal
temp,PORTH_DIR
temp,0x80
PORTH_DIR,temp
temp,PORTH_OUT
temp,0x80
PORTH_OUT,temp
r16,1
delayby1ms
temp,PORTH_OUT
temp,0x7F
PORTH_OUT,temp
; initialize the SP
; (use SPL for Mega devices)
; "
; (use SPH for Mega devices)
; not needed for Mega devices
; configure PH7 for output
; "
; "
; get the PORTH data register
; set pin 7 to high
; "
; wait for 1 ms
; "
; pull the PH7 pin low
; "
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
248
Chapter 8
■
Parallel I/O
ldi
r16,1
call
delayby1ms
rjmp
forever
.include “sysClock_XMega.asm”
.include “delays_XMega.asm”
; wait for 1 ms
; "
The C language version of the program is as follows:
#include ,avr\io.h.
#include “delays_XMega.h”
// include delays_XMega.c to the project
#include “sysClock_XMega.h”
// include sysClock_XMega.c to the project
void main (void)
{
setCPUclkto32Mwith16MCrystal();
PORTH.DIR |5 0x80; // configure PH7 pin for output
while(1){
PORTH.OUT |5 0x80;
// pull PH7 pin high
delayby1ms(1);
// wait for 1 ms
PORTH.OUT &5 0x7F;
// pull PH7 pin low
delayby1ms(1);
// wait for 1 ms
}
}
▲
8.7.4 Making a Sound using an I/O Pin
By connecting the PH7 pin in Example 8.8 to a speaker (or a buzzer) and making the frequency
in the audible range, a sound can be made. Because the frequency of the square wave generated in
Example 8.8 is in the audible range, a sound can be heard if a speaker is connected to the PH7 pin.
By alternating the frequency of the generated waveform from the I/O pin between two different values, a two-tone siren can be generated. The duration of the siren tone is variable. The
siren would sound more urgent if the tone duration is shorter. The following example generates
a two-tone siren that alternates between 250 Hz and 500 Hz, with each tone lasting for half of a
second. The period of a 250 Hz square wave is 4 ms. Therefore, we need to repeat this waveform
125 times in half a second. Similarly, the 500 Hz square wave needs to be repeated 250 times.
Example 8.9
▼
Write a program to generate a two-tone siren that alternates between 250 Hz and 500 Hz,
with each siren tone lasting for half of a second, using the PH7 pin driving a buzzer or speaker,
assuming that the CPU clock is 32 MHz.
Solution: The assembly program that generates the two-tone siren with the specified frequencies is as follows:
start:
.include ,ATXMega128A1def.inc.
.def
lpCnt 5 r17
.def
temp 5 r18
.cseg
.org
0x00
rjmp
start
.org
0xF6
ldi
temp,low(RAMEND)
; initialize the SP
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.7
■
Simple I/O Devices
ever:
f500Hz:
f250Hz:
249
out
CPU_SPL,temp
; (use SPL for Mega devices)
ldi
temp,high(RAMEND)
; "
out
CPU_SPH,temp
; (use SPH for Mega devices)
call
setCPUclkto32Mwith16MCrystal ; not needed for Mega devices
lds
temp,PORTH_DIR
; configure PH7 for output
ori
temp,0x80
; "
sts
PORTH_DIR,temp
; "
ldi
lpCnt,125
; repeat this tone for 0.5 s
lds
temp,PORTH_OUT
; create a tone of 250 Hz
ori
temp,0x80
; "
sts
PORTH_OUT,temp
; "
ldi
r16,2
; "
call
delayby1ms
; "
lds
temp,PORTH_OUT
; "
andi
temp,0x7F
; "
sts
PORTH_OUT,temp
; "
ldi
r16,2
; "
call
delayby1ms
; "
dec
lpCnt
brne
f500Hz
ldi
lpCnt,250
; repeat this tone for 0.5 s
lds
temp,PORTH_OUT
; creates a tone of 500 Hz
ori
temp,0x80
; "
sts
PORTH_OUT,temp
; "
ldi
r16,1
; "
call
delayby1ms
; "
lds
temp,PORTH_OUT
; "
andi
temp,0x7F
; "
sts
PORTH_OUT,temp
; "
ldi
r16,1
; "
call
delayby1ms
; "
dec
lpCnt
brne
f250Hz
rjmp
ever
.include “sysClock_XMega.asm”
.include “delays_XMega.asm”
The C language version of the program is as follows:
#include ,avr/io.h.
#include “delays_XMega.h”
// also include delays_XMega.c to the project
#include “sysClock_XMega.h”
// also include sysClock_XMega.c to the project
int main(void)
{
unsigned int k;
setCPUclkto32Mwith16MCrystal();
PORTH.DIR |5 0x80;
// configure PA7 pin for output
while(1) {
for(k 5 0; k , 125; k11){ // repeat for half of a second
PORTH.OUT
|5 0x80;
delayby1ms(2);
PORTH.OUT
&5 0x7F;
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
250
Chapter 8
■
Parallel I/O
delayby1ms(2);
}
for(k 5 0; k , 250; k11){ // repeat for half of a second
PORTH.OUT
|5 0x80;
delayby1ms(1);
PORTH.OUT
&5 0x7F;
delayby1ms(1);
}
}
}
▲
8.7.5 Interfacing with DIP Switches
A switch is probably the simplest input device we can find. To make input more efficient,
a set of eight switches organized as a dual inline package (DIP) is often used. A DIP package can
be connected to any input PORT with eight pins. An example of circuit connection for a DIP
package is shown in Figure 8.20.
VCC
PJ7
PJ6
PJ5
PJ4
PJ3
PJ2
PJ1
PJ0
Figure 8.20
■
XMega128A1
Source: Atmel Corporation, The Atmel AVR Microcontroller
10 kΩ
Connecting a DIP package to PORTJ of XMega128A1
Example 8.10
▼
Write a sequence of instructions to read the value from a DIP package connected to the
PORTJ of the XMega128A1 (or a Mega device), and leave it in register r0.
Solution: The instruction sequence to configure PORTJ for input and read its contents into r0 is
as follows:
ldi
sts
lds
r16,0x00
PORTJ_DIR,r16
r0,PORTJ_IN
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.8
■
251
Interfacing with a D/A Converter
8.8 Interfacing with a D/A Converter
A D/A converter converts a digital value into an analog voltage. A few important DAC
characteristics are listed here:
•
Resolution. The resolution of a DAC refers to the number of bits used to represent
a value to be converted. In general, the more bits the better. The resolution of a
commercial DAC may range from 8 bits to 24 bits.
•
Conversion Time. DAC conversion time is the amount of time required to
convert a digital value to an analog voltage or current. It is desirable to have short
conversion time for a DAC. The DAC conversion time has a wide range. It could be
as short as 10 ns or longer than 30 µs.
•
Number of channels. This parameter refers to the number of outputs that a DAC
chip has.
•
Input Format. A DAC may require data to be input in parallel format or serial
format (using the SPI or I2C interface). Parallel format is more suitable for highspeed DAC. Serial input format is more suitable for low pin count MCUs and those
applications that do not require very high throughput.
8.8.1 The AD7302 DAC
The AD7302 is a dual-channel, 8-bit, DAC chip from Analog Devices that has a parallel
interface with the microcontroller. The AD7302 converts an 8-bit digital value into an analog
voltage. The block diagram of the AD7302 is shown in Figure 8.21. To send data to the AD7302,
the CS signal must be pulled to low. On the rising edge of the WR or CS signal, the values on
pins D7 through D0 are latched into the input register. When the signal LDAC is low, the data
in the input register are transferred to the DAC register, and a new D/A conversion is started.
If the LDAC signal is tied low, then the data in the input register are transferred to the DAC
register on the rising edge of the WR signal.
Input
register
DAC
register
I DAC A
I/V
VOUTA
D7
D0
Input
register
DAC
register
I DAC B
I/V
VOUTB
A/B
WR
CS
Control
logic
÷2
PD
Figure 8.21
Power on
reset
MUX
■
CLR
LDAC
REFIN
VDD
DGND
AGND
Source: Atmel Corporation, The Atmel AVR Microcontroller
AD7302
Functional block diagram of the AD7302
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
252
Chapter 8
■
Parallel I/O
The AD7302 needs a reference voltage to perform D/A conversion. The reference voltage
can come from either the external REFIN input or the internal VDD. The A /B signal selects the
channel (A or B) to perform the D/A conversion. Channel A is selected when this signal is low.
Otherwise, Channel B is selected. When the PD pin is low, the AD7302 is placed in the powerdown mode and reduces the power consumption to 1 µW. Each digital sample takes about 1.2 µs
to convert.
The AD7302 operates from a single 2.7 to 5.5 V power supply and typically consumes
15 mW at 5 V, making it suitable for battery-powered applications. The output voltage (VOUTA
or VOUTB) from either DAC is given by
VOUT A/B 5 2 3 VREF 3 (N/255)
where,
VREF is derived internally from the voltage applied at the REFIN pin or VDD. If the
voltage applied to the REFIN pin is within 1 V of the VDD, VDD/2 is used as the
reference voltage automatically. Otherwise, the voltage applied at the REFIN pin is
used as the reference voltage. The range of VREF is from 1 V to VDD/2.
N is the decimal equivalent of the code loaded to the DAC register, ranging from 0 to 255.
8.8.2 Interfacing the AD7302 with the AVR Mega or XMega Devices
AD7302
Mega2560
PA7~PA0
D7..D0
3.3 V
VDD
REFIN
PB0
VDD
WR
PD
CLR
PB1
A/B
CS
LDAC
Figure 8.22
■
VOUTA
VOUTB
AGND
DGND
Source: Atmel Corporation, The Atmel AVR Microcontroller
The data to be sent to the AD7302 for conversion can be sent via a parallel PORT (connect to pins D7~D0). Both the CS and LDAC signals can be tied to ground permanently. An
output pin can be used (as the WR signal) to control the transferring of data to the input
register. An example of circuit connection between the Mega2560 and the AD7302 is shown
in Figure 8.22.
Circuit connection between the AD7302 and the Mega2560
Example 8.11
▼
Write a program to generate a sawtooth waveform from the VOUTA pin, assuming that the
Mega2560 is running with an 8 MHz crystal oscillator.
Solution: One way to generate a sawtooth waveform is to divide one period of the sawtooth
waveform into certain number of points (for example, 52 points). The program starts from
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.8
■
253
Interfacing with a D/A Converter
outputting 0 and then increments the output value by 5 in each following step until the value
255 is reached, and then repeats.
The assembly program that follows this algorithm to generate the sawtooth waveform is as
shown here:
start:
again:
loop:
.include
.def
.def
.def
.def
.cseg
.org
rjmp
.org
ldi
out
ldi
out
ldi
sts
sts
ldi
ldi
clr
clr
cbi
cbi
out
sbi
nop
nop
nop
add
inc
cp
brne
rjmp
,m2560def.inc.
temp 5 r16
j
5 r17
delta 5 r18
LpEnd 5 r19
0x00
start
0xF6
temp,low(RAMEND)
SPL,temp
temp,high(RAMEND)
SPH,temp
temp,0xFF
DDRA,temp
DDRB,temp
delta,5
LpEnd,52
j
temp
PORTB,1
PORTB,0
PORTA,temp
PORTB,0
temp,delta
j
j, LpEnd
loop
again
; loop index
; amount of increment
; Loop end value (5 52)
; initialize the SP
; (use CPU_SPL for XMega devices)
; "
; (use CPU_SPH for XMega devices)
; configure PORTA for output
; configure PORTB for output
; set up increment amount
; set up loop limit
; start j from 0
; start temp from 0
; select channel A
; enable write to AD7302
; send a value to be converted
; start DAC
; insert idle time
; to allow enough internal DAC operation to complete
; "
; increment to next step
; increment loop count
; reach the end of the loop?
The C language version of the program is as follows:
#include ,avr\io.h.
void main (void)
{
unsigned char j, tmp, delta;
delta 5 5;
DDRA 5 0xFF;
// configure PORTA for output
DDRB 5 0xFF;
// configure PORTB for output
PORTB &5 0xFD;
// select VOUTA output
while (1) {
tmp 5 0;
for (j 5 0; j , 52; j11){
PORTB &5 0xFE; // enable write
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
254
Chapter 8
■
Parallel I/O
PORTA 5 tmp;
// output the value to be converted
PORTB |5 0x01; // start DAC
tmp 15 delta;
}
}
}
▲
8.9 Summary
A user employs I/O devices to interact with embedded systems. LEDs are often used to
indicate whether the product is functioning properly and whether the power is on. LEDs are
also used to display certain patterns. Matrix displays are based on LEDs and are often used to
display messages in public buildings. Today, LEDs are even used to provide lighting because of
their low power consumption.
A set of DIP switches is used as a simple input device. The software needs to output a message to remind the user to set up a value in the DIP switches and assert an interrupt to inform
the MCU to read the value.
The AVR Mega and XMega devices have many signal pins. These signal pins are divided
into I/O PORTs. An I/O PORT consists of a set of signal pins and registers required for the I/O
operation. Because an I/O pin can be used for input and output, the user must configure the
direction of the I/O pin before using it in data transfer. This is achieved by writing an appropriate value into a data direction register. For AVR Mega and XMega devices, a pin is configured for
output if a 1 is written to its associated bit position of the PORT data direction register. In addition, the AVR allows the user to configure the input pin sensing edge and pull-up or pull-down.
To output data, the MCU writes data to the PORT data register. To input data, the MCU reads
from the PORT input register.
When interfacing peripheral chips with the microcontroller, the user must make sure that
these peripheral chips are electrically compatible with the microcontroller.
D/A converters are often used to convert digital values into voltages. Square, saw-tooth,
triangular, staircase, and sinusoidal waveforms can be generated from a D/A converter easily.
The digital value to be converted can be represented in 8 bits, 10 bits, or many more bits. The
more bits are used, the better the resolution gets. A high-fidelity digital audio system uses 24
bits to encode a value to be converted back to audio sound.
8.10 Exercises
E8.1 Write an instruction sequence to output the value 0x53 to PORTA.
E8.2 Write an instruction sequence to read the voltage levels on PORTB pins and place the
value in register r20.
E8.3 Suppose that the PORTA pins PA4~PA0 are connected to green, yellow, red, blue, and
purple LEDs. The circuit connection is similar to that in Figure 8.16. Write a program to light
the green, yellow, red, blue, and purple in turn for 0.1, 0.2, 0.3, 0.4, and 0.5 seconds forever. Use
both the assembly and C languages.
E8.4 Traffic light controller simulation. Use PORTC pins PC5~PC0 of the XMega and green,
yellow, and red LEDs to simulate a traffic-light controller. The traffic-light patterns and durations for the east–west and north–south traffic are given in Table 8E.4. Write an assembly and
C program to control the light patterns, and connect the circuit to demonstrate the change of
lights.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.10
■
255
Exercises
East-West
North-South
Duration
(sec)
Green
Yellow
Red
Green
Yellow
Red
PC5
PC4
PC3
PC2
PC1
PC0
1
0
0
0
0
1
0
1
0
0
0
1
5
0
0
1
1
0
0
20
0
0
1
0
1
0
4
25
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 8E4
■
Traffic light pattern and duration
E8.5 For the circuit shown in Figure 8.18, write a program to display 1, 2, 3, 4, 5, and 6 from left
to right, one digit at a time, with each digit lasting for 100 ms.
E8.6 Write a program to display the following patterns from the seven-segment display circuit
shown in Figure 8.18 from display #5 to #0, and repeat with each pattern lasting for 600 ms:
123456
234567
345678
456789
567890
678901
789012
890123
901234
012345
E8.7 Write a C program to display the following patterns from the seven-segment display
circuit shown in Figure 8.18, from display #5 to #0, and repeat with each pattern lasting for
600 ms:
0
10
210
3210
43210
543210
654321
765432
876543
987654
098765
109876
210987
321098
432109
E8.8 Write an instruction sequence to configure pins 0, 2, 3, and 7 of PORTB with pull-up
operation and sense falling edge for the XMega devices.
E8.9 Write an instruction sequence to map PORTs A, B, C, and D of XMega to virtual
PORTs 0, 1, 2, and 3, respectively.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
256
Chapter 8
■
Parallel I/O
E8.10 For the circuit shown in Figure 8.22, write an assembly program to generate a triangular
waveform from the VOUTB pin, assuming that the Mega2560 is running with an 8 MHz crystal
oscillator.
E8.11 For the circuit shown in Figure 8.22, write an assembly program to generate a triangular
waveform from VOUTA pin and a sine wave from the VOUTB pin, assuming that the Mega2560
is running with an 8 MHz crystal oscillator. Divide both waveforms into 50 points per period.
E8.12 Suppose that common-anode seven-segment displays are used instead of commoncathode seven-segment displays. Show the changes that must be made in the circuit shown in
Figure 8.17. What needs to be modified in Table 8.18 for the seven-segment displays?
E8.13 Can the HCT technology drive the ABT technology at the same power supply?
E8.14 Verify whether the XMega with 3.3 V power supply is electrically compatible with the
BCT technology with 5 V power supply.
E8.15 Are the FCT technology with 5 V power supply and the XMega devices with 3.3 V power
supply electrically compatible?
8.11 Lab Assignments
L8.1 Three-Tone Siren Generation. Connect the PH7 pin to a speaker or buzzer. Write a program
to generate a three-tone siren with frequency equals 250 Hz, 500 Hz, and 1 kHz, respectively.
Each tone lasts for half a second.
L8.2 Waveform Generation. Use a circuit similar to that in Figure 8.22 to generate a 1 kHz
square wave from V OUTA and a 2 kHz square wave from V OUTB simultaneously. Use the
oscilloscope to display the generated waveform.
L8.3 Waveform Generation. Use the circuit similar to that in Figure 8.22 to generate a sine
wave from VOUTA pin. Divide one period of the sine waveform into 52 points.
L8.4 LED Flashing. Write a program to flash the LEDs driven by PORTK on your demo board
with the following pattern:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Turn on all LEDs for 200 ms and turn them off for 200 ms.
Repeat Step 1 three more times.
Turn on one LED at a time, from left to right, with each LED turned on for 200 ms.
Repeat Step 3 three more times.
Turn on one LED at a time, from right to left, with each LED turned on for 200 ms.
Repeat Step 5 three more times.
Turn LEDs driven by pins PK7 and PK0 on and off four times. The on and off times
both 200 ms.
Turn LEDs driven by pins PK6 and PK1 on and off four times. The on and off times
both 200 ms.
Turn LEDs driven by pins PK5 and PK2 on and off four times. The on and off times
both 200 ms.
Turn LEDs driven by pins PK4 and PK3 on and off four times. The on and off times
both 200 ms.
Turn LEDs driven by pins PK3 and PK4 on and off four times. The on and off times
both 200 ms.
Turn LEDs driven by pins PK2 and PK5 on and off four times. The on and off times
both 200 ms.
Turn LEDs driven by pins PK1 and PK6 on and off four times. The on and off times
both 200 ms.
are
are
are
are
are
are
are
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
8.11
■
Lab Assignments
257
14. Turn LEDs driven by pins PK0 and PK7 on and off four times. The on and off times are
both 200 ms.
15. Go to Step 1 and repeat.
L8.5 Use PORTH to drive two 74HC48s. The 74HC48 is a common cathode seven-segment
display driver that accepts a four-digit binary number and converts it into the corresponding
seven-segment pattern. Write a program that displays the value from 00 to 99 on these two
7-segment displays three times and then stops. Display each value for 200 ms.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9
Interrupt Handling, Resets,
and Power Management
9.1 Objectives
After completing this chapter, you will be able to
• Explain the nature of interrupts and resets.
• Explain how interrupts are handled by the
CPU.
•
•
•
•
Enable and disable interrupts.
Set up interrupt priority.
Write interrupt service routines.
Use a watchdog timer reset to detect software
errors.
• Use the low-power mode to save power
consumption.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
260
Chapter 9
■
Interrupt Handling, Resets, and Power Management
9.2 Basic Concepts on Interrupt
In computing, an interrupt is an asynchronous signal indicating the need for attention,
or a synchronous event in software indicating the need for a change in execution. A hardware
interrupt causes the processor to save its state of execution and begin execution of an interrupt
handler (also referred to as an interrupt service routine). The state of execution consists of at
least the contents of the program counter and a few other important registers.
Software interrupts are usually implemented as instructions in the instruction set, which
causes a context switch to an interrupt handler similar to a hardware interrupt. Not all of the
microcontrollers implement software interrupts.
Interrupts are often used to implement computer multitasking, especially in real-time
computing. Such a system is said to be interrupt driven. An act of interrupting is referred to as
an interrupt request (IRQ).
9.2.1 Why Interrupt Is Useful
Most computers and embedded products are designed to perform multiple functions. In
addition to executing general-purpose instructions, the MCU also needs to perform the following operations:
•
I/O operations. Before reading data from an input device, the CPU needs to know
whether the I/O device has new data. We can either let the CPU find out whether
new data are available by polling the I/O device or getting the I/O device to inform
the CPU of this condition by using an interrupt signal. If the polling method is
used, then the CPU cannot perform any other operation until new data become
available, which is quite wasteful for the CPU time. Using the interrupt approach,
the CPU can continue to perform other operations before new data become
available. To output data, the CPU has to make sure that the output device can
accept new data before it sends out data. Again, we can either let the CPU find out
whether the output device is ready for more data or let the output device inform
the CPU, using an interrupt signal. Apparently, the interrupt method prevents the
CPU from busy waiting.
•
Routine tasks. Many computers and embedded systems have to perform routine
works such as checking and informing appointment times; updating and
redisplaying time of day; checking and measuring environment temperature,
pressure, humidity, and so on. Routine tasks are performed by using the timer
interrupts. A timer can be set up to overflow periodically and interrupt the CPU.
Whenever a timer interrupt occurs, the CPU is reminded to perform those routine
tasks. It is difficult to imagine how the CPU could perform them without a timer
interrupt.
•
Response to emergent events. Emergent events such as fire alarm, power failure,
overheat, and so on, require the CPU to take action immediately. The interrupt
mechanism forces the CPU to divert from normal program execution to do this,
thus avoiding severe damage or data loss.
9.2.2 Enabling and Disabling Interrupts
An interrupt may be useful in some situations, but not desirable in other situations.
Modern microcontrollers are designed to have the capability to selectively pay attention to
interrupts. Whenever an interrupt is useful, the MCU enables it. Whenever an interrupt is not
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.2
■
Basic Concepts on Interrupt
261
desirable, the MCU disables it. An interrupt that can be enabled and disabled selectively is
called a maskable interrupt. There are other types of interrupts that the CPU cannot ignore and
must take immediate action for; these are called nonmaskable interrupts.
A program can request the CPU to service or ignore a maskable interrupt by setting or
clearing an enable bit. An interrupt is said to be pending when it is active but not serviced by
the CPU. A pending interrupt may or may not be serviced by the CPU, depending upon whether
it is enabled.
To make the interrupt system more flexible, a computer system normally provides a global
and local interrupt masking capability. When none of the interrupts are desirable, the processor can disable all of the interrupts by clearing the global interrupt enable bit (or setting the
global interrupt mask bit for some other microprocessors). In other situations, the processor can
enable certain interrupts while at the same time disabling other undesirable interrupts. This is
achieved by providing each interrupt source an enable bit in additional to the global interrupt
enable bit. Today, almost all commercial processors have been designed to provide a two-level
(or even three-level) interrupt-enabling capability.
9.2.3 Prioritizing Multiple Interrupts
If a computer system supports multiple interrupt sources, then it is possible that several
interrupts could be pending at about the same time. The CPU has to decide which interrupt
should receive service first. The common solution is to prioritize all interrupt sources. In this
approach, the CPU provides service to the interrupt with the highest priority among all pending
interrupts. Most microcontrollers prioritize interrupts in hardware. For those microcontrollers
that do not, the software can be written to handle certain interrupts before others, thus essentially prioritizing them.
9.2.4 Servicing the Interrupt
When an enabled interrupt occurs, the CPU is forced to provide service to it by executing an interrupt service routine, after which it must resume the execution of the interrupted
program. To be able to do so, the CPU saves the program counter before executing the interrupt service routine. After saving the program counter, the CPU had to identify the source of
interrupt and locate the starting address of the interrupt service routine before it can begin to
execute the interrupt service routine. When the CPU finishes the execution of the interrupt
service routine, which is often very short, it restores the saved program counter and returns to
the interrupted program for execution.
An interrupt service routine is not much different from a subroutine, except for the last
instruction. The last instruction of an interrupt service routine must be the return from
interrupt (RETI) instruction. An interrupt service routine is not to be called. Instead, the execution of an interrupt service routine is triggered by the occurrence of the associated interrupt.
9.2.5 The Interrupt Vector
The starting address of the interrupt service routine is referred to as an interrupt vector.
The microcontroller must find out the starting address of the service routine of the pending
interrupt in order to provide appropriate service to it. For some microcontrollers, each interrupt
source has its own predefined interrupt vector (i.e., at a fixed location), whereas others store all
the interrupt vectors in a table. Each interrupt vector is stored in a fixed location in a table that
is referred to as the interrupt vector table.
When the first approach is used, the CPU jumps to a predefined location to service the
pending interrupt. However, the CPU needs to fetch the interrupt vector from the interrupt
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
262
Chapter 9
■
Interrupt Handling, Resets, and Power Management
vector table in the second approach. The Atmel AVR devices use the first approach to locate
the interrupt vector. A table that contains the first four bytes of all interrupt service routines is predefined. The first four bytes of each interrupt service routine are of the following
format:
jmp
xxx_ISR ; xxx_ISR is the actual service routine for an interrupt
9.2.6 Writing an Interrupt-Driven Program
Interrupt programming consists of three major steps:
Step 1
Initialization of the interrupt vector table. The purpose of this step is to place interrupt
vectors in the interrupt vector table. This is achieved by using the assembly directives as
follows:
.org
.dw
.dw
…
0x03
ISR1
ISR2
This step is not needed for the AVR microcontroller.
Step 2
Write the service routine. The interrupt service routine must be as short as possible. An
interrupt service routine for INT0 may be as simple as the following:
int0ISR:
.def
…
inc
out
reti
cnt = r15
cnt
PORTA,cnt
; output cnt to PORTA
; return from interrupt
Step 3
Enable interrupts. An interrupt must be enabled before it can signal the MCU to provide
service. It is a common mistake to forget enabling interrupts when writing interruptdriven programs.
9.3 Resets
When a computer is first powered up, the initial values of program counter, CPU registers,
flip-flops, and I/O control registers are unknown. The computer cannot execute programs correctly under these conditions. In order for computers to execute a program correctly after they
are powered up, they are designed to have a reset mechanism. All critical registers, the program
counters, and flip-flops are forced to a default value after a power-up reset so that the computer
can start to execute a program correctly. For example, the program counter of the AVR MCU
is forced to 0x0000 after reset, and hence, it always starts program execution from the address
0x0000 after power-on reset.
In addition to the power-on reset, a computer may provide several resets to improve the
performance and flexibility of the computer system. These resets include manual reset (applied
to a pin), brown-out reset, watchdog reset, clock monitor reset, software reset, and so on.
A manual reset without power-down has the same effect as power-on reset; it can force the
program counter and critical registers to default values and allows the computer to reboot itself
after a reset. Other reset sources are discussed later.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.4
■
263
The AVR Mega Interrupts
9.4 The AVR Mega Interrupts
A Mega family device may have up to 56 interrupt sources, all of which are maskable and
are divided into three categories:
•
•
•
Internal peripheral interrupts. The interrupt sources associated with timers, USART
modules, SPI interface, TWI interface, A/D converter, CAN, and USB are in this category.
External pin interrupts. A Mega AVR device may have up to eight external
interrupt pins (INT0~INT7) that assert interrupt signals to the MCU. An interrupt
may be asserted when one of these pins stays low, going low (falling edge), going
high (rising edge), or simply toggles.
Pin change interrupts. A Mega AVR device may have three pin change interrupts
(PCINT0~PCINT2). These interrupts are mainly used to wake up the MCU when it
is in sleep mode. These interrupts share the same pins with I/O PORTs B, E, J, and K.
9.4.1 AVR Mega Device Interrupt Vectors
The 100-pin Mega devices (ATMega640/1280/2560) have the most interrupt sources among
all Mega devices. The Mega devices with fewer pins have fewer interrupt sources. The reset and
interrupt vectors of the ATMega640/1280/2560 are listed in Table 9.1.
Vector no.
Vector addr.
Source
Interrupt definition
1
0×0000
RESET
Pin Reset, Power-on, brown-out, watchdog, JTAG reset
2
0×0002
INT0
External interrupt request 0
3
0×0004
INT1
External interrupt request 1
4
0×0006
INT2
External interrupt request 2
5
0×0008
INT3
External interrupt request 3
6
0×000A
INT4
External interrupt request 4
7
0×000C
INT5
External interrupt request 5
8
0×000E
INT6
External interrupt request 6
9
0×0010
INT7
External interrupt request 7
10
0×0012
PCINT0
Pin change interrupt request 0
11
0×0014
PCINT1
Pin change interrupt request 1
12
0×0016
PCINT2
Pin change interrupt request 2
13
0×0018
WDT
Watchdog time-out interrupt
14
0×001A
Timer2 COMPA
Timer/Counter2 compare match A
15
0×001C
Timer2 COMPB
Timer/Counter2 compare match B
16
0×001E
Timer2 OVF
Timer/Counter2 overflow
17
0×0020
Timer1 CAPT
Timer/Counter1 capture event
18
0×0022
Timer1 COMPA
Timer/Counter1 compare match A
19
0×0024
Timer1 COMPB
Timer/Counter1 compare match B
20
0×0026
Timer1 COMPC
Timer/Counter1 compare match C
21
0×0028
Timer1 OVF
Timer/Counter1 overflow
Table 9.1
■
Reset and interrupt vectors for ATMega640/1280/2560
(Continued)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
264
Chapter 9
Table 9.1
■
■
Interrupt Handling, Resets, and Power Management
(Continued)
Vector no.
Vector addr.
22
0×002A
Timer0 COMPA
Source
Timer/Counter0 compare match A
Interrupt definition
23
0×002C
Timer0 COMPB
Timer/Counter0 compare match B
24
0×002E
Timer0 OVF
Timer/Counter0 overflow
25
0×0030
SPI, STC
SPI serial transfer complete
26
0×0032
USATR0 RX
USART0 Rx complete
27
0×0034
USATR0 UDRE
USART0 data register empty
28
0×0036
USART0 TX
USART0 Tx complete
29
0×0038
Analog Comp
Analog comparator
30
0×003A
ADC
ADC conversion complete
31
0×003C
EE Ready
EEPROM ready
32
0×003E
Timer3 CAPT
Timer/Counter3 capture event
33
0×0040
Timer3 COMPA
Timer/Counter3 compare match A
34
0×0042
Timer3 COMPB
Timer/Counter3 compare match B
35
0×0044
Timer3 COMPC
Timer/Counter3 compare match C
36
0×0046
Timer3 OVF
Timer/Counter3 overflow
37
0×0048
USART1 RX
USART1 Rx complete
38
0×004A
USART1 UDRE
USART1 data register empty
39
0×004C
USART1 TX
USART1 Tx complete
40
0×004E
TWI
2-wire serial interface
41
0×0050
SPM Ready
Store program memory ready
42
0×0052
Timer4 CAPT
Timer/Counter4 capture event
43
0×0054
Timer4 COMPA
Timer/Counter4 compare match A
44
0×0056
Timer4 COMPB
Timer/Counter4 compare match B
45
0×0058
Timer4 COMPC
Timer/Counter4 compare match C
46
0×005A
Timer4 OVF
Timer/Counter4 overflow
47
0×005C
Timer5 CAPT
Timer/Counter5 capture event
48
0×005E
Timer5 COMPA
Timer/Counter5 compare match A
49
0×0060
Timer5 COMPB
Timer/Counter5 compare match B
50
0×0062
Timer5 COMPC
Timer/Counter5 compare match C
51
0×0064
Timer5 OVF
Timer/Counter5 overflow
52
0×0066
USART2 RX
USART2 Rx complete
53
0×0068
USART2 UDRE
USART2 data register empty
54
0×006A
USART2 TX
USART2 Tx complete
55
0×006C
USATR3 RX
USART3 Rx complete
56
0×006E
USATR3 UDRE
USART3 data register empty
57
0×0070
USART3 TX
USART3 Tx complete
Source: Atmel Corporation, The Atmel AVR Microcontroller
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.4
■
265
The AVR Mega Interrupts
The Mega devices reserve a block of program memory starting from 0×0000 and allocate
two words to service the reset and each interrupt source. Because two words are not enough for
any interrupt handling, the user normally uses a jump instruction to send the CPU to another
location to execute the actual interrupt service routine. The most typical and general program
setup for the reset and interrupt vector addresses in ATMega640/1280/2560 is as follows:
word
Address
code
0x0000
0x0002
0x0004
….
….
0x0070
;
0x0072 reset:
0x0073
0x0074
0x0075
0x0076
0x0077
jmp
jmp
jmp
reset
INT0
INT1
comments
jmp
USART3_TXC
ldi
out
ldi
out
sei
…
r16,high(RAMEND)
SPH,r16
r16,low(RAMEND)
SPL,r16
; reset handler
; INT0 handler
; INT1 handler
; other interrupt handlers
; "
; USART3 TX complete handler
; main program starts
; set stack pointer
; "
; "
; enable interrupts
However, the user can also relocate the reset vector and interrupt vectors to the boot section by programming the BOOTRST fuse and the IVSEL bit of the microcontroller configuration
register (MCUCR). The BOOTRST fuse can be programmed from the AVR Studio IDE. The
possible reset and interrupt vectors placement are shown in Table 9.2.
BOOTRST
IVSEL
Reset address
Interrupt vectors start address
1
0
0×0000
0×0002
1
1
0×0000
Boot reset address 1 0×0002
0
0
Boot reset address
0×0002
0
1
Boot reset address
Boot reset address 1 0×0002
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.2
■
Reset and interrupt vectors placement
When the BOOTRST fuse is programmed (cleared to 0), the boot section size is set to 8 kB
and the IVSEL bit in the MCUCR register is set to 1 before any interrupt is enabled, the most
typical and general program setup for the reset and interrupt vector addresses is as follows:
word
Address
code
comments
;
0x1F000
0x1F002
0x1F004
.org
jmp
jmp
jmp
0x1F000
reset
EXT_INT0
EXT_INT1
; reset handler
; INT0 handler
; INT1 handler
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
266
Chapter 9
■
Interrupt Handling, Resets, and Power Management
…
0x1F070
;
0x1F072 reset:
0x1F073
0x1F074
0x1F075
0x1F076
0x1F077
jmp
USART3_TXC
; USART3 TX complete handler
ldi
out
ldi
out
sei
<instrr> xxx
r16,high(RAMEND)
SPH,r16
r16,low(RAMEND)
SPL,r16
; main program start
; set up stack pointer
; "
; "
; enable interrupt
9.4.2 The Mega AVR Microcontroller Configuration Register (MCUCR)
The placement of the interrupt vectors is controlled by the MCUCR register. In addition to
controlling the interrupt vectors placement, this register also controls the enabling of I/O pins
pull-up and the JTAG interface. The contents of the MCUCR register are shown in Figure 9.1.
6
5
4
3
2
1
0
—
—
PUD
—
—
IVSEL
IVCE
R/W
R
R
R/W
R
R
R/W
R/W
Reset value
= 0x00
JTD: JTAG Disable
0: JTAG interface is Enabled.
1: JTAG interface is Disabled.
PUD: Pullup Disable
0: Enable pull-ups of all pins of all I/O PORTs.
1: Disable pull-ups of all pins of all I/O PORTs.
IVSEL: Interrupt vector select
0: Interrupt vectors are placed at the start of the flash memory (i.e., 0x0002).
1: Interrupt vectors are placed at the start of the boot section. The start of the boot section is set
by programming the BOOTSZ fuses.
IVCE: Interrupt vector change enable
0: Disable interrupt vector change
1: Enable interrupt vector to be changed
Figure 9.1
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
JTD
MCU configuration register
A special write procedure must be followed in order to change the IVSEL bit:
Step 1
Write the IVCE bit to 1.
Step 2
Within four system clock cycles, write the desired value to IVSEL while writing a 0 to the
IVCE bit. The following assembly instruction sequence implements this procedure:
in
mov
ori
out
ori
out
r16,MCUCR
r17,r16
r16,(1 << IVCE)
MCUCR,r16
r17,(1 << IVSEL)
MCUCR,r17
; sets the IVCE bit
; sets IVSEL bit and clears IVCE bit
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.4
■
267
The AVR Mega Interrupts
The same operation is implemented by the following sequence of C statements:
unsigned
…
temp
MCUCR
MCUCR
char temp;
= MCUCR;
= temp | (1 << IVCE);
= temp | (1 << IVSEL);
// sets the IVCE bit
// sets the IVSEL bit and clears the IVCE bit
9.4.3 AVR Mega External Interrupt Pins
7
6
5
4
3
2
1
0
ISC31
ISC30
ISC21
ISC20
ISC11
ISC10
ISC01
ISC00
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
ISCn1: ISCn0: External interrupt 3~0 sense control bits
00 = The low level of INTn generates an interrupt request.
01 = Any edge of INTn generates an interrupt request.
10 = The falling edge of INTn generates an interrupt request.
11 = The rising edge of INTn generates an interrupt request.
n = 0~3.
■
External interrupt control register A (EICRA)
7
6
5
4
3
2
1
0
ISC71
ISC70
ISC61
ISC60
ISC51
ISC50
ISC41
ISC40
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
ISCn1: ISCn0: External interrupt 7~4 sense control bits
00 = The low level of INTn generates an interrupt request.
01 = Any edge of INTn generates an interrupt request.
10 = The falling edge of INTn generates an interrupt request.
11 = The rising edge of INTn generates an interrupt request.
n = 7, …, 4.
Figure 9.3
■
External interrupt control register B (EICRB)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Figure 9.2
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The INT7:0 pins trigger interrupt requests to the MCU. These interrupts share the use
of pins with PORTD and E (INT0/PD0, INT1/PD1, INT2/PD2, INT3/PD3, INT4/PE4, INT5/
PE5, INT6/PE6, INT7/PE7). External interrupts are triggered by a falling edge, a rising edge, or
a low level. This is set up by programming the EICRA and EICRB registers. The EICRA register controls the triggering method for INT3~0, and the EICRB register controls the triggering
method for INT7:4. The contents of EICRA and EICRB are shown in Figure 9.2 and Figure 9.3,
respectively.
Each of these external interrupt is disabled by clearing the associated mask bit in the
EIMSK register. Whenever one of these external interrupt conditions occurs, the associated flag
bit in the EIFR register is set to 1. The flag bit is cleared when the associated interrupt service
routine is entered. The flag bit is also cleared by writing a 1 to it. The contents of EIMSK and
EIFR are shown in Figure 9.4 and Figure 9.5, respectively.
■
Interrupt Handling, Resets, and Power Management
7
6
5
4
3
2
1
0
INT7
INT6
INT5
INT4
INT3
INT2
INT1
INT0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
INTn: External interrupt request n enable (n = 0, …, 7)
0 = External interrupt n is disabled.
1 = External interrupt n is enabled.
Figure 9.4
■
External interrupt mask register (EIMSK)
7
6
5
4
3
2
1
0
INTF7
INTF6
INTF5
INTF4
INTF3
INTF2
INTF1
INTF0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
INTFn: External interrupt flag n (n = 0, …, 7)
0 = External interrupt n condition did not occur since last time this flag was cleared.
1 = External interrupt n condition has occurred.
Figure 9.5
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
Chapter 9
Source: Atmel Corporation,
The Atmel AVR Microcontroller
268
External interrupt flag register (EIFR)
9.4.4 Pin Change Interrupt
The ATMega640/1280/2560 has 24 pins (PCINT23~0) that generate interrupt whenever one
or more of these pins toggle. Pin change interrupt PCINT2 triggers if any enabled PCINT23~16
pin toggles; pin change interrupt PCINT1 triggers if any enabled PCINT15~8 pin toggles; and
pin change interrupt PCINT0 triggers if any enabled PCINT7~0 pin toggles.
Pin change interrupts on PCINT23:0 are detected asynchronously. This implies that these
interrupts are used to wake up the MCU from sleep mode or idle mode.
Each of the three pin change interrupts is enabled by setting the corresponding bit in the
PCICR register, and each has an associated flag bit in the PCIFR register. The contents of these
registers are shown in Figure 9.6 and Figure 9.7, respectively.
Each of the 24 pins must be enabled before it can generate a pin change interrupt. The registers
PCMSK2, PCMSK1, and PCMSK0 control the enabling and disabling of these 24 pins from generating interrupts. The contents of these three registers are shown in Figure 9.8 through Figure 9.10.
6
5
4
3
2
1
0
—
—
—
—
PCIE2
PCIE1
PCIE0
R
R
R
R
R
R/W
R/W
R/W
PCIE2: Pin change interrupt enable 2
0 = Pin change interrupt 2 disabled
1 = Pin change interrupt 2 enabled (any change on any enabled PCINT23~16 pin will cause an
interrupt; PCINT23~16 pins are enabled individually by the PCMSK2 register).
PCIE1: Pin change interrupt enable 1
0 = Pin change interrupt 1 disabled
1 = Pin change interrupt 1 enabled (any change on any enabled PCINT15~8 pin will cause an
interrupt; PCINT15~8 pins are enabled individually by the PCMSK1 register).
PCIE0: Pin change interrupt enable 0
0 = Pin change interrupt 0 disabled
1 = Pin change interrupt 0 enabled (any change on any enabled PCINT7~0 pin will cause an
interrupt; PCINT7~0 pins are enabled individually by the PCMSK0 register).
Figure 9.6
■
Reset value
= 0x00
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
—
Pin change interrupt control register (PCICR)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
7
6
5
4
3
2
1
0
—
—
—
—
—
PCIF2
PCIF1
PCIF0
R
R
R
R
R
R/W
R/W
R/W
Reset value
= 0x00
PCIF2: Pin change interrupt flag 2
0 = No pins among PCINT23~16 have changed value.
1 = At least one of the PCINT23~16 pins has changed value.
PCIF1: Pin change interrupt flag 1
0 = No pins among PCINT15~8 have changed value.
1 = At least one of the PCINT15~8 pins has changed value.
PCIF0: Pin change interrupt flag 0
0 = No pins among PCINT7~0 have changed value.
1 = At least one of the PCINT7~0 pins has changed value.
■
Pin change interrupt flag register (PCIFR)
7
6
5
4
3
2
1
0
PCINT23
PCINT22
PCINT21
PCINT20
PCINT19
PCINT18
PCINT17
PCINT16
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
PCINTn: Pin change enable mask n (n = 23, …, 16)
0 = Disable pin change interrupt on the PCINTn pin
1 = Enable pin change on the PCINTn pin to interrupt the CPU. Both this bit and the PCIE2 bit of the
PCICR register must be set in order for the interrupt to be enabled.
Figure 9.8
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
Figure 9.7
Source: Atmel Corporation, The Atmel AVR Microcontroller
269
The AVR Mega Interrupts
Pin change mask register 2 (PCMSK2)
7
6
5
4
3
2
1
0
PCINT15
PCINT14
PCINT13
PCINT12
PCINT11
PCINT10
PCINT9
PCINT8
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
PCINTn: Pin change enable mask n (n = 15, …, 8)
0 = Disable pin change interrupt on the PCINTn pin
1 = Enable pin change on the PCINTn pin to interrupt the CPU. Both this bit and the PCIE1 bit of the
PCICR register must be set in order for the interrupt to be enabled.
Figure 9.9
■
Pin change mask register 1 (PCMSK1)
7
6
5
4
3
2
1
0
PCINT7
PCINT6
PCINT5
PCINT4
PCINT3
PCINT2
PCINT1
PCINT0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
PCINTn: Pin change enable mask n (n = 7, …, 0)
0 = Disable pin change interrupt on the PCINTn pin
1 = Enable pin change on the PCINTn pin to interrupt the CPU. Both this bit and the PCIE0 bit of the
PCICR register must be set in order for the interrupt to be enabled.
Figure 9.10
Source: Atmel Corporation,
The Atmel AVR Microcontroller
■
■
Pin change mask register0 (PCMSK0)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation,
The Atmel AVR Microcontroller
9.4
270
Chapter 9
■
Interrupt Handling, Resets, and Power Management
Example 9.1
▼
Write a main program and an interrupt service routine for the INT0 interrupt in assembly
language. The main program configures PORTA for output and enables INT0 to interrupt on
the falling edge and also initializes the variable cnt to 0. After that, the main program stays in an
infinite loop to wait for INT0 interrupt to occur. The INT0 service routine simply increments
cnt by 1 and outputs it to PORTA.
Solution: The assembly language version of the program is as follows:
.include <m2560def.inc>
.def
cnt = r20
.def
tmp = r16
.cseg
.org
0x00
jmp
start
jmp
INT0_ISR
.org
0xF6
ldi
tmp,low(RAMEND)
out
SPL,tmp
ldi
r16,high(RAMEND)
out
SPH,tmp
ldi
tmp,0xFF
out
DDRA,tmp
lds
tmp,DDRD
andi
tmp,0xFE
sts
DDRD,tmp
ldi
cnt,0
ldi
tmp,0x02
sts
EICRA,tmp
ldi
tmp,0x01
sts
EIMSK,tmp
sei
jmp
again
start:
again:
; use r20 as cnt
; initialize the SP
; "
; "
; "
; configure PORTA for output
; "
; configure PD0/INT0 pin for input
; "
; "
; initialize cnt to 0
; configure INT0 to interrupt on the falling edge
; "
; enable INT0 interrupt
; "
; enable interrupt globally
; forever loop
; -------------------------------------------------------------------------------------------------------------; The following is the service routine for INT0
; -------------------------------------------------------------------------------------------------------------INT0_ISR:
inc
out
reti
cnt
PORTA,cnt
; output cnt to PORTA
▲
9.4.5 Writing Interrupt Service Routine in C for AVR Mega Devices
The AVR interrupt is enabled and disabled globally by invoking the following two macros
(defined in interrupt.h):
•
•
sei()—enables interrupt globally
cli()—disables interrupt globally
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.4
■
The AVR Mega Interrupts
271
To provide service to interrupt, the AVR Studio C compiler requires the user to use the following format to write an interrupt service routine:
ISR (vector number of the interrupt)
{
…
}
The symbolic names of all interrupt vector numbers and interrupt vectors have been defined
in the appropriate header file (C language) and include file (assembly language). For example,
the symbolic names of all interrupt vector numbers for the ATMega640/1280/2560 are defined
in the iomxx0_1.h and are listed in Table 9.3. The symbolic name of the INT0 vector number
is INT0_vect. The user also needs to include the interrupt.h file into his or her program. This
file contains all the definitions and macros related to interrupt handling. For assembly language, the user derives the symbolic name of an interrupt source by changing the suffix _vect
to Addr in Table 9.3 for each interrupt source when dealing with the Mega device interrupts.
For example, use INT0addr is the symbolic name of the INT0 interrupt in assembly language.
Example 9.2
▼
Write the C language version of the interrupt service routine and the main function
described in Example 9.1.
Solution: The C language version of the interrupt service routine and the main function are as
follows:
#include <avr\io.h>
#include <avr\interrupt.h>
unsigned char cnt;
int main (void)
{
DDRA
= 0xFF;
// configure PORTA for output
DDRD
&= 0xFE; // configure PD0/INT0 pin for input
EICRA
= 0x02;
// configure INT0 to interrupt on the falling edge
EIMSK
= 0x01;
// enable INT0 interrupt
sei();
// enable interrupt globally
cnt
= 0;
while(1);
// wait for INT0 to occur
return 0;
}
// -----------------------------------------------------------------------------------------------------// INT0 interrupt service routine.
// -----------------------------------------------------------------------------------------------------ISR(INT0_vect)
{
cnt++;
PORTA
= cnt;
// output cnt to PORTA
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
272
Chapter 9
Interrupt source
INT0
■
Interrupt Handling, Resets, and Power Management
Vector number
1
Symbolic name
INT0_vect
Interrupt source
ADC
Vector number
29
Symbolic name
ADCC_vect
INT1
2
INT1_vect
EE READY
30
ERDY_vect
INT2
3
INT2_vect
TIMER3 CAPT
31
ICP3_vect
INT3
4
INT3_vect
TIMER3 COMPA
32
OC3A_vect
INT4
5
INT4_vect
TIMER3 COMPB
33
OC3B_vect
INT5
6
INT5_vect
TIMER3 COMPC
34
OC3C_vect
INT6
7
INT6_vect
TIMER3 OVF
35
OVF3_vect
INT7
8
INT7_vect
USART1 RX
36
URXC1_vect
PCINT0
9
PCI0_vect
USART1 UDRE
37
UDRE1_vect
PCINT1
10
PCI1_vect
USART1 TX
38
UTXC1_vect
PCINT2
11
PCI2_vect
TWI
39
TWI_vect
WDT
12
WDT_vect
SPM READY
40
SPMR_vect
TIMER2 COMPA
13
OC2A_vect
TIMER4 CAPT
41
ICP4_vect
TIMER2 COMPB
14
OC2B_vect
TIMER4 COMPA
42
OC4A_vect
TIMER2 OVF
15
OVF2_vect
TIMER4 COMPB
43
OC4B_vect
TIMER1 CAPT
16
ICP1_vect
TIMER4 COMPC
44
OC4C_vect
TIMER1 COMPA
17
OC1A_vect
TIMER4 OVF
45
OVF4_vect
TIMER1 COMPB
18
OC1B_vect
TIMER5 CAPT
46
ICP5_vect
TIMER1 COMPC
19
OC1C_vect
TIMER5 COMPA
47
OC5A_vect
TIMER1 OVF
20
OVF1_vect
TIMER5 COMPB
48
OC5B_vect
TIMER0 COMPA
21
OC0A_vect
TIMER5 COMPC
49
OC5C_vect
TIMER0 COMPB
22
OC0B_vect
TIMER5 OVF
50
OVF5_vect
TIMER0 OVF
23
OVF0_vect
USART2 RX
51
URXC2_vect
SPI STC
24
SPI_vect
USART2 UDRE
52
UDRE2_vect
USART0 RX
25
URXC0_vect
USART2 TX
53
UTXC2_vect
USART0 UDRE
26
UDRE0_vect
USART3 RX
54
URXC3_vect
USART0 TX
27
UTXC0_vect
USART3 UDRE
55
UDRE3_vect
ANALOG COMP
28
ACI_vect
USART3 TX
56
UTXC3_vect
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.3
■
Symbolic name of vector numbers for ATMega640/1280/2560
9.5 The XMega Device Interrupts
The interrupt structure of the XMega family of AVR devices is different from that of the
Mega family. The XMega has a programmable multi-level interrupt controller (PMIC). The
XMega supports maskable and nonmaskable interrupts. All peripheral interrupts are maskable. These interrupts are programmed to three different priority levels: high, medium, or
low. Medium-level interrupts may interrupt low-level interrupt service routines. High-level
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.5
■
The XMega Device Interrupts
273
interrupts may interrupt both low- and medium-level interrupt service routines. Low-level
interrupts have an optional round-robin scheme to make sure all interrupts are serviced within
a certain amount of time. The built-in oscillator failure detection mechanism can issue a
nonmaskable Interrupt (NMI).
9.5.1 PMIC Operation
Interrupts must be globally enabled for any interrupt to be generated. This is done by setting the global interrupt enable bit (I bit) in the CPU status register. The I bit is not cleared when
an interrupt is acknowledged (also true for Mega devices). Each interrupt level (high, medium,
and low) must be enabled before interrupts at the corresponding level can be generated.
When an interrupt is enabled and the interrupt condition is present, the PMIC receives the
interrupt request. Based on the interrupt level and interrupt priority of all ongoing interrupts,
the new interrupt is either acknowledged or kept pending until it has the priority.
The PMIC status register contains state information that ensures that the PMIC returns
to the correct interrupt level when the RETI instruction is executed at the end of an interrupt
handler. Returning from an interrupt returns the PMIC to the state it was at before entering the
interrupt service routine.
9.5.2 XMega Maskable Interrupts
All interrupts have an interrupt flag and individual control bits for enabling and setting
the interrupt level. When the interrupt condition is present, the interrupt flag is set, even if the
corresponding interrupt is not enabled. For most interrupts, the interrupt flag is automatically
cleared when the interrupt service routine is entered. The interrupt flag can also be cleared by
writing a 1 to it.
If an interrupt condition occurs while another interrupt of higher priority is being serviced
or pending, the interrupt flag is set and remembered until the interrupt has the priority. If an
interrupt condition occurs while the corresponding interrupt is not enabled, the interrupt flag
is set and remembered until the interrupt is enabled or the flag is cleared by software. Similarly,
if one or more interrupt conditions occur while global interrupts are disabled, the corresponding interrupt flag is set and remembered until the global interrupt is enabled. All pending interrupts are then serviced according to their orders of priority.
Interrupts are automatically disabled for up to 4 CPU clock cycles when the configuration
change protection register (CPU.CCP) is written with the correct signature. There are two CCP
signatures. One signature (0x9D) is for the store program memory (SPM) instruction. The other
(0xD8) is for protecting unintentional write into the protected peripheral registers. The user
must load the correct signature value into the CCP register before he or she can execute the
SPM instruction or write into the peripheral register protected by this mechanism.
9.5.3 XMega Nonmaskable Interrupt
Currently, the XMega devices have only one nonmaskable interrupt (NMI)—crystal
oscillator failure. An NMI is serviced regardless of the setting of the I bit and it does not change
the I bit. No maskable interrupt can interrupt a NMI interrupt handler.
9.5.4 XMega Interrupt Level
The interrupt level can be independently set for each interrupt source. Each interrupt
source uses two bits to configure its level as shown in Table 9.4.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
274
Chapter 9
■
Interrupt Handling, Resets, and Power Management
Interrupt level
configuration
Group configuration
00
OFF
Interrupt disabled
01
LO
Low-level interrupt
10
MED
11
HI
Description
Medium-level interrupt
High-level interrupt
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Table 9.4
XMega interrupt level
9.5.5 XMega Interrupt Priority
Within each interrupt level, all interrupts have a priority. Whenever several interrupt
requests are pending, the order of which interrupts are acknowledged is decided both by the
level and the priority of the interrupt request. Interrupts in high or medium level have static
priority. Low-level interrupts may have either static or round-robin (dynamic) priority within
the low level.
Interrupt vectors are located at fixed addresses. For static priority, the interrupt vector
decides the priority within one interrupt level where the lowest interrupt vector has the highest
priority. When the round-robin scheduling is enabled for low-priority interrupts, the interrupt
vector for the last acknowledged low-level interrupt has the lowest priority next time one or
more interrupts from the low level is requested. This is shown in Figure 9.11.
IVEC x is the last
acknowledged interrupt
IVEC 0
IVEC 0
Lowest priority
Highest priority
IVEC N
Figure 9.11
IVEC x
IVEC x+1 Lowest priority
IVEC x+2 Highest priority
IVEC N
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
IVEC x
IVEC x+1
IVEC x+1 is the last
acknowledged interrupt
Round-robin interrupt priority scheduling
9.5.6 PMIC Registers
The PMIC has three registers to support its functioning. The PMIC status register (PMIC.
STATUS) indicates which type of interrupts is being serviced (nonmaskable, high level, medium
level, or low level). The PMIC priority register (PMIC.INTPRI) stores the interrupt vector of the
last acknowledged low-level interrupt when the round-robin scheduling is enabled. The PMIC
control register (PMIC.CTRL) enables/disables round-robin scheduling, high-level interrupts,
medium-level interrupts, low-level interrupts, and interrupt vector relocation to boot section.
The contents of these registers are shown in Figure 9.12, Figure 9.13, and Figure 9.14, respectively.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
275
The XMega Device Interrupts
6
5
4
3
—
—
—
—
R
R
R
R
R
2
1
0
HILVLEX MEDLVLEX LOLVLEX
R
R
Reset value
= 0x00
R
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
NMIEX
NMIEX: Nonmaskable interrupt executing
0: Nonmaskable interrupt service routine is not executing.
1: Nonmaskable interrupt service routine is executing.
HILVLEX: High-level interrupt executing
0: High-priority-level interrupt service routine is not executing.
1: High-priority-level interrupt service routine is executing.
MEDLVLEX: Medium-level interrupt executing
0: Medium-priority-level interrupt service routine is not executing.
1: Medium-priority-level interrupt service routine is executing.
LOLVLEX: Low-level interrupt executing
0: Low-priority-level interrupt service routine is not executing.
1: Low-priority-level interrupt service routine is executing.
Figure 9.12
■
7
PMIC status register (PMIC.STATUS)
6
5
4
3
2
1
0
R/W
R/W
R/W
INTPRI[7:0]
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
INTPRI: Interrupt priority
When round-robin scheduling is enabled, this register stores the interrupt vector of the last acknowledged
low-level interrupt. The stored interrupt vector will have the lowest priority next time one or more low-level
interrupts are pending. The register is accessible from software to change the priority queue. This register
is not reinitialized to its initial value if round-robin scheduling is disabled. So if default static priority is
needed the register must be written into zero.
Figure 9.13
■
PMIC priority register (PMIC.INTPRI)
7
6
5
4
3
RREN
IVSEL
—
—
—
R/W
R/W
R
R
R
2
1
0
HILVLEN MEDLVLEN LOLVLEN
R/W
R/W
Reset value
= 0x00
R/W
RREN: Round-robin scheduling enable
0 = Low-level interrupts round-robin is disabled.
1 = Low-level interrupts round-robin is enabled.
IVSEL: Interrupt vector select
0 = Interrupt vectors are placed at the start of on-chip flash memory.
1 = Interrupt vectors are moved to the start of the boot section of the flash memory.
HILVLEN: High-level interrupt enable
0 = High-level interrupts disabled
1 = High-level interrupts enabled
MEDLVLEN: Medium-level interrupt enable
0 = Medium-level interrupts disabled
1 = Medium-level interrupts enabled
LOLVLEN: Low-level interrupt enable
0 = Low-level interrupts disabled
1 = Low-level interrupts enabled
Figure 9.14
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
■
PMIC control register (PMIC.CTRL)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
9.5
276
Chapter 9
■
Interrupt Handling, Resets, and Power Management
To change the IVSEL bit of the PMIC.CTRL register, the user must write the signature
value 0xD8 into the configuration change protection register (CCP) and then write the appropriate value into the PMIC.CTRL register to change the IVSEL bit.
9.5.7 XMega Interrupt Sources
Among all XMega devices, the XMega64A1/128A1/256A1/384A1 have the most pins and
interrupt sources. A base address is assigned to each peripheral module’s interrupts and each
peripheral module may have one or multiple interrupt sources. The base interrupt addresses
for the XMega A1 devices are given in Table 9.5. If a module has only one interrupt source,
then the base interrupt address is also its interrupt vector. The include file ATXMega128A1def.
inc (provided by AVR Studio IDE) contains the symbolic names of all interrupt vectors for the
assembly language programmers. The list of all interrupt vectors and their symbolic names is
given in Appendix B. The header file iox128a1.h contains the symbolic names of all interrupt
vector numbers (of XMega64A1/128A1/256A1/384A1) to be used to indicate interrupt source in
the interrupt service routine (for C language programmers). The complete list of these symbolic
names is given in Appendix C.
Base address
(word address)
Source
Description
0×000
RESET
0×002
OSCF_INT_vect
Crystal oscillator failure interrupt vector (NMI)
0×004
PORTC_INT_base
PORTC interrupt base
0×008
PORTR_INT_base
PORTR interrupt base
0×00C
DMA_INT_base
DMA controller interrupt base
0×014
RTC_INT_vect
Real-time counter interrupt base
0×018
TWIC_INT_base
Two-wire interface on PORTC interrupt
base
0×01C
TCC0_INT_vect
Timer/Counter0 on PORTC interrupt base
0×028
TCC1_INT_vect
Timer/Counter1 on PORTC interrupt base
0×030
SPIC_INT_vect
SPI on PORTC interrupt base
0×032
USARTC0_INT_base
USART0 on PORTC interrupt base
0×038
USARTC1_INT_base
USART1 on PORTC interrupt base
0×03E
AES_INT_vect
AES interrupt vector
0×040
NVM_INT_base
Nonvolatile memory interrupt base
0×044
PORTB_INT_base
PORTB interrupt base
0×048
ACB_INT_base
Analog comparator on PORTB interrupt base
0×04E
ADCB_INT_base
Analog to digital converter on PORTB
interrupt base
0×056
PORTE_INT_base
PORTE interrupt base
0×05A
TWIE_INT_base
Two-wire interface on PORTE interrupt base
0×05E
TCE0_INT_base
Timer/Counter0 on PORTE interrupt base
(Continued)
Table 9.5
■
Reset and interrupt vector base addresses
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.5
■
277
The XMega Device Interrupts
Table 9.5
■
(Continued)
Base address
(word address)
Source
Description
0×06A
TCE1_INT_base
Timer/Counter1 on PORTE interrupt base
0×072
SPIE_INT_vect
SPI on PORTE interrupt vector
0×074
USARTE0_INT_base
USART0 on PORTE interrupt base
0×07A
USARTE1_INT_base
USART1 on PORTE interrupt base
0×080
PORTD_INT_base
PORTD interrupt base
0×084
PORTA_INT_base
PORTA interrupt base
0×088
ACA_INT_base
Analog comparator on PORTA interrupt base
0×08E
ADCA_INT_base
Analog to digital converter on PORTA
interrupt base
0×096
TWID_INT_base
Two-wire interface on PORTD interrupt base
0×09A
TCD0_INT_base
Timer/Counter0 on PORTD interrupt base
0×0A6
TCD1_INT_base
Timer/Counter1 on PORTD interrupt base
0×0AE
SPID_INT_vect
SPI on PORTD interrupt vector
0×0B0
USARTD0_INT_base
USART0 on PORTD interrupt base
0×0B6
USARTD1_INT_base
USART1 on PORTD interrupt base
0×0BC
PORTQ_INT_base
PORTQ interrupt base
0×0C0
PORTH_INT_base
PORTH interrupt base
0×0C4
PORTJ_INT_base
PORTJ interrupt base
0×0C8
PORTK_INT_base
PORTK interrupt base
0×0D0
PORTF_INT_base
PORTF interrupt base
0×0D4
TWIF_INT_base
Two-wire interface on PORTF interrupt base
0×0D8
TCF0_INT_base
Timer/Counter0 on PORTF interrupt base
0×0E4
TCF1_INT_base
Timer/Counter1 on PORTF interrupt base
0×0EC
SPIF_INT_base
SPI on PORTF interrupt base
0×0EE
USARTF0_INT_base
USART0 on PORTF interrupt base
0×0F4
USARTF1_INT_base
USART1 on PORTF interrupt base
Source: Atmel Corporation, The Atmel AVR Microcontroller
9.5.8 XMega PORT Interrupt
Unlike Mega devices, XMega devices have neither dedicated interrupt pins nor pin-change
interrupts. Instead, each XMega I/O PORT has two interrupt vectors. Every pin can be configured to trigger an interrupt request. The I/O PORT uses a sensing circuit to detect an edge
or the level on the I/O pin. The different sense configurations that are available to each pin
are detection of a rising edge, a falling edge, both edges, and a low level. A high level can be
detected by using an inverted input. Input sensing is used to trigger interrupt requests or sense
when there is a change on the pin.
As shown in Figure 9.15, the I/O pins support synchronous and asynchronous input sensing. Synchronous sensing requires presence of the peripheral clock, while asynchronous sensing
does not require any clock.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
278
Chapter 9
■
Interrupt Handling, Resets, and Power Management
Edge
detect
Interrupt
control
IREQ
Synchronous sensing
Pn
Synchronizer
Edge
detect
D Q D Q
R
R
Inverted I/O
EVENT
clkIO
■
Figure 9.15
Source: Atmel Corporation, The Atmel AVR Microcontroller
Asynchronous sensing
XMega input sensing circuit
For synchronous sensing, all sense configurations are used to generate interrupts. For edge
detection, the changed pin value must be sampled once by the peripheral clock for an interrupt
request to be generated.
For asynchronous sensing, only the pin 2 of each PORT has full asynchronous sense support. This means that for edge detection, pin 2 detects and latches any edge, and it always triggers an interrupt request. The other PORT pins have limited asynchronous sense support. This
means that for edge detection the changed value must be held until the device wakes up and a
clock is present. If the pin value returns to its initial value before the end of the device startup
time, the device still wakes up, but no interrupt request is generated.
A low level is always detected by all pins, regardless of a peripheral clock being present or
not. If a pin is configured for low-level sensing, the interrupt is triggered as long as the pin is held
low. In active mode the low level must be kept until the completion of the currently executing
instructions for an interrupt to be generated. In all sleep modes the low level must be kept until
the end of the device startup time for an interrupt to be generated. If the low level disappears
before the end of the startup time, the device still wakes up, but no interrupt is generated.
INT0
AND
I N T 1 I N T E R R U P T C O N F I G U R AT I O N
7
6
5
4
3
—
—
—
—
INT1LVL[1:0]
R
R
R
R
R/W
INTnLVL[1:0]: Interrupt n level, n = 0 or 1
00 = Interrupt disabled
01 = Low level
10 = Medium level
11 = High level
Figure 9.16
■
2
R/W
1
0
INT0LVL[1:0]
R/W
R/W
Reset value
= 0x00
Source: Atmel Corporation, The Atmel
AVR Microcontroller
Like any other interrupt source, INT0 and INT1 can be configured to low, medium, or high
level. The PORTx.INTCTRL (x = A, …, R) register controls the setting of interrupt levels of
INT0 and INT1 for PORTx. The contents of this register are shown in Figure 9.16.
Interrupt control register (PORTx.INTCTRL)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.5
■
279
The XMega Device Interrupts
ASSIGNING I/O PINS
AS
SOURCES
OF
INT0
OR
INT1
6
5
4
3
2
1
0
R/W
R/W
R/W
2
1
0
R/W
R/W
R/W
INT0MSK[7:0]
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
INT0MSK[n]: Interrupt 0 mask, n = 7, …, 0
0 = Pin n is not the source for INT0 interrupt.
1 = Pin n is the source for INT0 interrupt.
Figure 9.17
■
7
Interrupt 0 mask register (PORTx.INT0MASK)
6
5
4
3
INT1MSK[7:0]
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
INT1MSK[n]: Interrupt 0 mask, n = 7, …, 0
0 = Pin n is not the source for INT1 interrupt.
1 = Pin n is the source for INT1 interrupt.
Figure 9.18
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
7
Source: Atmel Corporation,
The Atmel AVR Microcontroller
The user uses the PORTx.INT0MASK (x = A, …, R) and PORTx.INT1MASK registers to
select those pins that can generate INT0 or INT1 interrupt, respectively. The contents of these
two registers are shown in Figure 9.17 and Figure 9.18, respectively.
Interrupt 1 mask register (PORTx.INT1MASK)
I N P U T S E N S E C O N F I G U R AT I O N
7
6
5
4
3
2
1
0
R/W
R/W
R/W
MPCMASK[7:0]
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
MPCMASK[n]: Multi-pin configuration mask (n = 7, …, 0)
0 = Pin n is not part of the multi-pin configuration.
1 = Pin n is part of the multi-pin configuration.
When a pin configuration is written to one of the PINnCTRL registers of the PORT, that value is written
to all the PINnCTRL registers of the pins matching the bit pattern in the MPCMASK register for that
PORT. It is not necessary to write to one of the registers that is set by the MPCMASK register. The
MPCMASK register is automatically cleared after any PINnCTRL registers is written.
Figure 9.19
■
Multipin configuration mask register (PORTCFG.MPCMASK)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR
Microcontroller
After assigning a pin as a source of INT0 or INT1, the user also needs to configure the sense
of the pin. By configuring the sense of a pin, the user can choose to use the low level, rising
edge, falling edge, or both edges of a pin to interrupt the MCU. Each pin has an associated configuration register. The contents of the pin configuration register are shown in Figure 8.12. It
is common for multiple pins to have the same configuration. The multipin configuration mask
register allows multiple pins with identical configuration to be configured at the same time.
The contents of this register are shown in Figure 9.19.
280
Chapter 9
■
Interrupt Handling, Resets, and Power Management
INTERRUPT FLAG REGISTER
7
6
5
4
3
2
1
0
—
—
—
—
—
—
INT1IF
INT0IF
R
R
R
R
R
R
R/W
R/W
Reset value
= 0x00
INTnIF: Interrupt n flag (n = 0 or 1)
0 = No interrupt n condition occurred
1 = One or more of the input change according to the pin configuration has occurred.
Figure 9.20
■
Source: Atmel Corporation,
The Atmel AVR Microcontroller
The INT0 and INT1 interrupts of an I/O PORT has an associated flag bit in the interrupt flag register. The INTxIF flag is set when a pin change according to the pin’s input sense
configuration occurs, and the pin is set as source for PORT interrupt n. Writing a 1 to this
flag’s bit location clears the flag. The contents of the interrupt flag register are shown in
Figure 9.20.
Interrupt flag register (PORTx.INTFLAGS)
Example 9.3
▼
Write a sequence of assembly instructions to configure PORTA pins 3~0 as sources of INT0
and pins 7~4 as sources of INT1. Configure pins 3~0 to interrupt on the falling edge and pins
7~4 to interrupt on the rising edge. Place INT0 and INT1 at high- and medium-level priority,
respectively.
Solution: For pins 3~0, we disable slew rate limit and pin inverting input, configure pin to totem
pole, and interrupt on the falling edge. For pins 7~4, we disable slew rate limit and pin inverting input, configure pin output to totem pole, and interrupt on the rising edge. The following
instruction sequence can achieve the specified setting:
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
tmp,0
PORTA_DIR,tmp
tmp,0x0B
PORTA_INTCTRL,tmp
tmp,0x0F
PORTA_INT0MASK,tmp
tmp,0xF0
PORTA_INT1MASK,tmp
tmp,0x0F
PORTCFG_MPCMASK,tmp
tmp,0x02
PORTA_PIN0CTRL,tmp
tmp,0xF0
PORTCFG_MPCMASK,tmp
tmp,0x01
PORTA_PIN4CTRL,tmp
; configure PORTA for input
; INT1 at medium level, INT0 at high level
; "
; assign pin 3~0 as source of INT0
; "
; assign pin 7~4 as source of INT1
; "
; let pins 3~0 to be configured simultaneously
; "
; configure pins 3~0 to interrupt MCU
; on their falling edge, disable slew rate limit
; let pins 7~4 to be configured simultaneously
; "
; configure pins 7~4 to interrupt MCU
; on their rising edge, disable slew rate limit
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.5
■
281
The XMega Device Interrupts
Example 9.4
▼
Write a sequence of C statements to configure PORTA pins as described in Example 9.3.
Solution: The following C statements can perform the same configuration as that in Example 9.3:
PORTA.DIR
PORTA.INTCTRL
PORTA.INT0MASK
PORTA.INT1MASK
PORTCFG.MPCMASK
PORTA.PIN0CTRL
PORTCFG.MPCMASK
PORTA.PIN4CTRL
= 0;
= 0x0B;
= 0x0F;
= 0xF0;
= 0x0F;
= 0x02;
= 0xF0;
= 0x01;
// configure PORTA for input
// place INT1, INT0 at high, medium level
// assign pin 3~0 as source of INT0
// assign pin 7~4 as source of INT1
// let pin 3~0 to be configured simultaneously
// configure pin 3~0 to interrupt on falling edge
// let pin 7~4 to be configured simultaneously
// configure pin 7~4 to interrupt on rising edge
▲
Example 9.5
▼
Write an assembly main program and the service routine for the INT0 interrupt associated with
PORTF. The main program assigns the pin 0~3 of PORTF as a source of INT0 and configures it to interrupt on the rising edge and also configures PORTC pin 7, 5, 3, and 1 for output. INT0 is placed at highlevel priority. The INT0 service routine for PORTF simply toggles the PORTC odd pins and returns.
Solution: The following program performs the specified operations:
.include
.def
.cseg
.org
jmp
.org
jmp
.org
start: ldi
out
ldi
out
call
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
<ATXMega128A1def.inc>
tmp = r16
0x00
start
PORTF_INT0_vect
PF_INT0_ISR
0xF6
tmp,low(RAMEND)
CPU_SPL,tmp
tmp,high(RAMEND)
CPU_SPH,tmp
setCPUclkto32Mwith16Mcrystal
tmp,0xAA
PORTC_DIR,tmp
tmp,0xAA
PORTC_OUT,tmp
tmp,0
PORTF_DIR,tmp
tmp,0x0F
PORTF_INT0MASK,tmp
tmp,0x03
PORTF_INTCTRL,tmp
tmp,0x07
PMIC_CTRL,tmp
tmp,0x0F
; PORTF INT0 interrupt vector
; initialize the SP
; "
; "
; "
; configure PORTC pins 7, 5, 3, and 1 for output
; "
; set PORTC pins 7, 5, 3, and 1 to high initially
; "
; configure PORTF pin 0~3 for input
; "
; place pin 0~3 as a source of INT0
; "
; place INT0 at high-level priority
; "
; enable high-, medium-, and low-priority interrupts
; configure pin 0~3
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
282
Chapter 9
■
Interrupt Handling, Resets, and Power Management
sts
PORTCFG_MPCMASK,tmp
ldi
tmp,0x01
; configure PORTF pin 3~0 to interrupt
sts
PORTF_PIN0CTRL,tmp
; on the rising edge
sei
; enable interrupt globally
again: rjmp
again
; wait for INT0 interrupt to occur
; -------------------------------------------------------------------------------------------------------------; PORTF INT0 interrupt service routine toggles all PORTC pins and returns.
; -------------------------------------------------------------------------------------------------------------PF_INT0_ISR:
ldi
tmp,0x01
; clear the INT0IF flag
sts
PORTF_INTFLAGS,tmp
; "
ldi
tmp,0xAA
sts
PORTC_OUTTGL,tmp
; toggle pins PC7, PC5, PX3, and PC0
reti
.include "sysClock_XMega.asm"
▲
Example 9.6
▼
Write the C language version of the main function and interrupt service routine described
in Example 9.5.
Solution: The C language version of the main function and the service routine for the PORTF
INT0 interrupt are as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
#include "sysClock_XMega.h"
void main (void)
{
setCPUclkto32Mwith16MCrystal();
PORTC.DIR
= 0xAA;
// configure PORTC pins 7, 5, 3, and 1 for output
PORTC.OUT
= 0xAA;
// turn on PORTC odd pins
PORTF.DIR
= 0;
// configure PORTF pin 0~3 for input
PORTF.INT0MASK
= 0x0F;
// include PORTF pin 0~3 as sources of INT0
PORTF.INTCTRL
= 0x03;
// disable INT1, enable INT0 and place it at high-priority level
PORTCFG.MPCMASK
= 0x0F;
// configure PORTF pins 0~3 at the same time
PORTF.PIN0CTRL
= 0x01;
// configure PORTF pins 3~0 to interrupt on the rising edge
PMIC.CTRL
= 0x07;
// enable high-, medium-, and low-level interrupts
sei();
// enable interrupt globally
while(1);
}
// ----------------------------------------------------------------------------------------------------------------// PORTF INT0 interrupt service routine clears INT0IF flag and toggles PORTC pins.
// ----------------------------------------------------------------------------------------------------------------ISR (PORTF_INT0_vect)
{
PORTF.INTFLAGS
= 0x01;
// clear INT0IF flag
PORTC.OUTTGL
= 0xAA;
// toggle PORTC pins 7, 5, 3, and 1
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.6
■
283
AVR Mega Reset
9.6 AVR Mega Reset
During reset, all I/O registers are set to their default values, and the program starts execution from the reset vector. The ATMega640/1280/2560 has five sources of reset:
•
Power-on reset. The MCU is reset when the supply voltage is below the power-on
reset threshold (VPOT). A power-on reset (POR) circuit ensures that the device is
reset when the power is turned on. After VCC reaches VPOT, the POR circuit starts
a delay counter which determines the amount of time that the MCU remains in
reset state.
•
External reset. The MCU is reset when a low level is present on the RESET pin for
longer than the minimum pulse width (the minimum interval that the voltage on
the RESET pin is below VRST).
•
Brown-out reset. The MCU is reset when the supply voltage VCC is lower than the
brown-out reset threshold (VBOT–) and the brown-out detector is enabled. When
the power supply drops below the acceptable level, the MCU cannot execute
instructions correctly without corrupting the nonvolatile memory. The solution
is to reset the MCU. The reset state in this situation is called brown-out reset.
The MCU gets out of brown-out reset when VCC rises above a level (VBOT+) slightly
higher than VBOT−.
•
JTAG AVR reset. The MCU is reset as long as there is a logic 1 in the reset register,
one of the scan chains of the JTAG system.
•
Watchdog reset. The MCU is reset when the watchdog timer overflows and the
watchdog is enabled.
7
6
5
4
3
2
1
0
—
—
—
JTRF
WDRF
BORF
EXTRF
PORF
R
R
R
R/W
R/W
R/W
R/W
R/W
JTRF: JTAG reset flag
0 = Reset is not caused by JTAG reset.
1 = Reset is caused by a logic 1 in the JTAG reset register selected by the JTAG instruction AVR_RESET.
This bit is cleared by a power-on reset or writing a 0 to it.
WDRF: Watchdog reset flag
0 = Reset is not caused by watchdog time out.
1 = Reset is caused by watchdog time out (timer overflow). This bit is cleared by a power-on reset or
writing a 0 to it.
BORF: Brown-out reset flag
0 = Reset is not caused by brown out.
1 = Reset is caused by brown-out reset. This bit is cleared by a power-on reset or writing a 0 to it.
EXTRF: External reset flag
0 = Reset is not caused by RESET pin.
1 = Reset is caused by RESET pin. This bit is cleared by a power-on reset or writing a 0 to it.
PORF: Power-on reset flag
0 = Reset is not caused by power-on reset.
1 = Power-on reset occurred. This bit is cleared by a power-on reset or writing a 0 to it.
Figure 9.21
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
The reset service routine finds out the cause of reset by examining the MCU status register
(MCUSR). The contents of MCUSR are shown in Figure 9.21.
MCU status register (MCUSR)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
284
Chapter 9
■
Interrupt Handling, Resets, and Power Management
9.7 AVR Mega Watchdog Timer
ATMega640/1280/2560 has a watchdog timer that derives its clock signal from an on-chip
128-kHz oscillator. The WDT triggers an interrupt or reset when the counter overflows. To prevent the WDT from timing out, execute the WDR instruction to restart the WDT.
In interrupt mode, the WDT generates an interrupt when the timer overflows. This interrupt is used to wake up the MCU from sleep mode, and also as a general system timer. One
example is to limit the maximum time allowed for certain operations, by requesting an interrupt when the operation has run longer than expected. In system reset mode, the WDT resets
the MCU when the timer expires. This is often used to prevent a system from hanging-up in
case of runaway code. The third mode, interrupt and system reset mode, combines the other
two modes by first requesting an interrupt and then switch to system reset mode. This mode
allows a safe shutdown by saving critical parameters before a system reset.
The WDT can be forced to operate in system reset mode by programming the
Watchdog-always-on fuse (WDTON bit cleared to 0). The operation of WDT is controlled by
the Watchdog timer control register (WDTCSR). When the Watchdog-always-on fuse is programmed, the system reset mode bit (WDE) and interrupt mode bit (WDIE) is locked to 1 and
0, respectively, which forces the WDT to operate in system reset mode. The contents of the
WDTCSR register are shown in Figure 9.22.
6
5
4
3
2
1
0
WDIE
WDP3
WDCE
WDE
WDP2
WDP1
WDP0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0b0000 x 000
WDIF: Watchdog interrupt flag
0 = WDT did not time out since last time it was cleared.
1 = WDT was configured in interrupt mode and a WDT time-out has occurred. This bit is cleared
by writing a 1 to it or when its service routine is entered.
WDIE: Watchdog interrupt enable
See Table 9.6.
WDCE: WDT change enable
This bit is used in timed sequences for changing WDE and prescaler bits. To clear the WDE bit,
and/or change the prescaler bits, WDCE must be set.
WDE: Watchdog system reset enable.
See Table 9.6. WDE is overridden by WDRF in MCUSR. To clear WDE, WDRF must be cleared
first.
WDP3~0: Watchdog timer prescaler 3, 2, 1, and 0.
This four bits determine the Watchdog timer prescaling when the Watchdog timer is running. The
possible prescale factors are listed in Table 9.7.
Figure 9.22
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
WDIF
Watchdog timer control register (WDTCSR)
WDCE
WDE
WDIE
Mode
Action on time-out
1
0
0
Stopped
None
1
0
1
Interrupt mode
Interrupt
1
1
0
System reset mode
Reset
1
1
1
Interrupt and system reset mode
Interrupt, then go to system reset mode
0
x
x
System reset mode
Reset
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.6
■
Watchdog timer configuration
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.7
■
285
AVR Mega Watchdog Timer
WDP3
WDP2
WDP1
WDP0
Number of WDT
oscillator cycles
Typical time-out at
VCC = 5.0 V
0
0
0
0
2 k cycles
16 ms
0
0
0
1
4 k cycles
32 ms
0
0
1
0
8 k cycles
64 ms
0
0
1
1
16 k cycles
0.125 ms
0
1
0
0
32 k cycles
0.25 ms
0
1
0
1
64 k cycles
0.5 s
0
1
1
0
128 k cycles
1.0 s
0
1
1
1
256 k cycles
2.0 s
1
0
0
0
512 k cycles
4.0 s
1
0
0
1
1024 k cycles
8.0 s
1
0
1
0
1
0
1
1
1
1
0
0
1
1
0
1
1
1
1
0
1
1
1
1
Reserved
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.7
■
Watchdog timer prescale select
To ensure program security, the user is required to follow a timed sequence to change the
WDT configuration:
1. In the same operation, write a logic 1 to the Watchdog change enable (WDCE) and
WDE. A logic 1 must be written to WDE regardless of the previous value of the WDE
bit.
2. Within the next four clock cycles, write the WDE and watchdog prescaler bits (WDP)
as desired, but with the WDCE bit cleared. This must be done in one operation.
Example 9.7
▼
Write an assembly subroutine to disable Watchdog timer.
Solution: The following subroutine disables the Watchdog timer:
disableWDT:
cli
wdr
in
ori
out
lds
ori
sts
; disable global interrupt
; reset WDT
r16, MCUSR
r16,(1 << WDRF)
MCUSR,r16
r16,WDTCSR
r16,(1<<WDCE)|(1<<WDE)
WDTCSR,r16
; clear WDRF bit by writing a 1 to WDRF flag
; "
; get a copy of WDTCSR
; sets WDCE and WDE bits
; enable WDT change
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
286
Chapter 9
■
ldi
sts
sei
ret
Interrupt Handling, Resets, and Power Management
r16,0
WDTCSR,r16
; clear WDE and WDCE bits
; "
; turn on global interrupt
▲
Example 9.8
▼
Write a C function to disable the Watchdog timer.
Solution: The following C function disables the Watchdog timer:
#include <avr\wdt.h> // include WDT definition
#include <avr\interrupt.h> // include interrupt definitions
void disableWDT (void)
{
cli();
// disable global interrupt
wdt_reset(); // execute wdt instruction to reset WDT
MCUSR |= (1 << WDRF); // clear the WDRF flag by writing a 1 to it
WDTCSR |= (1<<WDCE) | (1 << WDE); // allow WDCE to change
WDTCSR = 0x00;
// disable WDT timer
sei();
// turn on global interrupt
}
▲
9.8 XMega Reset
The XMega devices have seven reset sources:
•
•
•
•
•
•
•
Power-on reset
Brown-out reset
Spike detection reset (not available in Mega devices)
Software reset (not available in Mega devices)
External reset pin reset
Watchdog reset
Program and debug interface (PDI) reset (similar to JTAG reset of Mega device)
If more than one reset source is active, the device is kept in reset until all reset sources
have released their reset. After reset is released from all reset sources, the default oscillator is
started and calibrated before the internal reset is released and the device starts running.
The XMega reset system has a status register (shown in Figure 9.23) with individual flags
for each reset source. The status register is cleared at power-on reset; hence this register shows
which source that has issued a reset since the last power-on. A software reset feature makes
it possible to issue a system reset from the user software in case of severe program bugs. The
software reset is triggered by writing a 1 to the bit 0 (SWRST) of the reset control register (RST.
CTRL). Only the bit 0 of this register is implemented.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
287
XMega Reset
7
6
5
4
3
2
1
0
—
SDRF
SRF
PDIRF
WDRF
BORF
EXTRF
PORF
R
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Initial value
= 0x00
SDRF: Spike detection reset flag
0 = No power-spike reset occurred
1 = Power-spike reset has occurred since last power-on reset.
SRF: Software reset flag
0 = No software reset occurred
1 = Software reset has occurred since last power-on reset.
PDIRF: Program and debug interface reset flag
0 = Program and Debug interface reset didn’t occur.
1 = Program and Debug interface reset has occurred.
WDRF: Watchdog reset flag
0 = Watchdog timer didn’t time out since last power-on reset.
1 = Watchdog timer has time out (timer overflow). This bit is cleared by a power-on reset or writing a 0 to it.
BORF: Brown-out reset flag
0 = Reset is not caused by brown out.
1 = Reset is caused by brown-out reset. This bit is cleared by a power-on reset or writing a 0 to it.
EXTRF: External reset flag
0 = Reset is not caused by RESET pin.
1 = Reset is caused by RESET pin. This bit is cleared by a power-on reset or writing a 0 to it.
PORF: Power-on reset flag
0 = Reset is not caused by power-on reset.
1 = Power-on reset occurred. This bit is cleared by a power-on reset or writing a 0 to it.
Figure 9.23
■
XMega reset status register (STATUS)
9.8.1 XMega Brown-Out Reset
The operation of the XMega brown-out detection circuit is similar to that of the Mega
devices with two exceptions:
•
XMega devices have a programmable brown-out level. The brown-out reset trigger
level can be set to from 1.6 up to 3.2 V by programming the fuse BODLEVEL[2:0]
using the AVR Studio IDE. Possible brown-out voltage levels are given in Table 9.8.
BOLDLEVEL[2:0]
VBOT (V)
111
1.6
110
1.8
101
2.0
100
2.2
011
2.4
010
2.7
001
2.9
000
3.2
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.8
■
Programmable BODLEVEL setting
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
9.8
288
Chapter 9
•
■
Interrupt Handling, Resets, and Power Management
The brown-out circuit of the XMega device has three modes of operation: sampled,
enabled, and disabled. The mode of operation is selected by programming the BODACT
and BODDS fuses. The settings of these two sets of fuses are shown in Table 9.9.
BODACT[1:0]/
BODDS[1:0]
Mode
00
Reserved
01
Sampled
10
Enabled
11
Disabled
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.9
■
BOD setting fuse decoding
9.8.2 Spike Detector Reset
tSD
VCC
VDROP
tTOUT
Time-out
Internal
reset
Figure 9.24
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The spike detection (SD) circuit detects negative spikes on VCC. When enabled the spike
detection circuit continuously monitors the VCC level and triggers a reset if there is a negative
spike on the VCC level. For a spike to be detected, the VCC fall must be significant and last for
longer than a minimum time. The voltage drop, VDROP, and the minimum, tSD, is dependent on
each other. A large voltage drop requires a shorter minimum time to generate a reset and vice
versa. The operation of spike detection is illustrated in Figure 9.24.
Spike detection reset
9.8.3 XMega Watchdog Timer
Unlike Mega devices, the Watchdog timer of the XMega device can only reset the MCU.
The WDT of the XMega device operates in normal mode or window mode.
In normal mode, a single time-out period is set for the WDT. If the WDT is not reset
from the application code before the time out occurs the WDT triggers a system reset. There
are 11 possible WDT time-out periods selectable from 8 ms to 8 s. The normal mode WDT
time-out period is defined by bit 5~2 of the Watchdog control register (WDT.CTRL). The
contents of WDT.CTRL are shown in Figure 9.25. The default time-out period is controlled
by fuses.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
289
XMega Reset
7
6
—
—
5
R
R/W
4
3
2
PER[3:0]
R/W
R/W
R/W
1
0
ENABLE
CEN
R/W
R/W
R/W
Reset value
= 0b00xxxxx0
PER[3:0]: Watchdog time-out period
These bits determine the Watchdog time-out period as a number of 1-kHz ultra-low-power
oscillator cycles. The different typical time-out periods are given in Table 9.10. The initial values of
these bits are set by the Watchdog time-out period (WDP) fuses.
ENABLE: Watchdog enable
0 = Watchdog timer disabled
1 = Watchdog timer enabled. The CEN bit must be set in order to change this bit.
CEN: Watchdog change enable
This bit enables the possibility to change the configuration of the CTRL register. When writing a new
value to this register, this bit must be written to one at the same time for the changes to take effect.
Figure 9.25
■
XMega Watchdog timer control register (WDT.CTRL)
PER[3:0]
Group configuration
Typical time-out periods
0000
8 CLK
8 ms
0001
16 CLK
16 ms
0010
32 CLK
32 ms
0011
64 CLK
64 ms
0100
125 CLK
0.125 ms
0101
250 CLK
0.25 ms
0110
500 CLK
0.5 s
0111
1 kCLK
1.0 s
1000
2 kCLK
2.0 s
1001
4 kCLK
4.0 s
1010
8 kCLK
8.0 s
1011
1100
1101
Reserved
1110
1111
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.10
■
Watchdog time-out periods
In window mode, the WDT uses two different time-out periods, a closed window time-out
period (TOWDTW) and the normal time-out period (TOWDT). The closed window time-out period
defines a duration from 8 ms to 8 s, during which the WDT cannot be reset: If the WDT is reset
in this period the WDT issues a system reset. The normal WDT time-out period, which is also
8 ms to 8 s, defines the duration of the open period, in which the WDT can be reset. The open
period follows the closed period, so the total duration of the time-out period is the sum of the
closed window and the open window time-out periods. The default closed window time-out
period is controlled by fuses. The closed window time-out period is defined by the window mode
control register (WDT.WINCTRL). The contents of WDT.WINCTRL are given in Figure 9.26.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
9.8
Chapter 9
■
Interrupt Handling, Resets, and Power Management
7
6
5
—
—
R
R/W
4
3
2
WPER[3:0]
R/W
R/W
R/W
R/W
1
0
WEN
WCEN
R/W
R/W
Reset value =
0b00xxxxx0
WPER[3:0]: Watchdog window mode time-out period
These bits determine the closed window period as a number of 1-kHz ultra-low-power oscillator
cycles in window mode operation. The different typical time-out periods are given in Table 9.11.
The initial values of these bits are set by the Watchdog window time-out period (WDWP) fuses.
WEN: Watchdog window mode enable
0 = Watchdog window mode disabled
1 = Watchdog window mode enabled. The WCEN bit must be set in order to change this bit.
WCEN: Watchdog window mode change enable
This bit enables the possibility to change the configuration of the WINCTRL register. When writing
a new value to this register, this bit must be written to one at the same time for the changes to
take effect.
Figure 9.26
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
290
XMega Window mode control register (WDT.WINCTRL)
WPER[3:0]
Group configuration
Typical closed window
periods
0000
8 CLK
8 ms
0001
16 CLK
16 ms
0010
32 CLK
32 ms
0011
64 CLK
64 ms
0100
125 CLK
0.125 ms
0101
250 CLK
0.25 ms
0110
500 CLK
0.5 s
0111
1 kCLK
1.0 s
1000
2 kCLK
2.0 s
1001
4 kCLK
4.0 s
1010
8 kCLK
8.0 s
1011
1100
1101
Reserved
1110
1111
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.11
■
Watchdog closed window periods
The WDT is clocked from the 1-kHz output from the internal 32-kHz ultra-low-power
oscillator. To avoid unintentional changes of the WDT settings, the WDT is designed with two
security mechanisms. The first mechanism is the configuration change protection mechanism,
employing a timed write procedure for changing the WDT control registers. In addition, for the
new configuration to be written to the control registers, the register’s change enable bit must
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.8
■
291
XMega Reset
be written at the same time. The second mechanism is to lock the configuration by setting the
WDT lock fuse. When this fuse is set, the watchdog time control register cannot be changed;
hence the WDT cannot be disabled from software. When the WDT lock fuse is programmed
the window mode time-out period cannot be changed, but the window mode itself can still be
enabled or disabled.
When writing to the WDT.CTRL or WDT.WINCTRL registers, the WDT needs to be synchronized to other clock domains. During synchronization the SYNCBUSY bit of the watchdog
status register is read as one. This bit is automatically cleared after the synchronization is finished. Synchronization only takes place when the ENABLE bit for the Watchdog Timer is set.
The contents of the STATUS register are shown in Figure 9.27.
7
6
5
4
3
2
1
—
—
—
—
—
—
—
0
Reset value
SYNCBUSY = 0x00
SYNCBUSY: Watchdog busy synchronization bit
0 = WDT is synchronized to other clock domain already.
1 = WDT is synchronizing to other clock domain.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 9.27
■
WDT status register (WDT.STATUS)
9.8.4 XMega WDT Programming
When accessing WDT-associated registers, the user needs to refer to the WDT module. For
example, the WDT control register can be accessed by referring to the name WDT.CTRL. The
available module names for the XMega devices are listed in Appendix D.
Example 9.9
▼
Write a function to enable Watchdog timer to normal mode, a function to enable watchdog timer to normal mode and also set its time-out period, and a function to disable the
Watchdog timer.
Solution: The C function that enables the Watchdog without changing the time-out period is
as follows:
#define WDT_IsSyncBusy() (WDT.STATUS & WDT_SYNCBUSY_bm)
void WDT_Enable(void)
{
unsigned char temp = WDT.CTRL | WDT_ENABLE_bm | WDT_CEN_bm;
CCP
= CCP_IOREG_gc; // signature for accessing protected registers
WDT.CTRL
= temp;
/* Wait for WD to synchronize with new settings. */
while(WDT_IsSyncBusy());
}
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
292
Chapter 9
■
Interrupt Handling, Resets, and Power Management
The C function that enables the Watchdog and also changes its time-out period is as follows:
void EnableWDTAndSetTimeout (WDT_PER_t period)
{
unsigned char temp;
temp
= WDT_ENABLE_bm | WDT_CEN_bm | period;
CCP
= CCP_IOREG_gc; // signature for accessing protected registers
WDT.CTRL = temp;
/* Wait for WD to synchronize with new settings. */
while(WDT_IsSyncBusy());
}
The function that disables the Watchdog timer is as follows:
void WDT_Disable(void)
{
unsigned char temp;
temp
= (WDT.CTRL & ~WDT_ENABLE_bm) | WDT_CEN_bm;
CCP
= CCP_IOREG_gc; // signature for accessing protected register
WDT.CTRL = temp;
}
▲
Example 9.10
▼
Write a function to enable the Watchdog to window mode without changing its time-out
period, a function to enable the Watchdog to window mode and also set its time-out period, and
also a function to disable window mode.
Solution: The C function that enables the Watchdog timer to window mode without changing
the time-out period is as follows:
// The WDT must be enabled before enabling window mode and a true value is returned if this condition
// is met.
#define WDT_IsSyncBusy() (WDT.STATUS & WDT_SYNCBUSY_bm)
unsigned char WDT_EnableWindowMode(void)
{
unsigned char wd_enable = WDT.CTRL & WDT_ENABLE_bm;
unsigned char temp = WDT.WINCTRL | WDT_WEN_bm | WDT_WCEN_bm;
CCP = CCP_IOREG_gc; // signature for accessing protected register
WDT.WINCTRL = temp;
while (WDT_IsSyncBusy()); // Wait for WDT to synchronize with new settings.
return wd_enable;
}
The C function that enables the Watchdog timer to window mode and also sets the timeout period is as follows:
// The WDT must be enabled before enabling window mode and a true value is returned if this condition // is met.
WDT_WPER_t is an enumeration type that defines all the possible values for window mode // period.
unsigned char EnableWDTWindowModeAndSetTimeout(WDT_WPER_t period)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.9
■
Power Management and Sleep Modes
293
{
unsigned char wd_enable = WDT.CTRL & WDT_ENABLE_bm;
unsigned char temp = WDT_WEN_bm | WDT_WCEN_bm | period;
CCP = CCP_IOREG_gc; // signature for accessing protected register
WDT.WINCTRL = temp;
while(WDT_IsSyncBusy()); // Wait for WDT to synchronize with new settings.
return wd_enable;
}
The following function disables the WDT window mode:
void DisableWDTWindowMode(void)
{
unsigned char temp = (WDT.WINCTRL & ~WDT_WEN_bm) | WDT_WCEN_bm;
CCP = CCP_IOREG_gc; // signature for accessing protected register
WDT.WINCTRL = temp;
}
▲
9.9 Power Management and Sleep Modes
Most microcontrollers/microprocessors (including AVR) are fabricated using the CMOS
technology. When the CMOS transistors are not switching, they consume no power. This principle is used to reduce the power consumption of microprocessors/microcontrollers.
Because embedded systems are often powered by batteries, it is crucial to reduce the power
consumption of their controllers—microcontrollers so that the user does not need to change
batteries frequently. Both the AVR Mega and XMega devices provide several sleep modes to
save power consumption. Since the switching of modules within the MCU is controlled by the
clock signal, the sleep mode cuts down power consumption by turning off clock input to the
appropriate modules.
Sleep mode is entered by setting the SE bit of the SMCR register of the Mega device (or the
SEN bit of the SLEEP.CTRL register of the XMega device) and execute the SLEEP instruction.
A sleeping MCU is woken up by an enabled interrupt or a reset. The available interrupt wakeup sources are dependent on the selected sleep mode. When an enabled interrupt occurs, the
device wakes up and executes the interrupt service routine before continuing normal program
execution from the first instruction after the SLEEP instruction. After waking up, the CPU
is halted for four clock cycles in addition to the system clock startup time before executing
instructions. If a reset occurs during sleep mode, the MCU wakes up and executes from the
reset vector.
Because the sleep mode of the Mega and XMega are slightly different, they are described in
separate sections.
9.9.1 Mega Sleep Modes
The Mega device has six sleep modes as summarized in Table 9.12.
The sleep mode is selected by the SMCR register. The contents of the SMCR register are
shown in Figure 9.28. The SE bit of this register should be written to one just before the execution of the SLEEP instruction and cleared immediately after waking up.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Interrupt Handling, Resets, and Power Management
clkASY
Main clock source
enabled
Timer OSC enabled
INT7:0 and pin change
TWI address match
ADT interrupt
Other I/O
X
X
X
X
X(1)
X
X
X
X
X
X
X
X
X
X
X(1)
X(2)
X
X(1)
X
X
X
X(2)
X
X(2)
X
(2)
X
X
X(2)
X
ADCNRM
Power-down
Power-save
Standby
Wakeup sources
clkADC
Idle
Oscillators
clkIO
clkCPU
Sleep mode
clkFLASH
Active clock domain
(1)
X
(3)
X
X
Extended
standby
X(1)
X(1)
X
ADC
■
SPM/EEPROM ready
Chapter 9
Timer2
294
X
X
X
X
X
X
Notes: 1. If Timer/Counter2 is running in asynchronous mode.
2. For INT7:4, only level interrupt
3. Only recommended with external crystal or resonator selected as clock source
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Summary of Mega device sleep modes
7
6
5
4
3
2
1
0
—
—
—
—
SM2
SM1
SM0
SE
R
R
R
R
R/W
R/W
R/W
R/W
Reset value
= 0x00
SM2~SM0: Sleep mode select bits
000 = Idle mode
001 = ADC noise reduction
010 = Power-down
011 = Power save
110 = Standby (recommended for external crystals or oscillators)
111 = Extended standby (recommended for external crystals or oscillators)
100~101 = Reserved
SE: Sleep enable
0 = Disable sleep mode
1 = Enable sleep mode
Figure 9.28
■
Sleep mode control register (SMCR)
IDLE MODE
In this mode, the CPU is stopped, and the clock inputs (clkCPU and clkFLASH) to the CPU
and flash memory are disabled. Other modules, including the SPI, USART, Analog comparator,
ADC, TWI, Timer/Counters, Watchdog, and the interrupt system, continue to operate. In this
mode, the CPU is woken up by resets, external triggered interrupts, and internal ones like timer
overflow and USART transmit complete interrupts.
ADC NOISE REDUCTION MODE
This sleep mode halts clkI/O, clkCPU, and clkFLASH while allowing the other clocks to run;
hence the associated peripheral modules are allowed to operate. This mode improves the noise
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.12
9.9
■
Power Management and Sleep Modes
295
environment for the ADC, enabling higher resolution measurements. If the ADC is enabled, a
conversion starts automatically when this mode is entered. Apart from the ADC conversion
complete interrupt, an external reset, a TWI interrupt, a Timer/Counter2 interrupt, an SPM/
EEPROM ready interrupt, an external-level interrupt on INT7~4, or a pin change interrupt
wakes up the MCU from the ADC noise reduction mode.
POWER-DOWN MODE
In this mode, the external oscillator is stopped, while the external interrupts, TWI, and the
Watchdog continue to operate (if enabled). In this mode, the MCU is awakened by an external
reset, a watchdog reset, a brown-out reset, a TWI address match, an external level interrupt on
INT7~4, an external interrupt on INT3~0, or a pin change interrupt. This mode halts all generated clocks, allowing operation of asynchronous modules only.
When waking up from this mode, a delay from the wake-up condition occurs until the
wake-up becomes effective. This allows the clock to restart and become stable after having
been stopped. The wake-up period is defined by the same CLSEL fuses that define the reset
time-out period explained earlier.
POWER-SAVE MODE
This mode is identical to power-down mode with one exception: If Timer/Counter2 is
enabled, it keeps running during sleep. The device wakes up from either Timer overflow
or output compare match from Timer2 if these two interrupts are enabled (global interrupt
enable bit must be set too). If Timer/Counter2 is not running, then power-down mode is recommended instead of this mode.
The Timer/Counter2 can be clocked both synchronously and asynchronously in powersave mode. If the Timer/Counter2 is not using the asynchronous clock, the Timer/Counter
oscillator is stopped during sleep. If the Timer/Counter2 is not using the synchronous clock,
then it is stopped during sleep.
S TA N D B Y M O D E
This mode is identical to the power-down mode with the exception that the oscillator is
kept running. From this mode, the MCU wakes up in six clock cycles.
E X T E N D E D S TA N D B Y M O D E
This mode should only be chosen when an external oscillator/oscillator is selected as the
system clock source. This mode is identical to the power-save mode with the exception that
the oscillator is kept running. From this mode, the device wakes up in six clock cycles.
POWER REDUCTION REGISTER
In addition to the appropriate sleep mode, the user can also disable the clock input to modules that are not needed in the application via one of the Power Reduction Registers (PRR0
and PPR1) to reduce power consumption. Disabling clock inputs to an idle module is done in
the normal mode. The contents of PRR0 and PRR1 are shown in Figure 9.29 and Figure 9.30,
respectively.
It is easy to enable the sleep mode. For example, the following instruction sequence enables
the Mega MCU to standby mode:
ldi
sts
sleep
r16,0x0D
SMCR,r16
; enable standby sleep mode
; "
; put the MCU in standby sleep mode
The following C statements achieve the same setting:
SMCR = 0x0D;
__asm__ __volatile__ ("sleep");
// there are two underscore characters before and after
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
Interrupt Handling, Resets, and Power Management
7
6
5
4
3
2
1
0
PRTWI
PRTIM2
PRTIM0
—
PRTIM1
PRSPI
PRUSART0
PRADC
R
R
R
R
R/W
R/W
R/W
R/W
Reset value
= 0x00
PRTWI: Power reduction TWI
Writing a logic 1 to this bit shuts down the TWI by stopping the clock to the module. When waking
up the TWI again, the TWI should be reinitialized to ensure proper operation.
PRTIM2: Power reduction Timer/Counter2
Writing a logic 1 to this bit shuts down the Timer/Counter2 module in synchronous mode (AS2 is 0).
When the Timer/Counter2 is re-enabled, operation will continue like before the shutdown.
PRTIM0: Power reduction Timer/Counter0
Writing a logic 1 to this bit shuts down the Timer/Counter0 module. When the Timer/Counter0 is
re-enabled, operation will continue like before the shutdown.
PRTIM1: Power reduction Timer/Counter1
Writing a logic 1 to this bit shuts down the Timer/Counter1 module. When the Timer/Counter1 is
re-enabled, operation will continue like before the shutdown.
PRSPI: Power reduction SPI
Writing a logic 1 to this bit shuts down the SPI module by stopping the clock to the module. When
waking up the SPI again, the SPI should be reinitialized to ensure proper operation.
PRUSART0: Power reduction USART0
Writing a logic 1 to this bit shuts down the USART0 by stopping the clock to the module. When
waking up the USART0 again, the USART0 should be reinitialized to ensure proper operation.
PRADC: Power reduction ADC
Writing a logic 1 to this bit shuts down the ADC. The ADC must be disabled before shut down. The
analog comparator cannot use the ADC input MUX when the ADC is shut down.
Figure 9.29
■
Power reduction register 0 (PRR0)
7
6
5
4
3
—
—
PRTIM5
PRTIM4
PRTIM3
R
R
R
R
R/W
2
1
0
Reset value
PRUART3 PRUSART2 PRUSART1 = 0x00
R/W
R/W
R/W
PRTIM5: Power reduction Timer/Counter5
Writing a logic 1 to this bit shuts down the Timer/Counter5 module. When the Timer/Counter5
is re-enabled, operation will continue like before the shutdown.
PRTIM4: Power reduction Timer/Counter4
Writing a logic 1 to this bit shuts down the Timer/Counter4 module. When the Timer/Counter4
is re-enabled, operation will continue like before the shutdown.
PRTIM3: Power reduction Timer/Counter3
Writing a logic 1 to this bit shuts down the Timer/Counter3 module. When the Timer/Counter3
is re-enabled, operation will continue like before the shutdown.
PRUSART3: Power reduction USART3
Writing a logic 1 to this bit shuts down the USART3 module. When the USART3 is re-enabled,
the USART3 must be reinitialized to ensure proper operation.
PRUSART2: Power reduction USART2
Writing a logic 1 to this bit shuts down the USART2 module by stopping clock input to the
module. When waking up the USART2 again, the USART2 should be reinitialized to ensure
proper operation.
PRUSART1: Power reduction USART0
Writing a logic 1 to this bit shuts down the USART1 by stopping the clock to the module. When
waking up the USART1 again, the USART1 should be reinitialized to ensure proper operation.
Figure 9.30
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Chapter 9
Source: Atmel Corporation, The Atmel AVR Microcontroller
296
Power reduction register 1 (PRR1)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.9
■
297
Power Management and Sleep Modes
9.9.2 XMega Sleep Modes
The XMega MCU has a sleep module to control the sleep mode operation. There are five
sleep modes. A summary of these sleep modes is given in Table 9.13. The sleep mode is enabled
and selected via the control register (CTRL) in the SLEEP module. The contents of the CTRL
register are shown in Figure 9.31.
X
Power-down
Power-save
X
Standby(1)
X
X
Extended
standby
X
X
All interrupts
X
Real-time clock
interrupt
X
TWI address
match interrupt
RTC clock source
X
X
X
X
X
X
X
X
X
X
X
X
X
Asynchronous
PORT interrupt
System clock
source
Idle
Wake-up sources
RTC clock
Sleep mode
Oscillators
Peripheral clock
CPU clock
Active clock domain
X
X
X
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 9.13
■
Summary of XMega device sleep modes
7
6
5
4
—
—
—
—
R
R
R
R
3
2
1
R/W
R/W
0
SEN
SMODE[2:0]
R/W
Reset value
= 0x00
R/W
SMODE[2:0] SEN
Group configuration
Description
xxx
0
OFF
No sleep mode enabled
000
1
IDLE
Idle mode
010
1
PDOWN
Power-down mode
011
1
PSAVE
Power-save mode
110
1
STDBY
Standby mode
111
1
ESTDBY
Extended standby mode
Others
1
—
Reserved
SEN: Sleep enable
This bit must be set to make the MCU enter the selected sleep mode
when the SLEEP instruction is executed.
Figure 9.31
■
Sleep control register (SLEEP .CTRL)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
SMODE[2:0]: Sleep mode selection
298
Chapter 9
■
Interrupt Handling, Resets, and Power Management
IDLE MODE
In this mode, the CPU and flash memory are disabled, but all peripheral modules, including
the interrupt controller, event system, and DMA controller, are running. The device is woken
up by any interrupt and reset.
POWER-DOWN MODE
In this mode, all system clock sources, including the real-time counter (RTC) clock source are
stopped. This allows operation of asynchronous modules only. The only interrupts that can wake
up the MCU are the TWI interface address match interrupts and asynchronous PORT interrupts.
POWER-SAVE MODE
The power-save mode is identical to the power-down mode with one exception: If the RTC
is enabled, it keeps running during sleep, and the device can also wake up from either RTC
overflow or compare match interrupt.
S TA N D B Y M O D E
This mode is identical to the power-down mode, with the exception that the enabled system clock sources are kept running, whereas the CPU, peripheral and RTC clocks are stopped.
This reduces the wake-up time.
E X T E N D E D S TA N D B Y M O D E
This mode is identical to the power-save mode, with the exception that the enabled system
clock sources are kept running while the CPU clocks are stopped. This reduces the wake-up time.
The user further reduces power consumption by disabling the appropriate peripheral
modules by programming the general power reduction register (PRGEN) and the power reduction PORT register (PRPx) associated with PORTs A, B, C, D, E, and F in the power reduction module (PR). The contents of these registers are shown in Figure 9.32, Figure 9.33, and
Figure 9.34.
6
5
4
3
2
1
0
—
—
AES
EBI
RTC
EVSYS
DMA
R
R
R
R/W
R/W
R/W
R/W
R/W
Reset value
= 0x00
AES: AES module
Setting this bit stops the clock to the AES module. When the bit is cleared, the peripheral should
be reinitialized to ensure proper operation.
EBI: External bus interface
Setting this bit stops the clock to the external bus interface. When the bit is cleared, the peripheral
should be reinitialized to ensure proper operation.
RTC: Real-time counter
Setting this bit stops the clock to the real-time counter. When the bit is cleared, the module continues
like before the shutdown.
EVSYS: Event system
Setting this bit stops the clock to the event system. When the bit is cleared, the module continues
like before the shutdown.
DMA: DMA controller
Setting this bit stops the clock to the DMA controller. This bit can only be set if the DMA controller
is disabled.
Figure 9.32
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
—
General power reduction register (PR.PRGEN)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
299
Power Management and Sleep Modes
7
6
5
4
3
2
1
0
—
—
—
—
—
DAC
ADC
AC
R
R
R
R
R
R/W
R/W
R/W
Reset value
= 0x00
DAC: Power reduction DAC
Setting this bit stops the clock to the DAC. The DAC should be disabled before shutdown.
ADC: Power reduction ADC
Setting this bit stops the clock to the ADC. The ADC should be disabled before shutdown.
AC: Power reduction analog comparator
Setting this bit stops the clock to the analog comparator. The AC should be disabled before
shutdown.
Figure 9.33
■
Power reduction PORTA/B register (PR.PRPA, PR.PRPB)
7
6
5
4
3
2
1
0
—
TWI
USART1
USART0
SPI
HIRES
TC1
TC0
R
R
R
R
R
R/W
R/W
R/W
Reset value
= 0x00
TWI: Two-wire interface
Setting this bit stops the clock to the TWI interface. When the bit is cleared, the TWI should be
reinitialized to ensure proper operation.
USART1:
Setting this bit stops the clock to the USART1. When this bit is cleared, the USART1 should be
reinitialized to ensure proper operation.
USART0:
Setting this bit stops the clock to the USART0. When this bit is cleared, the USART0 should be
reinitialized to ensure proper operation.
SPI: Serial peripheral interface
Setting this bit stops the clock to the SPI. When this bit is cleared, the SPI should be reinitialized to
ensure proper operation.
HIRES: Hi-resolution extension
Setting this bit stops the clock to the hi-resolution extension for the Timer/Counters. When the bit
is cleared, the HIRES should be reinitialized to ensure proper operation.
TC1: Timer/Counter1
Setting this bit stops the clock to the Timer/Counter1. When the bit is cleared, the TC1 will continue
like before the shutdown.
TC0: Timer/Counter0
Setting this bit stops the clock to the Timer/Counter0. When the bit is cleared, the TC0 will continue
like before the shutdown.
Figure 9.34
■
Power reduction PORTC/D/E/F register (PR.PRPC~PR.PRPF)
The following instruction sequence enables the XMega MCU to standby mode:
ldi
sts
sleep
Source: Atmel Corporation, The Atmel AVR
Microcontroller
■
r16,0x0D
SLEEP_CTRL,r16
; enable standby sleep mode
; "
; put the MCU in standby sleep mode
The following C statements achieve the same setting:
SLEEP_CTRL = 0x0D;
__asm__ __volatile__ ("sleep");
// there are two underscore characters before and after
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
9.9
300
Chapter 9
■
Interrupt Handling, Resets, and Power Management
There are many ways to use the sleep mode. One way is to use timer interrupt to trigger
the entering of sleep mode and then use interrupt to exit sleep mode. An outline for using
the sleep mode to save power is shown in Figure 9.35. Embedded system software is often
written as an infinite loop. After power-on reset, the MCU starts to perform system initialization. After system initialization, the embedded system is waiting for the user to request the
execution of an application. If the user requests the execution of a certain application, the
MCU stops the idle timer and identifies the operation to perform. Whenever the MCU finishes
execution of the selected application, it starts the idle timer and waits for new requests. If the
idle timer times out due to the lack of user requests, the MCU executes the idle timer interrupt service routine. The idle timer interrupt service routine enables the sleep mode and the
MCU enters sleep state. If the user requests the embedded system to perform an operation
when the MCU is sleeping, the MCU wakes up and executes the associated interrupt service
routine which disables the sleep mode and returns to identify an application to execute. The
whole process repeats.
Start
Idle timer
interrupt
service routine
User request for
application?
t
rrup
Inte
Start the idle timer
No
Stop idle timer
Identify the application
requested by the user
Figure 9.35
■
Perform
application 2
Enable sleep
mode
Sleep mode
Yes
Perform
application 1
Start
Interrupt
Start
Perform
application n
Disable sleep
mode
Source: Atmel Corporation, The Atmel AVR Microcontroller
System initialization after
power on
Outline for using sleep mode in embedded system
9.10 Summary
In computing, an interrupt is an asynchronous signal indicating the need for attention
or a synchronous event in software indicating the need for a change in execution. Interrupts
make I/O activity more efficient, because the CPU no longer needs to poll the input device to
find out if new data is available nor to poll the output device to find out whether it can accept
more data.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.10
■
Summary
301
In addition, interrupts also allow emergency events to be handled in time. The handling
of routine works is also facilitated by using the timer interrupt. Most microcontrollers support
multiple interrupt sources. The microcontroller prioritizes interrupt sources so that whenever
there are two or more interrupts occur at the same time, the pending interrupt at the highest
priority receives service first.
Interrupts are not always desirable. The CPU should disable certain interrupts when they
are not needed. This is implemented by using an enable bit to allow or disallow the interrupt to
occur. An interrupt that can be enabled or disabled is called a maskable interrupt. Otherwise, it
is referred to as a nonmaskable interrupt.
To handle interrupts, the CPU needs to identify the source of interrupt and also to locate
the starting address of the service routine that handles the interrupt. The starting address of
the interrupt service routine is referred to as an interrupt vector. Interrupt vectors may be
predefined or stored in a table. The AVR interrupt vectors are predefined. Different Mega and
XMega devices have different number of interrupt sources. Four bytes are allocated to each
interrupt source starting from location 0x02 (word address) in flash memory. This table can be
relocated to the boot sector. A Mega device may have up to 57 interrupt sources whereas an
XMega device may have up to 86 interrupt sources.
The Mega device has only maskable interrupts. Each interrupt has a static priority. The
interrupt with the smallest interrupt vector has the highest priority whereas the interrupt with
the highest interrupt vector has the lowest priority. The XMega device has both nonmaskable
(only one) and maskable interrupts. An XMega interrupt may be placed at high, medium, or low
priority. The priority of a high- or medium-level interrupt is static. However, the priority of a
low-level interrupt may be programmed to be round-robin.
There are three steps in the AVR interrupt programming in assembly language:
Step 1
Write the interrupt service routine.
Step 2
Place a jump instruction in the memory location at the predefined interrupt vector so that
it jumps to the actual interrupt service routine.
Step 3
Enable interrupt locally and globally. There are two steps in the AVR interrupt
programming in C language:
Step 1
Write the interrupt service routine with the first line written as ISR (interrupt vector
number). The user can use the symbolic name corresponding to the particular interrupt
to replace the interrupt vector number so that he or she does not need to memorize the
actual vector number.
Step 2
Enable interrupt locally and globally.
All microprocessors and microcontrollers have the reset mechanism. A reset provides
default values to registers and flip-flops and initializes all I/O interface modules so that processors can execute a program correctly. The Mega has five reset sources:
•
•
•
•
•
Power-on
Reset pin
Brown-out
JTAG Debug interface
Watchdog timer time-out
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
302
Chapter 9
■
Interrupt Handling, Resets, and Power Management
In addition to all of these reset sources, the XMega devices also have spike and software
reset. The Watchdog timer is mainly used to detect software errors. A Watchdog timer needs to
be reset before it times out (overflows). Otherwise, it resets the CPU. When using the watchdog
timer, the application must be written in a way that it restarts the Watchdog timer before it
overflows to prevent the CPU from being reset.
A CMOS transistor consumes power when it is switching. The MCU can be designed to
use clock signals to control the switching of transistors. AVR MCUs implement several sleep
modes which turn off certain modules (by disabling their clock inputs) while at the same time
keep other modules working to match the needs of applications. By doing this, power consumption is minimized.
9.11 Exercises
E9.1 What is interrupt?
E9.2 Write an instruction sequence to configure the ATMega1280 odd interrupt pins to interrupt
the CPU on the rising edge and the even interrupt pins to interrupt the CPU on the falling edge.
E9.3 Write a sequence of C statements to configure the ATMega1280 interrupt pins 7, 5, 2, and
0 to interrupt on the falling edge and pins 6 and 1 to interrupt on both edges.
E9.4 Write a sequence of C statements to configure PCINT0, PCINT1, PCINT4, PCINT8,
PCINT9, PCINT14, PCINT18, PCINT20, and PCINT23 to interrupt the Mega CPU.
E9.5 Write an instruction sequence to enable INT0 and INT1 interrupt of PORTB and place
pins 0, 1, and 2 in INT0 and place pins 3, 6, and 7 in INT1 group for the XMega128A1 device.
Pins 0, 1, and 2 interrupt the MCU on the rising edge whereas pins 3, 6, and 7 interrupt the
MCU on the falling edge.
E9.6 Write a sequence of C statements to enable INT0 and INT1 interrupt of PORTB and place
pins 0, 3, and 7 in INT0 and place pins 1, 2, and 5 in INT1 group for the XMega128A1 device.
Pins 7, 3, and 0 interrupt on the falling edge whereas pins 5, 2, and 1 interrupt on both edges.
Configure INT0 to interrupt at high level whereas INT1 interrupt at medium level.
E9.7 Write a sequence of instructions to configure the Watchdog timer of the Mega device so
that it resets the CPU if it is not restarted in 2 s.
E9.8 Write a sequence of C statements to configure the Watchdog timer of the XMega device so
that it resets the CPU if it is not restarted in 1 s.
9.12 Lab Assignments
L9.1 INT0 and INT1 Interrupt Experiment. Connect debounced switches (or use those available on the demo board) to INT0 and INT1 pins, respectively. Write a main program that performs the following operations:
•
•
•
Enables INT0 and INT1 pin to interrupt on the rising edge.
Initializes two variables cnt1 and cnt2 to 0.
Configures a PORT (e.g., PORTC) for output and connects it to eight LEDs.
Write a service routine for INT0 interrupt that increments cnt0, clears the interrupt flag,
and outputs cnt0 to LEDs (driven by PORTC). Write a service routine for INT1 interrupt that
increments cnt1, clears the interrupt flag, and output cnt2 to LEDs driven by PORTC. Assemble (or compile) the program and download it onto the demo board for execution. Press INT0
and INT1 randomly and observe the change of LED patterns.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
9.12
■
303
Lab Assignments
L9.2 Connect a 2-Hz periodical signal (taken from a function generator) to the INT0 pin. The
circuit connection is shown in Figure L9.2. Use an I/O PORT of your choice to drive eight
LEDs. Write a main program that initializes a variable (unsigned char) cnt to 0 and enables
INT0 interrupt to high priority (required for XMega device). Write the interrupt service routine
that clears the INT0 flag, increments cnt by 1, and outputs cnt to LEDs.
XMega128A1
INT0
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure L9.2 ■ XMega (or Mega) INT0 pin
interrupt circuit
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10
Advanced Parallel I/O
10.1 Objectives
After completing this chapter, you will be able to
• Perform keypad and keyboard scanning,
debouncing, and ASCII code lookup.
• Use a hardware debouncing circuit to perform key
switch debouncing.
• Configure the LCD.
• Write programs to display information on the
LCD.
• Explain the principles of operation of stepper
motors.
• Write programs to drive stepper motors.
• Write programs to generate waveforms using a
D/A converter.
• Explain the operation of the XMega DMA
controller.
• Write programs to perform data transfer using
direct memory access (DMA).
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
306
Chapter 10
■
Advanced Parallel I/O
10.2 Interfacing a Parallel PORT to a Keypad
A keypad is another commonly used input device. Like a keyboard, a keypad is arranged
as an array of switches, which could be mechanical, membrane, capacitive, or Hall effect in
construction. In mechanical switches, two metal contacts are brought together to complete
an electric circuit. In membrane switches, a plastic or rubber membrane presses one conductor onto another; this type of switch can be made very thin. Capacitive switches comprise two
plates of a parallel plate capacitor; pressing the key cap effectively increases the capacitance
between two plates. A special circuit is needed to detect this change in capacitance. In the Hall
effect key switches, the motion of the magnetic flux lines of a permanent magnet perpendicular to a crystal is detected as voltage appearing between the two faces of the crystal; it is this
voltage that registers a switch closure.
Mechanical keypads and keyboards are most popular due to their low cost and strength of
construction.
However, mechanical switches have a common problem called contact bounce. Instead of
producing a single, clean pulse output, pressing a mechanical switch generates a series of pulses
because the switch contacts do not come to rest immediately. This phenomenon is illustrated
in Figure 10.1.
VCC
5 to 20 ms
To MCU
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 10.1
■
Key switch contact bounce
When the key is not pressed, the voltage output to the computer is at VCC. To detect
which key has been pressed, the microcontroller has to scan every key switch of the keypad.
A human being cannot press and release a key switch in less than 20 ms. During this interval, the microcontroller can scan the same key switch closure tens or even hundreds of thousand times, interpreting each low signal as a new input when in fact only one input should
be sent.
Because of the contact bounce and the disparity in speed between the microcontroller and
human key pressing, a debouncing process is needed. A keypad input program can be divided
into three stages:
1. Keypad scanning. This step is to find out which key was pressed.
2. Key switch debouncing. This step is to make sure a key is indeed pressed.
3. Table lookup. This step is to look up the ASCII code of the pressed key.
10.2.1 Keypad Scanning
Keypad scanning is usually performed row by row and column by column. A 16-key keypad
can easily be interfaced with any available I/O PORT. Figure 10.2 shows a 16-key keypad organized into four rows with each row consisting of four switches.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.2
■
307
Interfacing a Parallel PORT to a Keypad
PJ7
PJ6
PJ5
PJ4
3
2
1
0
PJ3
PJ2
PJ1
PJ0
10kΩ
XMega128A1
VCC
Figure 10.2
■
7
6
5
4
B
A
9
8
0
E
D
C
Source: Atmel Corporation, The Atmel AVR Microcontroller
For the keypad input application, the upper four pins (PJ7~PJ4) of PORTJ should be
configured for output, whereas the lower four pins (PJ3~PJ0) of PORTJ should be configured
for input.
Sixteen-key keypad connected to the XMega128A1
The rows and columns of a keypad are simply conductors. In Figure 10.2, PORTJ pins
PJ3~PJ0 are pulled up to high by pull-up resistors. Whenever a key switch is pressed, the corresponding row and column are shorted together. To distinguish the row being scanned from
those not being scanned, the row being scanned is driven low, whereas the other rows are driven
high. The row selection of the 16-key keypad is shown in Table 10.1.
PJ7
PJ6
PJ5
PJ4
Selected keys
1
1
1
0
0, 1, 2, and 3
1
1
0
1
4, 5, 6, and 7
1
0
1
1
8, 9, A, and B
0
1
1
1
C, D, E, and F
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.1
■
Sixteen-key keypad row selection
10.2.2 Keyboard Debouncing
Contact bounce is due to the dynamics of a closing contact. The signal falls and rises a few
times within a period of about 5 ms as a contact bounces. Because a human being cannot press
and release a switch in less than 20 ms, a debouncer recognizes that the switch is closed after
the voltage is low for about 10 ms and recognizes that the switch is open after the voltage is
high for about 10 ms.
Both hardware and software solutions to the key bounce problem are available. Hardware
solutions to contact bounce include an analog circuit that uses a resistor and a capacitor to
smooth the voltage, and two digital solutions that use set–reset latches or CMOS buffers and
double-throw switches. Dedicated scanner chips that perform keypad scanning and debouncing
are also available. National Semiconductor 74C922 and 74C923 are two examples.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
308
Chapter 10
■
Advanced Parallel I/O
HARDWARE DEBOUNCING TECHNIQUES
The following are hardware debouncing techniques:
•
Set–reset latches. A key switch is debounced by using the set–reset latch shown
in Figure 10.3a. Before being pressed, the key is touching the set input, and the Q
voltage is high. When pressed, the key moves toward the reset position. When the
key touches the reset position, the Q voltage goes low. When the key is bouncing
and touching neither the set nor the reset input, both set and reset inputs are
pulled low by the pull-down resistors. Because both set and reset are low, the Q
voltage remains low and the key is recognized as pressed.
•
Noninverting CMOS buffer with high input impedance. The CMOS buffer output
is identical to its input. When the switch is pressed, the input of the buffer
chip 4050 is grounded and hence VOUT is forced to low. When the key switch
is bouncing (not touching the input), the resistor R keeps the output voltage
low. This is due to the high input impedance of 4050, which causes a negligible
voltage drop on the feedback resistor. Thus the output is debounced. This
solution is shown in Figure 10.3b.
•
Integrated debouncers. The RC constant of the integrator determines the rate at
which the capacitor charges up toward the supply voltage once the ground connection
via the switch has been removed. As long as the capacitor voltage does not exceed the
logic 0 threshold value, the VOUT signal continues to be recognized as a logic 0. This
solution is shown in Figure 10.3c.
VDD
Set
Q
R
Q
Reset
Reset
R
Set
(a) Set–reset latch
VDD
4050B
Vout
(b) CMOS buffer gate
VDD
VOUT
R
X
Vout
C
Threshold level
Time
Switch closed
(c) Integrating RC circuit
Figure 10.3
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
R
Hardware debouncing techniques
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.2
■
Interfacing a Parallel PORT to a Keypad
309
SOFTWARE DEBOUNCING TECHNIQUES
A simple software debouncing method is wait-and-see; that is, wait for 10 ms and reexamine
the same key to see whether it is still pressed. A key is considered pressed if its output voltage
is still low 10 ms after it is detected low. If the output voltage is high, the program considers
the signal as noise or the key still bouncing. In either case, the program continues to perform
keypad scanning. For most applications, this simple wait-and-see method is adequate.
10.2.3 ASCII Code Lookup
For an application that needs a keyboard, the easiest way to find out the ASCII code of the
pressed key is to perform a table lookup. However, table lookup is not necessary for the keypad
because ASCII code lookup can be embedded in the program that performs the scanning and
debouncing.
Example 10.1
▼
Write an assembly language subroutine and a C function to perform keypad scanning and
debouncing and return the ASCII code of the pressed key in r22 (assembly) to the caller.
Solution:
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine performs keypad scanning, debouncing, and returns
; the ASCII code of the pressed key in r22.
; ----------------------------------------------------------------------------------------------------------------------------------------------.def
temp
5 r16
.def
maskc
5 r18
; the mask to scan a column
.def
maskr
5 r19
; the mask to scan a row
.def
column
5 r20
; the column being scanned
.def
row
5 r21
; the row being scanned
.def
temp1
5 r17
; total columns and rows
getkey:
ldi
temp1,3
; set up loop limit comparator
ldi
temp,0xF0
; configure PORTJ upper 4 pins for output
sts
PORTJ_DIR,temp
; lower 4 pins for input
gkloope:
clr
row
; start from row 0
ldi
maskr,0xEF
; mask for selecting row 0
nextrow:
clr
column
; start from column 0
ldi
maskc,0x01
; mask for scanning column 0
sts
PORTJ_OUT,maskr
; select a row to scan
gkloopi:
lds
temp,PORTJ_IN
; select a column to check
and
temp,maskc
; "
breq
debounce
scan_next:
cp
column,temp1
; reach the end of a row?
brne
inc_col
; if not yet, increment the column number
cp
row,temp1
; scan all the rows?
brne
inc_row
; if not yet, scan next row.
rjmp
gkloope
; start from row 0 again
inc_col:
inc
column
; increment the column number
rol
maskc
; update column mask
rjmp
gkloopi
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
310
Chapter 10
■
inc_row:
debounce:
getcode:
isdeci:
Advanced Parallel I/O
inc
rol
rjmp
call
lds
and
breq
rjmp
mov
rol
rol
add
ldi
cp
brlt
ldi
add
ret
ldi
add
ret
row
maskr
nextrow
delay10ms
temp,PORTJ_IN
temp,maskc
getcode
scan_next
temp,row
temp
temp
temp,column
temp1,10
temp,temp1
isdeci
r22,0x37
r22,temp
; increment the row number
; update the row number
r22,0x30
r22,temp
; the pressed key is between 0 and 9
; wait for 10 ms
; recheck the same key
; "
; if still pressed, get the ASCII code
; go to scan next key
; compute row * 4 1 column
; "
; "
; "
; compare key number with 10
; "
; the key is between A and F
; ----------------------------------------------------------------------------------------------------------------------------------------------; insert the delay10ms subroutine here.
; ----------------------------------------------------------------------------------------------------------------------------------------------The C function that performs key scanning, debouncing, and ASCII code lookup is as
follows:
void delay10ms (void);
#define keypad_dir PORTJ_DIR
#define keyscan PORTJ_OUT
#define keycheck PORTJ_IN
unsigned char getkey(void)
{
char rmask, cmask, row, col;
unsigned char keycode;
keypad_dir 5 0xF0;
while(1){
rmask 5 0xEF;
for (row 5 0; row , 4; row11) {
cmask 5 0x01;
keyscan 5 keycheck & rmask;
for (col 5 0; col , 4; col11) {
if(!(keycheck & cmask)) { // check whether a key is pressed
delay10ms();
if(!(keycheck & cmask)) { // recheck the same key
keycode 5 row * 4 1 col; // compute the key value
if(keycode , 10)
return(0x30 1 keycode);
else
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.3
■
311
Driving the Stepper Motor
return (0x37 1 keycode);
}
}
cmask 5 cmask ,, 1;
}
rmask 5 (rmask ,, 1) | 0x0F;
}
}
}
▲
10.3 Driving the Stepper Motor
Stepper motors are digital motors. They are convenient for applications where a high degree
of positional control is required. Printers, tape drives, disk drives, and robot joints, for example,
are typical applications of stepper motors.
10.3.1 Principles of Rotation
In its simplest form, a stepper motor has a permanent magnet rotor and a stator consisting
of two coils. The rotor aligns with the stator coil that is energized. By changing the coil being
energized, as illustrated in Figure 10.4a~d, the rotor is turned.
C L O C K W I S E F U L L - S T E P R O TAT I O N
C4
Current flow
1st
N
S
S
N
C1
C2
C3
2nd
Figure 10.4a
■
N
S
Source: Atmel Corporation, The Atmel AVR Microcontroller
In Figure 10.4a~d, the permanent magnet rotor lines up with the coil pair that is energized.
The direction of current determines the polarity of the magnetic field and thus the angular position of the rotor. With the energizing current in Figure 10.4a, the rotor aligns with coil pair C1
and C2. Energizing coil pair C3 and C4 and de-energizing C1 and C2 cause the rotor to align
with coil pair C3 and C4. In this example, the direction of the current causes the rotor to rotate
in a clockwise direction, as shown in Figure 10.4b.
Stepper motor full step 1
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
312
Chapter 10
■
Advanced Parallel I/O
Source: Atmel Corporation, The Atmel AVR Microcontroller
S
C4
N
1st
S
N
C2
C1
S
Current flow
C3
2nd
N
■
Stepper motor full step 2
C4
Current flow
1st
N
S
N
S
N
S
C1
C2
C3
2nd
Figure 10.4c
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 10.4b
Stepper motor full step 3
C4
S
1st
N
C2
S
Current flow
C3
2nd
Figure 10.4d
C1
N
S
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
N
Stepper motor full step 4
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.3
■
313
Driving the Stepper Motor
Next, coils C1~C2 are energized again, but with a current opposite to that in step 1. The
rotor moves 90 degrees in a clockwise direction, as shown in Figure 10.4c. The last full step
moves the rotor another 90 degrees in a clockwise direction. Note that again the coil pair
C3~C4 is energized, but with a current opposite to that in step 2.
C O U N T E R C L O C K W I S E F U L L - S T E P R O TAT I O N
The stepper motor can also be rotated in a counterclockwise manner. This is achieved by
reversing the polarities of coils of C3 and C4 in Figure 10.4a~d. Figure 10.5 shows the counterclockwise sequence.
N
S
C4 Rotor
C4 Rotor
N
C1
N
Step 1
N
N
C3
S
S
N S
C2
S
N S
C1
C3
Step 2
C4 Rotor
C4 Rotor
S
N
C2
C1
S N
C2
S
Step 3
Figure 10.5
N
■
C3
Step 4
S
N
C3
S N
C1
Source: Atmel Corporation, The Atmel AVR Microcontroller
S
C2
Full-step counter clockwise operation of step motor
H A L F - S T E P O P E R AT I O N
A half-step occurs when the rotor (in a four-pole step) is moved to eight discrete positions
(45 degrees). To operate the stepper motor in half steps, sometimes both coils have to be energized at the same time. When two coils in close proximity are energized, there is a resultant
field whose center depends on the relative strengths of the two magnetic fields. Figure 10.6
illustrates the half-stepping sequence.
The step sizes of stepper motors vary from approximately 0.72° to 90°. However, the
most common step sizes are 1.8°, 7.5°, and 15°. The steps of 90° or 45° are too crude for many
applications.
The actual stator (the stationary electromagnets) of a real motor has more segments on it
than previously indicated. One example is shown in Figure 10.7. The rotor is also a little bit different and is also shown in Figure 10.7.
In Figure 10.7, the stator has eight individual sections (coils) on it, and hence the angle
between two adjacent sections is 45°. The rotor has six sections on it and hence there are 60°
between two adjacent sections. Using the principle of a Vernier mechanism, the actual movement of the rotor for each step would be 60° – 45°, or 15°. Interested reader should try to
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 10
■
Advanced Parallel I/O
S
N
S
C4 Rotor
S
S
Step 1
N
C1
N
N
S
S
N
N
C2
S
S
Step 2
C3
N
N
N S
C1
N
C3
Step 3
N
S
S
C2
N
S
C1
C3
S
N
C4 Rotor
Rotor
C4
S
N
C1
N
S
S
C2
N
C3
C4
N
S
S
S
Step 5
Rotor
N
Step 4
N
C2
C4
S
N
S
Rotor
S
N
S
C1
C2
C3
C4
N S
C2
Rotor
C4
N
N
Step 6
S
Rotor
S
N
N
C1
C3
Rotor
C4
S
N
S
S
N
S
C1
C2
N
N S
Step 7
Figure 10.6
■
Step 8
N
C1
S
C3
S
N
C2
N
C3
Source: Atmel Corporation, The Atmel AVR Microcontroller
314
Half-step operation of the stepper motor
figure out how these sections are energized to rotate the motor in the clockwise and counterclockwise directions.
Driving a stepper motor involves applying a series of voltages to the coils of the motor.
A subset of coils is energized at the same time to cause the motor to rotate one step. The pattern
of coils energized must be followed exactly for the motor to work correctly. The pattern varies
depending on the mode used on the motor. A microcontroller can easily time the duration that
the coils are energized and hence controls the speed of the stepper motor in a precise manner.
The user can use discrete transistors or a dedicated integrated stepper driver chip to drive a
stepper motor. These two approaches are described in the following sections.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.3
■
315
Driving the Stepper Motor
C1
S
Rotor
N
C7
S
S
N
N
N
C3
S
S
N
C4
C6
C5
Figure 10.7
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
C2
C8
Actual internal construction of stepper motor
10.3.2 Discrete Stepper Motor Drivers
The circuit in Figure 10.8 shows how the transistors are used to switch the current to each
of the four coils of the stepper motor. The diodes in Figure 10.8 are called fly-back diodes and
are used to protect the transistors from reverse bias. The transistor loads are the windings in the
stepper motor. The windings are inductors, storing energy as a magnetic field. When the current is cut off, the inductor dispenses its energy in the form of an electric current. This current
attempts to flow through the transistor, reverse biasing its collector-emitter pair. The diodes are
placed to prevent this current from going through the transistors.
VCC
R
R
Q4
PA3
R
PA2
R
Q3
VCC
PA1
R
PA0
R
Step motor
VCC
Q2
VCC
R
Figure 10.8
■
R
VCC
Q1
Source: Atmel Corporation, The Atmel AVR Microcontroller
VCC
Driving a stepper motor
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
316
Chapter 10
■
Advanced Parallel I/O
For higher-torque applications, the normal full-step sequence is used, as shown in Table 10.2.
For lower-torque applications, the half-step mode is used, and its sequence is shown in Table 10.3.
To control the motor, the microcontroller must output the values in the table in the sequence
shown. Table 10.2 and Table 10.3 are circular in that after the last step, the next output must be
the first step. The values may be output in the order shown to rotate the motor in one direction,
or in reverse order to rotate in the reverse direction. It is essential that the order be preserved
even if the motor is stopped for a while. The next step to restart the motor must be the next
sequential step following the last step used. The mechanical inertia of the motor requires a short
delay (usually 5 to 20 ms) between two steps to prevent the motor from missing steps.
Step
Q4
PA3
Q3
PA2
Q2
PA1
Q1
PA0
1
on
on
off
off
1100
2
off
on
on
off
0110
3
off
off
on
on
0011
4
on
off
off
on
1001
Value
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.2
■
Full-step sequence for clockwise rotation
Step
Q4
PA3
Q3
PA2
Q2
PA1
Q1
PA0
Value
1
on
off
off
off
1000
2
on
on
off
off
1100
3
off
on
off
off
0100
4
off
on
on
off
0110
5
off
off
on
off
0010
6
off
off
on
on
0011
7
off
off
off
on
0001
8
on
off
off
on
1001
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.3
■
Half-step sequence for clockwise rotation
Example 10.2
▼
Suppose that the pins PA3~PA0 are used to drive the four transistors, as shown in
Figure 10.8. Write a subroutine (or function) to rotate the stepper motor clockwise one cycle in
full step and a subroutine to rotate in half-step, respectively. These two subroutines are to be
run by the Mega devices.
Solution: The assembly language subroutines are as follows:
.equ
.equ
.equ
.equ
.equ
FSTEP1 5 0x0C
FSTEP2 5 0x06
FSTEP3 5 0x03
FSTEP4 5 0x09
HSTEP1 5 0x08
; values to rotate a full step
; "
; "
; "
; values to rotate a half-step
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.3
■
317
Driving the Stepper Motor
.equ
.equ
.equ
.equ
.equ
.equ
.equ
HSTEP2 5 0x0C
HSTEP3 5 0x04
HSTEP4 5 0x06
HSTEP5 5 0x02
HSTEP6 5 0x03
HSTEP7 5 0x01
HSTEP8 5 0x09
;
;
;
;
;
;
;
"
"
"
"
"
"
"
; ----------------------------------------------------------------------------------------------------------------------------------------------; This subroutine rotates the stepper motor clockwise in full-step sequence. The lower 4 pins
; of PORTA must be configured for output before calling this subroutine.
; ----------------------------------------------------------------------------------------------------------------------------------------------.def
temp 5 r20
FScw:
ldi
temp,FSTEP1
; output the first step pattern
out
PORTA,temp
; "
rcall
wait10ms
; provide time for motor to react
ldi
temp,FSTEP2
out
PORTA,temp
rcall
wait10ms
ldi
temp,FSTEP3
out
PORTA,temp
rcall
wait10ms
ldi
temp,FSTEP4
out
PORTA,temp
rcall
wait10ms
ret
; ----------------------------------------------------------------------------------------------------------------------------------------------; This subroutine rotates the stepper motor clockwise in half-step sequence. The lower 4 pins
; of PORTA must be configured for output before calling this subroutine.
; ----------------------------------------------------------------------------------------------------------------------------------------------.def
temp1 5 r21
HScw:
ldi
temp1,HSTEP1
; send out the first step pattern
out
PORTA,temp1
; "
rcall
wait10ms
; provide time for motor to react
ldi
temp1,HSTEP2
out
PORTA,temp1
rcall
wait10ms
ldi
temp1,HSTEP3
out
PORTA,temp1
rcall
wait10ms
ldi
temp1,HSTEP4
out
PORTA,temp1
rcall
wait10ms
ldi
temp1,HSTEP5
out
PORTA,temp1
rcall
wait10ms
ldi
temp1,HSTEP6
out
PORTA,temp1
rcall
wait10ms
ldi
temp1,HSTEP7
out
PORTA,temp1
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
318
Chapter 10
■
Advanced Parallel I/O
rcall
wait10ms
ldi
temp1,HSTEP8
out
PORTA,temp1
rcall
wait10ms
ret
.include “delays_Mega.asm”
The C language versions of the functions are straightforward and hence are left as exercise
problems.
▲
10.3.3 Integrated Stepper Motor Driver
IN1
1
16 OUT1
IN2
2
15 OUT2
IN3
3
14 OUT3
IN4
4
13 OUT4
IN5
5
12 OUT5
IN6
6
11 OUT6
IN7
7
10 OUT7
9 Common (VCC)
GND 8
■
The ULN2003 Darlington array chip
5V
Common
Mega2560
PA3
IN1
OUT1
PA2
IN2
OUT2
PA1
IN3
OUT3
PA0
In4
OUT4
8
Figure 10.10
■
9
Step motor
VCC
GND
VCC
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 10.9
Source: Atmel Corporation, The Atmel AVR Microcontroller
A direct replacement to the discrete transistors described in Figure 10.8 is the Darlington array
chip ULN2003. The pin assignment of the ULN2003 is shown in Figure 10.9. The inverters in
Figure 10.9 are Darlington pairs, whereas the diodes protect the Darlington pairs from reverse bias.
A circuit that uses the ULN2003 to drive the step motor shown in Figure 10.8 is illustrated in 10.10.
The program in Example 10.2 can drive the stepper motor in Figure 10.10 without any modification.
Driving a stepper motor using the ULN2003
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.4
■
Direct Memory Access (DMA) Transfer
319
There are other types of stepper driver chips, for example, the EDE1200. Readers are
encouraged to explore the use of these chips.
10.4 Direct Memory Access (DMA) Transfer
Direct memory access (DMA) transfer is a type of data transfer in which the CPU is responsible for the setup but does not get involved during the data transfer phase. The actual data
transfer is carried out by the DMA controller. Data transfer is an indispensable operation performed by any embedded system software. A data transfer operation may involve one byte or
multiple bytes. So far we only have learned the CPU-controlled data transfer operation. To
transfer a byte during a multiple-byte transfer, the CPU is required to perform the following
operations:
1. Read from the source (may update the source address pointer).
2. Write to the destination (may update the destination address pointer).
3. Update the byte count.
4. Decide whether to continue.
As a result, a byte transfer may take four to five clock cycles for the AVR MCU. Therefore,
the CPU-controlled data transfer is not efficient. In addition, the CPU cannot carry out any
other operation when performing a data transfer. The direct memory access (DMA) supported
by the XMega is introduced to improve data transfer efficiency. In addition, the CPU may be
able to execute instruction in parallel with a DMA transfer if the instruction being executed
does not need to use data bus.
10.4.1 Overview of the XMega DMA Controller
The XMega DMA controller can transfer data from one memory area to another, from a
memory area to a peripheral, from a peripheral to a memory area, and from a peripheral to
another peripheral. The DMA controller contains four channels with separate transfer triggers,
interrupt vectors, and addressing modes.
A complete DMA read and write operation between memories and/or peripherals is called
a DMA transaction. A single DMA transaction can transfer from 1 to 16 million bytes of data.
A DMA transaction is divided into a number of block transfers. The size of a block transfer can
be from 1 to 64 kB. Each block transfer is further divided into smaller burst transfers. A burst
transfer can transfer 1, 2, 4, or 8 bytes. Whenever the DMA controller occupies the data bus, it
does so until all bytes in the burst are transferred before it yields the data bus if there is a pending bus request with higher priority.
The source address and destination address of a DMA transfer must be specified before it
starts. During a DMA transaction, the source address and destination address may be static,
incrementing, or decrementing. At the end of a burst, block, or transaction, source and destination addresses may be reloaded. An interrupt may be requested at the end of a DMA
transaction.
10.4.2 DMA Registers
The DMA controller has a control register (CTRL), a status register (STATUS), an interrupt
flag register (INTFLAGS), and a 16-bit temporary register (TEMP) to control the overall operation. The contents of the CTRL register are shown in Figure 10.11.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 10
■
Advanced Parallel I/O
7
6
ENABLE RESET
R/W
5
4
—
—
R
R
R/W
3
2
DBUFMODE[1:0]
R/W
R/W
1
0
PRIMODE[1:0]
R/W
Reset value
= 0x00
R/W
ENABLE: DMA enable
0: DMA controller is disabled.
1: DMA controller is enabled.
RESET: DMA software reset
Setting this bit enables software reset. This bit is automatically cleared when reset is
completed. This bit can only be set when the DMA controller is disabled (ENABLE=0).
DBUFMODE[1:0]: DMA double buffer mode
00 = Double buffer disabled
01 = CH01 – double buffer enabled on channel 0/1
10 = CH23 – double buffer enabled on channel 2/3
11 = CH01CH23 – double buffer enabled on channel 0/1 and channel 2/3
PRIMMODE[1:0]: DMA channel priority settings
00 = RR0123: Round robin
01 = CH0RR123: Channel 0 > round robin (channel 1, 2, and 3)
10 = CH01RR23: Channel 0 > Channel 1 > round robin (channel 2 and 3)
11 = CH0123: channel 0 > channel 1 > channel 2 > channel 3
Figure 10.11
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
320
DMA control register (DMA_CTRL)
7
6
5
4
3
2
1
0
CH3ERRIF
CH2ERRIF
CH1ERRIF
CH0ERRIF
CH3TRNFIF
CH2TRNFIF
CH1TRNFIF
CH0TRNFIF
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
CHnERRIF[3:0]: DMA Channel n error interrupt flag (n = 0, 1, 2, or 3)
This flag will be set to 1 when an error condition on DMA channel n is detected. Writing
a 1 to this bit will clear the flag.
CHnTRNFIF[3:0]: DMA channel n transaction complete interrupt flag (n = 0, 1, 2, or 3)
This flag will be set to 1 when a transaction on channel n is completed. If unlimited
repeat count is enabled, this flag is read as one after each block transfer. Writing a 1 to
this bit location will clear the flag.
Figure 10.12
■
Reset value
= 0x00
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Setting the ENABLE bit allows the user to use DMA transfer to send data between memories and peripherals. DMA reset clears all DMA registers and can only be done when the DMA
controller is disabled. To allow for continuous transfer, two channels can be interlinked so that
the second takes over the transfer when the first is finished and vice versa. This is called double buffering. When the transmission in the first channel is completed, the second channel is
enabled. When a request is detected on the second channel, the transfer starts; and when this is
completed, the first channel is enabled again.
Because the DMA controller has four channels, it is possible that several channels may
request data transfer at the same time. However, only one DMA channel is allowed to perform
DMA data transfer at a time. The relative priorities of DMA channels determine which channel
can control the data bus for data transfer. The DMA controller allows the application software to
decide whether one or more channels should have a fixed priority or if a round-robin scheme
should be used. A round-robin scheme means that the channel that last transferred data has the
lowest priority.
The INTFLAGS register contains DMA error flags and the channel transaction complete
flags. These flags could interrupt the CPU if they are enabled. The contents of this register are
shown in Figure 10.12.
DMA interrupt flag register (DMA_INTFLAGS)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.4
■
321
Direct Memory Access (DMA) Transfer
The STATUS register contains information regarding whether a channel is busy and
whether there is a pending request on each DMA channel. The contents of the STATUS register
are shown in Figure 10.13.
6
5
4
3
2
1
0
R
R
R
R
R
R
R
Reset value
= 0x00
R
CHnBUSY[3:0]: DMA Channel n busy flag (n = 0, 1, 2, or 3)
This flag will be set to 1 when channel n starts a DMA transaction. This flag is
automatically cleared when the DMA channel is disabled, when the channel n
transaction complete interrupt flag is set, or if the DMA channel n error flag is set.
CHnPEND[3:0]: DMA channel n pending (n = 0, 1, 2, or 3)
This flag will be set to 1 when a block transfer is pending on channel n. This flag is
automatically cleared when the block transfer starts, or if the transfer is aborted.
Figure 10.13
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
7
CH3BUSY CH2BUSY CH1BUSY CH0BUSY CH3PEND CH2PEND CH1PEND CH0PEND
DMA status register (DMA_STATUS)
The TEMP register is a WORD register (16-bit) to support 24-bit read and write in the DMA
controller. The TEMP register consists of two 8-bit registers: TEMPH and TEMPL.
10.4.3 DMA Channel Operation
Each DMA channel has a set of registers to support its operation. These registers are listed
in Table 10.4. Before a channel can perform DMA data transfer, appropriate registers listed in
Table 10.4 must be programmed accordingly.
Name
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
CTRLA
CHEN
CHRST
REPEAT
TRFREQ
--
SINGLE
CTRLB
CHBUSY
CHPEND
ERRIF
TRNIF
ADDCTRL
SRCRELOAD[1:0]
SRCDIR[1:0]
TRIGSRC
Bit 1
Bit 0
BURSTLEN[1:0]
ERRINTLVL[1:0]
TRNINTLVL[1:0]
DESTRELOAD[1:0]
DESTDIR[1:0]
TRIGSRC[7:0]
TRFCNTL
TRFCNT[7:0]
TRFCNTH
TRFCNT[15:8]
REPCNT
REPCNT[7:0]
SRCADDR0
SRCADDR[7:0]
SRCADDR1
SRCADDR[15:8]
SRCADDR2
SRCADDR[23:16]
DESTADDR0
DESTADDR[7:0]
DESTADDR1
DESTADDR[15:8]
DESTADDR2
DESTADDR[23:16]
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.4
■
DMA channel register summary
The source address of the DMA transfer must be set up in registers SRCADDR0~SRCADDR2,
with SRCADDR0 holding the least significant 8 bits of the address. The destination address is
set up using the DESTADDR0~DESTADDR2 registers, with DESTADDR0 holding the least
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
322
Chapter 10
■
Advanced Parallel I/O
significant 8 bits of the address. When a DMA transaction transfers no more than 64 kB, it can
be carried out in one block transfer. The number of bytes to be transferred in one block transfer is specified using the TRFCNTL~TRFCNTH registers. When there are more than 64 kB of
data to be transferred, the DMA transaction is divided into several block transfers. All except
the last block transfer will transfer the same number of bytes, whereas the number of block
transfers is specified as the repetition count using the REPCNT register. To allow the transfer of
more than 64 kB, the REPEAT bit of the channel control register A (CTRLA) must be set to 1.
Please note that when 0 is loaded into both the TRFCNTL and TRFCNTH registers, the block
transfer count is set to 64 kB.
A block transfer is further divided into a sequence of burst transfers. The length of a burst
transfer sets the duration of time that the DMA controller holds the data bus. The burst length
can be 1, 2, 4, or 8 bytes. The contents of the CTRLA register are shown in Figure 10.14. The
operation and error conditions, interrupt flags, and interrupt priority setting are captured in the
channel control register B (CTRLB) shown in Figure 10.15.
After transferring a byte in a DMA operation, the source and destination addresses are
updated. The source and destination address may stay the same, incremented, or decremented.
At the end of a DMA transaction, a block transfer, or even a burst transfer, the source and destination addresses may have to be reloaded with their initial values. All of these controls are
programmed via the address control register (ADDRCTRL) shown in Figure 10.16.
6
5
4
CHRST
REPEAT
TRFREQ
3
—
SINGLE
2
R/W
R/W
R/W
R/W
R/W
R/W
1
0
BURSTLEN[1:0]
R/W
Reset value
= 0x00
R/W
CHEN: DMA channel enable
Setting this bit enables the DMA channel. This bit is automatically cleared when the
transaction is completed. If the DMA channel is enabled and this bit is written to 0, the
CHEN bit is not cleared before the internal buffer is empty and the DMA transfer is aborted.
CHRST: DMA channel software reset
Setting this bit enables the channel reset. This bit is automatically cleared when reset is
completed. This bit can only be set when DMA channel is disabled (CHEN = 0).
REPEAT: DMA channel repeat mode
Setting this bit enables repeat mode. In repeat mode, this bit is cleared by hardware at
the beginning of the last block transfer. The REPCNT register should be configured before
setting this bit.
TRFREQ: DMA transfer request
Setting this bit requests a data transfer on the DMA channel. This bit is automatically
cleared at the beginning of the data transfer.
SINGLE: DMA single shot data transfer
Setting this bit enables the single shot mode. The channel will then do a burst transfer of
BURSTLEN bytes on the transfer trigger. This bit cannot be changed if the channel is busy.
BURSTLEN: DMA channel burst mode
00 = 1 byte burst mode (group configuration is 1BYTE)
01 = 2 byte burst mode (group configuration is 2BYTE)
10 = 4 byte burst mode (group configuration is 4BYTE)
11 = 8 byte burst mode (group configuration is 8BYTE)
Figure 10.14
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
CHEN
DMA channel control register A (CTRLA)
DMA transfers can only be started when a DMA transfer request is detected. A transfer
request is triggered from software, from an external trigger source (peripheral module), or from an
event. Each DMA channel has its own trigger source selections. The available trigger sources vary
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
323
Direct Memory Access (DMA) Transfer
7
6
5
4
CHBUSY
CHPEND
ERRIF
TRNIF
R
R
R/W
R/W
3
2
1
0
ERRINTLVL[1:0]
TRNINTLVL[1:0]
R/W
R/W
R/W
R/W
CHBUSY: DMA channel busy
0 = DMA channel is disabled, channel transaction is completed, or there is an DMA error.
1 = A new DMA transaction is started and not completed.
CHPEND: DMA channel pending
0 = There is no pending transfer request on the channel.
1 = A block transfer is pending on the DMA channel.
ERRIF: DMA channel error interrupt flag
0 = There is no DMA error.
1 = An DMA error condition has occurred. Writing a one to this flag will clear this flag.
TRNIF: DMA channel n transaction complete interrupt flag.
0 = The current DMA transaction is not completed.
1 = A DMA transaction has completed. When unlimited repeat is enabled the TRNIF is set after
each block transfer. This flag can be cleared by writing a 1 to it. This interrupt share the same
vector with the ERRIF interrupt.
ERRINTLVL[1:0]: DMA channel error interrupt level
00 = DMA channel error interrupt disabled
01 = DMA channel error interrupt is enabled at low level.
10 = DMA channel error interrupt is enabled at medium level.
11 = DMA channel error interrupt is enabled at high level.
TRNINTLVL[1:0]: DMA transaction complete interrupt level
00 = DMA transaction complete interrupt disabled
01 = DMA transaction complete interrupt is enabled at low level.
10 = DMA transaction complete interrupt is enabled at medium level.
10 = DMA transaction complete interrupt is enabled at high level.
Figure 10.15
■
Reset value
= 0x00
Source: Atmel Corporation, The Atmel AVR Microcontroller
10.4
DMA channel control register B (CTRLB)
from device to device, depending on the modules or peripherals that exist in the device. Using
a transfer trigger for a module or peripherals that do not exist has no effect. The DMA trigger
source is selected by programming the TRIGSRC register shown in Figure 10.17. The value to be
written into the TRIGSRC register is equal to the sum of the base value of the module to which
the source belongs and the offset value of the trigger source. For example, the trigger value for
channel 3 of the analog-to-digital converter A (ADCA) is equal to 0x10 (base value of ADCA)
1 0x03 (offset of channel 3) 5 0x13. When channel 3 of the ADCA is selected as the trigger
source, the DMA transfer is triggered whenever the A/D conversion on channel 3 of ADCA is
completed. Please note that the data transferred by the DMA operation need not be related to the
trigger source.
By default, a transfer trigger starts a block transfer operation. The transaction continues
until the whole block is transferred. When a block is transferred, the channel waits for the
next trigger to arrive before it starts transferring the next block. It is possible to select the
trigger to start a burst transfer instead of a block transfer. This is called a single shot transfer.
A new trigger then starts a new burst transfer. When the repeat mode is enabled, the start of
transfer of the next block does not require a transfer trigger. It starts as soon as the previous
block is done.
The transfer request generated by the trigger source during an ongoing transfer is kept pending, and the transfer starts when the ongoing one is done. Only one pending transfer request can
be kept. If the trigger source generates more transfer requests when one is already pending,
these additional requests will be lost.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
324
Chapter 10
■
Advanced Parallel I/O
7
6
5
SRCDIR[1:0]
SRCRELOAD[1:0]
R/W
4
R/W
R/W
R/W
3
2
1
DESTRELOAD[1:0]
R/W
0
DESTDIR[1:0]
R/W
R/W
Reset value
= 0x00
R/W
SRCRELOAD[1:0]: DMA channel source address reload
SRCRELOAD Group configuration
00
01
10
11
NONE
BLOCK
BURST
TRANSACTION
Description
No reload performed
DMA source address reload with initial value at end of block transfer.
DMA source address reload with initial value at end of burst transfer.
DMA source address reload with initial value at end of each transaction.
SRCDIR[1:0]: DMA channel source address mode
SRCDIR
Group configuration
00
01
10
11
FIXED
INC
DEC
Description
Fixed
Increment
Decrement
Reserved
—
00
01
10
11
NONE
BLOCK
BURST
TRANSACTION
Source: Atmel Corporation, The Atmel AVR Microcontroller
DESTRELOAD[1:0]: DMA channel destination address reload
DESTRELOAD Group configuration
Description
No reload performed
DMA desti. address reload with initial value at end of block transfer.
DMA desti. address reload with initial value at end of burst transfer.
DMA desti. address reload with initial value at end of each transaction.
DESTDIR[1:0]: DMA channel destination address mode
DESTDIR
Group configuration
00
01
10
11
FIXED
INC
DEC
—
■
7
DMA channel address control register (ADDRCTRL)
6
5
4
3
2
1
0
Reset value
= 0x00
TRIGSRC[7:0]
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
TRIGSRC[7:0]: DMA channel trigger source select
These bits select which trigger source is used for triggering a transfer on the DMA channel.
A zero value means that the trigger source is disabled. For each trigger source the value to
put in the TRIGSRC register is the sum of the module or peripheral’s base value, and the
offset value for the trigger source in the module or peripherals. For modules or peripheral
which does not exist for a device, the transfer trigger does not exist. Table 10.5 shows the
base value for all module and peripherals. Table 10.6 through Table 10.9 shows the offset
value for the trigger sources in the different modules and peripheral types.
Figure 10.17
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Figure 10.16
Description
Fixed
Increment
Decrement
Reserved
DMA channel trigger source register (TRIGSRC)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.4
■
325
Direct Memory Access (DMA) Transfer
TRIGSRC base
value
Group configuration
0x00
OFF
Software triggers only
0x01
SYS
System DMA triggers base value
0x10
ADCA
ADCA DMA triggers base value
0x15
DACA
DACA DMA triggers base value
0x20
ADCB
ADCB DMA triggers base value
0x25
DACB
DACB DMA triggers base value
0x40
TCC0
Timer/Counter C0 DMA triggers base value
0x46
TCC1
Timer/Counter C1 DMA triggers base value
SPIC DMA triggers base value
Description
0x4A
SPIC
0x4B
USARTC0
USART C0 DMA triggers base value
0x4E
USARTC1
USART C1 DMA triggers base value
0x60
TCD0
Timer/Counter D0 DMA triggers base value
0x66
TCD1
Timer/Counter D1 DMA triggers base value
SPID DMA triggers base value
0x6A
SPID
0x6B
USARTD0
USART D0 DMA triggers base value
0x6E
USARTD1
USART D1 DMA triggers base value
0x80
TCE0
Timer/Counter E0 DMA triggers base value
0x86
TCE1
Timer/Counter E1 DMA triggers base value
0x8A
SPIE
SPIE DMA triggers base value
0x8B
USARTE0
USARTE0 DMA triggers base value
0x8E
USARTE1
USARTE1 DMA triggers base value
0xA0
TCF0
Timer/Counter F0 DMA triggers base value
0xA6
TCF1
Timer/Counter F1 DMA triggers base value
0xAA
SPIF
SPIF DMA triggers base value
0xAB
USARTF0
USART F0 DMA triggers base value
0xAE
USARTF1
USART F1 DMA triggers base value
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.5
■
DMA trigger sources base value for all modules and peripherals
TRIGSRC offset
value
Group
configuration
0x00
CH0
Event channel 0
0x01
CH1
Event channel 1
0x02
CH2
Event channel 2
Description
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.6 ■ DMA trigger sources, offset values for the
event system triggers
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
326
Chapter 10
■
Advanced Parallel I/O
TRIGSRC offset value
Group configuration
Description
0x00
CH0
ADC/DAC channel 0
0x01
CH1
ADC/DAC channel 1
0x02
CH2(1)
ADC channel 2
0x03
CH3
ADC channel 3
0x04
CH4(2)
ADC channel 0, 1, 2,
and 3
Notes: 1. For DAC only, Channel 0 and 1 exists and can be used as
triggers.
2. Channel 4 equals ADC 0 to 3 OR’ed together.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.7
■
DMA trigger sources, offset values for DAC and ADC triggers
TRIGSRC offset value
Group configuration
Description
0x00
OVF
Overflow/underflow
0x01
ERR
Error
0x02
CCA
Compare or capture
channel A
0x03
CCB
Compare or capture
channel B
0x04
CCC(1)
Compare or capture
channel C
0x05
CCD
Compare or capture
channel D
Note: 1. CC channel C and D triggers are only available for Timer/Counter0
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.8
■
DMA trigger sources, offset values for Timer/Counter triggers
TRIGSRC offset value
Group configuration
Description
0x00
RXC
Receive complete
0x01
DRE
Data register empty
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.9
■
DMA trigger sources, offset values for USART triggers
The group configuration for a source is written as base_offset. For example, the transfer-trigger value for the Timer/Counter C1 channel A (CCA) is written as TCC1_CCA. The
transfer-trigger value for the USARTC0 receive complete is USARTC0_RXC.
To access the register within a DMA channel (0~3), precede the register name with the
prefix of DMA_CHn_ (n 5 0~3). For example, the CTRLA register of the DMA channel 0 can
be accessed by using the name of DMA_CH0_CTRLA in assembly language (or DMA.CH0.
CTRLA in C language).
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.4
■
327
Direct Memory Access (DMA) Transfer
Example 10.3
▼
Write a program to copy a block of 128 bytes of data starting from data memory location at
0x2000 to 0x2800, using DMA transfer.
Solution: We set block size to 2 kB, set the burst length to 8 bytes, and start DMA transfer manually.
The assembly program that performs the specified DMA transfer is as follows:
start:
.include <ATXMega128A1def.inc>
.def
temp 5 r16
.def
lpCnt 5 r20
.cseg
.org
0x00
rjmp
start
.org
0xF6
ldi
temp,low(RAMEND)
out
CPU_SPL,temp
ldi
temp,high(RAMEND)
out
CPU_SPH,temp
call
setCPUclkto32Mwith16MCrystal
; initialize the SP
; "
; "
; "
; ----------------------------------------------------------------------------------------------------------------------------------------------; Copy test data from program memory to data memory.
; ----------------------------------------------------------------------------------------------------------------------------------------------ldi
lpCnt,128
ldi
ZL,low(tstDat,,1)
ldi
ZH,high(tstDat,,1)
ldi
XL,low(0x2000)
ldi
XH,high(0x2000)
cpLoop:
lpm
temp,Z1
st
X1,temp
dec
lpCnt
brne
cpLoop
; ----------------------------------------------------------------------------------------------------------------------------------------------lds
temp,DMA_CTRL
; enable DMA
ori
temp,DMA_ENABLE_bm
; "
sts
DMA_CTRL,temp
; "
ldi
temp,0x83
; enable DMA channel 0 and set burst length to 8 bytes
sts
DMA_CH0_CTRLA,temp
; "
ldi
temp,0x11
; no reload on source and destination address
sts
DMA_CH0_ADDRCTRL,temp
; increment source and destination address
ldi
temp,0
; select manual trigger source
sts
DMA_CH0_TRIGSRC,temp
; "
ldi
temp,128
; set transfer block size to 128 bytes
sts
DMA_CH0_TRFCNT,temp
; "
ldi
temp,0
; "
sts
DMA_CH0_TRFCNT11,temp
; "
ldi
temp,0x00
; set source address to 0x2000
sts
DMA_CH0_SRCADDR0,temp
; "
ldi
temp,0x20
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
328
Chapter 10
dmalp:
tstDat:
■
Advanced Parallel I/O
sts
DMA_CH0_SRCADDR1,temp
; "
ldi
temp,0x00
;
sts
DMA_CH0_SRCADDR2,temp
; "
ldi
temp,0
; set destination address to 0x2800
sts
DMA_CH0_DESTADDR0,temp
; "
ldi
temp,0x28
; "
sts
DMA_CH0_DESTADDR1,temp
; "
clr
temp
; "
sts
DMA_CH0_DESTADDR2,temp
; "
lds
temp,DMA_CH0_CTRLA
; start the DMA transfer manually
ori
temp,DMA_CH_TRFREQ_bm
; "
sts
DMA_CH0_CTRLA,temp
; "
lds
temp,DMA_CH0_CTRLB
; wait until transfer is completed
sbrs
temp,DMA_CH_TRNIF_bp
; skip if transaction complete
rjmp
dmalp
nop
.include “sysClock_XMega.asm”
.db
1,2,3,4,5,6,7,8,9,10
.db
11,12,13,14,15,16,17,18,19,20
.db
21,22,23,24,25,26,27,28,29,30
.db
31,32,33,34,35,36,37,38,39,40
.db
41,42,43,44,45,46,47,48,49,50
.db
51,52,53,54,55,56,57,58,59,60
.db
61,62,63,64,65,66,67,68,69,70
.db
71,72,73,74,75,76,77,78,79,80
.db
81,82,83,84,85,86,87,88,89,90
.db
91,92,93,94,95,96,97,98,99,100
.db
101,102,203,104,105,106,107,108,109,110
.db
111,112,113,114,115,116,117,118,119,120
.db
121,122,123,124,125,126,127,128
The C language version of the program is as follows:
#include <avr/io.h>
#include “sysClock_XMega.h”
char tstDat[128] 5 {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,
61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,
101,102,103,104,105,106,107,108,109,110,111,112,113,114,
115,116,117,118,119,120,121,122,123,124,125,126,127,128};
void main (void)
{
setCPUclkto32Mwith16MCrystal();
DMA.CTRL |5 DMA_ENABLE_bm;
DMA.CH0.CTRLA
|5 DMA_CH_ENABLE_bm; // enable DMA channel 0
DMA.CH0.CTRLA
5 0x83;
// set DMA channel 0 burst length to 8 bytes
DMA.CH0.ADDRCTRL
5 0x11;
// no reload on source and destination
DMA.CH0.TRIGSRC
5 0;
// manual trigger DMA transfer
DMA.CH0.TRFCNT
5 128;
// block transfer count set to 128 bytes
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.5
■
329
Liquid Crystal Displays (LCDs)
DMA.CH0.SRCADDR0 5 0;
DMA.CH0.SRCADDR1 5 0x20;
DMA.CH0.SRCADDR2 5 0;
DMA.CH0.DESTADDR0 5 0;
DMA.CH0.DESTADDR1 5 0x28;
DMA.CH0.DESTADDR2 5 0;
DMA.CH0.CTRLA
|5 DMA_CH_TRFREQ_bm;
while(!(DMA.CH0.CTRLB & DMA_CH_TRNIF_bm));
while(1);
// set source address to 0x2000
// set destination address to 0x2800
// start the DMA transfer
// wait for DMA transfer to complete
}
DMA transfers related to peripherals can be performed similarly.
▲
10.5 Liquid Crystal Displays (LCDs)
Although seven-segment displays are easy to use, they are bulky and quite limited in the
set of characters that they can display. When more than a few characters are to be displayed,
seven-segment displays become inadequate. Liquid crystal displays (LCDs) come in handy
when the application requires the display of many characters.
A liquid crystal display has the following advantages:
•
•
•
•
High contrast
Low-power consumption
Small footprint
Ability to display both characters and graphics
The basic construction of an LCD is shown in Figure 10.18. The most common type of
LCD allows light to pass through when activated. A segment is activated when a low-frequency
bipolar signal in the range of 30 to 1000 Hz is applied to it. The polarity of the voltage must
alternate, or the LCD cannot change very quickly.
When a voltage is applied across the segment, an electrostatic field is set up that aligns the
crystals in the liquid. This alignment allows light to pass through the segment. If no voltage is
applied across a segment, the crystals appear to be opaque because they are randomly aligned.
Random alignment is assured by the AC excitation voltage applied to each segment. In a digital
watch, the segments appear darker when they are activated because light passes through the
segment to a black cardboard backing that absorbs all light. The area surrounding the activated
segment appears to grow brighter in color because the randomly aligned crystals reflect much of
the light. In a backlit computer display, the segment appears to grow brighter because of a light
placed behind the display; the light is allowed to pass through the segment when it is activated.
In recent years, the price of LCD displays has dropped to such an acceptable level that all
PC vendors bundle LCD displays instead of CRT displays with their PC systems. Notebook
computers used LCD as displays right from the beginning. Because of the price reduction of
LCDs, the prices of notebook computers also have dropped sharply, and more and more computer users have switched from desktop to notebook computers.
Although LCDs can display graphics and characters, only character-based LCDs are discussed in this text. LCDs are often sold in a module that consists of the LCD and its controller.
The Hitachi HD44780 is one of the most popular LCD display controllers in use today. Because
of the popularity of this LCD controller, many semiconductor vendors produce HD44780compatible LCD controllers.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 10
■
Advanced Parallel I/O
Segment
Frontplane
Glass
Liquid crystal
Figure 10.18
■
Backplane
Black cardboard backing
Source: Atmel Corporation, The Atmel AVR Microcontroller
330
A liquid crystal display (LCD)
10.6 The HD44780 LCD Controller
The LCD is often sold as a kit that incorporates an LCD controller, an LCD panel, and
some other supporting chips. The block diagram of an LCD kit that uses the HD44780 as the
driver is shown in Figure 10.19.
LCDP (FRD7069)
DB0
E
R/ W
RS
VEE
VCC
VSS
Figure 10.19
CONTROLLER
LSI
HD44780U
S1~S40
SEG 160
V1~V5
SEGMENT DRIVER × 4
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
C1~16
DB7
Block diagram of a HD44780-based LCD kit
The DB7~DB0 pins are used to exchange data with the microcontroller. The E pin is an
enable signal to the kit. The R/Wsignal determines the direction of data transfer. The RS signal selects the register to be accessed. When the RS signal is high, the data register is selected.
Otherwise, the instruction register is selected.
An LCD module can be used as a memory-mapped device and be enabled by an address
decoder. The E signal is normally connected to the address decoder output qualified by other
control signals to meet the timing requirement. The R/W signal can be connected to the same
pin of the microcontroller. This approach is applicable only for those microcontrollers that
support external memory. The LCD programming in this approach is generally easier and more
straightforward.
An LCD module can also be interfaced directly with an I/O PORT. In this configuration, the designer needs to use I/O pins to control the signal E, R/W, and RS. Programming is
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
331
The HD44780 LCD Controller
slightly more cumbersome than it is with the memory-mapped approach because of the need
to manipulate these three signals. The HD44780 provides a set of instructions for the user to
set up the LCD parameters. The operations performed by these instructions are summarized in
Table 10.10. The meanings of certain programmable bits are explained in Table 10.11.
Code
Instruction
Clear display
Cursor home
R/W
B7
B6
B5
B4
B3
B2
B1
B0
0
0
0
0
0
0
0
0
0
1
Clears display and set DDRAM
address to 0×00 from address
counter AC
1.64 ms
*
Returns cursor to home position
without changing DDRAM
contents Also returns display
being shifted to the original
position.
1.64 ms
40 µs
0
0
0
0
0
0
0
0
1
Description
Execution
time
RS
Entry mode set
0
0
0
0
0
0
0
1
I/D
S
Sets cursor move direction (I/D);
specifies to shift the display (S).
These operations are performed
during data read write.
Display on/off
control
0
0
0
0
0
0
1
D
C
B
Turns on/off of display (D), cursor
on/off (c), and blink of cursor
position character (B).
40 µs
Cursor/display
shift
0
0
0
0
0
1
S/C
R/L
*
*
Sets cursor-move or display-shift
(S/C), shift direction (R/L) without
changing DDRAM data
40 µs
Function set
0
0
0
0
1
DL
N
F
*
*
Sets interface data length (DL),
number of display line (N), and
character font (F).
40 µs
Set CGRAM
address
0
0
0
1
Sets the CGRAM address.
CGRAM data are sent and
received after this setting.
40 µs
Set CGRAM
address
0
0
1
Sets the DDRAM address.
DDRAM data are sent and
received after this setting.
40 µs
Reads busy flag (BF) indicating
internal operation being
performed and reads CGRAM
or DDRAM address counter
contents (depending on previous
operation).
0 µs
CGRAM address
DDRAM address
Read busy flag
and address
counter
0
1
Write CGRAM
or DDRAM
1
0
write data
Writes data to CGRAM or
DDRAM
40 µs
Read from
CGRAM or
DDRAM
1
1
read data
Reads data from OGRAM or
DDRAM
40 µs
BF
CGRAM/DDRAM address
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.10
■
HD44780 LCD controller instruction set
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
332
Chapter 10
■
Advanced Parallel I/O
Bit name
Settings
I/D
0 5 Decrement cursor position
1 5 Increment cursor position
S
0 5 No display shift
1 5 Display shift
D
0 5 Display off
1 5 Display on
C
0 5 Cursor off
1 5 Cursor on
B
0 5 Cursor blink off
1 5 Cursor blink on
S/C
0 5 Move cursor
1 5 Shift display
R/L
0 5 Shift left
1 5 Shift right
DL
0 5 4-bit interface
1 5 8-bit interface
N
0 5 1/8 or 1/11 duty (1 line)
1 5 1/16 duty (2 lines)
F
0 5 538 dots
1 5 5310 dots
0 5 Can accept instruction
1 5 Internal operation in progress
BF
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.11
■
LCD instruction bit names
The HD44780 can be configured to control one-line, two-line, or four-line LCDs. The mappings of the character positions on the LCD screen and the DDRAM addresses are not sequential and are shown in Table 10.12. Because the HD44780 is so popular, there is an industrial
standard for its pin assignment. This pin assignment is shown in Table 10.13.
Visible
Display size
Character positions
DDRAM addresses
1*8
00..07
0x00..0x07
1*16
00..15
0x00..0x0F
1*20
00..19
0x00..0x13
1*24
00..23
0x00..0x17
1*32
00..31
0x00..0x1F
1*40
00..39
0x00..0x27
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.12a
■
DDRAM address usage for a 1-line LCD
Visible
Display size
Character positions
DDRAM addresses
2*16
00..15
0x00..0x0F10x40..0x4F
2*20
00..19
0x00..0x1310x40..0x53
2*24
00..23
0x00..0x1710x40..0x57
2*32
00..31
0x00..0x1F10x40..0x5F
2*40
00..39
0x00..0x2710x40..0x67
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.12b
■
DDRAM address usage for a 2-line LCD
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
333
The HD44780 LCD Controller
Visible
Display size
Character positions
DDRAM addresses
4*16
00..15
0x00..0x0F10x40..0x4F10x14..0x2310x54..0x63
4*20
00..19
0x00..0x1310x40..0x5310x14..0x2710x54..0x67
4*40
00..39 on 1st controller
and 00..39 on 2nd
controller
0x00..0x2710x40..0x67 on 1st controller and
0x00..0x2710x40..0x67 on 2nd controller
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.12c
■
DDRAM address usage for a 4-line LCD
Pin no.
Symbol
I/O
1
VSS
--
Function
Power supply (GND)
2
VCC
--
Power supply (15V)
3
VEE
--
Contrast adjust
4
RS
|
0 5 instruction input, 1 5 data input
5
R/W
|
0 5 write to LCD, 1 5 read from LCD
6
E
|
Enable signal
7
DB0
I/O
Data busline 0
8
DB1
I/O
Data busline 1
9
DB2
I/O
Data busline 2
10
DB3
I/O
Data busline 3
11
DB4
I/O
Data busline 4
12
DB5
I/O
Data busline 5
13
DB6
I/O
Data busline 6
14
DB7
I/O
Data busline 7
Note: Many users extend this connector to 16 pins by adding pin 15 and 16
and connect them to VCC and GND.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.13a
■
Pin no.
Symbol
I/O
1
DB7
I/O
Data busline 7
2
DB6
I/O
Data busline 6
3
DB5
I/O
Data busline 5
4
DB4
I/O
Data busline 4
5
DB3
I/O
Data busline 3
6
DB2
I/O
Data busline 2
7
DB1
I/O
Data busline 1
Table 10.13b
■
Pin assignment for displays with less than 80 characters
Function
(Continued)
Pin assignment for displays with more than 80 characters
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
334
Chapter 10
■
Advanced Parallel I/O
Table 10.13b
■
(Continued)
Pin no.
Symbol
I/O
8
DB0
I/O
Function
9
E1
|
Enable signal for row 0 and 1
10
R/W
|
0 5 Write to LCD, 1 5 Read from LCD
Data busline 0
11
RS
|
0 5 Instruction input, 1 5 Data input
12
VEE
--
Contrast adjust
13
VSS
--
Power supply (GND)
14
VCC
--
Power supply (15V)
15
E2
|
Enable signal for row 2 and 3
16
N.C.
--
Source: Atmel Corporation, The Atmel AVR Microcontroller
10.6.1 Display Data RAM
Display data RAM (DDRAM) stores display data represented in 8-bit character codes. Its
extended capacity is 80 3 8 bits, or 80 characters. The area in DDRAM that is not used for
display can be used as general data RAM. The relationships between DDRAM addresses and
positions on the LCD are shown in Table 10.12a~c.
10.6.2 Character Generator ROM (CGROM)
The character generator ROM generates 5 3 8- or 5 3 10-dot character patterns from 8-bit
character codes. CGROM can generate 208 five-by-eight characters and 32 five-by-ten characters from 8-bit character codes.
10.6.3 Character Generator RAM (CGRAM)
The user can define his or her own character fonts. For 5 3 8 fonts, eight character patterns
can be written, and for 5 3 10 fonts, four characters can be defined. By writing font data to
CGRAM, user defined characters can be used.
10.6.4 LCD Controller Registers
The HD44780 has two 8-bit registers, an instruction register (IR) and a data register (DR).
The IR register stores instruction codes, such as display clear and cursor move, and address
information for display data RAM (DDRAM) and character generator RAM (CGRAM). The
microcontroller writes commands into this register to set up the LCD operation parameters.
To write data into the DDRAM and CGRAM, the microcontroller writes data into the DR
register. Data written into the DR register are automatically written into the DDRAM or the
CGRAM by an internal operation. The DR register is also used for data storage when reading data from the DDRAM or the CGRAM. When address information is written into the IR
register, data are read and then stored in the DR register from the DDRAM or the CGRAM
by an internal operation. The microcontroller can then read data from the DR register. After
a read operation, data in the DDRAM or the CGRAM at the next address are sent to the
DR register, and the microcontroller does not need to send another address. The IR and DR
registers are distinguished by the RS signal. The IR register is selected when the RS input is
low. The DR register is selected when the RS input is high. Register selection is illustrated
in Table 10.14.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
335
The HD44780 LCD Controller
RS
R/W
Operation
0
0
IR write as an internal operation (display clear, etc.)
0
1
Read busy flag (DB7) and address counter (DB0 to DB6)
1
0
DR write as an internal operation (DR to DDRAM or CGRAM)
1
1
DR read as an internal operation (DDRAM or CGRAM to DR)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.14
■
Register selection
BUSY FLAG
The HD44780 has a busy flag (BF) to indicate whether the current internal operation is
complete. When BF is 1, the HD44780 is still busy with an internal operation. When RS 5 0 and
R/W is 1, the busy flag is output to the DB7 pin. The microcontroller can read this pin to find
out whether the HD44780 is still busy.
ADDRESS COUNTER (AC)
The HD44780 uses a 7-bit address counter to keep track of the address of the next DDRAM
or CGRAM location to be accessed. When an instruction is written into the IR register, the
address information contained in the instruction is transferred to the AC register. The selection
of the DDRAM or the CGRAM is determined by the instruction. After writing into (or reading
from) the DDRAM or the CGRAM, the contents of the AC register are automatically incremented (decremented) by 1. The contents of the AC register are output to the DB6~DB0 pins
when the RS signal is low and the R/W signal is high.
10.6.5 Instruction Description
The functions of LCD instructions are discussed in this section.
C L E A R D I S P L AY
This instruction writes the space code (0x20) into all DDRAM locations. It then sets 0 into
the address counter and returns the display to its original status if it was shifted. In other words,
the display disappears, and the cursor or blinking goes to the upper left corner of the display. It
also sets the I/D bit to 1 (increment mode) in entry mode.
RETURN HOME
This instruction sets DDRAM address 0 into the address counter and returns the display to
its original status if it was shifted. The DDRAM contents are not changed. The cursor or blinking goes to the upper left corner of the display.
ENTRY MODE SET
The I/D bit of this instruction controls the incrementing (I/D 5 1) or decrementing
(I/D 5 0) of the DDRAM address. The cursor or blinking is moved to the right or left, depending on whether this bit is set to 1 or 0. The same applies to writing and reading of the CGRAM.
The S bit of this instruction controls the shifting of the LCD display. The display shifts if
S 5 1. Otherwise, the display does not shift. If S is 1, it will seem as if the cursor does not move
but the display does. The display does not shift when reading from DDRAM. Also, writing into
or reading from CGRAM does not shift the display.
D I S P L AY O N / O F F C O N T R O L
This instruction has three bit parameters: D, C, and B. When the D bit is set to 1, the display is turned on; otherwise it is turned off. The cursor is turned on when the C bit is set to 1.
The character indicated by the cursor blinks when the B bit is set to 1.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
336
Chapter 10
CURSOR
■
OR
Advanced Parallel I/O
D I S P L AY S H I F T
This instruction shifts the cursor position to the right or left without writing or reading
display data. The shifting is controlled by two bits, as shown in Table 10.15. This function
is used to correct or search the display. When the cursor has moved to the end of a line, it is
moved to the beginning of the next line.
When the displayed data is shifted repeatedly, each line moves only horizontally. The second line of the display does not shift into the first row. The contents of the address counter do
not change if the only action performed is a display shift.
S/C
R/L
Operation
0
0
Shifts the cursor position to the left. (AC is decremented by 1)
0
1
Shifts the cursor position to the right. (AC is incremented by 1)
1
0
Shifts the entire display to the left. The cursor follows the display shift.
1
1
Shifts the entire display to the right. The cursor follows the display shift.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.15
■
LCD Shift function
FUNCTION SET
This instruction allows the user to set the interface data length, select the number of display lines, and select the character fonts. There are three bit variables in this instruction:
•
DL: Data are sent or received in 8-bit length (DB7 to DB0) when DL is set to 1, and
in 4-bit length (DB7 to DB4) when DL is 0. When the pin count is at a premium
for the application, the 4-bit data length should be chosen even though it is
cumbersome to perform the programming.
•
N: This bit sets the number of display lines. When set to 0, one-line display is
selected. When set to 1, two-line display is selected.
•
F: When set to 0, the 5 3 8 font is selected. When set to 1, the 5 3 10 font is selected.
SET CGRAM ADDRESS
This instruction contains the CGRAM address to be set into the address counter.
SET DDRAM ADDRESS
This instruction allows the user to set the address of the DDRAM in address counter. This
instruction is used whenever the user wants to set the cursor to a certain position on the LCD screen.
READ BUSY FLAG
AND
ADDRESS
This instruction reads the busy flag (BF) and the address counter. The BF flag indicates
whether the LCD controller is still executing the previously received instruction.
10.6.6 Interfacing the HD44780 to the AVR Microcontroller
The data transfer between the HD44780 and the Atmel AVR can be done in 4 bits or 8 bits
at a time. When in 4-bit mode, data are carried on the upper four data pins (DB7~DB4). The
upper four bits are sent over DB7~DB4 first and followed immediately by the lower four bits.
We have the choice of using I/O PORTs to interface with the LCD module or treating the
LCD as a memory device. Unless our application requires external data memory, there is no
reason to interface a LCD kit by treating it as a memory device. This chapter only treats the
LCD as an I/O device.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
337
The HD44780 LCD Controller
An example circuit connection of the LCD kit and the XMega AVR is shown in Figure 10.20
(the Mega device circuit connection is similar). In Figure 10.20, the XMega128A1 and the LCD
kit use different power supply. The electrical compatibility is verified by comparing the VIH, VIL
of the HD44780 and the VOH and VOL of the XMega128A1, respectively.
PK3
PK2
PK1
DB7~DB4
PK7~PK4
GND
Figure 10.20
■
GND
5V
Source: Atmel Corporation, The Atmel AVR
Microcontroller
HD44780 LCD
Controller
R/ W
VCC
RS
E
3.3 V XMega128A1
LCD interface example (4-bit bus used)
Certain timing parameters must be satisfied in order to access the LCD successfully. The read
and write timing diagrams for the HD44780 are shown in Figure 10.21 and Figure 10.22, respectively. The values of timing parameters for the HD44780 are shown in Table 10.16.
tH
tSU
R/W
tW
E
tr
DB7~DB0
tf
tD
tDH
Valid data
tC
Figure 10.21
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
RS
HD44780 LCD controller read timing diagram
tH
tSU
R/ W
tW
E
tr
DB0~DB7
tf
tSU1
tH1
Valid data
tC
Figure 10.22
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
RS
HD44780 LCD controller write timing diagram
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
338
Chapter 10
■
Advanced Parallel I/O
Parameter
Symbol
Min
Max
Unit
tC
500
--
ns
Enable high pulse width
tW
230
--
ns
Enable rise/fall time
tr/tf
--
20
ns
RS, R/W set up time
tSU
40
-
ns
RS, R/W hold time
tH
10
-
ns
Enable cycle time
Read data output delay
tD
--
160
ns
Read data hold time
tDH
5
-
ns
Write data setup time
tSU1
80
-
ns
Write data hold time
tH1
10
-
ns
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 10.16
■
HD44780 LCD controller timing parameters
10.6.7 LCD Startup Sequence
A startup sequence with specific timings is required to ensure proper LCD operation. The
startup sequence for the HD44780 is shown in Figure 10.23. After power-on, at least 30 ms must
elapse before the function-set instruction code can be written to set the bus width, number of lines,
and character patterns (4-bit interface, 2 lines, and 5 3 8 dots are appropriate). After the function-set
Power on
Wait 30 ms
Execute function set instruction
Wait 40 ms
Execute display control instruction
Execute display clear instruction
Wait 1.64 ms
Execute entry mode set instruction
Wait 40 ms
OK
Figure 10.23
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Wait 40 ms
LCD controller startup sequence
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
The HD44780 LCD Controller
339
instruction, at least 40 µs must elapse before the display-control instruction can be written (to turn
on the display, turn the cursor on or off, and set the cursor to blink or no blink). After another 40 µs,
the display-clear instruction can be issued. After another 1.64 ms, the entry mode set instruction
can set address increment (or address decrement) mode, and display shift mode (on or off). After
this sequence, data can be written into the DDRAM to cause information to appear on the display.
10.6.8 Writing LCD Programs
To implement the startup sequence specified in Figure 10.23, we need to write a subroutine
(or function) that can send a command (an LCD instruction) to the LCD controller. The procedure for sending a command to the IR register is as follows:
Step 1
Pull the RS and the E signals to low.
Step 2
Pull the R/W signal to low.
Step 3
Pull the E signal to high.
Step 4
Output the given LCD instruction to the I/O PORT attached to the LCD data bus. The I/O
PORT connected to the LCD data bus must be configured for output before this can be
done.
Step 5
Pull the E signal to low, and make sure that the internal operation is completed. This is
achieved by calling a delay subroutine.
This procedure simulates the timing shown in Figure 10.22. This procedure needs to be
repeated if a 4-bit data bus is used.
Example 10.4
▼
Write an assembly subroutine and a C function to send a command to the LCD controller
shown in Figure 10.20. Call a delay function to wait for 50 µs to allow all except the first two
instructions in Table 10.10 to complete execution.
Solution: The assembly subroutine that sends a command to the LCD controller is as follows:
.equ
lcdPORT
5 PORTK_OUT
; LCD data bus and control signals
.equ
lcdPORT_DIR 5 PORTK_DIR
; LCD PORT direction control
.def
tmp
5 r20
.equ
lcdE
5 0x02
; mask for E signal
.equ
lcdRS
5 0x04
; mask for RS signal
.equ
lcdRW
5 0x08
; mask for R/W signal
; ----------------------------------------------------------------------------------------------------------------------------------------------; This subroutine outputs the command in r16 to the LCD controller and waits for 50 us to
; make sure most of the LCD instructions have finished execution. The “Clear display” and
; “cursor home” instructions will need extra time to complete execution.
; ----------------------------------------------------------------------------------------------------------------------------------------------cmd2LCD:
lds
tmp,lcdPORT
andi
tmp,~(lcdRW1lcdRS)
; select IR register and write operation
sts
lcdPORT,tmp
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
340
Chapter 10
■
Advanced Parallel I/O
ori
sts
mov
andi
ori
sts
nop
nop
nop
nop
nop
nop
lds
andi
sts
nop
nop
nop
nop
nop
nop
nop
ori
sts
swap
andi
ori
sts
nop
nop
nop
nop
nop
nop
lds
andi
sts
call
ret
tmp,lcdE
lcdPORT,tmp
tmp,r16
tmp,0xF0
tmp,lcdE
lcdPORT,tmp
tmp,lcdPORT
tmp,~(lcdE)
lcdPORT,tmp
tmp,lcdE
lcdPORT,tmp
r16
r16,0xF0
r16,lcdE
lcdPORT,r16
tmp,lcdPORT
tmp,~(lcdE)
lcdPORT,tmp
delay50us
; pull E high
; "
; place cmd in tmp
; mask out the lower 4 bits
; combine cmd upper 4 bits, R/W, RS, and E
; output to LCD PORT
; extend E pulse to more than 250 us
; "
; "
; "
; "
; "
; pull E low
; to terminate write of upper 4 cmd bits
; extend E low time so that tC is longer than
; 500 us (see Figure 10.22)
; "
; "
; "
; "
; "
; pull E high
; "
; output lower 4 cmd bits, E, RS, and R/W bits
; "
; "
; "
; extend E pulse to more than 250 us
; "
; "
; "
; "
; "
; pull E low to terminate write of lower 4 cmd bits
; "
; "
; wait until command is completed
; ----------------------------------------------------------------------------------------------------------------------------------------------; insert the delay50us subroutine here.
; ----------------------------------------------------------------------------------------------------------------------------------------------The C function that sends a command to the LCD controller is as follows:
#include
#include
#define
#define
#define
#define
<avrio.h>
“delays_XMega.h”
lcdPORT
lcdPORT_DIR
lcdE
lcdRS
PORTK.OUT
PORTK.DIR
0x02 // bit mask for the LCD E signal
0x04 // bit mask for the LCD RS signal
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
341
The HD44780 LCD Controller
#define
lcdRW
0x08 // bit mask for the RW signal
// -------------------------------------------------------------------------------------------------------------------------------------------// This function sends a command to the LCD controller.
// -------------------------------------------------------------------------------------------------------------------------------------------void cmd2LCD(unsigned char cmd)
{
unsigned char temp;
temp
5 cmd;
cmd
&5 0xF0;
lcdPORT
&5 ~(lcdRS1lcdRW);
// select IR register & pull R/W low
lcdPORT
|5 lcdE;
// pull E input high
lcdPORT
5 cmd | lcdE;
// output upper 4 command bits, E, and RS
cmd
5 temp;
// lengthen E signal
cmd
5 cmd .. 3;
// lengthen E signal
lcdPORT
&5 ~lcdE;
// pull E low to terminate write of upper 4 bits
cmd
..5 3;
cmd
5 temp ,, 4;
// extract lower 4 bits
lcdPORT
|5 lcdE;
// pull E high
lcdPORT
5 cmd | lcdE;
// output lower 4 cmd bits, E, and RS
cmd
5 temp;
cmd
5 cmd .. 3;
// length E signal
lcdPORT
&5 ~lcdE;
// pull E low to terminate write of lower 4 bits
delay50us();
}
▲
Example 10.5
▼
Write a subroutine to configure the LCD in Figure 10.20 to operate with the following
characteristics:
•
•
•
•
•
Move the cursor to the right after reading or writing a character to the LCD.
Turn on display, cursor, and cursor blinking.
Select two-row display, 5 3 8 fonts, and 4-bit interface.
Clear display and move cursor to the upper left corner.
The delay functions written in Chapter 12 are available for use for this subroutine.
Solution:
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine initializes the LCD controller to operate with 2-row display, 5 x 8
; font, 4-bit interface, cursor move right, enable display, cursor, and cursor blinking.
; ----------------------------------------------------------------------------------------------------------------------------------------------openLCD:
ldi
sts
ldi
call
ldi
call
ldi
call
tmp,0xFF
lcdPORT_DIR,tmp
r16,3
delayby100ms
r16,0x33
cmd2LCD_XMega
r16,5
delayby1ms
; configure PORTK for output
; "
; wait for LCD finish internal initialization
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
342
Chapter 10
■
Advanced Parallel I/O
ldi
call
ldi
call
ldi
call
ldi
call
ldi
call
ldi
call
ldi
call
ret
r16,0x32
cmd2LCD_XMega
r16,2
delayby1ms
r16,0x28
cmd2LCD_XMega
r16,0x0F
cmd2LCD_XMega
r16,0x01
cmd2LCD_XMega
r16,2
delayby1ms
r16,0x06
cmd2LCD_XMega
; select 4-bit data, 2-line display, 5 x 8 font
; "
; turn on display, cursor, and cursor blinking
; "
; clear screen, move cursor to home position
; "
; wait for the last command to complete
; "
; move cursor right
; "
The C function that performs the specified operation is as follows:
// -------------------------------------------------------------------------------------------------------------------------------------------// This function configures LCD to select 4-bit data bus, 2-line display, 5x8 font,
// turn on display, cursor, and cursor blinking, move cursor right, clear screen.
// move cursor to upper left corner.
// -------------------------------------------------------------------------------------------------------------------------------------------void openLCD(void)
{
lcdPORT_DIR 5 0xFF;
// configure PORTK for output
delayby100ms(3);
// wait for LCD internal initialization to complete
cmd2LCD(0x33);
delayby1ms(5);
cmd2LCD(0x32);
delayby1ms(2);
cmd2LCD(0x28);
// select 4-bit data, 2-line display, 5 x 8 font
cmd2LCD(0x0F);
// turn on display, cursor, and cursor blinking
cmd2LCD(0x06);
// move cursor right
cmd2LCD(0x01);
// clear screen, move cursor to home position
delayby1ms(2);
// wait until “clear display” command is completed
}
To display information on the LCD, we need a subroutine (or function) that can output a
character on the LCD screen. This subroutine is only a minor modification of the cmd2LCD
subroutine.
▲
Example 10.6
▼
Write a subroutine that can output the character passed in r16 to the LCD.
Solution: The subroutine that output the character passed in r16 is as follows:
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine outputs a character passed in r16 to the LCD screen.
; -----------------------------------------------------------------------------------------------------------------------------------------------
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
343
The HD44780 LCD Controller
putc2LCD:
lds
ori
sts
andi
sts
ori
sts
mov
andi
ori
sts
nop
nop
nop
nop
nop
nop
lds
andi
sts
nop
nop
nop
nop
nop
nop
nop
ori
sts
swap
andi
ori
sts
nop
nop
nop
nop
nop
nop
lds
andi
sts
call
ret
tmp,lcdPORT
tmp,lcdRS
lcdPORT,tmp
tmp,~lcdRW
lcdPORT,tmp
tmp,lcdE
lcdPORT,tmp
tmp,r16
tmp,0xF0
tmp,lcdRS1lcdE
lcdPORT,tmp
tmp,lcdPORT
tmp,~lcdE
lcdPORT,tmp
tmp,lcdE
lcdPORT,tmp
r16
r16,0xF0
r16,lcdRS1lcdE
lcdPORT,r16
r16,lcdPORT
r16,~lcdE
lcdPORT,r16
delay50us
; set RS signal high to select DR register
; "
; "
; pull R/W low to select write operation
; "
; pull E high
; "
; get a copy of data byte
; mask out lower 4 bits
; combine upper 4 data bits, RS, and E
; and output to LCD
; extend E pulse to more than 250 us
; "
; "
; "
; "
; "
; pull E low to terminate write of upper 4 data bits
; "
; "
; extend E low interval so that tC is longer than 500 us
; "
; "
; "
; "
; "
; "
; pull E high
; "
; swap upper and lower nibbles of data byte
; mask out the upper data nibble
; output lower 4 data bits, RS, and E
; "
; extend E pulse so that it is longer than 250 us
; "
; "
; "
; "
; "
; pull E low to terminate write of lower 4 data bits
; "
; "
; wait until data write is completed
The C function that outputs a character to the LCD is as follows:
// -------------------------------------------------------------------------------------------------------------------------------------------// This function sends a byte of data to the LCD controller to be displayed on the
// LCD panel.
// --------------------------------------------------------------------------------------------------------------------------------------------
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
344
Chapter 10
■
Advanced Parallel I/O
void putc2LCD(unsigned char cx)
{
unsigned char temp;
temp
5 cx;
lcdPORT
|5 lcdRS;
lcdPORT
&5 ~lcdRW;
lcdPORT
|5 lcdE;
cx
&5 0xF0;
lcdPORT
5 cx | (lcdRS 1 lcdE);
cx
5 temp;
cx
5 cx .. 3;
lcdPORT
&5 ~lcdE;
cx
..5 3;
cx
5 temp ,, 4;
lcdPORT
|5 lcdE;
lcdPORT
5 cx | (lcdRS 1 lcdE);
cx
5 temp;
cx
5 cx .. 3;
lcdPORT
&5 ~lcdE;
delay50us();
}
// select LCD data register
// select write operation
// pull E to high
// clear lower 4 bits
// output upper 4 data bits, RS, and E
// lengthen E signal
// lengthen E signal
// terminate upper 4 bits write
// make sure tC is longer than 500 us
// extract lower 4 bits
// pull E to high
// output lower 4 data bits, RS, and E
// lengthen E signal
// "
// pull E low to terminate write of lower 4 bits
We also need a subroutine that can output a string. A string may be stored in the program memory or data memory. Here we need to have two versions of the subroutine. One
version outputs a string in program memory and the other version outputs a string in data
memory.
▲
Example 10.7
▼
Write a subroutine to output a string stored in program memory and a subroutine to output
a string stored in data memory.
Solution: These two versions of the subroutine are as follows:
; ----------------------------------------------------------------------------------------------------------; The next subroutine outputs a string in program memory pointed to by Z
; ----------------------------------------------------------------------------------------------------------putSC2LCD:
loopSC:
lpm
r16,z1
cpi
r16,0
; reach the end of the string?
breq
doneCS
; "
call
putc2LCD
jmp
loopSC
doneCS:
ret
; ---------------------------------------------------------------------------------------------------------; The next subroutine outputs a string in data memory pointed to by Z.
; ---------------------------------------------------------------------------------------------------------putSD2LCD:
loopSD:
ld
r16,z1
cpi
r16,0
; reach the end of the string?
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.6
■
345
The HD44780 LCD Controller
breq
call
jmp
ret
doneDS:
doneDS
putc2LCD
loopSD
;
"
In C, the programmer only needs to write one version of the output string function. The
C compiler chooses the appropriate instructions to carry out the output operation. The C language version of the function is as follows:
void puts2LCD(unsigned char *ptr)
{
while(*ptr){
putc2LCD(*ptr);
ptr11;
}
}
▲
Example 10.8
▼
Write a program to output the following messages on the first and second row of the LCD:
XMega is fast!
LCD works fine!
Solution: The assembly language version of the program is as follows:
start:
again:
msg1:
msg2:
.include <ATXMega128A1def.inc>
.cseg
.org
0x00
jmp
start
.org
0xF6
ldi
r16,low(RAMEND)
out
CPU_SPL,r16
ldi
r16,high(RAMEND)
out
CPU_SPH,r16
call
setCPUclkto32Mwith16MCrystal
call
openLCD
ldi
r16,0x80
call
cmd2LCD_XMega
ldi
ZL,low(msg1,,1)
ldi
ZH,high(msg1,,1)
call
putsc2LCD_XMega
ldi
r16,0xC0
call
cmd2LCD_XMega
ldi
ZL,low(msg2,,1)
ldi
ZH,high(msg2,,1)
call
putsc2LCD_XMega
jmp
again
.db
“XMega is fast!”,0,0
.db
“LCD works fine!”,0
.include “delays_XMega.asm”
; set SYSCLK to 32 MHz
; initialize LCD parameters
; set LCD cursor position to first row, column 1
; "
; use Z as a pointer to the string
; "
; output “XMega is fast!”
; set LCD cursor to second row, column 1
; "
; use Z as a pointer to msg2
; "
; output “LCD works fine!”
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
346
Chapter 10
■
Advanced Parallel I/O
.include “sysClock_XMega.asm”
.include “lcdUtil_XMega.asm”
; this file contains all the previously written LCD subroutines
The C language version of the program is as follows:
#include <avrio.h>
#include “sysClock_XMega.h”
// include sysClock_XMega.c to project
#include “lcdUtil_XMega.h”
// include lcdUtil_XMega.c to project
#include “delays_XMega.h”
// include delays_XMega.c to project
unsigned char *msg1 5 “XMega is fast!”;
unsigned char *msg2 5 “LCD works fine!”;
void main (void)
{
setCPUclkto32Mwith16MCrystal(); // select SYSCLK source
openLCD();
puts2LCD(msg1);
cmd2LCD(0xC0);
puts2LCD(msg2);
while(1);
}
The LCD functions for the Mega devices are similar and hence are left for you to do as exercise
problems. An example of an LCD circuit and utility functions for the Mega device are given in
Appendix G.
▲
10.7 Summary
Keypads and keyboards are among the most important input devices for all the embedded
products. However, keypads and keyboards have a problem called key bouncing. In addition,
there is a huge gap between the speed of human data input and the MCU instruction execution.
A debouncing step is needed to address these two issues. There are three steps in keypad and
keyboard input: key scanning, key debouncing, and ASCII code lookup.
A stepper motor is a digital motor in the sense that each step of the rotation rotates a fixed
number of degrees. It is most suitable for applications that require a high degree of positional
control, such as plotters, disk drives, magnetic tape drives, robot joints, and so on. The resolution of one step of a stepper motor can be as small as 0.72oC and as large as 90oC. The simplest
motor has two pairs of coils.
Driving a stepper motor involves applying a series of voltages to the coils of the motor. A
subset of coils is energized at a time to cause the motor to rotate one step. The pattern of coils
energized must be followed exactly for the motor to work correctly. The pattern varies depending on the mode used on the motor. A microcontroller can easily time the duration during which
the coils are energized and hence control the speed of the stepper motor in a precise manner.
So far we have used CPU to control all the data transfer operation: the CPU reads a byte
from the source and then writes it to the destination. Each byte transfer takes about five clock
cycles, which is not very efficient. Direct memory access (DMA) is introduced to speed up data
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.8
■
Exercises
347
transfer for microprocessors/microcontrollers. Using the DMA transfer, the MCU sets up the
source address, destination address, the byte count to be transferred, and other parameters, and
lets the DMA controller control the actual transfer of every byte. DMA transfer can improve
the efficiency of data transfer when the amount of data to be transferred is very large. XMega
devices support DMA transfer, whereas the Mega devices do not.
LCD displays are used as the major output device by many embedded products because
they can display large amounts of information with very low power consumption. An LCD
needs a controller to generate the required control signals during the exchange of data between
the MCU and the LCD. The most popular character-based LCD controller is the Hitachi
HD44780.
LCD is often sold as a kit. The LCD kit consists of a control chip, an LCD panel, and several supporting chips. The Hitachi HD44780 is the most popular LCD controller chip and has
become the standard for character-based LCD kits. In this chapter, a set of utility functions has
been written to simplify the use of LCD.
10.8 Exercises
E10.1 Write a subroutine that rotates the stepper motor shown in Figure 10.8 counterclockwise
in full steps and also a subroutine that rotates the motor in half steps, respectively.
E10.2 Write an instruction sequence to configure the DMA transfer between the Timer/
Counter0 on PORTC and data memory. The destination address should be set to 0x2000,
whereas the source address should be set to Timer/Counter0 capture channel A associated with
PORTC. Set the block size to 64 bytes and the burst size to 2 bytes. Use Timer/Counter0 capture A associated with PORTC as the trigger source.
E10.3 Write a sequence of C statements to configure the DMA transfer between the Timer/
Counter1 associated with PORTF and data memory. The destination address should be set to
0x2000, whereas the source address should be set to Timer/Counter1 capture channel B. Set the
block size to 1 kB and the burst size to 2 bytes. Use Timer/Counter1 capture A as the trigger
source.
E10.4 Write an assembly program to display the following messages on the LCD from column
3 of both rows:
Today is good.
Class delayed.
E10.5 Write a C program to display the following messages on the LCD from column 2 of both
rows:
Enter you SS#
I forgot my SS#
E10.6 Assume that we use eight pins of the PORTJ of the XMega128A1 to drive the LCD data
bus and PH2, PH1, and PH0 pins to drive signals E, R/W, and RS, respectively. Write an 8-bit
version of the cmd2LCD assembly subroutine and C function assuming that XMega128A1 is
running with a 32 MHz system clock.
E10.7 Use the same assumption as in problem E10.6, write an 8-bit version of the putc2LCD
assembly subroutine and C function assuming that XMega128A1 is running with a 32 MHz
system clock.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
348
Chapter 10
■
Advanced Parallel I/O
10.9 Lab Assignments
L10.1 Stepper Motor Experiment. Use the stepper motor miniboard from Futurlec (http://
www.futurlec.com) to perform the stepper motor experiment. The stepper motor miniboard
implements the circuit shown in Figure 10.8. The IND, INC, INB, and INA signals must be
connected from most significant to least significant pins of Table 10.2 and Table 10.3. Perform
the following procedure:
Step 1
Configure the selected PORT for output.
Step 2
Use the lower four pins of the selected I/O PORT to drive the bases of four transistors.
Step 3
Write a sequence of instructions or C statements to rotate the stepper motor clockwise for
5 seconds using the full-step sequence. Insert a 10 ms delay between two steps.
Step 4
Repeat Step 3 but use the half-step sequence.
Step 5
Write a sequence of instructions or C statements to rotate the stepper motor counterclockwise for 5 seconds using the full-step sequence. Insert a 10 ms delay between two
steps.
Step 6
Repeat step 5, but use the half-step sequence.
Step 7
Repeat step 3 to 6, but use 5 ms as delay.
Step 8
Repeat step 3 to 6, but use 15 ms as delay.
L10.2 LCD Experiment. Enter the following C program as the main function of the project:
#include <avrio.h>
#include “lcdUtil_XMega.h”
#include “sysClock_XMega.h”
#include “delays_XMega.h”
char *msg1 5 “Shift cursor”;
void main (void)
{
setCPUclkto32Mwith16MCrystal();
openLCD();
cmd2LCD(0x85);
cmd2LCD(0x1C);
cmd2LCD(0x1C);
cmd2LCD(0x1C);
cmd2LCD(0x18);
cmd2LCD(0x18);
cmd2LCD(0x18);
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
10.9
■
Lab Assignments
349
puts2LCD(msg1);
while(1);
}
Perform the following procedure:
Step 1
Set system clock to 32 MHz and also initialize the LCD.
Step 2
Execute the command “cmd2LCD(0x85),” using the debug command “run to cursor”;
Step 3
Execute the following C statements one at a time, using the debug command “run to
cursor”:
cmd2LCD(0x1C);
cmd2LCD(0x1C);
cmd2LCD(0x1C);
Step 4
Execute the following C statements one at a time, using the debug command “run to
cursor”:
cmd2LCD(0x18);
cmd2LCD(0x18);
cmd2LCD(0x18);
Step 5
Output the message “Cursor shift” on the LCD screen.
L10.3 Keypad Input. Use the circuit shown in Figure 10.2 to perform keypad input practice. The
procedure is as follows:
Step 1
Configure the upper four pins of an I/O PORT that drives the keypad for output and the
lower four pins for input.
Step 2
Initialize the LCD properly.
Step 3
Output the message Enter an integer: on the first row of the LCD. After seeing this
message, you enter a number on the keypad. Use the F key to terminate the number. Your
program reads the number, converts it into a binary, and saves it in a buffer.
Step 4
Output the message Enter another integer: on the second row of the LCD. After seeing this
message, you enter a number on the keypad. Use the key F to terminate the number. Your
program reads in the number, converts it into a binary, and saves it in a buffer.
Step 5
Compute the gcd of these two numbers and display it on the LCD screen as follows:
The gcd of xxxx &
yyyy is z z z z.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11
Timer Functions of the
Mega AVR
11.1 Objectives
After completing this chapter, you will be able to
• Explain the overall structure of the Mega device
timer system.
• Use the timer function to create time delays.
• Use the input-capture function to measure signal
parameters, including frequency, pulse width,
period, and duty cycle.
• Use the output-compare function to create
time delays.
• Use the output-compare function to generate
waveforms with a specified duty cycle.
• Use the timer force function to force the outputcompare pin to either high or low.
• Configure the PWM function to generate periodic
waveforms with a specified frequency and
duty cycle.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
352
Chapter 11
■
Timer Functions of the Mega AVR
11.2 Introduction to the Microcontroller Timer System
A timer needs a clock input to count (increment or decrement). The clock input is generated from the MCU clock circuit or supplied from an I/O pin. When the clock is supplied
from an I/O pin, the timer is also called a counter. When the clock signal is generated from
the MCU clock circuit, the timer is said to operate in the timer mode. For this reason, many
microcontroller vendors call the timer module a timer/counter module. Most microcontrollers provide timer functions including input capture, output compare, and pulse-width
modulation (PWM). These functions are used to create time delays, measure signal parameters such as frequency, period, duty cycle, and pulse width, and generate periodic square
waveforms.
11.2.1 Using a Timer to Create Time Delays
A timer may have 8 bits, 16 bits, or even 32 bits. For an n-bit timer, the timer counts up
from 0 and reaches 2n – 1. After counting up to 2n – 1, the timer overflows and then rolls back to
0 to repeat the same process. Some timers may also count down instead of counting up. In the
countdown mode, the timer counts from 2n – 1 down to 0 and then repeats.
A timer is often used to create time delays. Let the frequency of the timer clock input
be fTC; then the timer count required to create a time delay tD (unit is second) is given by the
following expression:
TimerCount (tD) = tD × fTC
(11.1)
n
By loading the value 2 – tD × fTC into the timer and letting the timer count up to overflow, the
desired time delay tD is created. If the timer has a countdown mode, then the same delay is created by letting the timer count down from tD × fTC to 0.
11.2.2 Input Capture
When the timer system is configured to operate in the input-capture mode, an external
signal applied to an input-capture pin (ICP) is involved in the operation. The user chooses
to trigger the capture operation using the signal rising edge, falling edge, or both edges.
The value of the TCNT register is copied into the input-capture register (ICR) during this
operation.
The input-capture function can be used to measure the period of a periodic signal, the
width of a pulse, and the duty cycle of a periodic digital waveform. To measure the period,
we need to capture two consecutive rising or falling edges. The signal period is then equal to
the difference of these two edges multiplied by the timer clock period. We may need to include
the timer overflow count into the calculation if timer overflow occurs, which is detailed later.
To measure the pulse width of a signal, we need to capture one rising and then the following
falling edge of the signal. To measure the duty cycle of a digital periodic waveform, we need
to capture three consecutive edges—a rising, a falling, and a rising edge. The signal parameter
measurement is illustrated in Figure 11.1, Figure 11.2, and Figure 11.3.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 11.1a ■ Capture two rising
edges to measure signal period
Figure 11.1b ■ Capture two falling
edges to measure signal period
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.2
■
Introduction to the Microcontroller Timer System
353
Source: Atmel Corporation, The Atmel
AVR Microcontroller
Figure 11.2 ■ Capture one rising and the
following falling edges to measure pulse width
tHI
Duty cycle = tHI ÷ TC
TC
Source: Atmel Corporation, The Atmel AVR Microcontroller
Figure 11.3
■
Duty cycle measurement
11.2.3 Output Compare
Most microcontrollers have implemented the output-compare module in their timer systems. An output-compare module would have an output-compare register (OCR), one or more
control registers, and one or more status registers, in addition to a base timer/counter (TCNT)
register. A signal pin (called an output-compare [OC] pin) to be controlled by the outputcompare module is also provided.
The output-compare module compares the OCR register with the TCNT register in every
timer clock cycle. When the values of these two registers are equal, the output-compare module
takes the following actions:
•
•
It sets a flag to 1 (this may caused an interrupt to be requested).
•
•
•
Make a copy of the TCNT register.
It optionally changes the OC pin signal level (pull to high, pull to low, or toggle).
To use the output-compare function, we need to take the following actions:
Add an appropriate delay count to this copy.
Store the sum in the OCR register.
These three steps are often repeated to achieve the desired result.
The output-compare function is used to generate periodic interrupts, create time delays,
trigger events, and generate waveforms to control other equipment or machinery.
11.2.4 Pulse-Width Modulation (PWM)
Waveform generation using the output-compare function requires the CPU to restart the
output-compare operation after each compare match. This requires frequent CPU involvement during the waveform generation process. For many applications, the frequency and duty
cycles are not changed very often. A special circuitry is added to the timer system so that
the CPU only has to set up the duty cycle and period once, and the waveform continues by
itself until the duty cycle or period must be changed. This waveform is called pulse-width
modulation (PWM).
In general, a PWM module consists of an output pin, a timer/counter, a period register,
a duty register, and other control circuitry. There are two types of PWM: single-slope and
dual-slope PWM.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
354
Chapter 11
■
Timer Functions of the Mega AVR
up
nt-
u
Co
up
nt-
u
Co
Source: Atmel Corporation, The Atmel AVR Microcontroller
Timer value
The operation of a single-slope PWM is illustrated in Figure 11.4a. In this mode, a PWM
waveform cycle starts with the counter counting up from 0 and the waveform outputting high.
When the timer/counter counts up to equal the duty register, the output pin voltage drops to 0.
The timer/counter continues to count up until it equals the value in the period register. At that
point, the timer/counter resets to 0 and the process repeats.
The dual-slope PWM operation is shown in Figure 11.4b. In the dual-slope mode, a PWM
waveform cycle starts with the counter counting up from 0 and waveform outputting high.
When the counter counts up to equal the duty register, the PWM output drops to low. The
counter continues to count up until it matches the period register, and then it starts to count
down. When the counter counts down to equal the duty register, the PWM output goes high
again. The counter continues to count down until it becomes 0. At this point, the process
repeats.
The PWM is used to control the motor speed, the fan speed, the lamp brightness, and so on.
Timer/Counter =
Duty register
PWM output
Timer/Counter =
Period register
Single-slope PWM operation
up
nt-
u
Co
Timer/Counter =
Period register
Co
un
t-d
ow
n
Timer/Counter =
Duty register
PWM output
Figure 11.4b
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Timer value
Figure 11.4a
Dual-slope PWM operation (one cycle)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.3
■
Overview of the Mega AVR Timer System
355
11.3 Overview of the Mega AVR Timer System
The 100-pin ATMega640/1280/2560 devices provide the most timer functions of all Mega
devices. The ATMega640/1280/2560 devices have six timers. Timer 0 and 2 are 8-bit timers,
whereas Timer 1, 3, 4, and 5 are 16-bit timers.
All timers except Timer 2 derive their clock input by dividing the internal clkI/O by a
prescaler or receive their clock input from an external pin (Tn, n = 0, 1, 3, 4, or 5). Timer 2
derives its clock input by dividing one of the following three clock sources by a prescaler:
•
•
•
clkI/O
The external 32.768 kHz crystal oscillator connected to the TOSC1 and TOSC2 pins
The external clock signal connected to the TOSC1 pin
The 8-bit Timer/Counter0 has two output-compare units (OC0A and OC0B). Each outputcompare unit generates PWM output. The 8-bit Timer/Counter0 (TCNT0) compares with the
output-compare registers OCR0A and OCR0B in every timer clock cycle. Two output-compare pins,
OC0A and OC0B, are associated with Timer/Counter0. Timer/Counter0 has three interrupt sources:
Timer/Counter0 overflow (TOV0), output compare A (OCF0A), and output compare B (OCF0B).
The 8-bit Timer/Counter2 is identical to the Timer/Counter0 in every aspect except that it
may also select to use a clock source provided by a 32.768 kHz crystal oscillator connected to
TOSC1 and TOSC2 pins (a prescaler is also applied to this clock source). The Timer/Counter2
also has two output pins (OC2A and OC2B).
Each 16-bit timer has one input-capture unit (ICn, n = 1, 3, 4, or 5), three independent
output-compare units (OCnA, OCnB, and OCnC, n = 1, 3, 4, or 5), and five interrupt sources
(TOVn, ICFn, OCFnA, OCFnB, and OCFnC, n = 1, 3, 4, or 5). Each output-compare unit has an
output-compare pin (OCnA, OCnB, and OCnC) and has the capability to generate PWM output.
The input-capture unit has an input-capture pin (ICPn).
To unify the description of timers/counters, we do the following:
•
Use MAX to refer to the maximum value that the timer/counter can count up to.
MAX is 0×FF (8-bit) or 0×FFFF (16-bit).
•
•
Use BOTTOM to refer to 0.
•
•
Use letter n to refer to the timer unit which may be 0, …, 5.
Use TOP to refer to the highest value of a count sequence. For the 8-bit timer, TOP
is either 0×FF or the value stored in the OCRnA register. For the 16-bit timer, TOP
is 0×00FF, 0×01FF, 0×03FF, the value stored in the OCRnA register, or the value
stored in the ICRn register.
Use letter x to refer to the output-compare unit associated with one timer module,
which may be A, B, or C.
11.3.1 Timers Pin Assignment
Timers share the use of signals with other peripheral signals and general I/O pins. The
signal assignment of timer pins is given in Table 11.1. Table 11.1 shows that OC0A and OC1C
cannot be used at the same time because they are assigned to the same pin.
11.3.2 8-Bit Timer Building Blocks
An 8-bit timer is divided into three major components: count unit, output-compare unit,
and compare match output unit. Because most of the descriptions applied to Timer 0 and Timer
2, we use the letter n to refer to either timer. The behaviors of output-compare unit A and B
for both Timer 0 and Timer 2 are identical in most cases. We use the letter x to refer to outputcompare unit A or B. For example, the TCCR0A refers to Timer/Counter0 Control Register A.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
356
Chapter 11
■
Timer Functions of the Mega AVR
Module
Signal pin assignment
Timer/Counter0
T0/PD7, OC0A/OC1C/PCINT7/PB7, OC0B/PG5
Timer/Counter1
T1/PD6, ICP1/PD4, OC1A/PCINT5/PB5, OC1B/PCINT6/PB6, OC0A/OC1C/PCINT7/PB7
Timer/Counter2
OC2A/PCINT4/PB4, OC2B/PH6, TOSC1/PG4, TOSC2/PG3
Timer/Counter3
T3/INT6/PE6, CLKO/ICP3/INT7/PE7, OC3A/AIN1/PE3, OC3B/INT4/PE4, OC3C/INT5/PE5
Timer/Counter4
T4/PH7, ICP4/PL0, OC4A/PH3, OC4B/PH4, OC4C/PH5
Timer/Counter5
T5/PL2, ICP5/PL1, OC5A/PL3, OC5B/PL4, OC5C/PL5
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.1
■
Mega device timer pin assignment
The block diagram of an 8-bit timer/counter is shown in Figure 11.5. In Figure 11.5, TOP is
the value of the OCRnA register or the fixed value 0xFF. When the value 0×FF is chosen as the
TOP value, both the OCnA and OCnB module are used to generate the pulse-width modulation
(PWM) waveform. However, when the value of the OCRnA register is used as the TOP value, only
Count
Clear
TOVn(int. req)
Control logic
Direction
Clock select
CLKTn
Edge
detector
Tn
TOP
From prescaler
BOTTOM
Timer/Counter
TCNTn
=
=0
OCFnA
Int. Req
Waveform
generator
Data bus
OCRnA
Fixed TOP
values
OCRnB
TCCRnA
Figure 11.5
■
OCFnB
Int. Req
Waveform
generator
=
TCCRnB
OCnA
OCnB
Source: Atmel Corporation, The Atmel AVR Microcontroller
=
8-Bit timer/counter block diagram
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.4
■
357
Timer Clock Source Selection
the OCnB module is used to generate the PWM waveform. The clock select block shown in this
figure is the clock select circuit of Timer 0. The clock circuit of Timer 2 is shown in Figure 11.9.
11.3.3 16-Bit Timer Building Blocks
A 16-bit timer has four building blocks: count unit, input-capture unit, output-compare
unit, and compare match output unit. Each 16-bit timer/counter may have two or three
output-compare (OCnx, n = 1, 3, 4, or 5; x = A, B, or C) and one input-capture modules (ICPn).
The block diagram of a 16-bit timer/counter is shown in Figure 11.6.
Count
Clear
TOVn(int. req)
Control logic
Direction
Clock select
TCLK
Edge
detector
TOP
Tn
From prescaler
BOTTOM
Timer/Counter
TCNTn
=
=0
OCFnA
Waveform
generator
=
OCnA
OCRnA
Fixed TOP
values
Waveform
generator
=
OCRnB
OCFnC
Waveform
generator
=
OCRnC
ICRn
TCCRnA
■
Edge
detector
TCCRnB
OCnC
From analog
comparator output
ICFn
Figure 11.6
OCnB
Noise
canceler
ICPn
TCCRnC
Source: Atmel Corporation, The Atmel AVR Microcontroller
Data bus
OCFnB
16-Bit timer/counter block diagram
11.4 Timer Clock Source Selection
A timer/counter requires a clock input to count. The clock source is selected by programming the Timer/Counter control register B (TCCRnB, n = 0, …, 5). The contents of Timer/
Counter control register B for Timer/Counter 0, 2, and 16-bit timers are shown in Figure 11.7a,
11.7b, and 11.7c, respectively. The clkT2S signal shown in Figure 11.7b is either clkI/O or TOSC1
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
358
Chapter 11
■
Timer Functions of the Mega AVR
selected by the AS2 bit in the asynchronous status register (ASSR). The contents of the ASSR
register are shown in Figure 11.8. Timer/Counter0 and all 16-bit counters receive their clock
input from the clkI/O divided by a prescaler or the Tn pin. The clock source selection for Timer/
Counter2 is illustrated in Figure 11.9.
W
4
—
3
WGM02
2
CS02
1
CS01
0
CS00
R
R
R/W
R/W
R/W
R/W
Reset value
= 0 x 00
FOC0A: Force output compare A
When a 1 is written to this bit in a non-PWM mode, an immediate compare match is
forced on the waveform generation mode. The OCnA output is changed according to
its COMnA1: 0 bits setting. No interrupt will be generated. This bit is read as 0.
FOC0B: Force output compare B (n = 0 or 2)
When a 1 is written to this bit in a non-PWM mode, an immediate compare match is
forced on the waveform generation mode. The OCnB output is changed according to
its COMnB1: 0 bits setting. No interrupt will be generated. This bit is read as 0.
WGM02: Waveform generation mode bit 2
See Table 11.5.
CS02~CS00: Clock select
000: No clock source (Timer/Counter stops)
001: clkI/O (no prescaling)
010: clkI/O /8 (from prescaler)
011: clkI/O /64 (from prescaler)
100: clkI/O /256 (from prescaler)
101: clkI/O /1024 (from prescaler)
110: External clock source on T0 pin. Clock on falling edge
111: External clock source on T0 pin. Clock on rising edge
Figure 11.7a
■
Timer/Counter0 control register B(TCCR0B)
7
6
5
4
3
2
1
0
FOC2A
FOC2B
—
—
WGM22
CS22
CS21
CS20
W
W
R
R
R/W
R/W
R/W
R/W
FOC2A: Force output compare A
When a 1 is written to this bit in a non-PWM mode, an immediate compare match is forced
on the waveform generation mode. The OCnA output is changed according to its COMnA1:0
bits setting. No interrupt will be generated. This bit is read as 0.
FOC2B: Force output compare B (n = 0 or 2)
When a 1 is written to this bit in a non-PWM mode, an immediate compare match is forced
on the waveform generation mode. The OCnB output is changed according to its COMnB1:0
bits setting. No interrupt will be generated. This bit is read as 0.
WGM22: Waveform generation mode bit 2
See Table 11.5.
CS22~CS20: Clock select
000: No clock source (Timer/Counter stops)
001: clkT2S (no prescaling)
010: clkT2S/8 (from prescaler)
011: clkT2S/32 (from prescaler)
100: clkT2S/64 (from prescaler)
101: clkT2S/128 (from prescaler)
110: clkT2S/256 (from prescaler)
111: clkT2S/1024 (from prescaler)
Figure 11.7b
■
Reset value
= 0 x 00
Source: Atmel Corporation, The Atmel AVR Microcontroller
W
5
—
Source: Atmel Corporation, The Atmel AVR Microcontroller
7
6
FOC0A FOC0B
Timer/Counter2 control register B(TCCR2B)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
359
Timer Clock Source Selection
7
ICNCn
6
ICESn
5
—
R/W
R/W
R
4
3
WGMn3 WGMn2
R/W
R/W
2
CSn2
1
CSn1
0
CSn0
R/W
R/W
R/W
Reset value
= 0 x 00
ICNCn: Input-capture noise canceler
0 = Disable input-capture noise canceler.
1 = Enable input-capture noise canceler.
ICESn: Input-capture edge select
0 = Falling edge triggers input capture.
1 = Rising edge triggers input capture.
(If ICRn is used as TOP value, then the ICPn is disconnected and input capture is
disabled).
WGMn3:2: Waveform generation mode bits 3 and 2
See Table 11.6
CSn2~CSn0: Clock select
000 = No clock source (Timer/Counter stopped)
001 = clkI/O (no prescaling)
010 = clkI/O /8 (from prescaler)
011 = clkI/O /64 (from prescaler)
100 = clkI/O /256 (from prescaler)
101 = clkI/O /1024 (from prescaler)
110 = External clock source on Tn pin. Clock on falling edge
111 = External clock source on Tn pin. Clock on rising edge
Figure 11.7c
■
Timer/Counter n control register B(TCCR1B, TCCR3B, TCCR4B, TCCR5B)
7
6
5
4
—
EXCLK
AS2
TCN2UB
3
2
1
OCR2AUB OCR2BUB TCR2AUB
0
Reset value
TCR2BUB = 0 x 00
R
R
R/W
R/W
R
R
R
R
EXCLK: Enable external clock input
0: Crystal oscillator (32,768 Hz) is selected.
1: Asynchronous clock (from TOSC1 pin) instead of the crystal oscillator is selected.
AS2: Asynchronous Timer/Counter2
0: Timer/Counter2 is clocked from the I/O clock, clkI/O.
1: Timer/Counter2 is clocked from the TOSC1 pin (can be a crystal oscillator or an external clock).
TCN2UB: Timer/Counter2 update busy
0: TCNT2 is ready to be updated with a new value.
1: Timer/Counter2 operates asynchronously and TCNT2 is written.
OCR2xUB: Output-compare register 2 update busy (x = A or B)
0: OCR2x is ready to be updated with a new value. (x = A or B)
1: Timer/Counter2 operates asynchronously and OCR2A is written but hasn’t received the new
value from the temporary storage register.
TCR2xUB: Timer/Counter control register 2 update busy (x = A or B)
0: TCCR2x is ready to be updated with a new value.
1: When Timer/Counter2 operates asynchronously and TCCR2A is written, this bit becomes set.
■
Timer/Counter2 asynchronous status register (ASSR)
TOSC1
T/C
oscillator
TOSC2
Prescaler
clkI/O
Figure 11.9
■
clkT2
Source: Atmel Corporation,
The Atmel AVR Microcontroller
Figure 11.8
Timer/Counter2 clock source selection
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
11.4
360
Chapter 11
■
Timer Functions of the Mega AVR
11.5 Timer/Counter Operation Modes
A timer/counter (8-bit or 16-bit) has five operation modes (normal, CTC, fast PWM, phasecorrect PWM, and phase-and-frequency-correct PWM). Some operation modes may have several
possible TOP values.
11.5.1 8-Bit Timer/Counter Operation Modes
7
6
5
4
3
2
1
0
COMnA1
COMnA0
COMnB1
COMnB0
—
—
WGMn1
WGMn0
R/W
R/W
R/W
R/W
R
R
R/W
R/W
Reset value
= 0 x 00
COMnx1:COMnx0: Compare match output mode (n = 0 or 2; x = A or B)
The behavior of the output-compare pin (OCnx) is controlled by these two bits together with the
waveform generation mode bits (WGMn2:0). The compare match output pin behavior in non-PWM,
fast-PWM, and phase-correct-PWM modes are given in Tables 11.2, 11.3, and 11.4, respectively.
WGMn1:0: Waveform generation mode bits
Combined with the WGMn2 bit in the TCCRnB register, these bits control the counting sequence
of the counter, the source for maximum (TOP) counter value, and what type of waveform generation to be used as shown in Table 11.5.
Modes supported by the timer/counter includes normal mode (counter), clear timer on compare
match (CTC) mode, fast PWM mode, and phase- correct-PWM modes.
Figure 11.10
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
The operation mode of a timer is selected by the Timer/Counter control register A
(TCCRnA, n = 0, …, 5) and one or two bits in the Timer/Counter control register B (TCCRnB,
n = 0, …, 5 shown in Figure 11.7). The contents of the Timer/Counter control register A are
shown in Figure 11.10. For the 8-bit timer/counter, the WGMn1:WGMn0 bits of the TCCRnA
register (n = 0 or 2) and the WGMn2 bit of the TCCRnB register select the operation mode, as
shown in Table 11.5.
The 8-bit timer/counter (TCNTn, n = 0 or 2) is compared with the output-compare register (OCRnA and OCRnB, n = 0 or 2) in each timer clock cycle. Whenever the value in the
TCNTn counter equals that of the OCRnx register, the voltage level of the associated pin
may change (pin voltage level change is also called pin action), and the associated outputcompare match flags are set. The output-compare pin actions associated with the normal
and CTC (non-PWM), fast PWM, and phase-correct PWM modes are shown in Table 11.2
through Table 11.4, respectively. The output-compare match flags and the time overflow flags
are contained in Timer/Counter interrupt flag register 0 and 2 shown in Figure 11.11. Interrupts are requested if they are enabled. Timer/Counter2 output-compare match and overflow
interrupts are enabled/disabled by programming the Timer/Counter2 interrupt mask register
shown in Figure 11.12.
Timer/Counter control register A(TCCR0A and TCCR2A)
COMnx1
COMnx0
Description
0
0
Normal PORT operation, OCnx flip-flop disconnected from OCnx pin
0
1
Toggle OCnx signal on compare match
1
0
Clear OCnx signal on compare match
1
1
Set OCnx signal on compare match
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.2
■
Compare match output behavior in non-PWM mode (8-bit timer)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.5
■
361
Timer/Counter Operation Modes
COMnx1
COMnx0
Description
0
0
1
0
1
1
Normal PORT operation, OCnA flip-flop disconnected from OCnA pin
1
0
Clear OCnx signal on compare match, set OCnx at BOTTOM (non-inverting mode)
1
1
Set OCnx signal on compare match, clear OCnx at BOTTOM (inverting mode)
Normal PORT operation, OCnx flip-flop disconnected from OCnx pin
Note: 1. This option is not available for OCnB (n = 0 or 2) module.
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Table 11.3a
(8-bit timer)
Compare match output behavior in Fast-PWM mode (WGMn2:0 = 011, TOP = 0xFF)
COMnx1
COMnx0
0
0
Description
01
11
Toggle OCnA on compare match
1
0
Set OCnx at BOTTOM (non-inverting mode)
1
1
Clear OCnx at BOTTOM (inverting mode)
Normal PORT operation, OCnx flip-flop disconnected from OCnx pin
Note: 1. This option is not available for OCnB (n = 0 or 2) module.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.3b ■ Compare match output behavior in Fast-PWM mode (WGMn2:0 = 111,
TOP = OCRnA) (8-bit timer)
COMnx1
COMnx0
Description
0
0
Normal PORT operation, OCnx flip-flop disconnected from OCnx pin
02
12
WGMn2=0: normal PORT operation, OCnA flip-flop disconnected from OCnA pin
1
0
1
1
WGMn2=1: Toggle OCnA on compare match
Clear OCnx flip-flop on compare match during up-counting
Set OCnx flip-flop on compare match during down-counting
Set OCnx flip-flop on compare match during up-counting
Clear OCnx flip-flop on compare match during down-counting
Notes: 1. A special case occurs when OCRnx equals TOP and COMnx1 is set to 1. In this case, the compare
match is ignored, but the set or clear is done at the TOP.
2. This option is not available for OCnB (n = 0 or 2) module.
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
Compare match output behavior in Phase-Correct-PWM mode1 (8-bit timer)
7
6
5
4
3
2
1
0
—
—
—
—
—
OCFnB
OCFnA
TOVn
R
R
R
R
R
R
R
R
Reset value
= 0 x 00
OCFnB: Timer/Counter n output compare match B flag
0 = Compare match between Timer n and OCRnB did not occur.
1 = Compare match between Timer n and OCRnB has occurred.
OCFnA: Timer/Counter n output compare match A flag
0 = Compare match between Timer n and OCRnA did not occur.
1 = Compare match between Timer n and OCRnA has occurred.
TOVn: Timer/Counter n overflow interrupt enable
0 = Timer/Counter n hasn’t overflown since this flag was last cleared.
1 = Timer/Counter n has overflown since this flag was last cleared.
Figure 11.11
■
Timer/Counter n interrupt flag register (TIFR0, TIFR2)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.4
Chapter 11
■
Timer Functions of the Mega AVR
7
6
5
4
3
2
1
0
—
—
—
—
—
OCIEnB
OCIEnA
TOIEn
R
R
R
R
R
R /W
R/W
R/W
Reset value
= 0 x 00
OCIEnB: Timer/Counter n output compare match B interrupt enable
0 = Disable the OCnB match interrupt
1 = Enable the OCnB match interrupt
OCIEnA: Timer/Counter n output compare match A interrupt enable
0 = Disable the OCnA match interrupt
1 = Enable the OCnA match interrupt
TOIEn: Timer/Counter n overflow interrupt enable
0 = Disable Timer/Counter n overflow interrupt
1 = Enable Timer/Counter n overflow interrupt
Figure 11.12
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
362
Timer/Counter n interrupt mask register (TIMSK0 and TIMSK2)
In Table 11.5,
Mode
WGM2
•
The TOP value refers to the maximum value that the 8-bit timer/counter can
count up to.
•
The Update of OCRx at column refers to the time that the output-compare register
is updated.
•
The timer overflow flag (TOV) can be set when the timer/counter counts to the
MAX, BOTTOM, or TOP value, depending upon the operation mode.
WGM1
WGM0
Timer/Counter mode of
operation
TOP
Update of
OCRx at
TOV flag set
on(1)(2)
0
0
0
0
Normal
0xFF
immediate
MAX
1
0
0
1
PWM, phase correct
0xFF
TOP
BOTTOM
2
0
1
0
CTC
OCRnA
immediate
MAX
3
0
1
1
Fast PWM
0xFF
TOP
MAX
4
1
0
0
Reserved
—
—
—
5
1
0
1
PWM, phase correct
OCRnA
TOP
BOTTOM
6
1
1
0
Reserved
—
—
—
7
1
1
1
Fast PWM
OCRnA
BOTTOM
TOP
Notes: 1. MAX
= 0xFF.
2. BOTTOM = 0x00.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.5
■
8-Bit timer/counter waveform generation mode bit description
11.5.2 16-Bit Timer/Counter Operation Modes
A 16-bit timer/counter has five operation modes, as listed in Table 11.6. These operation
modes are selected by programming the WGMn3:WGMn2 bits of the Timer/Counter control
register B (TCCRnB, n = 1, 3, 4, or 5) together with the WGMn1:WGMn0 bits of the Timer/
Counter control register A (TCCRnA, n = 1, 3, 4, 5). The contents of the TCCRnA (n = 1, 3, 4, or 5)
are shown in Figure 11.13.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.5
■
363
Timer/Counter Operation Modes
Mode
WGMn3
WGMn2
WGMn1
WGMn0
Timer/Counter mode of
operation
TOP
Update of
OCRx at
TOV flag
set on
0
0
0
0
0
Normal
0xFFFF
Immediate
MAX
1
0
0
0
1
PWM, phase correct, 8-bit
0x00FF
TOP
BOTTOM
2
0
0
1
0
PWM, phase correct, 9-bit
0x01FF
TOP
BOTTOM
3
0
0
1
1
PWM, phase correct, 10-bit
0x03FF
TOP
BOTTOM
4
0
1
0
0
CTC
OCRnA
Immediate
MAX
5
0
1
0
1
Fast PWM, 8-bit
0x00FF
BOTTOM
TOP
6
0
1
1
0
Fast PWM, 9-bit
0x01FF
BOTTOM
TOP
7
0
1
1
1
Fast PWM, 10-bit
0x03FF
BOTTOM
TOP
8
1
0
0
0
PWM, phase and frequency
correct
ICRn
BOTTOM
BOTTOM
9
1
0
0
1
PWM, phase and frequency
correct
OCRnA
BOTTOM
BOTTOM
10
1
0
1
0
PWM, phase correct
ICRn
TOP
BOTTOM
11
1
0
1
1
PWM, phase correct
OCRnA
TOP
BOTTOM
12
1
1
0
0
CTC
ICRn
Immediate
MAX
13
1
1
0
1
(Reserved)
–
–
–
14
1
1
1
0
Fast PWM
ICRn
BOTTOM
TOP
15
1
1
1
1
Fast PWM
OCRnA
BOTTOM
TOP
Source: Atmel Corporation, The Atmel AVR Microcontroller
■
16-Bit timer waveform generation mode bit description
7
6
5
4
3
2
1
0
COMnA1
COMnA0
COMnB1
COMnB0
COMnC1
COMnC0
WGMn1
WGMn0
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
Reset value
= 0 x 00
COMnA1:0: Compare output mode for channel A (n = 1, 3, 4, or 5)
COMnB1:0: Compare output mode for channel B
COMnC1:0: Compare output mode for channel C
COMnA1:0, COMnB1:0, COMnC1:0 control the output pins (OCnA, OCnB, and OCnC, respectively)
behavior. If one or both of the COMnA1:0 bits are written to 1, the OCnA output overrides the
normal port functionality of the I/O pin it is connected to. If one or both of the COMnB1:0 bits are
written to 1, the OCnB output overrides the normal port functionality of the I/O pin it is
connected to. If one or both of the COMnC1:0 bits are written to 1, the OCnC output overrides
the normal port functionality of the I/O pin it is connected to.
When the OCnA, OCnB, or OCnC is connected to the pin, the function of the COMnx1:0 bits is
dependent of the WGM3:0 bits setting. Tables 11.7, 11.8, and 11.9 show the COMnx1:0 bit
functionality for different WGMn3:0 settings.
WGMn1:0: Waveform generation mode bits
Combined with the WGMn3:2 bits in TCCRnB register, these bits control the counting sequence of
the counter, the source for maximum (TOP) counter value, and what type waveform generation to
be used. Modes of operations supported by the Timer/Counter unit are listed in Table 11.6.
Figure 11.13
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.6
Timer/Counter n control register A (TCCR1A, TCCR3A, TCCR4A, TCCR5A)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
364
Chapter 11
■
Timer Functions of the Mega AVR
Once enabled, the 16-bit timer/counter (TCNTx, x = 1, 3, 4, or 5) is compared with the
16-bit output-compare register (OCRnx, 1, 3, 4, or 5, x = A, B, or C) in each timer clock cycle.
When these two registers are equal, the output-compare pin (OCnx, n = 1, 3, 4, or 5, x = A, B,
or C) voltage level may be changed. The pin action (i.e., the OCnx pin voltage-level change) on
compare match depends on the operation modes and is defined in Table 11.7 (normal and CTC
modes), Table 11.8, and Table 11.9, respectively.
COMnx1
COMnx0
Description
0
0
Normal PORT operation, OCnA/OCnB/OCnC disconnected
0
1
Toggle OCnA/OCnB/OCnC on compare match
1
0
Clear OCnA/OCnB/OCnC (pull low) on compare match
1
1
Set OCnA/OCnB/OCnC (pull high) on compare match
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.7
■
Compare match output behavior in non-PWM mode (16-bit timer)
COMnx1
COMnx0
0
0
Normal PORT operation, OCnA/OCnB/OCnC disconnected
Description
0
1
WGMn 3:0 = 14 or 15: toggle OCnA on compare match, OCnB and OCnC
disconnected (normal PORT operation). For all other PWM WGMn settings,
normal PORT operation, OCnA/OCnB/OCnC disconnected.
1
0
Clear OCnA/OCnB/OCnC (pull low) on compare match, set OCnA/OCnB/OCnC
at BOTTOM (non-inverting mode)
1
1
Set OCnA/OCnB/OCnC (pull high) on compare match, clear OCnA/OCnB/OCnC
at BOTTOM (inverting mode)
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.8
■
Compare match output behavior in Fast-PWM mode (16-bit timer)
COMnx1
COMnx0
Description
0
0
Normal PORT operation, OCnA/OCnB/OCnC disconnected
0
1
WGMn 3:0 = 9 or 11: toggle OCnA on compare match, OCnB and OCnC
disconnected (normal PORT operation). For all other PWM WGMn settings,
normal PORT operation, OCnA/OCnB/OCnC disconnected.
1
0
Clear OCnA/OCnB/OCnC (pull low) on compare match when up-counting, set
OCnA/OCnB/OCnC on compare match when down-counting
1
1
Set OCnA/OCnB/OCnC (pull high) on compare match when up-counting. Clear
OCnA/OCnB/OCnC on compare match when down-counting.
Source: Atmel Corporation, The Atmel AVR Microcontroller
Table 11.9 ■ Compare output mode, Phase Correct and Phase-and-Frequency-Correct PWM
mode (16-bit)
The 16-bit timer/counter also supports the input-capture operation. The input-capture
operation is triggered by the falling edge or the rising edge of the associated input-capture pin
(ICPn pin). The capture edge is selected by the bit 6 of the Timer/Counter control register B
(shown in Figure 11.7c). The occurrence of input-capture and output-compare match causes the
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
■
365
Timer/Counter Operation Modes
7
6
5
4
3
2
1
0
—
—
ICFn
—
OCFnC
OCFnB
OCFnA
TOVn
R
R
R/W
R
R/W
R/W
R/W
R/W
Reset value
= 0 x 00
Figure 11.14
■
Timer/Counter n interrupt flag register (TIFR1, TIFR3, TIFR4, TIFR5)
7
6
5
4
3
2
1
0
—
—
ICIEn
—
OCIEnC
OCIEnB
OCEnA
TOIEn
R/W
R/W
R
R
R/W
R
R/W
R/W
ICIEn: Timer/Counter n, input-capture interrupt enable
0 = Disable Timer/Counter n input-capture interrupt
1 = Enable Timer/Counter n input-capture interrupt
OCIEnC: Timer/Counter n output compare C match interrupt enable
0 = Disable Timer/Counter n output compare C match interrupt
1 = Enable Timer/Counter n output compare C match interrupt
OCIEnB: Timer/Counter n output compare B match interrupt enable
0 = Disable Timer/Counter n output compare B match interrupt
1 = Enable Timer/Counter n output compare B match interrupt
OCIEnA: Timer/Counter n output compare A match interrupt enable
0 = Disable Timer/Counter n output compare A match interrupt
1 = Enable Timer/Counter n output compare A match interrupt
TOIEn: Timer/Counter n, overflow interrupt enable
0 = Disable Timer/Counter n overflow interrupt
1 = Enable Timer/Counter n overflow interrupt
Figure 11.15
■
Source: Atmel Corporation, The Atmel AVR Microcontroller
ICFn: Timer/Counter n, input-capture flag
0 = No capture event occurred on the ICPn pin.
1 = A capture event has occurred on the ICPn pin.
OCFnC: Timer/Counter n output compare C match flag
0 = TCNTn has not matched the OCRnC register since this flag was last cleared.
1 = TCNTn has matched the OCRnC register.
OCFnB: Timer/Counter n output compare B match flag
0 = TCNTn has not matched the OCRnB register since this flag was last cleared.
1 = TCNTn has matched the OCRnB register.
OCFnA: Timer/Counter n output compare A match flag
0 = TCNTn has not matched the OCRnA register since this flag was last cleared.
1 = TCNTn has matched the OCRnA register.
TOVn: Timer/Counter n, overflow interrupt flag
0 = TCNTn has not overflowed since this flag was last cleared.
1 = TCNTn has overflowed.
Note: All of these flags will be cleared when their interrupt service routines are entered. The user can
also write a 1 to each individual flag to clear it.
Reset value
= 0 x 00
Source: Atmel Corporation, The Atmel AVR Microcontroller
11.5
Timer/Counter n interrupt mask register (TIMSK1, TIMSK3, TIMSK4, TIMSK5)
associated flag bits in the interrupt flag register (TIFRn, n = 1, 3, 4, or 5) shown in Figure 11.14
to be set. Interrupts may be requested if they are enabled. The timer/counter interrupts are
enabled by programming the timer/counter interrupt mask register (TIMSKn, n = 1, 3, 4, or 5)
shown in Figure 11.15.
The 16-bit timer and output-compare registers are divided into high byte (TCNTnH,
OCRnxH) and low byte (TCNTnL, OCRnxL). Like any other 16-bit register, the read access of
the TCNTn and OCRnx registers should start from the low byte, whereas the write access of
the TCNTn and OCRnx registers should start from the high byte.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
366
Chapter 11
■
Timer Functions of the Mega AVR
7
6
5
4
3
2
1
0
FOCnA
FOCnB
FOCnC
—
—
—
—
—
R/W
R/W
R/W
R
R
R
R
R
Reset value
= 0 x 00
FOCnA: Force output compare for channel A
FOCnB: Force output compare for channel B
FOCnC: Force output compare for channel C
These bits are active only when WGMn3:0 bits specify a non-PWM mode. When writing a logical
one to the FOCnA/FOCnB/FOCnC bit, an immediate compare match is forced on the waveform
generation unit. The OCnA/OCnB/OCnC output is changed according to its COMnx1:0 setting. No
interrupt is generated. Nor will timer be cleared in CTC mode using OCRnA as TOP.
Figure 11.16
■
Source: Atmel Corporation, The Atmel AVR
Microcontroller
The output-compare pin can be forced to either high or low by programming the Timer/
Counter control register C as shown in Figure 11.16.
Timer/Counter n control register C(TCCR1C, TCCR3C, TCCR4C, TCCR5C)
11.6 Applications of Each Timer/Counter Operation Mode
A timer/counter may be used to create time delay, generate waveforms, and measure signal
parameters. The applications of a timer depend on its operation mode. We describe the applications of the AVR timer based on its application modes.
11.7 Using the Timer Normal Mode
In this mode, the timer counts up from 0 to the TOP value (0×FF for 8-bit timers and
0×FFFF for 16-bit timers), rolls over to 0, and then counts up again. The timer/counter overflow
flag (TOVn) is set to 1 when the timer/counter rolls over to 0. This flag is cleared whenever
the timer/counter overflow interrupt service routine is entered. It is also cleared by writing
a 1 to it.
A timer (8-bit and 16-bit) in normal mode is used to create time delays and generate digital
waveforms. The 16-bit timer in normal mode is also used to measure signal parameters such as
period, pulse width, frequency, and duty cycle because it supports input-capture function (not
supported by an 8-bit timer).
11.7.1 Using the Normal Mode in Creating Time Delays
Although all timers can be used to generate a time delay, we do not use 8-bit timers in this
application because the counting range of an 8-bit timer is quite limited.
The user can use two methods to create a time delay:
•
Timer overflow: Let the timer count up from certain value until it overflows. Using
this method, we calculate the timer count (TC) required to create the desired time
delay (tD). Place the value 2n – TC in the timer, let it count up, and wait until it
overflows.
•
Output-compare match: Using this method, we calculate the timer count required
to create the desired delay, add this count to the current timer value, place the sum
in an appropriate output-compare register (OCRnx), and let the timer to count up
until its value matches that of the OCRnx register.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
Using the Timer Normal Mode
367
Example 11.1
▼
Write a function to create a time delay that is a multiple of 100 ms using the Timer/
Counter1, assuming that fclkI/O = 16 MHz.
Solution: By choosing clkI/O as the clock input and setting the prescaler to 64, the timer count
required to create a 100 ms delay is 25,000 (= 100 × 1023 × 16 × 106 ÷ 64). The subroutine that
uses the timer overflow method to create a time delay that is a multiple of 100 ms is as follows:
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine creates a time delay that is a multiple of 100 ms
; using the Timer 1 overflow. The multiple is passed in register R16.
; ----------------------------------------------------------------------------------------------------------------------------------------------.def
tmp1 = r20
delayby100ms:
ldi
tmp1,0
; configure Timer 1 to normal mode
sts
TCCR1A,tmp1
; with clock source set to
ldi
tmp1,0x03
; clk_I/O/64
sts
TCCR1B,tmp1
; "
wp100:
ldi
tmp1,high(40536) ; Let Timer 1 count up from 40536 (2**16 – 25000) so that it
sts
TCNT1H,tmp1
; overflows in 25000 clock cycles
ldi
tmp1,low(40536) ; "
sts
TCNT1L,tmp1
; "
ldi
tmp1,1<<TOV1
; clear TOV1 flag
sts
TIFR1,tmp1
; "
wt100:
lds
tmp1,TIFR1
; wait until TOV1 flag is set to 1
sbrs tmp1,TOV1
; "
rjmp wt100
; "
dec
r16
brne wp100
ret
The C function that creates the same delay is as follows:
void delayby100ms(unsigned char cx)
{
TCCR1A = 0;
// configure Timer 1 to normal mode with clock source
TCCR1B = 0x03;
// set to clkI/O/64
while(cx){
TCNT1 = 40536;
// load 40536 into TCNT1 so that it overflows in 25000 clock cycles
TIFR1 = 1 << TOV1;
// clear TOV1 flag
while(!(TIFR1 & (1<<TOV1)));
// wait until TOV1 is set to 1
cx– –;
}
}
The subroutine that uses the output-compare function to create a delay that is a multiple
of 100 ms is as follows:
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine uses Timer 1 OC1A to create a time delay that is a multiple of
; 100 ms. The multiple is passed in R16.
; ----------------------------------------------------------------------------------------------------------------------------------------------.def
tmp1 = r8
.def
tmp2 = r20
.def
tmp3 = r21
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
368
Chapter 11
■
Timer Functions of the Mega AVR
dlyby100msOC:
ldi
sts
ldi
sts
wp100:
lds
lds
ldi
add
ldi
adc
sts
sts
ldi
sts
wt100:
lds
sbrs
rjmp
dec
brne
ret
tmp2,0
TCCR1A,tmp2
tmp2,0x03
TCCR1B,tmp2
tmp1,TCNT1L
tmp2,TCNT1H
tmp3,low(25000)
tmp1,tmp3
tmp3,high(25000)
tmp2,tmp3
OCR1AH,tmp2
OCR1AL,tmp1
tmp2,1 << OCF1A
TIFR1,tmp2
tmp1,TIFR1
tmp1,OCF1A
wt100
r16
wp100
; configure timer 1 to normal mode
; with clock source set to
; clkI/O /64
; "
; make a copy of Timer 1
; "
; add a delay count of 25000 to this copy
; "
; "
; "
; start an output compare operation
; "
; clear OCF1A flag
; "
; wait until OCF1A flag is set to 1
; "
; "
; is the multiple decremented to 0 yet?
The C language version of the function is as follows:
// -------------------------------------------------------------------------------------------------------------------------------------------// The next function creates a time delay that is a multiple of 100 ms using OC1A function.
// -------------------------------------------------------------------------------------------------------------------------------------------void dlyby100msOC (unsigned char cx)
{
TCCR1A = 0;
// configure Timer 1 to operate in normal mode
TCCR1B = 0x03;
// using clkI/O /64 as its clock source
while(cx){
OCR1A = TCNT1 + 25000;
// start Timer 1 OC1A compare operation
TIFR1 = 1 << OCF1A;
// clear the OCF1A flag
while(!(TIFR1 & (1<<OCF1A)));
// wait until OCF1A flag is set
cx– –;
}
}
▲
A set of time delay functions and subroutines for the Mega MCUs have been created and
stored in files delays_Mega.asm and delays_Mega.c and saved in the complimentary CD.
11.7.2 Using the Timer Normal Mode in Waveform Generation
To use the timer normal mode to generate waveform, the OCnx pin of interest must be
configured for output. The pin action of compare match toggle (COMnx1:COMnx0 = 01) of
normal mode is used to generate periodic square wave with any duty cycle. The CPU needs to
involve frequently in the waveform generation process. For example, the procedure to generate
a waveform with 50% duty cycle and period equal to 2*N timer clock cycles is as follows:
Step 1
Configure OCnx to operate in normal mode and set the COMnx1:COMnx0 bits to 01
(toggle). Choose appropriate clock source for the Timer/Counter n.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
369
Using the Timer Normal Mode
Step 2
Make a copy of the timer/counter value (TCNTn, n = 0, …, 5).
Step 3
Add N to this copy and store the sum in the output-compare register x (OCRnx).
Step 4
Enable OCnx interrupt and write an interrupt service routine for OCnx that performs the
operations described in Step a and b.
Step a
Clear the OCFnx flag (n = 0, …, 5 and x = A, …, C).
Step b
Add N to the OCRnx register and return from interrupt.
Step 5
The MCU continues to perform other operations.
Example 11.2
▼
Write a program to generate a 5 kHz square wave with a 50% duty cycle from the OC0A
pin, assuming that the frequency of clkI/O is 16 MHz.
Solution: The period of a 5 kHz square wave is 0.2 ms. To generate a 5 kHz square wave, the
OC0A pin must be toggled every 0.1 ms. By setting the prescaler to 8, the timer count required
to toggle OC0A pin every 0.1 ms is 0.1 ms × 16 × 106/8 = 200.
The following assembly program implements the previous procedure and generates a 50%
duty cycle 5 kHz square waveform:
start:
.include <m2560def.inc>
.def
tmp = r16
.def
tmp1= r17
.equ
NN = 200
.cseg
.org
0x00
jmp
start
.org
OC0AAddr
jmp
oc0AISR
.org
0xF6
ldi
tmp,low(RAMEND)
out
SPL,tmp
ldi
r16,high(RAMEND)
out
SPH,tmp
ldi
tmp,0x80
out
DDRB,tmp
ldi
tmp,0x40
out
TCCR0A,tmp
ldi
tmp,0x02
out
TCCR0B,tmp
ldi
tmp,0x02
sts
TIMSK0,tmp
out
TIFR0,tmp
in
tmp,TCNT0
; delay count for output compare operation
; initialize the SP
; "
; "
; "
; configure PORTB pin 7 (OC0A pin) for output
; "
; OC0A pin toggle on compare match
; "
; select normal mode and set clock source
; to clk_I/O/8
; enable OC0A compare match interrupt
; "
; clear OCF0A interrupt flag
; start the first OC0A compare operation with
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
370
Chapter 11
again:
■
Timer Functions of the Mega AVR
ldi
add
out
sei
jmp
tmp1,NN
tmp,tmp1
OCR0A,tmp
again
; delay equal to NN
; "
; "
; enable interrupt globally
; wait for OC0A interrupt
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following instruction sequence is the OC0A compare match interrupt service routine.
; ----------------------------------------------------------------------------------------------------------------------------------------------oc0AISR:
in
ldi
add
out
ldi
out
reti
tmp,OCR0A
tmp1,NN
tmp,tmp1
OCR0A,tmp
tmp,0x02
TIFR0,tmp
; start the next OC0A compare operation
; with NN as its delay count
; "
; "
; clear OCF0A interrupt flag
; "
The C language version of the program is as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
#define NN 200
void main (void)
{
DDRB
|= 0x80;
TCCR0A = 0x40;
TCCR0B = 0x02;
TIMSK0 = 0x02;
TIFR0
= 0x02;
OCR0A = TCNT0 + NN;
sei();
while(1);
}
// delay count to be used in OC0A compare operation
// configure OC0A pin for output
// OC0A pin toggle on compare match
// normal mode, clock source set to clkI/O÷8
// enable OC0A compare match interrupt
// clear OCF0A flag
// start the first compare operation
// enable interrupt globally
// wait for interrupt to occur
// -------------------------------------------------------------------------------------------------------------------------------------------// OC0A interrupt service routine. It starts the next compare operation and clears the OCF0A flag.
// -------------------------------------------------------------------------------------------------------------------------------------------ISR(TIMER0_COMPA_vect)
{
OCR0A += NN;
}
// start the next OC0A compare with NN as delay count
▲
Example 11.3
▼
Write a program that uses the OC1A pin to generate a 50 Hz square wave with 75% duty
cycle, assuming that fclk_I/O = 16 MHz.
Solution: By selecting clkI/O ÷ 8 as the timer clock source, the high and low intervals of one cycle
of the 50 Hz waveform consist of 30,000 and 10,000 timer clock cycles, respectively.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
Using the Timer Normal Mode
371
We force the OC1A pin to high initially and choose toggle as the compare match pin action.
Interrupt is used to restart the subsequent output-compare operations required to sustain the
waveform. The assembly program that generates the specified waveform is as follows:
.include <m2560def.inc>
.def
tmp
= r16
.def
tmp1
= r17
.def
tmp2
= r18
.def
HioLo
= r29
.equ
hiCnt
= 30000
; delay count for output compare operations
.equ
loCnt
= 10000
; "
.cseg
.org
0x00
jmp
start
.org
oc1AAddr
; interrupt vector of OC1A
jmp
oc1AISR
.org
0xF6
start:
ldi
tmp,low(RAMEND)
; initialize the SP
out
SPL,tmp
; "
ldi
r16,high(RAMEND)
; "
out
SPH,tmp
; "
ldi
tmp,0x20
; configure OC1A/PB5 pin for output
out
DDRB,tmp
; "
ldi
tmp,0xC0
; OC1A compare match is pull high
sts
TCCR1A,tmp
; "
ldi
tmp,0x02
; set Timer 1 clock prescaler to 8,
sts
TCCR1B,tmp
; and select normal mode
ldi
tmp,0x80
; force OC1A pin high immediately
sts
TCCR1C,tmp
; "
ldi
tmp,0x40
; select toggle for compare match on OC1A
sts
TCCR1A,tmp
; "
ldi
tmp2,high(hiCnt)
; perform an OC1A compare operation with hiCnt
ldi
tmp1,low(hiCnt)
; as the delay count
lds
tmp,TCNT1L
; "
add
tmp1,tmp
; "
lds
tmp,TCNT1H
; "
adc
tmp2,tmp
; "
sts
OCR1AH,tmp2
; "
sts
OCR1AL,tmp1
; "
ldi
HioLo,0
; next compare operation uses loCnt as delay count
ldi
tmp,0x02
; enable OC1A interrupt
sts
TIMSK1,tmp
; "
out
TIFR1,tmp
; clear OC1FA flag
sei
; enable interrupt globally
here:
rjmp
here
; ----------------------------------------------------------------------------------------------------------------------------------------------; The OC1AISR interrupt routine restart a new compare operation to OC1A using either
; loCnt or hiCnt as the delay count depending upon whether HioLo is 0 or 1.
; ----------------------------------------------------------------------------------------------------------------------------------------------oc1AISR: sbrc
HioLo,0
; select pin action for output compare operation
rjmp
addHi
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
372
Chapter 11
addHi:
startOC:
■
Timer Functions of the Mega AVR
ldi
ldi
ldi
rjmp
ldi
ldi
ldi
lds
add
lds
adc
sts
sts
reti
tmp1,low(loCnt)
tmp2,high(loCnt)
HioLo,1
startOC
tmp1,low(hiCnt)
tmp2,high(hiCnt)
HioLo,0
tmp,OCR1AL
tmp1,tmp
tmp,OCR1AH
tmp2,tmp
OCR1AH,tmp2
OCR1AL,tmp1
; use loCnt as the delay count of the current
; output compare operation
; next compare operation uses hiCnt as delay count
; use hiCnt as the delay count of the current
; output compare operation
; next compare operation uses loCnt as delay count
; start a new compare operation on OC1A channel
; "
; "
; "
; "
; "
The C language version of the program is as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
#define
hiCnt
30000
#define
loCnt
10000
#define
HI
1
#define
LO
0
char HIoLO
void main (void)
{
DDRB
|= 0x20;
TCCR1A = 0xC0;
TCCR1B = 0x02;
TCCR1C |= 0x80;
TCCR1A = 0x40;
OCR1A = TCNT1 + hiCnt;
HIoLO
= LO;
TIMSK1 |= 0x02;
TIFR1
= 0x02;
sei();
while(1);
}
// delay count for high interval in a period
// delay count for low interval in a period
// flag to select hiCnt or loCnt
// configure OC1A pin for output
// OC1A pin pull high on compare match
// normal mode, clock source set to clk_I/O/8
// force OC1A pin to high
// select toggle as the OC1A pin action on compare match
// start the first output compare operation
// enable OC1A interrupt
// clear the OCF1A flag
// enable interrupt globally
// wait for interrupt to occur
// -------------------------------------------------------------------------------------------------------------------------------------------// OC1A interrupt service routine. It starts the next compare operation and clears the OCF1A flag.
// -------------------------------------------------------------------------------------------------------------------------------------------ISR(TIMER1_COMPA_vect)
{
if(HIoLO){
OCR1A = OCR1A + hiCnt;
HIoLO = LO;
} else {
OCR1A = OCR1A + loCnt;
HIoLO = HI;
}
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
373
Using the Timer Normal Mode
11.7.3 Using the Normal Mode to Make Sound
Mega MCU
3.3 μF
OC1A
Figure 11.17
■
Speaker
Source: Atmel Corporation, The Atmel AVR
Microcontroller
Making sound is easy. Connecting a waveform with an appropriate frequency (between
20 Hz to 20 kHz) to a speaker or a buzzer can make a sound. A two-tone siren is generated by
connecting the OC1A (or any other output-compare pin) to a speaker or a buzzer and switching
between two different frequencies. The circuit connection between the OC1A pin and a speaker
is shown in Figure 11.17.
Circuit connection for a speaker
Example 11.4
▼
Describe how to use OC1A pin of the Timer/Counter1 to generate a two-tone siren that
oscillates between 440 and 880 Hz, assuming that the frequency of clkI/O is 16 MHz.
Solution: By choosing clkI/O ÷ 8 as the clock source of Timer/Counter1, the frequency of the
clock input of Timer/Counter1 is set to 2 MHz. In each cycle of the siren tone, the OC1A pin
must be toggled twice. The periods of the 440 and 880 Hz siren tone are 2.2727 and 1.1364 ms,
respectively. The delay counts of output-compare operation for the 440 and 880 Hz tones are
calculated to be 2273 and 1136, respectively.
The procedure for generating a siren is as follows:
Step 1
Connect an 8 V speaker to the OC1A pin.
Step 2
Configure Timer 1 to operate in normal mode, and set the compare match output action to
toggle.
Step 3
Enable OC1A interrupt. Start the first OC1A operation with 2273 as the delay count.
Step 4
Write the service routine for the OC1A interrupt, which simply restarts the OC1A
operation with 2273 as the delay count.
Step 5
Wait for half a second.
Step 6
Change the delay count for the OC1A operation to 1136, and use it in the OC1A interrupt
service routine.
Step 7
Wait for half a second.
Step 8
Change delay count to 2273 and go to Step 5.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
374
Chapter 11
■
Timer Functions of the Mega AVR
The assembly that generates the two–tone siren is as follows:
.include <m2560def.inc>
.equ
hiCnt = 1136
; delay count for creating 880 Hz tone
.equ
loCnt = 2273
; delay count for creating 440 Hz tone
.def
dlyHi = R20
.def
dlyLo = R21
.def
tmpH = R22
.def
tmpL = R23
.cseg
.org
0x00
jmp
start
.org
OC1Aaddr
jmp
oc1AISR
.org
0xF6
start:
ldi
tmpH,low(RAMEND)
; initialize the SP
out
SPL,tmpH
; "
ldi
tmpH,high(RAMEND)
; "
out
SPH,tmpH
; "
ldi
tmpH,0x20
; configure OC1A/PB5 pin for output
sts
DDRB,tmpH
; "
ldi
tmpH,0x40
; configure TMR1 to operate in normal mode with compare
sts
TCCR1A,tmpH
; match action set to toggle
ldi
tmpH,0x02
; select clk_I/O/8 as clock input to Timer 1
sts
TCCR1B,tmpH
; "
ldi
dlyHi,high(hiCnt)
; initialize the delay count for the compare operation
ldi
dlyLo,low(hiCnt)
; (use the delay count for 880 Hz)
lds
tmpL,TCNT1L
; read the 16-bit timer 1
lds
tmpH,TCNT1H
; "
add
tmpL,dlyLo
adc
tmpH,dlyHi
sts
OCR1AH,tmpH
; start the first OC1A operation to start the high tone
sts
OCR1AL,tmpL
; "
ldi
tmpH,0x02
; enable OC1A interrupt locally
sts
TIMSK1,tmpH
; "
sts
TIFR1,tmpH
; clear OCF1A flag
sei
; enable interrupt globally
again:
ldi
R16,5
; wait for 0.5 s
call
dlyby100msOC
; "
ldi
dlyHi,high(loCnt)
; change delay count to that for 440 Hz
ldi
dlyLo,low(loCnt)
; "
ldi
R16,5
; wait for 0.5 s
call
dlyby100msOC
; "
ldi
dlyHi,high(hiCnt)
; change delay count to that for 880 Hz
ldi
dlyLo,low(hiCnt)
; "
rjmp
again
; jump to switch tone
; ----------------------------------------------------------------------------------------------------------------------------------------------; The OC1AISR interrupt routine restarts a new compare operation to OC1A using
; dlyHi:dlyLo as delay count.
; ----------------------------------------------------------------------------------------------------------------------------------------------oc1AISR: lds
tmpL,OCR1AL
lds
tmpH,OCR1AH
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
375
Using the Timer Normal Mode
add
adc
sts
sts
reti
tmpL,dlyLo
tmpH,dlyHi
OCR1AH,tmpH
OCR1AL,tmpL
; "
; start the next compare operation for
; channel OC1A
; ----------------------------------------------------------------------------------------------------------------------------------------------; Include the dlyby100msOC subroutine here
; ----------------------------------------------------------------------------------------------------------------------------------------------The C language version of the program is as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
#define hiCnt
1136
#define loCnt
2273
unsigned delay;
void dlyby100msOC(int k);
void main (void)
{
DDRB
|= 0x20;
// configure OC1A/PB5 for output
delay
= loCnt;
// prepare to generate the low tone (440 Hz)
TCCR1A = 0x40;
// configure OC1A to normal mode, compare match action set to toggle
TCCR1B = 0x02;
// use clk_I/O/8 as Timer 1 clock source
OCR1A = TCNT1 + delay;
// start the first compare operation
TIMSK1 = 0x02;
// enable OC1A compare match interrupt
TIFR1
= 0x02;
// clear OCF1A flag
sei();
// enable interrupt globally
while (1) {
dlyby100msOC(5);
// wait for 0.5 s
delay = hiCnt;
// switch to delay count for 880 Hz tone
dlyby100msOC(5);
delay = loCnt;
// switch to delay count for 440 Hz tone
}
}
// -------------------------------------------------------------------------------------------------------------------------------------------// Include the dlyby100msOC() function here.
// --------------------------------------------------------------------------------------------------------------------------------------------// -------------------------------------------------------------------------------------------------------------------------------------------// OC1A interrupt service routine. It starts the next compare operation and clears the OCF1A flag.
// -------------------------------------------------------------------------------------------------------------------------------------------ISR(TIMER1_COMPA_vect)
{
OCR1A += delay;
// start a new output compare operation
TIFR1 = 0x02;
// clear OCF1A flag
}
▲
11.7.4 Using the Normal Mode to Play a Song
A siren can be considered as a song with two notes. A song is created by modifying the siren
program. Each note has two components: one is the frequency and the other is the duration. To
make the switching of frequency easier, the whole song score should be stored in a table. The
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
376
Chapter 11
■
Timer Functions of the Mega AVR
duration of a quarter note is about 0.4 s. The durations of other notes are derived proportionally.
The complete list of the music notes and their frequencies is given in Appendix F.
To play a song using the speaker, we place the frequencies and durations of all the notes
in a music score in a table. For each note, the user program uses the output-compare function
to generate the digital waveform with the specified frequency and duration. It is common for
a song to have several contiguous identical notes in several different measures. When playing multiple contiguous identical notes, the buzzer/speaker generates one long note instead of
multiple notes. This problem is solved by inserting a short note between two adjacent identical
notes with an inaudible frequency (lower than 20 Hz or higher than 20 kHz). A music score may
also have rest notes. A rest note can be played by generating an inaudible sound with the specified duration. The following example illustrates this idea.
Example 11.5
▼
Use the circuit shown in Figure 11.17, and write a C program to play “Home Sweet Home,”
assuming that the frequency of clkI/O is 16 MHz.
Solution: To generate the correct note, we need to calculate the appropriate delay count for
each note in the music score. Assume that we select clkI/O ÷ 8 (= 2 MHz) as clock source to the
Timer/Counter1; then the delay count used in compare operation for a note with frequency f is
given by the following expression:
delay Count = 2 × 106 ÷ (2 × f)
(11.2)
For example, the delay count for the A4 note (440 Hz) is 2273 (= 2 × 106 ÷ (2 × 440)). We use
the delayby10msOC () function to generate durations for all the notes of the given song. This
function generates a time delay that is a multiple of 10 ms.
The assembly language version of the program is as follows:
.include
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
<m2560def.inc>
C4H
= high(3822)
C4L
= low(3822)
C4SH
= high(3608)
C4SL
= low(3608)
D4FH
= high(3608)
D4FL
= low(3608)
D4H
= high(3405)
D4L
= low(3405)
D4SH
= high(3214)
D4SL
= low(3214)
E4FH
= high(3214)
E4FL
= low(3214)
E4H
= high(3034)
E4L
= low(3034)
F4H
= high(2863)
F4L
= low(2863)
F4SH
= high(2703)
F4SL
= low(2703)
G4FH
= high(2703)
G4FL
= low(2703)
G4H
= high(2551)
G4L
= low(2551)
; delay count for creating 261.63 Hz tone
; delay count for creating 277.18 Hz tone
; 277.18 Hz
; 293.66 Hz
; 311.13 Hz
; 311.13 Hz
; 329.63 Hz
; 349.23 Hz
; 369.99 Hz
; 369.99 Hz
; 392.00 Hz
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
377
Using the Timer Normal Mode
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.equ
.def
.def
.def
.def
G4SH
G4SL
A4FH
A4FL
A4H
A4L
A4SH
A4SL
B4FH
B4FL
B4H
B4L
C5H
C5L
C5SH
C5SL
D5FH
D5FL
D5H
D5L
D5SH
D5SL
E5FH
E5FL
E5H
E5L
F5H
F5L
F5SH
F5SL
G5FH
G5FL
G5H
G5L
G5SH
G5SL
A5FH
A5FL
A5H
A5L
A5SH
A5SL
B5FH
B5FL
B5H
B5L
ZZH
ZZL
dlyHi
dlyLo
tmpH
tmpL
= high(2408)
= low(2408)
= high(2408)
= low(2408)
= high(2273)
= low(2273)
= high(2145)
= low(2145)
= high(2145)
= low(2145)
= high(2025)
= low(2025)
= high(1911)
= low(1911)
= high(1804)
= low(1804)
= high(1804)
= low(1804)
= high(1703)
= low(1703)
= high(1607)
= low(1607)
= high(1607)
= low(1607)
= high(1517)
= low(1517)
= high(1432)
= low(1432)
= high(1351)
= low(1351)
= high(1351)
= low(1351)
= high(1276)
= low(1276)
= high(1204)
= low(1204)
= high(1204)
= low(1204)
= high(1136)
= low(1136)
= high(1073)
= low(1073)
= high(1073)
= low(1073)
= high(1012)
= low(1012)
=0
= 20
= R20
= R21
= R22
= R23
; 415.30 Hz
; 415.30 Hz
; 440.00 Hz
; 466.16 Hz
; 466.16 Hz
; 493.88 Hz
; 523.25 Hz
; 554.37 Hz
; 554.37 Hz
; 587.33 Hz
; 622.25 Hz
; 622.25 Hz
; 659.26 Hz
; 698.46 Hz
; 739.99 Hz
; 739.99 Hz
; 783.99 Hz
; 830.61 Hz
; 830.61 Hz
; 880.00 Hz
; 932.33 Hz
; 932.33 Hz
; 987.77 Hz
; an inaudible note
; "
; delay count high byte
; delay count low byte
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
378
Chapter 11
■
Timer Functions of the Mega AVR
.cseg
.org
0x00
jmp
start
.org
OC1Aaddr
jmp
oc1AISR
.org
0xF6
start:
ldi
tmpH,low(RAMEND)
; initialize the SP
out
SPL,tmpH
; "
ldi
tmpH,high(RAMEND)
; "
out
SPH,tmpH
; "
ldi
tmpH,0x20
; configure OC1A/PB5 pin for output
out
DDRB,tmpH
; "
ldi
tmpH,0x40
; configure TMR1 to operate in normal mode and
sts
TCCR1A,tmpH
; set compare match action to toggle
ldi
tmpH,0x02
; select clk_I/O/8 as clock input to Timer 1
sts
TCCR1B,tmpH
; "
ldi
ZL,low(score<<1)
ldi
ZH,high(score<<1)
lpm
dlyLo,z+
lpm
dlyHi,z+
lds
tmpL,TCNT1L
; read the 16-bit timer 1
lds
tmpH,TCNT1H
; "
add
tmpL,dlyLo
adc
tmpH,dlyHi
sts
OCR1AH,tmpH
; start the first OC1A operation to start the song
sts
OCR1AL,tmpL
; "
ldi
tmpH,0x02
; enable OC1A interrupt locally
sts
TIMSK1,tmpH
; "
out
TIFR1,tmpH
; clear OCF1A flag
sei
; enable interrupt globally
ldi
ZL,low(score<<1)
ldi
ZH,high(score<<1)
songLp:
lpm
dlyLo,z+
; read OC delay count high and low bytes
lpm
dlyHi,z+
cpi
dlyHi,0
; is the upper byte equal to 0?
brne
rdDur
; no, continue to the low byte
cpi
dlyLo,0
; "
breq
done
; both bytes are zeros, stop
rdDur:
lpm
r16,z+
; read the duration of the current note
call
dlyby10msOC
; and place the current note for this duration
rjmp
songLp
; continue to the next note
done:
ldi
r16,0
; stop Timer 1
sts
TCCR1B,r16
; "
rjmp
done
; ----------------------------------------------------------------------------------------------------------------------------------------------; The OC1AISR interrupt routine restart a new compare operation to OC1A using
; dlyHi:dlyLo as the delay count.
; ----------------------------------------------------------------------------------------------------------------------------------------------oc1AISR:
lds
tmpL,OCR1AL
; start the next compare operation for
lds
tmpH,OCR1AH
; channel OC1A
add
tmpL,dlyLo
; "
adc
tmpH,dlyHi
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
Using the Timer Normal Mode
379
sts
OCR1AH,tmpH
; "
sts
OCR1AL,tmpL
; "
reti
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine uses Timer 3 OC3A to create a time delay that is a multiple of
; 10 ms. The multiple is passed in R16.
; ----------------------------------------------------------------------------------------------------------------------------------------------dlyby10msOC:
.def
tmp1 = r8
.def
tmp2 = r18
.def
tmp3 = r19
ldi
tmp2,0
; configure Timer 3 to normal mode
sts
TCCR3A,tmp2
; with clock source set to
ldi
tmp2,0x02
; clk_I/O/8
sts
TCCR3B,tmp2
; "
wp10:
lds
tmp1,TCNT3L
; make a copy of Timer 3
lds
tmp2,TCNT3H
; "
ldi
tmp3,low(20000)
; add a delay count of 20000 to this copy
add
tmp1,tmp3
; (equivalent to 10 ms)
ldi
tmp3,high(20000)
; "
adc
tmp2,tmp3
; "
sts
OCR3AH,tmp2
; start a compare operation on OC3A
sts
OCR3AL,tmp1
; "
ldi
tmp2,0x02
; clear OC3AF flag
out
TIFR3,tmp2
; "
wt10:
in
tmp1,TIFR3
; wait until OC3AF flag is set to 1
sbrs
tmp1,OCF3A
; "
rjmp
wt10
; "
dec
r16
; is the multiple decremented to 0 yet?
brne
wp10
ret
score:
.db
F4L,F4H,30, G4L,G4H,10, A4L,A4H,60, B4FL,B4FH,20, ZZL,ZZH,3, B4FL,B4FH,60
.db
C5L,C5H,20, ZZL,ZZH,3, C5L,C5H,60, A4L,A4H,20, ZZL,ZZH,3, A4L,A4H,40
.db
C5L,C5H,40, B4FL,B4FH,60, A4L,A4H,20, B4FL,B4FH,40
.db
G4L,G4H,40, A4L,A4H,120, F4L,F4H,30, G4L,G4H,10
.db
A4L,A4H,60, B4FL,B4FH,20, ZZL,ZZH,3, B4FL,B4FH,60, C5L,C5H,20, ZZL,ZZH,3
.db
C5L,C5H,80, A4L,A4H,40, C5L,C5H,40, B4FL,B4FH,60, A4L,A4H,20, B4FL,B4FH,40
.db
G4L,G4H,40, F4L,F4H,80, ZZL,ZZH,40, C5L,C5H,20
.db
ZZL,ZZH,3, C5L,C5H,20, F5L,F5H,60, E5L,E5H,20, D5L,D5H,60, C5L,C5H,20
.db
C5L,C5H,80, A4L,A4H,40, C5L,C5H,40, B4FL,B4FH,60, A4L,A4H,20, B4FL,B4FH,40
.db
G4L,G4H,40, A4L,A4H,120, C5L,C5H,20, ZZL,ZZH,3, C5L,C5H,20, F5L,F5H,60
.db
E5L,E5H,20, D5L,D5H,60, C5L,C5H,20, ZZL,ZZH,3, C5L,C5H,80, A4L,A4H,40
.db
C5L,C5H,40, C5L,C5H,40, B4FL,B4FH,80, G4L,G4H,40, F4L,F4H,120, ZZL,ZZH,40
.db
C5L,C5H,160, B4FL,B4FH,80, G4L,G4H,80, F4L,F4H,40, ZZL,ZZH,40, G4L,G4H,40
.db
ZZL,ZZH,40, A4L,A4H,80, ZZL,ZZH,40, C5L,C5H,40, F5L,F5H,60, E4L,E4H,20
.db
D5L,D5H,60, C5L,C5H,20, ZZL,ZZH,3, C5L,C5H,80, A4L,A4H,40, C5L,C5H,40
.db
B4FL,B4FH,60, A4L,A4H,20, B4FL,B4FH,40, G4L,G4H,40, F4L,F4H,120,0,0
The C program that plays the specified song is as follows:
#include
#include
#define
<avr\io.h>
<avr\interrupt.h>
C4
3822
// delay count for creating 261.63 Hz tone
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
380
Chapter 11
■
Timer Functions of the Mega AVR
#define
C4S
3608
// delay count for creating 277.18 Hz tone
#define
D4F
3608
// 277.18 Hz
#define
D4
3405
// 293.66 Hz
#define
D4S
3214
// 311.13 Hz
#define
E4F
3214
// 311.13 Hz
#define
E4
3034
// 329.63 Hz
#define
F4
2863
// 349.23 Hz
#define
F4S
2703
// 369.99 Hz
#define
G4F
2703
// 369.99 Hz
#define
G4
2551
// 392.00 Hz
#define
G4S
2408
// 415.30 Hz
#define
A4F
2408
// 415.30 Hz
#define
A4
2273
// 440.00 Hz
#define
A4S
2145
// 466.16 Hz
#define
B4F
2145
// 466.16 Hz
#define
B4
2025
// 493.88 Hz
#define
C5
1911
// 523.25 Hz
#define
C5S
1804
// 554.37 Hz
#define
D5F
1804
// 554.37 Hz
#define
D5
1703
// 587.33 Hz
#define
D5S
1607
// 622.25 Hz
#define
E5F
1607
// 622.25 Hz
#define
E5
1517
// 659.26 Hz
#define
F5
1432
// 698.46 Hz
#define
F5S
1351
// 739.99 Hz
#define
G5F
1351
// 739.99 Hz
#define
G5
1276
// 783.99 Hz
#define
G5S
1204
// 830.61 Hz
#define
A5F
1204
// 830.61 Hz
#define
A5
1136
// 880.00 Hz
#define
A5S
1073
// 932.33 Hz
#define
B5F
1073
// 932.33 Hz
#define
B5
1012
// 987.77 Hz
#define
ZZ
20
// 50000 Hz (inaudible sound)
unsigned int score[] = {
F4,G4, A4,B4F,ZZ,B4F,C5,ZZ,C5,A4, ZZ,A4, C5,B4F,A4,B4F,G4,A4,F4,G4,
A4,B4F,ZZ,B4F,C5,ZZ, C5,A4,C5,B4F,A4,B4F,G4,F4, ZZ,C5, ZZ,C5,F5,E5,D5,C5,
C5,A4, C5,B4F,A4,B4F,G4,A4,C5,ZZ, C5,F5, E5,D5, C5,ZZ, C5,A4,C5,
C5,B4F,G4,F4, ZZ,C5,B4F,G4,F4,ZZ, G4,ZZ,
A4,ZZ, C5,F5, E5,D5, C5,ZZ,C5,A4, C5,B4F,A4,B4F,G4,F4,0};
unsigned char dur[] = {
30,10, 60,20, 3, 60, 20,3, 60,20, 3, 40, 40,60, 20,40, 40,120,30,10,
60,20, 3, 60, 20, 3, 80,40,40,60, 20,40, 40,80, 40,20, 3, 20,60,20,60,20,
80,40, 40,60, 20,40, 40,120,20,3, 20,60, 20,60, 20,3, 80,40,40,
40,80, 40,120,40,160,80,80,40,40, 40,40,
80,40, 40,60, 20,60, 20,3, 80,40, 40,60, 20,40, 40,120};
unsigned int delay;
void delayby10msOC(unsigned char k);
void main (void)
{
unsigned
char j;
DDRB
|= 0x20;
// configure OC1A/PB5 for output
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
381
Using the Timer Normal Mode
delay
= score[0];
TCCR1A
= 0x40;
TCCR1B
= 0x02;
OCR1A
= TCNT1 + delay;
TIMSK1
= 0x02;
TIFR1
= 1<<OCF1A;
sei();
j = 0;
while(score[j]){
delay = score[j];
delayby10msOC(dur[j]);
j++;
}
TCCR1B = 0;
while(1);
// configure OC1A to normal mode, set compare match action to toggle
// use clk_I/O/8 as Timer 1 clock source
// start the first compare operation
// enable OC1A compare match interrupt
// clear OCF1A flag
// enable interrupt globally
// stop Timer 1
}
// -------------------------------------------------------------------------------------------------------------------------------------------// OC1A interrupt service routine. It starts the next compare operation and clears the OCF1A flag.
// -------------------------------------------------------------------------------------------------------------------------------------------ISR(TIMER1_COMPA_vect)
{
OCR1A
+= delay;
// start a new output compare operation
}
// -------------------------------------------------------------------------------------------------------------------------------------------// The following function creates a time delay that is a multiple of 10 ms using Timer 3
// OC3A function.
// -------------------------------------------------------------------------------------------------------------------------------------------void delayby10msOC(unsigned char k)
{
TCCR3A = 0;
// configure Timer 3 to normal mode
TCCR3B = 0x02;
// and select clk_I/O/8 as clock input
OCR3A = TCNT3 + 20000;
// start an output compare operation
TIFR3
= 1<<OCF3A;
// clear OCF3A flag
while(k) {
while(!(TIFR3 & (1<<OCF3A))); // wait for OCF3A flag to set
OCR3A
+= 20000;
// start a new OC3 compare operation
TIFR3
= 1<<OCF3A;
// clear OCF3A flag
K– –;
}
}
▲
11.7.5 Using the Normal Mode to Measure Signal Frequency
To measure the frequency of a signal, we need to use the signal as the clock source of the
timer/counter. After connecting the unknown signal to the external Tn pin input to the Timer/
Counter n and selecting Tn as the clock source, we enable Timer/Counter n to count up from
0 for 1 second. Depending upon the frequency of the unknown signal, the Timer/Counter n
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
382
Chapter 11
■
Timer Functions of the Mega AVR
may or may not overflow during the 1-second interval. The frequency of the unknown signal is
expressed as follows:
Frequency = tovCnt × 216 + final Timer count
(11.3)
where, tovCnt represents the number of times that Timer n overflows during the 1-second
period.
Example 11.6
▼
Write a program to measure the frequency of an unknown signal connected to the T1 pin,
assuming that fclk_I/O = 16 MHz.
Solution: We select T1 as the clock source to Timer 1 and use Timer 5 to create a delay of 1 second. The assembly program that measures the frequency of the unknown signal is as follows:
.include <m2560def.inc>
start:
again:
.def
tmp = r16
.def
.def
.def
.cseg
.org
jmp
.org
jmp
.org
ldi
out
ldi
out
cbi
ldi
sts
sts
sts
ldi
ldi
sts
ldi
sts
ldi
out
sts
sei
ldi
call
ldi
sts
lds
lds
jmp
t1OVCnt = r25
freqH = r2
freqL = r3
0x00
start
OVF1Addr
T1OVISR
0xF6
tmp,low(RAMEND)
SPL,tmp
tmp,high(RAMEND)
SPH,tmp
DDRD,6
tmp,0
TCCR1B,tmp
TCNT1H,tmp
TCNT1L,tmp
t1OVCnt,0
tmp,0
TCCR1A,tmp
tmp,7
TCCR1B,tmp
tmp,0x01
TIFR1,tmp
TIMSK1,tmp
tmp,10
dlyby100msOC
tmp,0
TCCR1B,tmp
freqL,TCNT1L
freqH,TCNT1H
again
; r25:r2:r3 holds the frequency
; "
; "
; initialize the SP
; "
; "
; "
; configure PD6 for input (T1 pin)
;
; stop Timer 1
; force Timer 1 to count from 0
; "
; initialize TCNT1 overflow count to 0
; configure Timer 1 to normal mode
; "
; configure Timer 1 to use T1 as its clock
; input and count using T1’s rising edge
; clear the TOV1 flag
; "
; enable Timer 1 overflow interrupt
; enable interrupt globally
; wait for 1 second
; "
; stop Timer 1
; "
; copy the TCNT1L
; copy the TCNT1H
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
Using the Timer Normal Mode
383
; ----------------------------------------------------------------------------------------------------------------------------------------------; Insert dlyby100msOC here
; ----------------------------------------------------------------------------------------------------------------------------------------------; ----------------------------------------------------------------------------------------------------------------------------------------------; The following is the Timer 1 overflow service routine.
; ----------------------------------------------------------------------------------------------------------------------------------------------T1OVISR:
inc
t1OVCnt
reti
The C language version of the program is as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
unsigned char tovCnt;
unsigned long freq;
void delayby100ms(unsigned char cx);
void main (void)
{
tovCnt
= 0;
DDRD
&= ~0x40;
// configure T1 for input
TCCR1A = 0;
// configure Timer 1 to normal mode
TCCR1B = 0;
// stop Timer 1
TCNT1H = 0;
// let Timer 1 to count up from 0
TCNT1L = 0;
// "
TIFR1
= 1 << TOV1;
// clear TOV1 flag
TIMSK1 = 1 << TOIE1;
// enable TOV1 interrupt
TCCR1B = 0x07;
// enable Timer 1 to count using T1 input as clock source
sei();
// enable interrupt globally
delayby100ms(10);
// wait for 1 second
TCCR1B = 0;
// stop Timer 1
freq
= (long)tovCnt * 65536 + (long)TCNT1;
while(1);
}
void delayby100ms(unsigned char cx)
{
TCCR3A = 0;
// configure Timer 3 to normal mode with clock source
TCCR3B = 0x03;
// set to clk_I/O/64
while(cx){
TCNT3 = 40536;
// let Timer 3 to count up from 40536
TIFR3 = 1 << TOV3;
// clear TOV3 flag
while(!(TIFR3 & (1<<TOV3)));
// wait until TOV3 is set to 1
cx– –;
}
}
// -------------------------------------------------------------------------------------------------------------------------------------------// Timer 1 overflow interrupt service routine.
// -------------------------------------------------------------------------------------------------------------------------------------------ISR (TIMER1_OVF_vect)
{
tovCnt++;
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
384
Chapter 11
■
Timer Functions of the Mega AVR
11.7.6 Measuring Signal Period Using the Normal Mode
The period of a signal can be measured by capturing two consecutive rising or falling edges.
The procedure is as follows:
Step 1
Configure the timer/counter properly.
Step 2
Wait for the first rising edge to arrive.
Step 3
Enable timer overflow interrupt and cleared ICV and TOV flags. Initialize timer overflow
count to 0. Force timer/counter to count up from 0.
Step 4
Wait for the arrival of the second rising edge.
The period of the signal is equal to the following expression:
Period = timer overflow count × 65536 + captured second edge
(11.4)
Example 11.7
▼
Assume that an unknown signal is connected to the ICP1 pin of the Mega2560 MCU and
fclk_I/O = 16 MHz. Write an assembly and C program to measure the period of the signal and represent the period in the unit of Timer 1 clock cycles.
Solution: The assembly program that measures the signal period is as follows:
; ----------------------------------------------------------------------------------------------------------------------------------------------; This program measures the signal period using ICP1 pin and represents the period
; in the unit of clock cycle.
; ----------------------------------------------------------------------------------------------------------------------------------------------.include
<m2560def.inc>
.def
t1OVCnt
= r25
.def
perHi
= r2
.def
perLo
= r3
.def
tmp
= r16
.cseg
.org
0x00
jmp
start
.org
OVF1Addr
jmp
T1OVISR
.org
0xF6
start:
ldi
tmp,low(RAMEND)
; initialize the SP
out
SPL,tmp
; "
ldi
tmp,high(RAMEND)
; "
out
SPH,tmp
; "
ldi
tmp,0xEF
out
DDRD,tmp
; configure PD4 for input (ICP1 pin)
ldi
tmp,0
sts
TCCR1A,tmp
; configure Timer 1 to normal mode
mov
t1Ovcnt,tmp
; initialize Timer 1 overflow count to 0
ldi
tmp,1<<ICF1
; clear ICF1 flag
out
TIFR1,tmp
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.7
■
Using the Timer Normal Mode
385
ldi
tmp,0x42
; capture rising edge, use clk_I/O/8 as clock source to Timer 1
sts
TCCR1B,tmp
; "
edge1:
in
tmp,TIFR1
; wait until the first rising edge arrives
sbrs
tmp,ICF1
; "
rjmp
edge1
; "
ldi
tmp,0
sts
TCNT1H,tmp
; force Timer 1 to count up from 0
sts
TCNT1L,tmp
; "
ldi
tmp,0x01
; enable Timer 1 overflow interrupt
sts
TIMSK1,tmp
; "
ldi
tmp,(1<<ICF1)|(1<<TOV1) ; clear ICF1 and TOV1 flags
out
TIFR1,tmp
; "
sei
; enable interrupt globally
edge2:
in
tmp,TIFR1
; wait until the second rising edge arrives
sbrs
tmp,ICF1
; (when ICF1 flag is set to 1)
rjmp
edge2
; "
lds
perLo,ICR1L
; copy the latched timer 1 value
lds
perHi,ICR1H
; "
ldi
tmp,0
; stop Timer 1
sts
TCCR1B,tmp
; "
here:
jmp
here
;
; ----------------------------------------------------------------------------------------------------------------------------------------------; The Timer 1 overflow interrupt service routine increment the overflow count by 1.
; ----------------------------------------------------------------------------------------------------------------------------------------------T1OVISR: inc
t1OVCnt
reti
The C language version of the program is as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
unsigned char tovCnt;
unsigned long period;
void main (void)
{
tovCnt = 0;
TCCR1A = 0;
// configure Timer 1 to normal mode
DDRD = 0xEF;
// configure ICP1 pin for input (PD4)
TIFR1 = 0x2F;
// clear all flags related to Timer 1
TCCR1B = 0x42;
// capture rising edge, use clk_I/O/8 as Timer 1 clock input
while(˜(TIFR1 & (1<<ICF1)));
// wait for the arrival of the first rising edge
TCNT1 = 0;
// let Timer 1 to count up from 0
TIFR1 = 0x21;
// clear ICF1 and TOV1 flags
TIMSK1 = 1;
// enable TOV1 interrupt
sei();
// enable interrupt globally
while(˜(TIFR1 & (1<<ICF1)));
// wait for the arrival of the second rising edge
TCCR1B = 0;
// stop Timer 1
period = (long)tovCnt * 65536 + (long)ICR1;
while(1);
}
// -------------------------------------------------------------------------------------------------------------------------------------------// Timer 1 overflow interrupt service routine.
// --------------------------------------------------------------------------------------------------------------------------------------------
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
386
Chapter 11
■
Timer Functions of the Mega AVR
ISR (TIMER1_OVF_vect)
{
tovCnt++;
}
▲
The pulse width and duty cycle of a signal are measured using a similar method, and hence
these are left as exercise problems.
11.8 Using the CTC Mode
In the clear timer on compare match (CTC) mode, the counter is cleared to 0 when the
Timer/Counter n (TCNTn) counts up to the TOP value (TOP is either the OCRnA register [for
all timers] or the ICRn register [for 16-bit timer only]). When the counter counts up to the TOP
value, either the OCFnA or ICFn flag is set, depending on whether the OCRnA or ICRn register
is selected as the TOP value. An associated interrupt is requested if it is enabled. If the TOP
value is set to the MAX value, then the TOVn flag is also set when the timer/counter counts up
to the TOP value.
The CTC mode is used to create time delay and generate waveforms.
11.8.1 Using the CTC Mode to Create Time Delay
To use CTC mode to create time delay, we use either the OCRnA or ICRn register to hold
the TOP value of the timer. The procedure in using the CTC mode to create time delay is as
follows:
Step 1
Calculate the timer count corresponding to the desired time delay.
Step 2
Place the calculated timer count in either the OCRnA or the ICRn register.
Step 3
Clear the OCFnA (when OCRnA holds the TOP value) or the ICFn flag (when ICRn holds
the TOP value).
Step 4
Select the appropriate clock source, and enable the timer to count up from 0.
Step 5
Wait until the OCFnA or the ICFn flag is set.
Example 11.8
▼
Write a function that uses the CTC mode of Timer/Counter3 to create a time delay that is
a multiple of 1 ms, assuming that frequency of the clkI/O clock is 16 MHz.
Solution: By setting the Timer 3 clock prescaler to 8, the timer count corresponding to 1 ms is
2000 clock cycles (10-3 × 16 × 106 ÷ 8 = 2000). Place 2000 in ICR3 register, let Timer 3 count up
from 0, and wait for the ICF3 flag to be set to 1; a 1-ms delay is created. The following subroutine creates a time delay that is a multiple of 1 ms.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.8
■
387
Using the CTC Mode
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following subroutine creates a time delay that is a multiple of 1 ms using
; Timer 3 CTC mode. The multiple is passed in register R16.
; ----------------------------------------------------------------------------------------------------------------------------------------------delayby1msCTC:
.def
tmp1 = r20
ldi
tmp1,0x00
; configure Timer 3 to CTC mode (WGM33:0 = 12)
sts
TCCR3A,tmp1
; use the ICR3 register to hold TOP value
ldi
tmp1,0x1A
; with clock source set to clkI/O /8
sts
TCCR3B,tmp1
; "
ldi
tmp1,0
; let Timer 3 count up from 0
sts
TCNT3H,tmp1
; "
sts
TCNT3L,tmp1
; "
wp1:
ldi
tmp1,high(2000)
; load 2000 into ICR3 so that Timer 3
sts
ICR3H,tmp1
; overflows in 2000 clock cycles
ldi
tmp1,low(2000)
; "
sts
ICR3L,tmp1
; "
nxtLp:
ldi
tmp1,1 << ICF3
; clear ICF3 flag
sts
TIFR3,tmp1
; "
wt1:
lds
tmp1,TIFR3
; wait until ICF3 flag is set to 1
sbrs
tmp1,ICF3
; "
rjmp
wt1
; "
dec
r16
brne
nxtLp
ret
The C language version of the function is as follows:
void delayby1ms (unsigned char k)
{
TCCR3A = 0x00;
TCCR3B = 0x1A;
TCNT3 = 0;
ICR3
= 2000;
TIFR3
= 1 << ICF3;
while(k) {
while (!(TIFR3 & 1<< ICF3));
TIFR3 = 1<< ICF3;
k– –;
}
}
// configure Timer 3 to CTC mode with clock
// set to clk_I/O/8 (WGM3:0 = 12)
// TCNT3 counts up from 0
// ICR3 holds the TOP value
// clear ICF3 flag
// wait for 1 ms
// clear ICF3 flag
▲
11.8.2 Using the CTC Mode to Generate Waveform
A periodic square wave with 50% duty cycle is easily generated using the timer CTC mode.
To generate a periodic square wave with 50% duty cycle and frequency fW, the TOP value is
computed using the following expression:
TOP = (fCLK_I/O ÷ Timer prescaler) ÷ (2 × fW) – 1
(11.5)
The next example illustrates this application.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
388
Chapter 11
■
Timer Functions of the Mega AVR
Example 11.9
▼
Write a program to generate a 500 Hz square wave with 50% duty cycle from the OC0A
pin, assuming that the fclk_I/O is 16 MHz.
Solution: By setting the Timer0 prescaler to 64 and using Equation 11.5, the value to be loaded
into the OCR0A register is calculated to be 249. The following assembly program generates the
desired waveform:
start:
again:
.include
.def
.equ
.cseg
.org
jmp
.org
ldi
out
ldi
out
ldi
out
ldi
out
ldi
out
ldi
out
sts
ldi
out
jmp
<m2560def.inc>
tmp = r16
NN = 249
0x00
start
0xF6
tmp,low(RAMEND)
SPL,tmp
r16,high(RAMEND)
SPH,tmp
tmp,0x80
DDRB,tmp
tmp,0x42
TCCR0A,tmp
tmp,0x03
TCCR0B,tmp
tmp,0x0
TCNT0,tmp
TIMSK0,tmp
tmp,NN
OCR0A,tmp
again
; value to be placed in OCR0A register
; initialize the SP
; "
; "
; "
; configure PORTB pin 7 (OC0A pin) for output
; "
; configure the OC0A pin to toggle on compare match
; "
; select CTC mode and set clock source
; to clkI/O/64
; disable OC0A compare match interrupt
; "
; load NN to OCR0A register
; "
; wait here or perform other operation
The C language version of the program is as follows:
#include <avr\io.h>
#define NN
249
void main (void)
{
DDRB
|= 0x80;
TCCR0A = 0x42;
TCCR0B = 0x03;
TIMSK0 = 0;
TCNT0
= 0;
OCR0A = NN;
while(1);
}
// value to be placed in OCR0A compare operation
// configure the OC0A pin for output
// OC0A pin to toggle on compare match
// in CTC mode, clock source set to clk_I/O/64
// disable OC0A match interrupt
// force TCNT0 to count up from 0
// start the first compare operation
// wait for waveform to be generated
A square wave with other duty cycle value (≠ 50%) is created in CTC mode by enabling
interrupt and changing the TOP value using the interrupt service routine. The next example
illustrates the procedure.
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.8
■
389
Using the CTC Mode
Example 11.10
▼
Write a program to generate a 1 kHz square wave with 30% duty cycle using Timer 0,
assuming that fclk_I/O is 16 MHz.
Solution: By setting the TCNT0 clock prescale factor to 64, the frequency of the TCNT0 clock
is set to 250 kHz. The period of a 1 kHz square wave is 1 ms. The high interval of a period for
the 1 kHz square wave corresponds to 75 clock cycles for the 250 kHz clock input and the low
interval correspond to 175 clock cycles. The following assembly program generates the specified 1 kHz square wave:
start:
again:
.include <m2560def.inc>
.def
tmp
= r16
.def
HIoLO = r17
.equ
hiCnt
= 75
.equ
loCnt
= 175
.equ
LO
=0
.equ
HI
=1
.cseg
.org
0x00
jmp
start
.org
OC0Aaddr
jmp
oc0AISR
.org
0xF6
ldi
tmp,low(RAMEND)
out
SPL,tmp
ldi
tmp,high(RAMEND)
out
SPH,tmp
ldi
tmp,0x80
out
DDRB,tmp
ldi
tmp,0xC2
out
TCCR0A,tmp
ldi
tmp,0x03
out
TCCR0B,tmp
ldi
tmp,0x83
out
TCCR0B,tmp
ldi
tmp,0x42
out
TCCR0A,tmp
ldi
tmp,0x02
sts
TIMSK0,tmp
out
TIFR0,tmp
ldi
tmp,0
out
TCNT0,tmp
ldi
tmp,hiCnt
out
OCR0A,tmp
ldi
HIoLO,LO
sei
jmp
again
; flag for selecting hiCnt or loCnt
; high interval clock count
; low interval clock count
; TCC0 capture/compare channel 0 interrupt vector
; initialize the SP
; "
; "
; "
; configure PORTB pin 7 (OC0A pin) for output
; "
; OC0A pin to be pulled high when TCNT0 matches OCR0A
; and select CTC mode
; set clock source to clkI/O/64
; "
; force OC0A
; and pull the OC0A pin high
; OC0A pin toggle on compare match
; "
; enable OC0A compare match interrupt
; "
; clear OCF0A interrupt flag
; let TCNT0 to count up from 0
; load OCR0A with hiCnt
; "
; next time load loCnt into OCR0A
; enable interrupt globally
; wait for OC0A interrupt
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
390
Chapter 11
■
Timer Functions of the Mega AVR
; ----------------------------------------------------------------------------------------------------------------------------------------------; The following instruction sequence is the OC0A compare match interrupt service routine.
; ----------------------------------------------------------------------------------------------------------------------------------------------oc0AISR:
sbrs
HIoLO,0
; skip if bit 0 is set
rjmp
setLO
ldi
tmp,hiCnt
; load OCR0A with hiCnt
out
OCR0A,tmp
; "
ldi
HIoLO,LO
reti
setLO:
ldi
tmp,loCnt
; load OCR0A with loCnt
out
OCR0A,tmp
; "
ldi
HIoLO,HI
reti
The C language version of the program is as follows:
#include <avr\io.h>
#include <avr\interrupt.h>
#define
hiCnt
75
// delay count for high interval in a period
#define
loCnt
175
// delay count for low interval in a period
#define
HI
1
#define
LO
0
char
HIoLO;
// flag to select hiCnt or loCnt
void main (void)
{
DDRB
|= 0x80;
// configure OC0A pin for output
TCCR0A = 0xC2;
// OC0A pin pull high on compare match
TCCR0B = 0x03;
// CTC mode, clock source set to clkI/O/64
TCCR0B = 0x83;
// force OC0A pin to high
TCCR0A = 0x42;
// toggle OC0A pin on match in CTC mode
TCNT0 = 0;
// let TCNT0 count up from 0
OCR0A = hiCnt;
// load high interval into OCR0A
HIoLO = 0;
// next time to load loCnt into OCR0A
TIMSK0 = 0x02;
// enable OC0A compare match interrupt
TIFR0
= 0x02;
// clear OCF0A flag
sei();
// enable interrupt globally
while(1);
// wait for interrupt to occur
}
// -------------------------------------------------------------------------------------------------------------------------------------------// OC0A interrupt service routine. It starts the next compare operation and clears the OCF0A flag.
// -------------------------------------------------------------------------------------------------------------------------------------------ISR(TIMER0_COMPA_vect)
{
if(HIoLO){
OCR0A = hiCnt;
HIoLO = LO;
} else {
OCR0A = loCnt;
HIoLO = HI;
}
}
▲
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.9
■
391
Using the Fast PWM Mode
11.9 Using the Fast PWM Mode
The fast PWM mode is mainly used to generate a single-slope PWM waveform shown in
Figure 11.4a. In the fast PWM mode, the timer counts from BOTTOM to TOP and then restarts
from BOTTOM. An 8-bit timer may use 0×FF or the value held in the OCRnA register as its
TOP value. However, a 16-bit timer may use 0×00FF, 0×01FF, 0×03FF, the value held in the
ICRn register, or the value held in the OCRnA register as its TOP value; where, n = 0, …, 5. The
frequency of the fast PWM waveform is given by the following equation:
ffastPWM = (fclk_I/O ÷ timer prescaler) ÷ TOP
(11.6)
11.9.1 Compare Match Pin Action in Fast PWM Mode
TCNTn = 0
TCNTn = OCRnx
TCNTn = TOP
(a) Non-inverting mode (COMnx1: 0 = 10)
TCNTn = OCRnx
TCNTn = 0
(b) Inverting mode (COMnx1: 0 = 11)
Figure 11.18
■
n = 0, …, 5
x = A, B, or C
Source: Atmel Corporation, The Atmel AVR Microcontroller
In the fast PWM mode, we mainly use the compare match pin actions 2 and 3. When the
COMnx1:COMnx0 bit field in the TCCRnA register is 10, the fast PWM mode operates in the
non-inverting mode. When the COMnx1:COMnx0 bit field in the TCCRnA register is 11, the fast
PWM mode operates in the inverting mode. These two modes are shown in Figure 11.18.
Fast PWM mode waveforms
11.9.2 Using OCRnA to Hold the TOP Value
When using the OCRnA register to hold the timer TOP value, the OCnA pin is not available for generating the PWM output. Only the OCnB and OCnC pins are used to generate PWM
waveforms. However, using the OCRnA register to hold the TOP value has an advantage: the
generated PWM waveform is always symmetric. The OCRnA register is double-buffered. When
a new value is written into the OCRnA register, it is written into the buffer register of OCRnA.
The OCRnA register is updated with the value in the buffer one timer clock cycle after the
TCNTn matches the TOP value, that is, at the moment when TCNTn is cleared to 0 and the
TOVn flag is set.
11.9.3 Using ICRn to Hold the TOP Value
The ICRn register is not double-buffered. This means that if ICRn is changed to a value
lower than the current TCNTn value, the counter misses the compare match at the TOP value.
The counter increments to the MAX value (0×FF or 0×FFFF) and rolls over to 0×0000 before the
compare match occurs. Please note that the ICRn register is not available in an 8-bit timer.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
392
Chapter 11
■
Timer Functions of the Mega AVR
Using the ICRn register to hold the TOP value works well when the TOP value is fixed. By
using ICRn, the OCRnA register is free to be used for generating a PWM output on the OCnA
pin. However, if the base PWM frequency is actively changed (by changing the TOP value),
using the OCRnA as TOP is clearly a better choice due to its double-buffered feature.
11.9.4 Extreme Cases for the Fast PWM
There are two extreme cases for the fast PWM mode. One case is when the OCRnx register is set equal to the BOTTOM (0×0000). In this case, the output is a narrow spike for
every TOP+1 timer clock cycle. Another extreme case is setting the OCRnx equal to TOP,
which results in a constant high or low depending on the polarity of the output set by the
COMnx1:0 bits.
A frequency (with 50% duty cycle) waveform output in fast PWM mode is achieved by setting OCnA (OCnB and OCnC are disconnected from pins in this case) to toggle its logical level
on each compare match (COMnA1:0 = 01 in Table 11.3 and Table 11.8). This applies only if the
OCRnA register is used to define the TOP value. The waveform generated has a maximum frequency of fOCnA = fclk_I/O/2 when OCRnA is set to 0.
Example 11.11
▼
Write an instruction sequence and a sequence of C statements to generate a PWM waveform with 60% duty cycle using the fast PWM non-inverting mode from OC0A pin, assuming
that fclk_I/O is 16 MHz. Set timer clock input prescaler to 8.
Solution: We use 255 as the TOP value. The value to be loaded into the OCR0A register is
256 × 60% = 154. The following instruction sequence generates the specified PWM waveform:
.def
ldi
out
ldi
out
ldi
out
ldi
out
ldi
out
tmp = R16
tmp,0x80
DDRB,tmp
tmp,0x83
TCCR0A,tmp
tmp,0x02
TCCR0B,tmp
tmp,0
TCNT0,tmp
tmp,154
OCR0A,tmp
; configure PORTB pin 7 (OC0A pin) for output
; "
; Fast PWM mode, clear the OC0A pin on compare match
; set OC0A at BOTTOM
; set clock source to clk_I/O/8
; "
; force TCNT0 to count up from 0
; "
; set duty cycle to 60%
; "
The following C statements generates the same waveforms:
DDRB
TCCR0A
TCCR0B
TCNT0
OCR0A
|= 0x80;
= 0x83;
= 0x02;
= 0;
= 154;
// configure OC0A pin for output
// select fast PWM, non-inverting mode
// and set clock prescaler to 8
// force TCNT0 to count up from 0
// set duty cycle to 60%
▲
Example 11.12
▼
Write a sequence of instructions to generate a 2 kHz square waveform with 40% duty cycle
from the OC1C pin using the fast PWM mode, assuming that fclk_I/O = 16 MHz.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.10
■
Using the Phase-Correct PWM Mode
393
Solution: There are many ways to generate the specified waveform using the fast PWM mode.
One possibility is as follows:
•
•
•
•
•
Select clkI/O /8 as the Timer 1 clock.
Select ICR1 to hold the TOP value.
The TOP value is (16 MHz ÷ 8) ÷ 2 kHz = 1000.
Set compare output mode to 10 (non-inverting mode).
Place 600 in the OCR1C register to set duty cycle to 60%.
The following instruction generates the specified waveform with the specified settings:
.def
sbi
ldi
sts
ldi
sts
ldi
sts
ldi
sts
ldi
sts
sts
ldi
sts
ldi
sts
tmp = r16
DDRB,7
tmp,high(1000)
ICR1H,tmp
tmp,low(1000)
ICR1L,tmp
tmp,high(600)
OCR1CH,tmp
tmp,low(600)
OCR1CL,tmp
tmp,0
TCNT1H,tmp
TCNT1L,tmp
tmp,0x0A
TCCR1A,tmp
tmp,0x1A
TCCR1B,tmp
; configure PB7 pin for (OC1C pin) output
; use ICR1 to hold TOP (1000)
; "
; "
; "
; set duty cycle (OCR1C <- 600)
; "
; "
; "
; let Timer 1 count up from 0
; select noninverting output compare mode (10)
; "
; select clk_I/O/8 as clock source, fast PWM mode
; using the ICR1 register to hold the TOP value
The following C statements generate the same waveform:
DDRB
ICR1
OCR1C
TCNT1
TCCR1A
TCCR1B
|= 0x80;
= 1000;
= 600;
= 0;
= 0x0A;
= 0x1A;
// configure OC1C pin for output
// use ICR1 to hold the TOP value
// OCR1C controls the duty cycle
// force Timer 1 to count up from 0
// select non-inverting output compare mode
// select clk_I/O/8 as clock input, choose fast PWM mode
▲
11.10 Using the Phase-Correct PWM Mode
The phase-correct PWM mode is also meant to generate periodic square wave with specified
frequency and duty cycle but is based on a dual-slope operation. The counter counts repeatedly
from BOTTOM (0x0000) to TOP and then from TOP to BOTTOM. In non-inverting compare
output mode, the output-compare (OCnx) signal is cleared on the compare match between
TCNTn and OCRnx while counting up, and set on the compare match while counting down.
In inverting output-compare mode, the operation is inverted. The dual-slope operation is illustrated in Figure 11.19.
The frequency of the frequency-correct PWM waveform is as follows:
fPCPWM = (fclk_I/O ÷ timer prescaler) ÷ (2 × TOP)
(11.7)
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
Chapter 11
■
Timer Functions of the Mega AVR
TCNTn == TOP
Counting
up
Counting
down
Counting
up
Counting
down
OCnx
OCnx
Figure 11.19
■
TCNTn == OCRnx
TCNTn == 0
Inverting
output-compare
mode
TCNTn == OCRnx
TCNTn == 0
TCNTn == 0
Non-inverting
output-compare
mode
TCNTn == TOP
Source: Atmel Corporation, The Atmel AVR Microcontroller
394
Phase-correct PWM mode, timing diagram
11.10.1 The Choice of the TOP Value
An 8-bit timer may use 0×FF or the OCRnA register (n= 0 or 2) as its TOP value whereas a
16-bit timer may set its TOP value to 0×00FF, 0×01FF, 0×03FF, the value in the OCRnA register,
or the value in the ICRn register. The timer/counter overflow flag (TOVn) is set each time the
timer counts down to the BOTTOM value. When either the OCRnA or ICRn register is used
for defining the TOP value, the OCFnA or ICFn flag is set accordingly at the same timer clock
cycle as the OCRnx Registers are updated with the double buffer value (when Timer counts up
to the TOP value). The interrupt flags are used to generate an interrupt each time the counter
reaches the TOP or BOTTOM value.
The TOP value must be selected to be higher than any compare register associated with the
same timer. If the TOP value is lower than any of the compare registers, a compare match never
occurs between the TCNTn and the OCRnx registers.
Changing the TOP value frequently while the timer/counter is running in the phase-correct
mode could result in an unsymmetrical output. The reason for this can be found in the time
of update of the OCRnx Register. Because the update of the OCRnx register occurs at TOP, the
PWM period starts and ends at TOP. This implies that the length of the falling slope is determined by the previous TOP value, while the length of the rising slope is determined by the new
TOP value. When these two values differ the two slopes of the period differ in length. The difference in length gives the unsymmetrical result on the output.
It is recommended to use the phase-and-frequency-correct mode instead of the phasecorrect mode when changing the TOP value while the timer/counter is running. When using a
static TOP value there are practically no differences between the two modes of operation.
11.10.2 Pin Action on Compare Match in the Phase-Correct PWM Mode
Like any other timer mode, there are four possible compare-match pin actions as shown in
Table 11.4 and Table 11.9. Since the frequency-correct PWM mode is provided to generate PWM
waveform, only the pin action choice 2 (non-inverting mode) and 3 (inverting mode) should be
selected.
Example 11.13
▼
Use the OC0A pin to generate a 40% duty cycle PWM waveform using the phase-correct
PWM non-inverting mode, assuming that the frequency of clkI/O is 16 MHz. Set timer clock
input prescaler to 8.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.10
■
Using the Phase-Correct PWM Mode
395
Solution: We set the TOP value to 0×FF. The value to be loaded into the OCR0A is 102 (= 256 ×
40%). The WGM2:0 bits should be set to 001. The following instruction sequence generates the
desired PWM waveform:
.def
ldi
out
ldi
out
ldi
out
ldi
out
ldi
out
tmp = R16
tmp,0x80
DDRB,tmp
tmp,0x81
TCCR0A,tmp
tmp,0x02
TCCR0B,tmp
tmp,102
OCR0A,tmp
tmp,0
TCNT0,tmp
; configure the PB7/OC0A pin for output
; "
; configure OC0A to phase-correct PWM, non-inverting mode
; "
; select clk_I/O/8 as the clock source
; to TCNT0
; set duty cycle to 40%
; "
; force TCNT0 to count up from 0
; "
The following C statements generate the same waveform:
DDRB
TCCR0A
TCCR0B
OCR0A
TCNT0
|= 0x80;
= 0x81;
= 0x02;
= 102;
= 0;
// configure OC0A pin for output
// configure OC0A to phase-correct, non-inverting PWM mode
// select clk_I/O/8 as the clock input to TCNT0
// set duty cycle to 40%
// force TCNT0 to count up from 0
▲
Example 11.14
▼
Write a sequence of instructions and C statements to generate a 5kHz PWM waveform
with 75% duty cycle using the OC1B pin, assuming that the frequency of the clkI/O clock is
16 MHz.
Solution: In this problem, we use the following settings to generate the specified waveform:
•
•
•
•
•
•
•
Select the phase-correct PWM mode to generate the specified waveform.
Set clk_I/O as the clock source of Timer 1.
Use ICR1 register to hold the TOP value.
The TOP value is 16 × 106 ÷ (2 × 5000) = 1600.
Place 1200 in OCR1B to set duty cycle to 75%.
Set compare output mode to 10 (non-inverting mode).
Select phase-correct PWM mode
The following instruction sequence generates the specified waveform accordingly:
.def
ldi
out
ldi
sts
ldi
sts
ldi
sts
tmp = r20
tmp,0x40
DDRB,tmp
tmp,high(1600)
ICR1H,tmp
tmp,low(1600)
ICR1L,tmp
tmp,high(1200)
OCR1BH,tmp
; configure OC1B/PB6 pin for output
; "
; use ICR1 to hold TOP (1600)
; "
; "
; "
; set duty cycle (OCR1B <- 1200)
; "
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
396
Chapter 11
ldi
sts
ldi
sts
sts
ldi
sts
ldi
sts
■
Timer Functions of the Mega AVR
tmp,low(1200)
OCR1BL,tmp
tmp,0
TCNT1H,tmp
TCNT1L,tmp
tmp,0x22
TCCR1A,tmp
tmp,0x11
TCCR1B,tmp
; "
; "
; let Timer 1 count up from 0
; "
; "
; select non-inverting output compare mode (10)
; "
; select clkI/O as clock source, phase-correct PWM mode
; "
The following C statements generate the specified waveform:
DDRB
ICR1
OCR1B
TCNT1
TCCR1A
TCCR1B
|= 0x40;
= 1600;
= 1200;
= 0;
= 0x22;
= 0x11;
// configure OC1B pin for output
// use ICR1 register to hold TOP
// OCR1B controls the duty cycle
// force Timer 1 to count up from 0
// select non-inverting output compare mode
// select clk_I/O/ as clock input, choose phase-correct PWM mode
▲
11.11 Using the Phase and Frequency Correct PWM Mode
Like the phase-correct PWM (PCPWM) mode, the phase-and-frequency-correct PWM
(PFCPWM) mode is based on a dual-slope operation and is available only in a 16-bit timer. The
counter counts repeatedly from BOTTOM to TOP and then from TOP to BOTTOM. In noninverting compare output mode, the output-compare (OCnx) signal is cleared on the compare
match between TCNTn and OCRnx while counting up, and set on the compare match while
counting down. In inverting compare output mode, the operation is inverted. The frequency
of the PWM output of the phase-and-frequency-correct PWM mode is given by the following
equation:
fPFCPWM = (fCLK_I/O ÷ timer prescaler) ÷ (2 × TOP)
(11.8)
The difference between the PCPWM and PFCPWM modes are found by examining Table 11.6:
•
The PCPWM mode has five possible TOP values whereas the PFCPWM mode may
have only two possible TOP values.
•
When both modes use the same TOP value, the PCPWM mode updates its
OCRx register when the timer counts up to the TOP value whereas the
PFCPWM mode updates its OCRx register when the timer counts down to
the BOTTOM value.
The timer/counter overflow flag (TOVn) flag is set at the same timer clock cycle as the
OCRnx registers are updated with the double buffer value (at BOTTOM). When either the
OCRnA or ICRn register is used to define the TOP value, the OCnA or ICFn flag is set when
TCNTn has reached the TOP value. The interrupt flag is then used to generate an interrupt
each time the counter reaches the TOP or BOTTOM value.
When changing the TOP value, the user must make sure that the new TOP value is higher
or equal to the value of all of the compare registers. If the TOP value is lower than any of
the compare registers, a compare match never occurs between the TCNTn and the OCRnx.
The length of the rising and the falling slopes is always equal because the OCRnx registers are
updated when the Timer counts down to BOTTOM. This gives symmetric output pulses and is
therefore frequency correct.
Copyright 2012 Cengage Learning. All Rights Reserved. May not be copied, scanned, or duplicated, in whole or in part. Due to electronic rights, some third party content may be suppressed from the eBook and/or eChapter(s).
Editorial review has deemed that any suppressed content does not materially affect the overall learning experience. Cengage Learning reserves the right to remove additional content at any time if subsequent rights restrictions require it.
11.12
■
397
Driving the DC Motor
The procedure of generating the PWM waveform using the PFCPWM mode is identical to
the PCPWM mode and hence is left as an exercise problem.
11.12 Driving the DC Motor
Mega2560
PA0
OC1A
Direction
Speed
Motor
driver
chip
DC motor
On/Off
ICP5
Figure 11.20
■
Source: Atmel Corporation, The Atmel
AVR Microcontroller
A DC motor is an analog motor and is available in just about any size and is therefore
common to many applications, especially those that require a large torque. Because the speed
and torque of DC motors are controlled precisely over a wide range, they are used extensively
in control systems as positioning devices. The DC motor has a permanent magnetic field, and
its armature is a coil. When a voltage is applied to the armature, the motor begins to spin. The
applied voltage level determines the speed of rotation.
Among the several variations of DC motors, the brushless DC motor is by far the most
popular one. Brushless DC motors are commonly used where precise speed control is necessary,
for example, computer disk drives, spindles within CD, DVD drives, and mechanisms within
office products (such as fans, laser printers, and photocopiers). Modern brushless DC motors
range in power from a fraction of a watt to many kilowatts. Larger brushless motors up to about
100-kW ratings are used in electric vehicles. They also find significant use in high-performance
electric model aircraft. To provide control to the speed, Hall-effect sensors are often used to provide speed information to the microcontroller that controls the DC motor.
The microcontroller digitally controls the angular velocity of a DC motor by monitoring
the feedback lines and driving the output lines. Almost every application that uses a DC motor
requires it to reverse its direction of rotation or vary its speed. Reversing the direction is done
by changing the polarity of the voltage applied to the motor. Changing the speed requires varying the voltage level of the input to the motor, and that means changing the input level to the
motor driver. In a digitally controlled system, the analog signal to the driver must come from
some form of D/A converter. However, adding a D/A converter to the circuit increases the chip
count, which means increasing the system cost and power consumption. The other alternative
is to vary the pulse width of a digital signal input to the motor. By varying the pulse width, the
average voltage delivered to the motor changes and so does the speed of the motor. The PWM
mode of the AVR timer/counter modules can be used to control the DC motor.
The AVR MCU interfaces with a DC motor through a driver, as shown in Figure 11.20.
This circuit takes up only three I/O pins. The pin that controls the direction can be an ordinary
I/O pin but the pin that controls the speed must be a PWM output. The pin that receives the
feedback must be an input-capture pin.
Simplified DC motor control circuit
Although some DC motors operate at 5 V or less, the AVR MCU cannot supply the necessary current to drive a motor directly. The minimum current required by any pract
Download