Lecture 12 Introduction To C For AVR
Lecture 12 Introduction To C For AVR
Lecture 12
2
Why program the AVR in C?
Compilers produce hex files that we download into the Flash of the microcontroller. The size of
the hex file produced by the compiler is one of the main concerns of microcontroller
programmers because microcontrollers have limited on-chip Flash. For example, the Flash space
for the ATmegal6 is 16K bytes.
How does the choice of programming language affect the compiled program size? While
Assembly language produces a hex file that is much smaller than C, programming in Assembly
language is often tedious and time consuming. On the other hand, С programming is less time
consuming and much easier to write, but the hex file size produced is much larger than if we used
Assembly language. The following are some of the major reasons for writing programs in С
instead of Assembly:
• It is easier and less time consuming to write in С than in Assembly.
• С is easier to modify and update.
• You can use code available in function libraries.
• С code is portable to other microcontrollers with little or no modification.
3
DATA TYPES IN С
Data Type Size in Bits Data Range/Usage
unsigned char 8-bit 0 to 255
char 8-bit -128 to+127
unsigned int 16-bit 0 to 65,535
int 16-bit -32,768 to +32,767
unsigned long 32-bit 0 to 4,294,967,295
long 32-bit -2,147,483,648 to +2,147,483,648
float 32-bit ±1.175e-38 to ±3.402e38
Double 32-bit ±1.175e-38 to ±3.402e38
4
Functions
A function is a "container" in which some piece of program code is executed. The
use of functions makes it easier to write and debug programs, since they are
convenient to place repeating groups of statements. Any C program contains a main
function called main (). This function is executed first when the program starts.
User-defined functions are defined after preprocessor directives and global type,
variable, and constant declarations in a source file or header file.
Functions have the following syntax:
7
Return a result from Functions
If a function is intended to return a value of some type, then the RETURN keyword is used
in its body. after which (separated by a space) indicate the return value. In this case, all
statements after the word return are ignored and returned to the calling function.
Example:
…
Int power3 (int n)
{
Return n*n*n;
}
void main ()
{ The word return can also be used without specifying a
int x; return expression. In this case, it simply means exit
x = power3(2); // x=8 from the function.
}
8
What C – Program consist of?
FunctionN
// Preprocessor directives {
#include <16F458.h> // Declarations of local types of variables
#use delay(clock=20000000) // and constants
#fuses HS,WDT …
// Operators
// Declarations of global types of variables and constants …
… }
// Functions
Function 1 // The main function of the program
{ int main (void)
// Declarations of local types of variables and constants {
// Operators // Declarations of local types of variables
} // and constants…
… // Operators
…
}
9
Arrays
An array is a data type that is used to represent a sequence of similar values. Arrays are declared like
ordinary variables, with the dimension (number of elements in the array) in square brackets:
int digits[10]; //Array of ten int elements
char str[10]; //Array of ten characters {string)
Access to array elements is implemented using an index (the element's serial number, starting from 0):
digits[0] = 0;
digits[1] = 12;
str[0] = 'Z';
str[1] = ‘a‘;
It is often much more convenient to initialize an array directly when it is declared, for example:
int digits [10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // in braces
char str[10] = {‘T’, ‘h’, ‘e', ‘ ‘, ’l’, ‘i’ , ’n’, ’e’};
int n;
char c;
n = digits[2]; //n = 2
с = str [1]; //c = ‘h’
10
Strings
A string in C is an array of type char. Above was an example of declaring such an array
corresponding to the string "The line". This declaration could also be made with a string
literal:
char str[10] = "The line";
However, in this case, you should remember that the compiler implicitly ends string
literals with the \0 symbol, and thus the actual length of the string is more per 1. This
should be taken into account so that when initializing the array, it does not go beyond its
limits. When initializing strings, the array dimension can be omitted explicitly:
In this case, the compiler will determine the dimension itself. (This rule applies to the
initialization of any other arrays as well)
11
Branch operators (If-else)
In its simplest case, the if-else statement has the following structure:
The C language allows you to use conditional expressions instead of the if-else statement,
like a construction of the form:
12
Branch operators (switch-case)
Only expressions that evaluate to TRUE OR FALSE can be used in an if-elee statement. In
cases where it is necessary to apply expressions that give an arbitrary numerical result, it
is more convenient to use the switch-case statement. This operator allows using some
variable to select one of the expressions corresponding to a given constant.
Its syntax is the following:
switch (expression) { void segchar (unsigned char seg)
{
case constant-expression1: code block switch (seg)
case constant-expression2 : code-block {
case constant-expression3 : code-block case 1: PORTD = 0b11111001; break;
default: code-block } case 2: PORTD = 0b10100100; break;
case 3: PORTD = 0b10110000; break;
case 4: PORTD = 0b10011001; break;
case 5: PORTD = 0b10010010; break;
}
}
13
Branch operators (switch-case - examples)
14
Loop constructions
Looping constructs are used to repeat a block of code based on loop conditions. The C
language uses looping constructs: while, for and do-while.
while construct
The while loop has the following syntax:
while (conditional expression)
{
// Execute loop body if expression is true
}
15
Loop constructions (Examples)
int c, i;
const char str[] - "0123456789";
char OddNums[5]; //String to store odd digits
c = 0; //Counter of cycles
i=0; //OddNums array index
while (c < 10) //As long as c is less than 10,...
{ //If the remainder after dividing c by 2 = 1,
//then we write the c-th element of the
//string str to the i-th position of the
//OddNums array, after which value i is
//automatically incremented
if ((c % 2) == 1) OddHums [i + + ] = str[c];
c++; //c = c + 1
}
16
Loop constructions (For)
18
Debuging (maximum finder)
A task: Find the maximum in an array
The solution:
#include <avr/io.h>
int main(void)
{
int my_array [5] = {11, 20, 100, 44, 12};
int maximum,i;
maximum=my_array[0];
for (i=1; i<5; i++)
if ( my_array[i] > maximum ) maximum = my_array[i];
}
19
Now lets start the Microchip Studio and make a C- project
20
To choose the Mega32a chip, type “mega32”
21
Lets try (maximum finder)
1. Write a code
2. Choose Simulator
3. Choose Debug > Step into
(or press F11)
4. After compile the
Watches will be available
22
Lets try (maximum finder)
6. Press QucikWatch button (Shift+F9)
7. Type variable name do you want to watch
and press Add Watch (maximum for
example)
8. Add My_array and I to
23
Lets try (maximum finder)
9. Press F11 to watch step by step
24
Loop constructions (Do-while)
In addition to while and for loops, which first check the truth of the loop condition, and
only then control is transferred to the block of loop statements, the C language also has
the do-while construct. It differs from the first two in that it first executes a block of
statements, and only then checks the condition. In other words, a do-while loop always
executes at least once, regardless of the condition of the loop.
The do-while loop has the following syntax:
do
{
// Execution of the block of loop statements
}
while (conditional expression);
25
Infinity
To organize an infinite loop as a conditional expression in a while or do-while
construct, you can simply specify the value TRUE or 1:
while(1)
statement_block;
26
Directives (#include)
The most common is #include directive, which is used in virtually all programs to
include header files (with definitions) with the .h extension, or .c files (not containing
the function main().
This directive can be used in two forms:
#include <filename>
or
#include "filename"
If the file name is enclosed between the "<" and ">" characters, then it is considered
part of the standard library supplied with the compiler. If the file name is enclosed in
double quotes, then it is considered that it is located in the same folder as the file with
the source code
27
Directives (#define)
The #define directive tells the preprocessor to perform substitution in the program text
of a certain sequence of characters with another sequence.
Directive format:
#define replacement_sequence substitution fragment
For example:
#define MyName "John Smith"
#define Condition (a > b)
#define Operation a = b
…
char str[] = MyName; //Equivalent to char str[] = "John Smith";
int a, b;
if Condition Operator; //Equivalent to if (a > b) a = b;
28
Lets remember about I / O ports
From a programmer's point of view, a port is three registers, each of which has its
own symbolic name:
• Control register (DDRx - Data Direct Register)
• Output data register (PORTx)
• Status register of input lines - pins (PINx)
Registers of port A
29
I / O ports hardware model.
From the point of view of an engineer, conventionally, a port is a register, each line of
which is an open collector transistor, so a load can be soldered to it both to the input
(button) and to the output (lightbulb). However, the port's load capacity is not high.
The maximum allowable total current on all 8 lines is no more than 20mA. Therefore,
we put the transistor on the LED and the current-limiting resistors on the button
30
Lets try (toggle LED)
//toggle LED connected to PB 100,00 times
#include <avr/io.h>
int main(void)
{
unsigned long z; //long is used because it should store more than 65535.
DDRB = 0xFF; //PORTB is output
while(1);
{
For (z=0; z<100000; z++)
PORTB = 0x55;
For (z=0; z<100000; z++)
PORTB = 0xAA;
}
}
31
Make a delay #include <avr/io.h>
#include <avr/io.h> #include <util/delay.h>
void delay (void)
{
unsigned int i; int main(void)
for(i=0; i<42150; i++); {
} DDRB = 0xFF;
int main(void) while (1)
{ {
DDRB = 0xFF; PORTB = 0xAA;
while (1) _delay_ms(500);
{
PORTB = 0x55;
PORTB = 0xAA;
delay(); _delay_ms(500) ;
PORTB = 0x55; }
delay() ; }
}
}
32
LED and Switches
EXAMPLE 1 EXAMPLE 2
#include <avr/io.h> //standard AVR header #include <avr/io.h>
int main(void) int main(void) {
{ DDRD = 0; DDRB = 0xFF;
unsigned char temp; unsigned char temp;
DDRB = 0xFF; //port B – LED so as output while(1)
DDRD = 0x00; //portD –SW so as input {
temp = PIND;
while (1) //forever if ( temp < 100 ) PORTB = temp;
{ else PORTB = 0b00111111;
temp = PIND; //read sw to temp }
PORTB = temp; //write to LED }
}
}
33