4. Programming in C.pptx
4. Programming in C.pptx
ATmega328P in C
1
Why Program the AVR in C?
• Compilers produce hex files, which are downloaded into Flash Program ROMs of
microcontrollers
• The sizes of hex files produced by compilers are of concern to microcontroller
programmers, since microcontrollers have limited on-chip Flash Program ROMs
• While Assembly-language produces hex files that are much smaller than C,
programming in Assembly language is tedious and time-consuming
• On the contrary, C programming is less time consuming and much easier although
the hex file produced is larger
• Some of the reasons for programming the AVR in C are:
1. It is easier and less time-consuming to write in C than in Assembly
2. C is easier to modify and update
3. Code available in function libraries can be used
4. C code is portable to other microcontrollers with little or no modification
2
Data Type Size in Bits Data Range
3
unsigned char
• It is an 8-bit data-type that takes values in the range 0 to 255 (00 to FFH)
• unsigned char takes one byte of RAM
• It must be used where there is no need for signed data
• unsigned char can be used for ASCII characters
signed char
• It is the default char data-type, unless the keyword unsigned is put in front of
char
• signed char is an 8-bit data-type that uses the MSB to represent the sign (1
representing negative and 0 positive) and 7 bits for the magnitude of the number
• signed char takes one byte of RAM
• It ranges from -128 to +127
• In cases where + and – are needed to represent a given quantity such as
temperature, the use of signed char is necessary
4
unsigned int
• unsigned int is a 16-bit data-type that takes values in the range 0 to 65,535 (0000
to $FFFF)
• It takes two bytes of RAM and the misuse of int variables will lead to larger hex
files, slower program execution and more memory usage
• unsigned int must be used for values greater than 255 (not where unsigned char
can be used)
signed int
• It is the default int data-type
• signed int is a 16-bit data-type that uses the MSB for sign and 15 bits for
magnitude, and takes values in the range -32,768 to +32,767
5
I/O Programming in C
• All port registers are both byte and bit accessible
• To access a port register as a byte, we use PORTx
Example 1
Write a C program to get a byte of data from PORTC. If it is less than 100, send it to
PORTB; otherwise, send it to PORTD
Solution (in the next slide)
6
#include <avr/io.h> //standard AVR header
int main(void)
{
DDRC = 0x00; //PORTC is input
DDRB = 0xFF //PORTB is output
DDRD = 0xFF //PORTD is output
unsigned char temp;
while(1)
{
temp = PINC; //read from PINC
if( temp < 100 )
PORTB = temp;
else
PORTD = temp;
}
return 0;
}
7
• To access a single bit of a given register, use bitwise operators
• Bitwise operators include AND(&), OR(|), XOR(^), invert(~), shift right (>>) and
shift left (<<)
• The following examples use bitwise operators:
▪ 0x35 & 0x0F =0x05 (ANDing)
▪ 0x04 | 0x68 = 0x6C (ORing)
▪ 0x54 ^ 0x78 = 0x2C (XORing)
▪ ~0x55 = 0xAA (Inverting)
▪ 0x0A >> 1 = 0x05 (shifting right)
▪ 0x0A << 1 = 0x14 (shifting left)
• Bitwise ORing, ANDing and XORing can be used to set, clear and toggle bits
▪ Anything ORed with a 1 results in a 1; anything ORed with a 0 results in no change
▪ Anything ANDed with a 0 results in 0; anything ANDed with a 1 results in no change
▪ Anything XORed with a 1 results in the complement; anything XORed with a 0 results in no
change
8
Time Delay
• There are three ways to generate a delay in AVR C:
1. Using a simple for loop
2. Using pre-defined C functions
3. Using AVR timers
• The frequency of the crystal oscillator is important in determining the time delay
• An example program for creating a delay using the for loop is given below:
int main(void)
{
unsigned long i;
for(i = 0; i < 47060; i ++) //assume XTAL = 16
}
11
Masking
• Masking is a process of hiding information that is not required
• We mask through bit-wise ANDing with a masking byte (with 0’s on bits to hide
and 1’s on bits needed)
• For example, we have eight switches connected to PORTD (one Switch to each
pin), and we want to read only PD3 and PD4.
• In this example, we only need information of PD3 and PD4 and, so, we mask with
1’s those pins and others with 0’s.
• Therefore, the masking byte is 00011000 and the instruction is: (PIND & 0x18)
• We apply masking in reading desired input pins, for example reading data
supplied to input pins or reading switches (to check their statuses - if closed or
open)
Swapping Nibbles
• This is done through masking followed by shifting 4 times to the right for lower
nibble and to the left for upper nibble of a port
12