You are on page 1of 94

AVR Programming in C

Topic/Week 9

ISMAIL FKE UTM 2017 1


C Development using Atmel AVR Studio 6.0
Why using C?

• C is a high-level programming language: C code is


easier to understand compared to other languages.
C supports low-level programming: We can use C to access all hardware
components of the microcontroller.

C has standard libraries for complex tasks: data type conversions, standard
input/output, long-integer arithmetic.

The Atmel AVR instruction set is designed to support C compilers: C code can be
converted efficiently to assembly code.
C tools
• We need two tools for C development: Atmel AVR Studio and WinAVR.
Atmel AVR Studio
 An integrated development environment for Atmel AVR microcontroller.
 It includes editor, assembler, emulator, HEX file downloader.
 Available at: www.atmel.com/tools/studioarchive.aspx

WinAVR
 A C compiler for AVR microcontrollers.
 Can be used alone, or as a plug-in for Atmel AVR Studio.
 Available at: winavr.sourceforge.net

Download setup files for Atmel AVR Studio and WinAVR


• Run setup file for Atmel AVR Studio. Accept default options
• Run setup file for WinAVR. Accept default options
AVR (Embedded) C vs ANSI C
• C (for desktop computers) and embedded C (for microcontroller) appear
different but they have more similarities than the differences.
• The share the same keyword, structure, datatypes, qualifier, operators and
same libraries names.
• C use resources that are OS managed which are transparent to
programmer no constrain on size of program or architecture of peripherals
but embedded C has to use with the limited resources (RAM, ROM, I/Os) on
an embedded processor that should be self manage within the program
(manage the code to optimise the use resources).
• Compilers for C (ANSI C) typically generate OS dependant executables that
uses a common library since drivers for different peripheral are at OS level
but embedded C executes program from reset.
• Embedded C requires that the drivers function be built within the program
or use available library for some common device (e.g. lcd.h for HD44780).
For this reason Embedded compilers give access to all resources (which is
not provided in compilers for desktop computer applications).

ISMAIL FKE UTM 2017 4


GCC, the GNU Compiler Collection
• The GNU Compiler Collection is used by Atmel Studio at the
build stage.
• The architecture specific versions of the GNU Compiler
Collection supports c-code compilation, assembly and
linking of C and C++.
• AVR C provide these libraries in the Atmel Studio and
are listed at link http://www.nongnu.org/avr-libc/user-
manual/modules.html
• Though many are available but not all may be immediately
necessary for amature programmer.
• Note: the “.h” header files contain definition of identifier
and prototypes of function declared in the libraries which
are built-in the GCC compiler.

ISMAIL FKE UTM 2017 5


The AVR-Libc
Libraries that of our amature concern for simplicity
purpose
<avr/interrupt.h>: Interrupts
<avr/io.h>: AVR device-specific IO definitions
<avr/pgmspace.h>: Program Space Utilities
<util/delay.h>: Convenience functions for busy-wait delay loops

ISMAIL FKE UTM 2017 6


avr/io.h
• This header file includes the appropriate IO definitions for the device that has
been specified in the project of Atmel Studio.
• Even a single line of code would require this particular header file. It resolves the
problem of handling the registers and provides a convenient way to treat the
registers as variables. This makes it simple to assign values to them.
• You can treat all other valid I/O register names of the device as specified in the
device Reference manual
• .E.g. to write data into port B data direction register, the register can be addressed
using the variable ‘DDRB’. In code, you can write an expression like this one (where
all the Register’s name and bit position are declared in avr/io.h :
DDRA=0xff; //all DDDRA bits set
PORTA=0xaa; //PORTA =0b10101010
TCNT0=255-250; //TCNT0=55
GICR=1<<INT0; //GICR = 0b00100000
DDRB|=1<<PINB7; //DDRB = 1xxxxxxx x denotes value of the bit position
//is not changed

ISMAIL FKE UTM 2017 7


util/delay.h
• The macro F_CPU is supposed to be defined to a constant defining the
CPU clock frequency (in Hertz).
• This header file defines 2 delay loops.
void _delay_ms(double __ms)//Perform a delay of __ms
• The maximal possible delay is 262.14 ms / F_CPU in MHz.
• When the user request delay which exceed the maximum possible one, _delay_ms()
provides a decreased resolution functionality.
• In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to
6.5535 seconds (independent from CPU frequency). The user will not be informed about
decreased resolution.
void _delay_us(double __us)//Perform a delay of __us
• The maximal possible delay is 768 us / F_CPU in MHz.
• If the user requests a delay greater than the maximal possible one, _delay_us() will
automatically call _delay_ms() instead. The user will not be informed about this case.
• These delay loops are accurate if there is no interrupt being service
(Interrupt service routine consume inhibit CPU time if executed in the
delay loop thus corrupting the executing time of the delay loop.
• When these delay loops in an ISR, its timing cannot be corrupted (because
in an ISR before it exit with a RTI, no other interrupt can be service).

ISMAIL FKE UTM 2017 8


util/delay.h
• Example
– On top of program
#define F_CPU 1000000
– #include <util/delay.h>
– “#define F_CPU 1000000” must be before declaring “#include
<util/delay.h>” to avoid following warning
1. “#warning "F_CPU not defined for <util/delay.h>”
2. "F_CPU" redefined [enabled by default]
….
//somewhere in program to get a 20ms delay
_delay_ms(20); // function will wait 20ms before returning

//somewhere in program to get a 20µs delay


_delay_us(20); // function will delay 20µs before returning

ISMAIL FKE UTM 2017 9


avr/interrupt.h
• A micro controller has several interrupt sources.
• Each of them has separate interrupt sub-routine.
• In ANSI C, there are no interrupt handling
schemes.
• But for micro controllers, interrupts are a matter
of special significance!
• Many programs are very much dependent upon it!
• So to help users to implement subroutine codes
more easily, there is a header
file avr/interrupt.h
• It defines some functions and macros described
below.

ISMAIL FKE UTM 2017 10


avr/interrupt.h
• sei()
This function enables the global interrupt by setting the global interrupt mask.
• cli()
This function disables the global interrupt by resetting the global interrupt mask.
• reti()
Enables interrupts by setting the global interrupt mask. This function compiles
into a single line of assembly code.
• ISR (INTERRUPT_vect)
ISR stands for Interrupt Service Routine.
– Using this macro, users can write up interrupt sub routine associated with
interrupts ‘INTERRUPT’.
– In the place of the argument of the macro, some symbols are supplied.
– Here, symbols are named after the interrupt vectors they are representing.
– For a particular micro controller, some specific symbols are valid.
– For them, look at the AVR GCC reference manual that comes with the AVR
Studio. Let’s see an example:

ISMAIL FKE UTM 2017 11


avr/interrupt.h
#include <avr/io.h> int main(void)
#include <avr/interrupt.h> {
ISR(INT0_vect) initInterrupt();
{ DDRB=0xff;
PORTB =~PORTB; PORTB=0x55;
} ISMAIL FKE UTM 2017
while(1)
void initInterrupt(void)
{
{
/*If interrupt INT0 is
cli(); triggered, here PORTB will
GICR=0x40; be complemented in
MCUCR=0x03; background when INT0 is
serviced*/
sei();
} }
}
ISMAIL FKE UTM 2017 12
Symbol Names for ATmega32
ATmel Studio C/C++ Symbol Names Interrupt Definition
Keywords
No needed since it is by default External Pin, Power -on Reset,
assigned by C/C++ compiler referencing Brown -out Reset, Watchdog
to main() function Reset, and JTAG AVR Reset
INT0_vect External Interrupt Request 0
INT1_vect External Interrupt Request 1

INT2_vect External Interrupt Request 2

TIMER1_COMPA_vect Timer/Counter1 Compare


Match A
TIMER2_OVF_vect Timer/Counter2 Overflow

TIMER1_CAPT_vect Timer/Counter1 Capture


Event
ISMAIL FKE UTM 2017 13
Symbol Names for ATmega32
ATmel Studio C/C++ Symbol Names Interrupt Definition
Keywords
TIMER2_COMP_vect Timer/Counter2 Compare
Match
TIMER1_COMPB_vect Timer/Counter1 Compare
Match B
TIMER1_OVF_vect TIMER1 OVF
Timer/Counter1 Overflow
TIMER0_COMP_vect Timer/Counter0 Compare
Match
TIMER0_OVF_vect Timer/Counter0 Overflow

SPI_STC_vect Serial Transfer


Complete
USART_RXC_vect USART Rx Complete

ISMAIL FKE UTM 2017 14


Symbol Names for ATmega32
ATmel Studio C/C++ Symbol Names Interrupt Definition
Keywords
USART_UDRE_vect USART Data Register
Empty
USART_TXC_vect USART, Tx Complete
ADC_vect ADC Conversion Complete

EE_RDY_vect EEPROM Ready

ANA_COMP_vect Analog Comparator

TWI_vect Two -wire Serial


Interface
SPM_RDY_vect Store Program Memory
Ready
ISMAIL FKE UTM 2017 15
avr/pgmspace.h - AVR Data in Program
Space
• The AVR is a Harvard architecture
processor, where Flash is used for the
program, RAM is used for data, and they
each have separate address spaces.
• To get constant data to be stored in the
Program Space, and to retrieve that data
to use it in the AVR application, AVR-
Libc provides a simple
macro PROGMEM that is defined as the
attribute syntax of GCC with
the PROGMEM attribute which are declared
the “avr/pgmspace.h” system header file.

ISMAIL FKE UTM 2017 16


avr/pgmspace.h
• Storing an array of byte size data in the Program Space
#include <avr/pgmspace.h>
/*Declaring data that will be stored in Program Memory Address
location will be assigned by handled by C compiler*/
…….
unsigned const char SS_table[4] PROGMEM = {0x3f,0x06,0x5b,0x4f};
unsigned const char numbers1[3] PROGMEM = {0x10,0x1,0x12};
• Retrieving a byte sized data in array identified as numbers1 the Program
Space (as declared above)
volatile char tempPGMdata;
tempPGMdata=pgm_read_byte_near(&numbers1[i]);
• Note: Declaration of data in the Program Space must be made in global
scope.

ISMAIL FKE UTM 2017 17


Generic C Program Structure
• Declare #define for F_CPU for operating speed of ATmega32
• Declare #include of all Library headers used
• Declare #define of identifier that represent constant value
• Declare global variables (normally used for environment variables (may be
used to passed data between functions) functions meaning main() ISR()
and the other functions created/used in the program.
• Declare functions prototypes (to avoid warning errors)
e.g. “Warning 1 implicit declaration of function ‘OutLED’”
• Declare ISR, Functions (with the codes in the {} structure) which are
appended/added as program is being developed.
• Declare main program (generated by default when a C/C++ executable is
created)
• In main Program
– Declare Local variables
– Intialise Environment variables
– Initialise I/O register if registers is operating or operated within main program
– Declare a “shell loop” (generated by default when a C/C++ executable is
created)

ISMAIL FKE UTM 2017 18


Writing an C program for Embedded
System
• Reference
– Embedded C Programming and the Atmel AVR,
Second Edition.pdf which is located at
https://www.dropbox.com/sh/dyq6btrlgwcdtrr/A
ABNBw6CqnRMA8WJ1fDJv1B4a?dl=0

ISMAIL FKE UTM 2017 19


Structure of a C program
A C program typically has two main sections.
 Section #include: to insert header files.
 Section main(): code that runs when the program starts.

In this example, header file <avr/io.h> contains all register definitions for the
selected AVR microcontroller.
#include <avr/io.h> // avr header file for all registers/pins
int main(void){
unsigned char i; // temporary variable
DDRA = 0x00; // set PORTA for input
DDRB = 0xFF; // set PORTB for output
PORTB = 0x00; // turn ON all LEDs initially
while(1){
// Read input from PORTA, which is connected to the 8 switches
i = PINA;
// Send output to PORTB, which is connected to the 8 LEDs
PORTB = i;
}
return 1;
}
C comments
• Comments are text that the compiler ignores.

For a single-line comment, use double forward slashes:


DDRA = 0x00; // set PORTA for input

For a multi-line comment, use the pair /* and */:


/* File: led.c
Description: Simple C program for the ATMEL AVR(ATmega32
chip)
It lets user turn on LEDs by pressing the switches on the
JTAGICE mk11
board*/
Always
*/ use comments to make program easy to understand.
C statements and blocks
• C statements
– C statements control the program flow.
– They consist of keywords, expressions and other
statements.
– A statement ends with semicolon.
DDRB = 0xFF; // set PORTB for output

C blocks
 A C block is a group of statements enclosed by braces {}.
 It is typically associated with if, switch, for, do, while, or functions.
while (1){
// Read input from PORTA - connected to the 8 switches
i = PINA;
// Send output to PORTB - connected to the 8 LEDs
PORTB = i;
}
#define Preprocessor Directive
• Preprocessor directives are not actually part
of the C language syntax, but they are
accepted as such because of their use and
familiarity.
• The preprocessor is a step separate from the
actual compilation of a program, which
happens before the actual compilation begins.

ISMAIL FKE UTM 2017 23


A Few Syntactical Rules and Some
Basic Terminology
• An identifier is a variable or function name
made up of a letter or underscore (_),
followed by a sequence of letters and/or digits
and/or underscores.
• Identifiers are case sensitive.
• Identifiers can be any length, but some
compilers may recognize only a limited
number of characters, such as the first thirty-
two. So beware!

ISMAIL FKE UTM 2017 24


Reserved Words Which Have Special
Meaning to The Compiler
auto defined float long static while
break do for register struct
bit double funcused return switch
case goto short typedef
char else if signed union
const enum inline sizeof unsigned
continue extern int sfrb void
default interrupt sfrw volatile

• Reserved word cannot be used as Identifiers


ISMAIL FKE UTM 2017 25
VARIABLES AND CONSTANTS
• Variables, as in algebra, are values that can be changed
• Constants are fixed.
• Variables and constants come in many forms and sizes; they
are stored in the data memory in a variety of forms.
• Variables and constants are stored in the limited memory
of the microcontroller, and the compiler needs to know
how much memory to set aside for each variable without
wasting memory space unnecessarily.
• A programmer must declare the variables, specifying both
the size of the variable and the type of the variable.

ISMAIL FKE UTM 2017 26


VARIABLE TYPES
Type
Size (Bits) Range
ANSI C C99
char int8_t 8 –128 to 127
unsigned char uint8_t 8 0 to 255
signed char 8 –128 to 127
int int16_t 16 –32768 to 32767
Unsigned int uint16_t 16 0 to 65535
unsigned long uint32_t 0 to 4294967296
long int int32_t 32 –2147483648 to 2147483647
float 32 ±1.175e-38 to ±3.402e38

• The first C standard was released 1989 nationally in USA, by their national
standard institute ANSI. This release is called C89 or ANSI-C. From 1989-
1990 this was "the C language".
• In 1999, the C standard was revised, lots of things changed (ISO
9899:1999). This version of the standard is called C99. From 1999-2011,
this was "the C language". Most C compilers still follow this version.
ISMAIL FKE UTM 2017 27
VARIABLE SCOPE
• Constants and variables must be declared prior to their use.
• The scope of a variable is its accessibility within the program.
• A variable can be declared to have either local or global scope.
• Local variables are memory spaces allocated by the function when the
function is entered, typically on the program stack or a compiler-created
heap space and are not accessible from other functions, which means
their scope is limited to the functions in which they are declared.
– The local variable declaration (using the same identifier) can be used in
multiple functions without conflict, since the compiler sees each of these
variables as being part of that function only.
• A global or external variable is a memory space that is allocated by the
compiler and can be accessed by all the functions in a program (unlimited
scope).
– A global variable can be modified by any function and will retain its value to
be used by other functions.

ISMAIL FKE UTM 2017 28


CONSTANTS
• Constants are fixed values.
• Is Desktop computer constant are located in RAM which are
initialise when the program is loaded but the values cannot
be changed.
• In embedded system, constants must be located in read-
only memory (ROM) or Flash memory.
• Constant cannot and should not be loaded in RAM since
RAM is volatile.
• In embedded system data to be used as constant are
declared in program memory.
• In AVR Atmel Studio GCC compiler, constant are declared
using the PROGMEM macro defined in the avr/pgmspace.h
library.

ISMAIL FKE UTM 2017 29


Constant Declarations
• Numeric constants can be declared in many ways by indicating their
numeric base and making the program more readable. Integer or
long integer constants may be written in
– Decimal form without a prefix (such as 1234)
– Binary form with 0b prefix (such as 0b101001)
– Hexadecimal form with 0x prefix (such as 0xff)
– Octal form with 0 prefix (such as 0777)
• There are also modifiers to better define the intended size and use
of the constant:
– Unsigned integer constants can have the suffix U (such as 10000U).
– Long integer constants can have the suffix L (such as 99L).
– Unsigned long integer constants can have the suffix UL (such as 99UL).
– Floating point constants can have the suffix F (such as 1.234F).
– Character constants must be enclosed in single quotation marks, ' a '
or 'A'.

ISMAIL FKE UTM 2017 30


Character Constants
• Character constants can be printable (like 0–9 and A–Z) or
non-printable characters (such as new line, carriage return,
or tab).
• Printable character constants may be enclosed in single
quotation marks (such as ‘a’).
• A backslash followed by the octal or hexadecimal value in
single quotes can also represent character constants:
– 't' can be represented by ‘116’ (decimal) or
– 't' can be represented by ‘0x74’ (hexadecimal)
• Backslash (\) and single quote (‘) characters themselves
must be preceded by a backslash to avoid confusing the
compiler. For instance, ‘\’ ’ is a single quote character and
‘\\’ is a backslash.

ISMAIL FKE UTM 2017 31


Data types and operators
The main data types in C are
 char: 8-bit integer in AVR
 int: 16-bit integer in AVR
 long int: 32-bit integer in AVR

The above data types can be modified by keyword ‘unsigned’.


char a; // range of values for a: -128, …, 0, …, 127
unsigned char b; // range of values for b: 0, 1, 2, …, 255
unsigned long int c;// range of values for c: 0, 1, …, 232 - 1

Examples of variable assignment:


a = 0xA0; // enter value in hexadecimal format
a = 0b11110000; // enter value in binary format
b = „1‟; // b stores ASCII code of character „1‟
c = 2000ul; // c stores an unsigned long integer 2000
Enumerations
• Enumerations are listed constants.
• The reserved word enum is used to assign sequential integer
constant values to a list of identifiers:
int num_val; //declare an integer variable
//declare an enumeration
enum { zero_val, one_val, two_val, three_val );
num_val = two_val; // the same as: num_val = 2;
• The name zero_val is assigned a constant value of 0, one_val of 1,
two_val of 2, and so on.
• An initial value may be forced, as in
enum { start=10, next1, next2, end_val };
• which will cause start to have a value of 10, and then each
subsequent name will be one greater. next1 is 11, next2 is 12, and
end_val is 13.

ISMAIL FKE UTM 2017 33


Enumerations
• Enumerations are used to replace pure numbers, which the programmer
would have to look up, with the words or phrases that help describe the
number’s use.
• Definitions are used in a manner somewhat similar to the enumerations in
that they will allow substitution of one text string for another. Observe the
following example:
enum { red_led_on = 1, green_led_on, both_leds_on };
#define leds PORTA
.
PORTA = 0x1; //means turn the red LED on
leds = red_led_on; //means the same thing
• The “#define leds PORTA” line causes the compiler to substitute the label
PORTA wherever it encounters the word leds.
• The enumeration sets the value of red_led_on to 1, green_led_on to 2,
and both_leds_on to 3.
• This might be used in a program to control the red and green LEDs where
outputting 1 turns the red LED on, 2 turns the green LED on, etc.
• The point is that “leds = red_led_on” is much easier to understand in the
program’s context than “PORTA = 0x1”.

ISMAIL FKE UTM 2017 34


Auto Storage Classes
• Variables can be declared in three storage classes: auto, static, and
register.
• Auto, or automatic, is the default class, meaning the reserved word
auto is not necessary.
• An automatic class local variable is uninitialized when it is allocated,
so it is up to the programmer to make sure that it contains valid
data before it is used.
• This memory space is released when the function is exited,
meaning the values will be lost and will not be valid if the function
is reentered.
• An automatic class variable declaration would appear as follows:
auto int value_1;
or
int value_1; // This is the common, default form.

ISMAIL FKE UTM 2017 35


Static Storage Classes
• A static local variable has only the scope of the
function in which it is defined (it is not
accessible from other functions), but it is
allocated in global memory space.
• The static variable is initialized to zero the first
time the function is entered, and it retains its
value when the function is exited.
• This allows the variable to be current and valid
each time the function is reentered.

ISMAIL FKE UTM 2017 36


Register Storage Classes
• A register local variable is similar to an automatic variable in that it is
uninitialized and temporary.
• The difference is that the compiler will try to use an actual machine
register in the microprocessor as the variable in order to reduce the
number of machine cycles required to access the variable.
• There are very few registers available compared to the total memory in a
typical machine.
• Therefore, this would be a class used sparingly and with the intent of
speeding up a particular process.
• The SRAM area of the AVR microcontroller includes a region called the
Register File.
• This region contains I/O ports, timers, and other peripherals, as well as
some “working” or “scratch pad” area.
• To instruct the compiler to allocate a variable to a register or registers, the
storage class modifier register must be used.
register int abc;

ISMAIL FKE UTM 2017 37


Volatile Storage
• The compiler may choose to automatically allocate a variable to a register
or registers, even if this modifier is not used.
• In order to prevent a variable from being allocated to a register or
registers, the volatile modifier must be used.
• This warns the compiler that the variable may be subject to outside
change during evaluation.
volatile int abc;
• When debugging a program, breakpoint breaks or “single stepping” on
statement that uses variable not assign with the volatile modifier will not
be “seen” thus the debugger will pass through the statement.
• So it is a good practice to assign the volatile modifier on every variables.

ISMAIL FKE UTM 2017 38



POINTERS
Pointers to these special memory regions are each handled differently
during program execution.
• Even though the pointers can point to FLASH and EEPROM memory areas,
the pointers themselves are always stored in SRAM.
• In these cases, the allocations are normal (char, int, and so on) but the
type of memory being referenced must be described so that the compiler
can generate the proper code for accessing the desired region.
• The size of pointer is the size of the program counter of the AVR processor
which is 16 bit for ATmega32.
• The PROGMEM and eeprom keywords in these cases are used to expound
on the name, like this:
/* Pointer to a string that is located in SRAM */
char *ptr_to_ram = "This string is placed in SRAM";
/* Pointer to a string that is located in FLASH */
char *ptr_to_flash PROGMEM= "This string is placed in FLASH";
/* Pointer to a string that is located in EEPROM */
char eeprom *ptr_to_eeprom = "This string is placed in EEPROM";
• When debugging a program, breakpoint breaks or “single stepping” on
statement that uses pointer not assign with the static volatile modifier will
not be “seen” thus the debugger will pass through the statement hence
not allowing you to see the execution of the statement .
• So it is a good practice to assign the static volatile modifier on every
pointers. ISMAIL FKE UTM 2017 39
TYPE CASTING
• To temporarily force the type and size of the variable.
• Allows the previously declared type to be overridden for the duration of
the operation (ot the statement) being performed.
• The cast, called out in parentheses, applies to the expressio
• Type casting is particularly important when arithmetic operations are
performed with variables of different sizes.
• In many cases, the accuracy of the arithmetic will be dictated by the
variable of the smallest type. Consider the following:
int z; // declare z
int x = 150; // declare and initialize x
char y = 63; // declare and initialize y
z = (y * 10) + x; n it precedes.

ISMAIL FKE UTM 2017 40


TYPE CASTING
• As the CPU processes the right side of the equation, it will look at the size
of y and make the assumption that (y * 10) is a character (8-bit)
multiplication.
• The result will have exceeded the width of the storage location, one byte
or a value of 255. and truncate the value to 118 (0x76) instead of the
correct value of 630 (0x276).
• In the next phase of the evaluation, the CPU would determine that the size
of the operation is integer (16 bits) and 118 would be extended to an
integer and then added to x. Finally, z would be assigned 268 . . .WRONG!!
• Type casting should be used to control the assumptions.
• Writing the same arithmetic as
z = ((int)y * 10) + x;
• will indicate to the compiler that y is to be treated as an integer (16 bits)
for this operation.
• This will place the integer value of 630 onto the stack as a result of a 16-bit
multiplication.
• The integer value x will then be added to the integer value on the stack to
create the integer result of 780 (0x30C). z will be assigned the value 780.

ISMAIL FKE UTM 2017 41


C operators
• C has a rich set of operators:
– Arithmetic operators
– Relational operators
– Logical operators
– Bit-wise operators
– Data access operators
– Miscellaneous operators
Bit-wise operators
These operators are applied on individual bits of a variable or constant.

Operator Name Example Description


Bit-wise
~ ~x Toggle every bit from 0 to 1, or 1 to 0
complement

& Bitwise AND x & y Bitwise AND of x and y

| Bitwise OR x | y Bitwise OR of x and y

^ Bitwise XOR x ^ y Bitwise XOR of x and y

<< Shift left x << 3 Shift bits in x three positions to the left

>> Shift right x >> 1 Shift bits in x one position to the right
Bitwise Operators
• Bitwise operators perform functions that will affect the operand at the bit
level.
• These operators work on integer constant (in an expression) or variables
(in an operation)

ISMAIL FKE UTM 2017 44


I/O OPERATIONS
• The #include <avr/io.h> will declare all I/O
registers’ name (for Atmega32) is as given in
Figure 2.7 as an 8 bit variable.
• The register are treated as variable and abide to
all rules that applies to a variable in the C
program.
• Example:
#include <avr/io.h>
DDRB=0x00;
PORTB=0xff;
MCUCR|=0b00001000;// MCUCR = MCUCR|0b00001000
MCUCR&=0b11111011;;// MCUCR = MCUCR&0b00001000

ISMAIL FKE UTM 2017 45


I/O Registers

ISMAIL FKE UTM 2017 46


Bitwise Operators
• Example:
#include <avr/io.h>
#define MaskOffLowerNibbleHigh 0b00001111
#define ActveLowOutput 0b11111111
.
MCUCR|=0b00001000; //Set bit #3 of MCUCR, others unchanged
MCUCR&=0b11111011; //Clear bit #2 of MCUCR, others unchanged

PORTA=PORTA<<1;//Shift left 1 bit data in PORTA


PORTB=~PORTB; //Invert data in PORTB
PORTA=data^ActveLowOutput; //Port A = inverted value of "data"

//Set lower nibble of MCUCR, others unchanged


SWData=PIND|MaskOffLowerNibbleHigh;
ISMAIL FKE UTM 2017 47
LOGICAL AND RELATIONAL
OPERATORS
• Logical and relational operators are all binary operators but yield a
result that is either TRUE or FALSE.
• TRUE is represented by a nonzero value, and FALSE by a zero
value.
• These operations are usually used in control statements to guide
the flow of program execution.
• Logical operators differ greatly from the bitwise operators in that
they deal with the operands in a TRUE and FALSE sense.
• As in the logical operators, the operands are evaluated left to right
and a TRUE or FALSE result is generated.
• They effectively “ask” about the relationship of two expressions in
order to gain a TRUE or FALSE reply.
• Relational operators as in the logical operators use comparison
operations evaluated left to right and a TRUE or FALSE result is
generated.

ISMAIL FKE UTM 2017 48


Logical operators

These operators are applied on logical variables or constants.

Operator Name Example Description (Returns a value of …

! Logical NOT !x 1 if x is 0, otherwise 0

&& Logical AND x && y 1 is both x and y are 1, otherwise 0

|| Logical OR x || y 0 if both x and y are 0, otherwise 1


Logical Operators
• The logical operators in order of precedence.

ISMAIL FKE UTM 2017 50


Relational operators

Operator Name Example Description (Return a value of …

> Greater than x > 5 1 if x is greater than 5, 0 otherwise

Greater than or
>= x >=5 1 is x is greater than or equal to 5, 0 otherwise
equal to

< Less than x < y 1 if x is smaller than y, 0 otherwise

Less than or
<= x <= y 1 is x is smaller than or equal to y, 0 otherwise
equal to

== Equal to x == y 1 is x is equal to y, 0 otherwise

!= Not equal to x != 4 1 is x is not equal to 4, 0 otherwise


Relational Operators

• Assume that x = 3 and y = 5.

ISMAIL FKE UTM 2017 52


INCREMENT, DECREMENT,AND
COMPOUND ASSIGNMENT
• Increment operators allow for an identifier to be modified, in place, in a
pre-increment or post-increment manner. For example,
x = x + 1;
is the same as
++x; // pre-increment operation
and as
x++; // post-increment operation
• For example,
i = 1;
k = 2 * i++; // at completion, k = 2 and i = 2
i = 1;
k = 2 * ++i; // at completion, k = 4 and i = 2

ISMAIL FKE UTM 2017 53


Arithmetic operators
Operator Name Example Description

* Multiplication x * y Multiply x times y

/ Division x / y Divide x by y

% Modulo x % y Remainder of x divided by y

+ Addition x + y Add x and y

- Subtraction x – y Subtract y from x

x++ Increment x by 1 after using it


++ Increment
++x Increment x by 1 before using it
x-- Decrement x by 1 after using it
-- Decrement
--x Decrement x by 1 before using it

- Negation -x Negate x
Decrement Operators Compound
Assignment Operators
• Decrement operators function in a similar manner, causing a subtraction-
of-one operation to be performed in a pre-decrement or post-decrement
fashion:
j--; // j = j-1
--j; // j = j-1
• Compound assignment operators are another method of reducing the
amount of syntax required during the construction of a program.
– Examples:
a += 3; // a = a + 3
b -= 2; // b = b – 2
c *= 5; // c = c * 5
d /= a; // d = d / a

ISMAIL FKE UTM 2017 55


Data-access operators
These operators are for arrays, structures or pointers.
We’ll learn more about them when required.

Operator Name Example Description

[] Array element x[2] Third element of array x

Address of the memory location where


& Address of &x
variable x is stored

* Indirection *p Content of memory location pointed by p

. Member selection x.age Field ‘age’ of structure variable x

-> Member selection p->age Field ‘age’ of structure pointer p


Miscellaneous operators

Operator Name Example Description


Call a library function to create a
() Function _delay_ms(250)
delay of 250ms
char x = 3; x is 8-bit integer
(type) Type cast
(int) x x is converted to 16-bit integer
This is equivalent to
if (x > 5)
Conditional char x;
? y = 10;
evaluation y = (x > 5)?10:20;
else
y = 20;

commonly used by C coders.


OPERATOR PRECEDENCE

• the operator precedence establishes the order in which expressions are evaluated
by the compiler.
• When in doubt, either nest the expressions with parentheses—to guarantee the
order of process—or look up the precedence for the operator in question.
• The primary operators like dot (.), bracket ([]), and indirection (->) are used in
ISMAIL FKE UTM 2017 58
Pointers and Arrays
Flow control in C
• By default, C statements are executed sequentially.
To change the program flow, there are six types of statements

 if-else statement
Conditional
 switch statement

 while statement
 for statement Iterative
 do statement

 goto statement Should be avoided!


CONTROL STATEMENTS
• WHILE LOOP
– When the execution of the program enters the top of the while loop,
the expression is evaluated.
– If the result of the expression is TRUE (non-zero), then the statements
within the while loop are executed otherwise will exit thus executing a
statement or a statement block while the expression is TRUE
while (expression)
{
statement1;
statement2;
...
}
or
while(expression)
statement;
ISMAIL FKE UTM 2017 60
‘while’ statement
• General syntax
while (expression){
statements;
}

Example: Compute the sum of 1 + 2 + … + 10.

int sum, i;
i = 1; sum = 0;
while (i <= 10){
sum = sum + i;
i = i + 1;
}
CONTROL STATEMENTS
• DO/WHILE LOOP
– The instructions in a do/while loop are always executed once before
the test on the expression determine whether or not to remain in the
loop.
do
{
statement1;
statement2;
...
} while (expression);
or
do
statement;
while (expression);
ISMAIL FKE UTM 2017 62
‘do’ statement
• General syntax
do {
statements;
} while (expression);

Example: Compute the sum of 1 + 2 + … + 10.

int sum, i;
i = 1; sum = 0; // Initialization
do{
sum = sum + i;
i = i + 1;
} while (i <= 10);
CONTROL STATEMENTS
• FOR LOOP
– A for loop construct (structure) executes a statement or a statement
block a specific number of times determined from a initialization, a
test, and an action declaration.
for (expr1; expr2; expr3)
{
statement1;
statement2;
...
}
or
for(expr1; expr2; expr3)
statement;
ISMAIL FKE UTM 2017 64
‘for’ statement
• General syntax
for (expression1; expression2; expression3){
statements;
}
– expression1 is run before the loop starts.
– expression2 is evaluated before each iteration.
– expression3 is run after each iteration.

Example: Compute the sum of 1 + 2 + … + 10.


int sum = 0;

for (int i = 1; i <= 10; i++){


sum = sum + i;
}
CONTROL STATEMENTS
• IF
– Determine to skip (if FALSE) the operation statement or block of
statements of the program based on the evaluation of an expression (
condition) on the IF statement.
if (expression)
{
statement1;
statement2;
...
}
or
if(expression)
statement;

ISMAIL FKE UTM 2017 66


CONTROL STATEMENTS
• IF/ELSE
– Determine to chose one of two statement or block of statements.
Executes statement or block statements and exits if the IF expression
is TRUE other wise executes the statement block of statement under
ELSE statements.

if(expression) or
{ if(expression)
statement1; statement1;
statement2; else
} statement2;
else ...
{
statement3;
statement4;
...
}

ISMAIL FKE UTM 2017 67


‘if-else’ statement
• General syntax
if (expression)
statement_1;
else
statement_2;

Example
char a, b, sum;
a = 4; b = -5;
sum = a + b;
if (sum < 0)
printf(“sum is negative”);
else if (sum > 0)
printf(“sum is positive”);
else
printf(“sum is zero”);
CONTROL STATEMENTS
• SWITCH/CASE
– The switch/case statement is used to execute a statement, or a group
of statements, selected by the value of an expression.
– SWITCH identify the Variable and CASE test the variable.
– If test is TRUE the statement under the particular CASE is executed
(block “{}” structure is not recognised) and proceed to execute next
statement.
– A BREAK statement is needed to exit the SWITCH block (structure)

ISMAIL FKE UTM 2017 69


switch statement
switch (expression)
{
case const1:
statement1;
statement2;
case const2:
statement3;
...
statement4;
case constx:
statement5;
statement6;
default:
statement7;
statement8;
}

ISMAIL FKE UTM 2017 70


CONTROL STATEMENTS
• BREAK, CONTINUE,AND GOTO
– The break statement is used to exit from a for, while, do/while, or
switch statement.
• If the statements are nested one inside the other, the break
statement will exit only from the immediate block of statements.
– The continue statement will allow the program to start the next
iteration of a while,, or for loop.
• The continue statement is like the break statement in that both
stop the execution of the loop statements at that point.
• The difference is that the continue statement starts the loop
again, from the top, where break exits the loop entirely.
– The goto statement is used to literally “jump” execution of the
program to a label marking the next statement to be executed.
• very unstructured and is aggravating to the “real programmer” but
in an embedded system it can be a very good way to save some
coding and the memory usage that goes with it.
ISMAIL FKE UTM 2017 71
‘break’ statement in loop
• The ‘break’ statement inside a loop forces early
termination of the loop.

What is the value of ‘sum’ after the following code is executed?

int sum, i;
i = 1; sum = 0;
while (i <= 10){
sum = sum + i;
i = i + 1;
if (i > 5)
break;
}
‘continue’ statement in loop
• The ‘continue’ statement skips the subsequent statements in
the code block, and forces the execution of the next iteration.

What is the value of ‘sum’ after the following code is executed?

int sum, i;
i = 1; sum = 0; // Initialization
while (i <= 10){
i = i + 1;
if (i < 5)
continue;
sum = sum + i;
}
‘switch’ statement
• General syntax
switch (expression)
case constant_1:
statement_1; Use ‘break’ to separate
break; different cases.
case constant_2:
statement_2;
break;

case constant_n:
statement_n;
break;
default:
statement_other;
}
‘switch’ statement ─ Example
Example: Find the bit pattern to display a digit on the 7-segment LED.

(a) 7 segments of the LED

(b) Bit assignment on the 8-pin connector


LED segment DP g f e d c b a
Bit number 7 6 5 4 3 2 1 0

To display ‘1’ 0 0 0 0 0 1 1 0
To display ‘2’ 0 1 0 1 1 0 1 1
‘switch’ statement ─ Example
#include <avr/io.h>

int main() {
unsigned char digit; // input
unsigned char led_pattern; // output

while (1) {
switch (digit) {
case ‘0’:
led_pattern = 0b00111111;
break;
case ‘1’:
led_pattern = 0b00000110;
break;
case ‘2’:
led_pattern = 0b01011011;
break;
//you can complete more cases here...
default:
}
PORTB = led_pattern; // send to PORTB and 7-segment LED (CC)
}
return 1;
}
C arrays
• An array is a list of values that have the same data type.
In C, array index starts from 0.

An array can be one-dimensional, two-dimensional or more.

This code example creates a 2-D array (multiplication table):


int a[8][10];
for (int i = 0; i < 8; i++)
for (int j = 0; i < 10; j++)
a[i][j]= i * j;

An array can be initialized when it is declared.


int b[3] = {4, 1, 10};
unsigned char keypad_key[3][4] = {{'1', '4', '7', '*'},
{'2', '5', '8', '0'},
{'3', '6', '9', '#'}};
C functions
• C functions are sub-routines that can be called from
the main program or other functions.

Functions enable modular designs, code reuse, and hiding of complex


implementation details.

A C function can have a list of parameters and produce a return value.

Let us study C functions through examples.


FUNCTIONS
• A function is a group of statements that together perform a task.
• Every C program has at least one function, which is main(), and all the
most trivial programs can define additional functions.
• The C standard library provides numerous built-in functions that your
program can call.
• You can built your own function but you need to declare it before you can
use it abiding to the format of the function.
• A function declaration tells the compiler about a function's name, return
type, and parameters (the format).
• A function definition provides the actual body of the function.
• A function can also be referred as a method or a sub-routine or a
procedure, etc.
• You can divide up your code into separate functions.
• How you divide up your code among different functions is up to you, but
logically the division is such that each function performs a specific task.

ISMAIL FKE UTM 2017 79


Defining aFunction
• The general form of a function definition in C programming language is as
follows:

ISMAIL FKE UTM 2017 80


Defining aFunction
A function definition in C programming consists of a function header
and a function body. Here are all the parts of a function:
• Return Type: A function may return a value.
– The return_type is the data type of the value the function returns.
– Some functions perform the desired operations without returning a
value.
– In this case, the return_type is the keyword void.
• Function Name: This is the actual name of the function.
– The function name and the parameter list together constitute the
function signature.
• Parameters: A parameter is like a placeholder.
– When a function is invoked, you pass a value to the parameter.
– This value is referred to as actual parameter or argument.
– The parameter list refers to the type, order, and number of the
parameters of a function. Parameters are optional; that is, a function
may contain no parameters.
• Function Body: The function body contains a collection of
statements that define what the function does.
ISMAIL FKE UTM 2017 81
Calling a Function
• While creating a C function, you give a definition of what the
function has to do. To use a function, you will have to call that
function to perform the defined task.
• When a program calls a function, the program control is transferred
to the called function. A called function performs a defined task and
when its return statement is executed or when its function-ending
closing brace is reached, it returns the program control back to the
main program.
• To call a function, you simply need to pass the required parameters
(same number same types) along with the function name, and if
the function returns a value, then you can store the returned value
to variable, pass it as a parameter to another function, use in an
expression or ignore.

ISMAIL FKE UTM 2017 82


#include <stdio.h> Example
/* function declaration */
int max(int num1, int num2);

/* function returning the max between two numbers */


int max(int num1, int num2)
{
/* local variable declaration */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}

int main ()
{
/* local variable definition */
int a = 100;
int b = 200;
int ret;
/* calling a function to get max value */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
} ISMAIL FKE UTM 2017 83
Call by Value
• The call by value method of passing arguments to a function copies the
actual value of an argument into the formal parameter of the function.
• In this case, changes made to the parameter inside the function have no
effect on the argument.

84
Call by Reference
• The call by reference method of passing arguments to a function copies
the address of an argument into the formal parameter. Inside the function,
the address is used to access the actual argument used in the call.
• It means the changes made to the parameter affect the passed argument.
• To pass a value by reference, argument pointers are passed to the
functions just like any other value.
• So accordingly, you need to declare the function parameters as pointer
types as in the following function swap(), which exchanges the values of
the two integer variables pointed to, by their arguments.

85
#include <stdio.h>
Call by Reference
/* function prototype*/
void swap(int *x, int *y);
/* function definition to swap the values */
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put temp into y */
return;
}
int main ()
{
/* local variable definition */
int a = 100;
int b = 200;
/* calling a function to swap the values.
* &a indicates pointer to a i.e. address of variable a and
* &b indicates pointer to b i.e. address of variable b.
*/
swap(&a, &b);
return 0;
}

86
Generic C Program
//Headers of Library used
//Declare #define for F_CPU for operating speed of ATmega32
#define F_CPU 1000000 //Define CPU speed as 1MHz
//Declare #include of all Library headers used
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//Declare #define of identifier that represent constant value
#define AsInput 0x00
#define AsOutput 0xff
#define EnablePullUpResistor 0xff
#define EnableINT0 1<<INT0
#define SetISC01 (1<<ISC01)
#define ClearISC00 ~(1<<ISC00)
#define NoSwitchPressed 0xffISMAIL FKE UTM 2017 87
Generic C Program
//Declare functions prototypes
void OutLED(uint8_t);
//Declare Interrupt Service Routine
INT0_vect()
{
GlobalCount++;
}
//Declare Function
void OutLED(uint8_t OutData)
{
DDRB=AsOutput;
PORTB=OutData;
_delay_ms(500);
}

ISMAIL FKE UTM 2017 88


Generic C Program
int main(void)
{
uint8_t SwData; //Declare Local variables
//Intialise Environment variables
GlobalCount=0;
//Initialise I/O register
DDRA=AsInput;
PORTA=EnablePullUpResistor;
cli();
GICR=GICR|EnableINT0;
MCUCR|=SetISC01;
MCUCR&=ClearISC00;
sei();
while(1) //Shell Loop

{
SwData=PINA;
if(SwData==NoSwitchPressed)
OutLED(GlobalCount);
}
} ISMAIL FKE UTM 2017 89
Significant Elements to Take Note
Elements Description
; A semicolon is used to indicate the end of an expression.An
expression
in its simplest form is a semicolon alone.
{} Braces “{}” are used to delineate the beginning and the end
of the
function’s contents. Braces are also used to indicate when a
series of
statements is to be treated as a single block.
“text” Double quotes are used to mark the beginning and the end
of a text
string.
// or /* . . . */ Slash-slash or slash-star/star-slash are used as comment
delimiters. Comments are just that, a programmer’s notes.
Comments are critical to the readability of a
program.
ISMAIL FKE UTM 2017 90
Exercise
• Write a C program which is to be loaded to an
ATmega32 or ATmega32A chip. The program will
display the count of 0 to 9 at a seven segment
display and roll over to zero at a 1 second pace.
The common anode active low single digit seven
segment display is connected to port B with the
“d.p segment” pin at the MSB of port B and the
“a segment” pin at the LSB of port B. Data for the
seven segment numeric character of display will
be stored in flash memory.

ISMAIL FKE UTM 2017 91


Exercise
LED1
11

S7
S6
S5
S4
S3 PButton1
S2
S1
S0

Figure Ex1

92
The Question
Referring to Figure Ex1 and “Appendix A for Laboratory sheet” program
Lab2Exp1.c,
1. Create a C GCC executable project
2. In the global scope, declare a variable that will store the look-up table
for seven segment character of 0 to 9 at the Flash Memory. Before the
“Shell loop” initialise all ports connected to switch and LEDs and Seven
Segment appropriately using a function calls. Enable internal pull-up
resistor on all input ports.
3. In the “Shell loop” read switch status.
4. By using “switch-case” control statement execute the following:
a) If SW0 is pressed, call a function that will count at the seven
segment from 0 to 9 and exit at a 500ms delay. The function will
retrieve the character from look-up table. Call a function in this
function to retrieve the character. Uses the delay function available
in util\delay.h library.
b) If SW1 is pressed, program will call another function which will
display a “Running Light” sequence pattern at the LED.
c) If other switch are pressed, its up to you what to do……

93
SUMMARY
• Header files, variables, variable storage class,
pointers, constants, bitwise/logical operators,
control statements , functions.

94

You might also like