KEMBAR78
Ch07 AVR Programming in C | PDF | Integer (Computer Science) | C (Programming Language)
0% found this document useful (0 votes)
17 views76 pages

Ch07 AVR Programming in C

This document provides an overview of AVR programming in C, highlighting the advantages of using C over Assembly language for microcontroller programming. It details data types in Arduino, I/O ports, and the structure of registers such as DDRx, PORTx, and PINx, along with example programs demonstrating basic operations. Additionally, it explains how to implement time delays and toggle outputs using predefined functions.

Uploaded by

xirer50826
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views76 pages

Ch07 AVR Programming in C

This document provides an overview of AVR programming in C, highlighting the advantages of using C over Assembly language for microcontroller programming. It details data types in Arduino, I/O ports, and the structure of registers such as DDRx, PORTx, and PINx, along with example programs demonstrating basic operations. Additionally, it explains how to implement time delays and toggle outputs using predefined functions.

Uploaded by

xirer50826
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 76

Microprocessor and Microcontroller

Chapter 07: AVR Programming in C

Engr. Rashid Farid Chishti


http://youtube.com/rfchishti
http://sites.google.com/site/chis
hti International Islamic University H-10, Islamabad, Pakistan
Languages
 High Level Languages
 Easy to develop and update
 C Language
 Acceptable performance
 Easy to develop and update
High Level Languages
 Portable (like VB, VC, C#, JAVA)
 Low Level Languages C Language
 High performance
Machine Language
 Not portable
Why program the AVR in C ?
 It is easier and less time consuming to write in C than in Assembly.
 C is easier to modify and update.
 You can use code available in function libraries.
 C code is portable to other microcontrollers with little or no modification.
 While Assembly language produces a hex file that is much smaller than C.
 Programming in Assembly language is often tedious and time consuming.
 C 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.
Data Types in Arduino
Data Type Size Range
bool 1 byte ( 8 true(1) or false(0)
bits)
byte or unsigned 1 byte ( 8 0 ~ 28-1 = 0 to 255 (for ASCII
char bits) Values)
char or signed 1 byte ( 8 (-27) ~ (+27-1) = -128 ~ +127
char bits)
short or signed short 2 bytes (16 (-215) ~ (+215-1) = -32,768 ~ +32,767
int or signed int bits)
word or unsigned 2 bytes (16 0 ~ 216-1 = 0 to 65,535
short bits)
long or signed long 4 bytes (32 (-231) ~ (+231-1) =
bits) -2,14,74,83,648 ~ +2,14,74,83,647
unsigned long 4 bytes (32 0 ~ (232 - 1) = 0 ~ 4,29,49,67,295
bits)
float or double 4 bytes (32 -3.4028 × 1038 ~ 3.4028 × 1038
Data Types in Arduino
Other useful data types are
 arrays e.g. char myStr[] = "hello world";
 string() e.g. string str = "Hello String";
 void e.g. void setup() { // ... }
 sizeof() e.g. sizeof(str);
 const e.g. const float pi = 3.14;
 static e.g. static int lenth;
 PROGMEM e.g. const PROGMEM char msg[]={"I AM
PREDATOR"};
 EEMEM e.g. byte EEMEM myByte;
AVR Simplest Connection

ATmega328P
Vcc

ATmega328

7
VCC
Vcc 20
AVCC

10K

1
RESET
22pF
10
XTAL2
Reset
Button 16MHz
8
GND XTAL1 9
22
GND
22pF
I/O Ports in AVR
 ATmega328 is 28-pin chip 777
666
 A total of 23 pins are set aside for the 3 ports XTAL1
XTAL2
555 PB5 (SCK)
444 PB4 (MISO)
RESET 333 PB3 (MOSI/OC2A)
 PORTB, PORTC, PORTD. VCC 222 PB2 (SS/OC1B)
GND 111 PB1 (OC1A)

Each port has 3 I/O registers associated with it


000
 AVCC
AREF
PINB
DDRB
PB0 (ICP1/CLK0)

PORTB

 They are designated as PORTC


DDRC
PINC
PORTD
DDRD
PIND

 DDRx (Data Direction Register) (ADC0) PC0 000 777 PD7 (AIN1)
PD6 (AIN0)
(ADC1) PC1 111 666
(ADC2) PC2 222 555 PD5 (T1)
 PORTx (Data Register) (ADC3) PC3 333 444 PD4 (T0/XCK)
(ADC4/SDA) PC4 444 333 PD3 (INT1)

 PINx (Port INput pins). (ADC5/SCL) PC5 555


666
222
111
PD2 (INT0)
PD1 (TXD)
777 000 PD0 (RXD)
 For example, for Port B we have PORTB, DDRB, PINB registers.
 Each of the I/O registers is 8 bits wide, and each port has a maximum of 8 pins.
The structure of IO pins
DDRx: 7 6 5 4 3 2 1 0 777
PORTx: 7 6 5 4 3 2 1 0
666
XTAL1 555 PB5 (SCK)
ATmega328P

PINx: 7 6 5 4 3 2 1 0
XTAL2 444 PB4 (MISO)
Px7 Px6 Px5 Px4 Px3 Px2 Px1 Px0
RESET 333 PB3 (MOSI/OC2A)
VCC 222 PB2 (SS/OC1B)
GND 111 PB1 (OC1A)
AVCC 000 PB0 (ICP1/CLK0)
PINB
AREF DDRB
PORTB

PORTC PORTD
DDRC DDRD
PINC PIND
(ADC0) PC0 PD7 (AIN1)
DDRx

000 777
0 1 (ADC1) PC1 111 666 PD6 (AIN0)
PORTx PD5 (T1)
(ADC2) PC2 222 555
444 PD4 (T0/XCK)
0 high impedance Out 0 (ADC3) PC3 3 3 3DDRx.n
333 PD3 (INT1)
(ADC4/SDA) PC4 444 PORTx.n

555 222 PD2 (INT0)


1 pull-up Out 1 (ADC5/SCL) PC5
666 PINx.n1 1 1 PD1 (TXD)
777 000 PD0 (RXD)
Data Direction Register ( DDRx )
 DDRx register is used for the purpose of making a 777
666

given port an input or output port.


XTAL1 555 PB5 (SCK)
XTAL2 444 PB4 (MISO)
RESET 333 PB3 (MOSI/OC2A)
 Setting (writing a one) to a bit in the DDRx con- VCC
GND
222
111
PB2 (SS/OC1B)
PB1 (OC1A)

figures the pin as an Output. AVCC


AREF
000
PINB
DDRB
PB0 (ICP1/CLK0)

PORTB
 Clearing (writing a zero) to a bit in the DDRx con PORTC
DDRC
PORTD
DDRD

figures the pin as an Input. e.g.


PINC PIND
(ADC0) PC0 PD7 (AIN1)
000 777
(ADC1) PC1 666 PD6 (AIN0)
111
 Imagine a person who has 0 dollars, he can only (ADC2) PC2
(ADC3) PC3
222
333
555
444
PD5 (T1)
PD4 (T0/XCK)

get money, not give it. Similarly when DDR con- (ADC4/SDA) PC4 444 333 PD3 (INT1)
(ADC5/SCL) PC5 555 222 PD2 (INT0)
666 111 PD1 (TXD)

tains 0’s the port gets data. 777 000 PD0 (RXD)

DDRC = 0xFF; // Configure PRTC as output


DDRB = 0x00; // Configure PRTB for input
Port Input Pin Register ( PINx )
 To read the data present at the pins, we should 777
666

read the PINx register.


XTAL1 555 PB5 (SCK)
XTAL2 444 PB4 (MISO)
RESET 333 PB3 (MOSI/OC2A)
 To send data out to pins we use the PORTx register. VCC
GND
222
111
PB2 (SS/OC1B)
PB1 (OC1A)
 There is a pull-up resistor for each of the AVR pins. AVCC
AREF
000
PINB
DDRB
PB0 (ICP1/CLK0)

PORTB

PORTC PORTD
DDRC DDRD
PINC PIND
(ADC0) PC0 PD7 (AIN1)
000 777
(ADC1) PC1 666 PD6 (AIN0)
111
(ADC2) PC2 222 555 PD5 (T1)
(ADC3) PC3 333 444 PD4 (T0/XCK)
(ADC4/SDA) PC4 444 333 PD3 (INT1)
555 222 PD2 (INT0)
Different States of a Pin in the AVR Microcontroller
(ADC5/SCL) PC5
666 111 PD1 (TXD)
777 000 PD0 (RXD)
DDRx
PORTx
0 1
0 Input & high impedance Out 0
1 Input & Pull-up Out 1
Data Register ( PORTx )
 The PORTx register controls if the pull-up is activated or not
 Writing a 1 to the PORTx register will activate the internal pull-up resistor
 Writing a 0 to the PORTx register will deactivate or turn off the internal pull-up
resistor
vcc
DDB = 0x00; // configure PORTB for input 1 = Close
PORTB = 0xFF; // turn-on the pull-up resistors PORTx.n 0 = Open

Different States of a Pin in the AVR Microcontroller


DDRx
PORTx
0 1 pin n of
port x PINx.n
0 Input & high impedance Out 0
1 Input & Pull-up Out 1 Outside the Inside the
AVR chip AVR chip
Using External or Internal Pull-up

AVR AVR
VCC VCC

PORTC.3 PORTC.3 vcc


1 = Close
PORTx.n 0 = Open

Different States of a Pin in the AVR Microcontroller


DDRx
PORTx
0 1 pin n of
port x PINx.n
0 Input & high impedance Out 0
1 Input & Pull-up Out 1 Outside the Inside the
AVR chip AVR chip
Example 1
// Write a program that sends values 0 to 9 on Port B continuously.

/*** SOLUTION ***/

// the setup function runs once when you press


// reset or power the board
void setup(){
DDRB = 0xFF;
}
// the loop function runs over and over again
// forever
void loop(){
for (int i = 0; i <= 9; i++)
{
PORTB = i;
delay(200); // call 0.2 sec delay
}
}
13
Example 2
// Write a program that sends values 00-FF to Port D continuously.

/*** SOLUTION ***/

// the setup function runs once when you press


// reset or power the board
void setup(){
DDRD = 0xFF;
}

// the loop function runs over and over again


// forever
void loop(){
PORTD++;
delay(100); // call 100 ms delay
}

14
Example 3
// Write a program to toggle Port D 200 times only.
1010 1010 =
0xAA
/*** SOLUTION ***/ Bitwise NOT
-----------
// the setup function runs once when you press 0101 0101 =
// reset or power the board 0x55
void setup(){
DDRD = 0xFF;
PORTD = 0xAA;
for (int i = 0; i < 200; i++) {
PORTD = ~PORTD;
delay(1000); // 1 sec delay
}
}

// the loop function runs over and over again


// forever
void loop(){

}
15
Time Delay in Arduino
You can use predefined functions of Arduino to make time delays
 Syntax delay(ms)
 Parameters ms the number of milliseconds to pause (unsigned long)
 Returns Nothing
Example 4
// Write a program to toggle all bits of PORTD 50,000 times only.

/*** SOLUTION ***/

void setup(){
DDRD = 0xFF; // PORTD is output
for(unsigned int i=0; i<50000 ; i++){
PORTD = ~PORTD;
delay(10); // put 10 ms sec delay
}
}

void loop(){
}

// Run the above program on your simulator to see how Port D toggles
// Notice that the maximum value for unsigned int is 65,535.
17
Example 5
// Write a program to toggle all bits of PORTD 100,000 times only.

/*** SOLUTION ***/

void setup(){
DDRD = 0xFF; // PORTD is output
for(long i=0; i<100000 ; i++){
PORTD = ~PORTD;
delay(10); // put 10 ms sec delay
}
}

void loop(){
}

// Run the above program on your simulator to see how Port D toggles
// Notice that the maximum value for long is 2,14,74,83,647.
18
Example 6
// Write a program to send string a
// “hello world” to Port D only once.

/*** SOLUTION ***/

char msg[] = "hello world";

void setup(){
DDRD = 0xFF; // PORTD is output port
// loop breaks at NULL
for(int i=0; msg[i]; i++) {
// send the character to PORTB
PORTD = msg[i] ;
delay(1000);// put 1 sec delay
}
}

void loop(){ Character h e l l o w o r l d \0


} ASCII Code 68 65 6C 6C 6F 20 77 6F 72 6C 64 00
19
Example 7
// Write a program to send following bytes to Port D
// {0x01, 0x02,0x04,0x08,0x10,0x20,0x40,0x80} continuously.

/*** SOLUTION ***/


byte num[] =
{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int PAUSE = 500, i;
void setup(){
DDRD = 0xFF; // PORTD is output
}
void loop(){
for( i=0; i<8; i++){ // loop breaks at i=8
PORTD = num[i] ; // send Byte to PORTB
delay(PAUSE);
}
for( i=7; i>=0; i--){ // loop breaks at i=-1
PORTD = num[i] ; // send Byte to PORTB
delay(PAUSE);
}
}
20
Bit-wise Operators

1110 1011 1110 1011 1110 1011


& 1100 1110 | 1100 1110 ^ 1100 1110 ~ 1110 1011

----------- ----------- ----------- -----------


1100 1010 1110 1111 0010 0101 0001 0100
= 0xCA = 0xEF = 0x25 = 0x14
Example 8
// Write a Program to Show the Result of
// (a) 1110 1011 & 1100 1110 on PORTD
// (b) 1110 1011 | 1100 1110 on PORTD
// (c) 1110 1011 ^ 1100 1110 on PORTD
// with 5 sec delay after each output

/*** SOLUTION ***/


const int PAUSE = 2000;

void setup(){
DDRD = 0xFF; // PORTD is output
}

void loop(){
PORTD = 0xEB & 0xCE ; delay(PAUSE);
PORTD = 0xEB | 0xCE ; delay(PAUSE);
PORTD = 0b11101011 ^ 0xCE ; delay(PAUSE);
}

22
Example 9
// Write a Program to toggle only lower 4
// bits of PORTD with 1 sec delay without
// disturbing the higher 4 bits of PORTD.
// Initial Value of PORTD is 0xFF.

/*** SOLUTION ***/


const int PAUSE = 1000;
void setup(){
DDRD = 0xFF; // PORTD is output
PORTD = 0xAA; // Initialize PORTD
}

void loop(){
PORTD = PORTD ^ 0x0F ; delay(PAUSE);
}

PORTD = 0xAA = 1010 1010 PORTD = 0xA5 = 1010 0101


Mask = 0x0F = 0000 1111 Mask = 0x0F = 0000 1111
XOR XOR
------------------------- -------------------------
23
PORTD = 0xA5 = 1010 0101 PORTD = 0xAA = 1010 1010
Simple Shift Operations in AVR
 data >> number of bits to be shifted right
 data << number of bits to be shifted left

1110 0000 >> 0000 0001 <<


3 2

-------------- --------------
0001 1100 0000 0100
= 0x1C = 0x04
Example 10
// Write a Program to Show the Result of
// (a) 1110 0000 >> 3 on PORTD
// (a) 0000 0001 << 2 on PORTD
// with 3 sec delay after each output

/*** SOLUTION ***/

const int PAUSE = 500;


int i; 1110 0000 >>
3
void setup(){ = 0001 1100
DDRD = 0xFF; = 0x1C
0000 0001 <<
} 2
= 0000 0100
void loop(){ = 0x04
PORTD = 0b11100000 >> 3; delay(PAUSE);
PORTD = 0b00000001 << 2; delay(PAUSE);
}

25
0x01 = 0000 0001
Example 11 1<<0
1<<1
=
=
0000
0000
0001
0010
=
=
0x01
0x02
1<<2
// 8 LEDs are connected to each pin of Port D. Write a program = 0000 0100 = 0x04
1<<3
// to turn on each LED on PORTD from pin PD0 to PD7 with some = 0000 1000 = 0x08
// delay. 1<<4 = 0001 0000 = 0x10 =
16
/*** SOLUTION ***/ 1<<5 = 0010 0000 = 0x20 =
const int PAUSE = 500; 32
1<<6 = 0100 0000 = 0x40 =
void setup(){ 64
DDRD = 0xFF; // PORTD is output 1<<7 = 1000 0000 = 0x80 =
} 128

void loop(){
for(int i =0; i<8; i++)
{
// loop breaks at i=8
// Turn On One LED at a time
PORTD = 1<<i ;
delay(PAUSE);
}
}
26
Setting a bit in a Byte to 1
 We can use | (Bitwise OR) operator to set a bit of a byte to 1

xxxx xxxx xxxx xxxx


| 0001 0000 | 1<<4

------------ ------------
xxx1 xxxx xxx1 xxxx

PORTB = PORTB | (1<<4); // Set bit 4 (5th bit)


PORTB |= (1<<4); // Set bit 4 (5th bit) of PORTB
Clearing a bit in a Byte to 0
 We can use & (Bitwise AND) operator to clear a bit of a byte to 0

xxxx xxxx xxxx xxxx


& 1110 1111 & ~(1<<4)

------------ ------------
xxx0 xxxx xxx0 xxxx

PORTB = PORTB & ~(1<<4); // Clear bit 4 (5th bit)


PORTB &= ~(1<<4); // Clear bit 4 (5th bit) of PORTB
Checking a bit in a Byte
 We can use & (Bitwise AND) operator to see if a bit in a byte is 1 or 0

xxxx xxxx xxxx xxxx


& 0001 0000 & 1<<4

------------ ------------
000x 0000 000x 0000

if(PINC & (1<<4)) // Check if the bit 4


// (5th bit) of PINC Register
// is 1
Example 12
// A Push Button is connected to PC4 with other end connected to ground. Write a
program to
// send 0x0F on PORTD when the input on PC4 is logic 0 and 0xF0 otherwise.

/*** SOLUTION ***/

void setup(){
// PC4 as input
DDRC = DDRC & 0b11101111 ;
// Enable Pull-up at PC4
PORTC = PORTC | 0b00010000 ;
DDRD = 0xFF ; // PORTD as output
}

void loop(){
// if we get logic 1 at PC4
if( PINC & 0b00010000)
PORTD = 0xF0 ; //
else
PORTD = 0x0F ; //
30
}
Example 13
// 1 LED is connected to PB5. A Push Button is connected to PC4 with other end
connected to
// ground. Write a program to turn ON LED when the Push Button is pressed and turn
OFF LED
// otherwise.
/*** SOLUTION ***/
void setup(){
// PB5 as output
DDRB = DDRB | 0b00100000 ;
// PC4 as input
DDRC = DDRC & 0b11101111 ;
// Enable Pull-up at PC4
PORTC = PORTC | 0b00010000 ;
}

void loop(){
if( PINC & 0b00010000) // if Button is released
PORTB = PORTB & 0b11011111 ; // Turn OFF LED
else
PORTB = PORTB | 0b00100000 ; // Turn ON LED
31
Example 14
// 1 LED is connected to PB5. A Push Button is connected to PC4 with other end
connected to
// ground. Write a program to turn ON LED when the Push Button is pressed and turn
OFF LED
// otherwise. Use Shift Operators for masking

/*** SOLUTION ***/


#define LED_PIN 5
void setup(){
// PB5(LED) as output
DDRB = DDRB | (1<<LED_PIN) ;
DDRC = DDRC & ~(1<<4); // PC4 as input
PORTC = PORTC | (1<<4); // Enable Pull-up
}

void loop(){
if( PINC & (1<<4)) // if we get logic 1 at PC4
PORTB = PORTB & ~(1<<LED_PIN) ; // Turn OFF LED
else
PORTB = PORTB | (1<<LED_PIN) ; // Turn ON LED
32
}
ATmega328 and Arduino UNO Pinout Diagram
Arduino MEGA 2560 Pinout Diagram
Arduino MEGA 2560 Pinout Diagram
pinMode() function in Arduino
pinMode() Configures the specified pin to behave either as an input or an
output.

 Syntax pinMode(pin , mode)

 Parameters
 pin: the number of the pin whose mode you wish to set
 mode : INPUT, OUTPUT, or INPUT_PULLUP.

 Returns Nothing
digitalWrite() function in Arduino
digitalWrite() Writes a HIGH or a LOW value to a digital pin.

 Syntax digitalWrite (pin , value)

 Parameters
 pin: the pin number on Arduino.
 value : HIGH or LOW.

 Returns Nothing
digitalRead() function in Arduino
digitalRead() Reads the value from a specified digital pin, either HIGH or
LOW.

 Syntax digitalRead (pin)

 Parameters
 pin: the pin number on Arduino.

 Returns HIGH(1) or LOW(0).


Example 15
// Write a program to blink on board LED with some delay in Adriano

/*** SOLUTION ***/

const unsigned int LED_PIN = 13;


const unsigned int PAUSE = 500;

void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(PAUSE);
digitalWrite(LED_PIN, LOW);
delay(PAUSE);
}

39
Example 16
// Write a program to Read input from pin 7 and send it to pin 13

/*** SOLUTION ***/

int ledPin = 13; // LED connected to digital pin 13


int inPin = 7; // pushbutton connected to digital pin 7
int val = 0; // variable to store the read value

void setup() {
pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output
pinMode(inPin, INPUT_PULLUP); // sets the digital pin 7 as input
}

void loop() {
val = digitalRead(inPin); // read the input pin
digitalWrite(ledPin, val); // sets the LED to the button's value
}

40
Example 17
// Write a program to read PB3 and PB4 of PORTB and issue an ASCII character to Port
D

/*** SOLUTION ***/

void setup(){
// Set PB3 and PB4 as input
DDRB = DDRB & 0b11100111 ;
// Enable Pull-up at PB3 and PB4
PORTB = PORTB | 0b00011000;
DDRD = 0xFF;// PORTD is output
}

void loop(){
switch( PINB & 0b00011000) { // make decision
case(0b00000000): PORTD = '0'; break; // issue ASCII 0
case(0b00001000): PORTD = '1'; break; // issue ASCII 1
case(0b00010000): PORTD = '2'; break; // issue ASCII 2
case(0b00011000): PORTD = '3'; break; // issue ASCII 3
}
41
}
Example 18
// Write a program to monitor PB3. If it is 1 make bit 4 of Port B input; otherwise,
change
// bit 4 of Port B to output.

/*** SOLUTION ***/

void setup(){
// Set PB3 as input
DDRB = DDRB & ~(1<<3) ;
// Enable Pull-up at PB3
PORTB = PORTB | (1<<3) ;
}

void loop(){
if( PINB & (1<<3))// if input pin is logic 1
// Set PB4 as input pin
DDRB = DDRB & ~(1<<4) ;
else
// Set PB4 as output pin
DDRB = DDRB | (1<<4) ;
42
}
BCD, Packed BCD and ASCII conversion.

ASCII and BCD Codes for Digits 0–9 BCD Codes

BCD1 BCD0

Packed BCD
Example 19
// Write a program to convert packed BCD 0x29 to
// ASCII and display the bytes on PORTD with 2 sec
// delay.

/*** SOLUTION ***/


byte P_BCD = 0x29, L, R;
void setup(){
DDRD = 0xFF ; // Set Port D as output port
R = P_BCD & 0x0F; // Clear upper 4 bits
R = R | 0x30; // Make it ASCII
L = P_BCD & 0xF0; // Clear lower 4 bits
L = L >> 4; // Shift it to lower 4 bits 0x29 0x29
L = L | 0x30; // Make it ASCII 0xF0 & 0x0F &
} ---- ----
0x20 >> 4 0x09
void loop(){ = 0x02 0x30 |
PORTD = L; delay(500); 0x30 | ----
PORTD = R; delay(500); ---- 0x39
} 0x32 R ='9'
L = '2' 44
Example 20
// Write a program to convert to convert ASCII digits of ‘2’ and ‘9’
// to packed BCD and display Packet BCD number on PORTD.

/*** SOLUTION ***/

byte P_BCD, L = '2', R = '9';


void setup(){
DDRD = 0xFF; // Set Port D as output port
L &= 0x0F; // Clear upper 4 bits
L <<= 4; // Shift it to upper 4 bits
R &= 0x0F; // Clear upper 4 bits
P_BCD = L | R; // Combine two to make packed BCD
0x32 0x39
PORTD = P_BCD; // Show on PORTD
0x0F & 0x0F
---- &
}
0x02 << 4 ----
L = 0x20 R = 0x09
void loop(){
P_BCD = L | R
} = 0x20 | 0x09
= 0x29 45
Example 21
// Write a program that has two BCD numbers 0x74.
// Swap these numbers to 0x47 and show the
// answer on PORTD.

/*** SOLUTION ***/


byte P_BCD = 0x74, L , R;

void setup(){
DDRD = 0xFF ; // Set Port D as output port
R = P_BCD << 4; // R = 0x40
L = P_BCD >> 4; // L = 0x07
PORTD = L|R; // PORTD = 0x47
}

void loop(){
0x74 >> 0x74 <<
} 4 4
L = 0x07 R = 0x40
PORD = L | R
= 0x07 | 0x40
= 0x47 46
Example 22
// Write a program to convert 0b11111101 (= 0xFD = 253) to decimal
// and display each digit after two sec delay on PORTD.

/*** SOLUTION ***/

byte N = 0xFD, D0,D1,D2;

void setup(){
DDRD = 0xFF ;// Set Port D as output port
D0 = N % 10; N /= 10; // D0 = 3, N = 25
D1 = N % 10; N /= 10; // D1 = 5, N = 2
D2 = N; // D2 = 2
}

void loop(){
PORTD = D2; delay(500); // Show 2
PORTD = D1; delay(500); // Show 5
PORTD = D0; delay(1000); // Show 3
}
47
Check Sum Byte in ROM
 To detect data corruption  E.g. For 0x25, 0x62, 0x3F, and 0x52
 Calculating checksum byte:  sum = 0x25+0x62+0x3F+0x52
 Add the bytes together and = 0x118
drop the carries sum = 0x18 discard caries
 Take the 2’s complement of the

total sum  checksum = ~sum + 1 = ~(0x18) + 1


 Testing checksum = 0xE7 + 1 = 0xE8
 Add the bytes together and  Error = 0x25 + 0x62 + 0x3F + 0x52 + 0xE8
drop the carries = 0x200
 Add the checksum byte to the

sum  After discarding carries if remaining 8-bit


 If the result is not zero, data is answer is zero that means no error.
corrupted
Example 23
// Write program to program to calculate the
// checksum byte for {0x25, 0x62, 0x3F, 0x52}
// and show it on PORTD

/*** SOLUTION ***/


byte data[] = {0x25, 0x62, 0x3F, 0x52};
byte sum = 0, check_sum;

void setup() {
DDRD = 0xFF ; // Set Port D as output port

for(int i=0; i<4; i++) // loop for i= 0 to 3


sum += data[i] ;// add them together sum = 0x18

check_sum = ~sum + 1; // check_sum = ~ 0x18 + 1 = 0xE8


PORTD = check_sum; // PORTD = 0xE8
}

void loop() {
}
49
Example 24
// Write a program to add the checksum byte 0xE8
// with data {0x25, 0x62, 0x3F, 0x52}. If the
// data is good, send ASCII character 'G'(0x47)
// to PORTD. Otherwise, send 'B'(0x42) to PORTD.

/*** SOLUTION ***/


byte data[] = {0x25, 0x62, 0x3F, 0x52};
byte sum = 0, check_sum = 0xE8;

void setup(){
DDRD = 0xFF ; // Set Port D as output port
for(int i=0; i<4; i++) // loop for i= 0 to 3
sum += data[i] ; // add them together sum = 0x18

sum += check_sum; // check_sum = 0x18 + 0xE8 = 0x00


PORTD = sum ? 'B':'G'; // PORTD = 'G' = 0x47 if sum == 0x00
}

void loop(){
}
50
Memory Types In AVR
 Flash Memory  RAM
 Not deleted when power is off  deleted when power is off
 Big in size
 Suitable for storing the data we
 Suitable for codes, tables and
want to manipulate because we
fixed data have fast access to read or
modify them.
 EEPROM
 Not deleted when power is off
 Not very big in size
 Suitable for small data that may

be modified but should not be lost


when power is off
Accessing Flash Memory
 Flash Memory
 You can Store data in flash (program) memory instead of SRAM using the
keyword PROGMEM.
 the keyword PROGMEM tells the compiler "put this information into flash
memory", instead of into SRAM.
#include <avr/pgmspace.h>
 Syntax: const dataType variableName[] PROGMEM = {data0, data1, data3…​};
 PROGMEM can also be used on a single variable.
 Using PROGMEM is also a two-step procedure. After getting the data into
Flash memory, it requires special methods (functions), also defined in the
pgmspace.h library, to read the data from program memory back into SRAM,
so we can do something useful with it.
Functions for Accessing Flash
pgm_read_byte(address_short) pgm_read_float(address_short)
pgm_read_byte_near(address_short) pgm_read_float_near(address_short)
pgm_read_byte_far(address_long) pgm_read_float_far(address_long)

pgm_read_word(address_short) pgm_read_ptr(address_short)
pgm_read_word_near(address_short) pgm_read_ptr_near(address_short)
pgm_read_word_far(address_long) pgm_read_ptr_far(address_long)

pgm_read_dword(address_short)
pgm_read_dword_near(address_short)
pgm_read_dword_far(address_long)
Example 25
// Write a program to store {5,6,7,4} in Flash and then read and
// show each byte on PORTD with 1 sec delay.

/*** SOLUTION ***/

#include <avr/pgmspace.h>
const byte PROGMEM lookup[] ={5,6,7,4};

void setup(){
DDRD = 0xFF ; // Set as output port
}

void loop(){
// loop from i= 0 to 3
for(int i=0; i<4 ; i++) {
PORTD = pgm_read_byte(&lookup[i]);
delay(500);
}
}
54
Example 26
// Write a program to store “ABC” in Flash and then read and
// show each byte on PORTD with 1 sec delay.

/*** SOLUTION ***/

#include <avr/pgmspace.h>
const char PROGMEM msg[] ="ABC";

void setup(){
DDRD = 0xFF ;// Port D as output port
}

void loop(){
// loop for i= 0 to 3
for(int i=0; i<3 ; i++) {
PORTD = pgm_read_byte_near(msg + i);
delay(500);
}
}
55
EEPROM
 EEPROM is a EEPROM Address Register (EEAR)
place to store EEPROM Data Register (EEDR)
Bit
data. It is not
15 14 13 12 11 10 9 8
EEPROM Control Register (EECR)
EEARH - - - - - - EEAR9 EEAR8

deleted when EEARL


Bit
EEAR7

7
EEAR6 EEAR5

6 5
EEAR4

4
EEAR3 EEAR2

3 2
EEAR1

1
EEAR0

0
power is off
 ATmega328 has
1024 bytes of
EEPROM EECR

In AVR 3 registers are


15 0
 EEARH EEARL
0

dedicated to EEPROM
EEDR
 EEARH:EEARL
 EEDR
 EECR 1023
EEPROM
Accessing EEPROM in AVR
 Every member of the AVR microcontrollers has some amount of on-chip
EEPROM.
 The data in SRAM will be lost if the power is disconnected.
 EEPROM memory can save stored data even when the power is cut off.
 The Size of EEPROM in different AVR Micro-controllers is given below
Chip Bytes Chip Bytes Chip Bytes

ATmega8 512 ATmega 16 512 ATmega328 1024

ATmega64 2048 ATmegal28 4096 ATmega256RZ 4096

ATmega640 4096 ATmegal280 4096 ATmega2560 4096


EEPROM Registers
 There are three I/O registers that are directly related to EEPROM. These are
 EECR (EEPROM Control Register)
 EEDR (EEPROM Data Register)
 EEARH-EEARL (EEPROM Address Register High-Low)

EEPROM Data Register (EEDR)


 To Read/write data to EEPROM, you have to Read/write to the EEDR register.

EEPROM Address Register (EEARH and EEARL)


 The EEARH:EEARL registers together make a 16-bit register to address each

location in EEPROM memory space.


 When you want to read from or write to EEPROM, you should load the

EEPROM location address in EEAR.


EEPROM Registers
 Only 10 bits of the EEAR registers are used in ATmega328. Because ATmega328
has 1024-byte EEPROM locations,
 ATmega16 has 512 bytes of EEPROM So 9 bits of the EEAR registers are used.
Bit 15 14 13 12 11 10 9 8
EEARH - - - - - - EEAR9 EEAR8

EEARL EEAR7 EEAR6 EEAR5 EEAR4 EEAR3 EEAR2 EEAR1 EEAR0

Bit 7 6 5 4 3 2 1 0
Figure 6-15: EEPROM Address Register

EEPROM Control Register (EECR)


 The EECR register is used to select the kind of operation to perform on. The

operation can be start, read, and write.


EEPROM Control Register (EECR)
 The bits of the EECR register are as follows:
 EEPROM Read Enable (EERE): If EEPE is zero, Setting EERE bit to one will cause
a read operation. When a read operation starts, one byte of EEPROM will be
read into the EEPROM Data Register (EEDR). The EEAR register specifies the
address of the desired byte.
 EEPROM Program Enable (EEPE) and EEPROM Master Program Enable
(EEMPE): When EEMWE is set,then within four clock cycles setting EEPE will
start a write operation. If EEMPE is zero, setting EEPE to one will have no
effect.
EECR - - EEPM1 EEPM0 EERIE EEMPE EEPE EERE

Bit 7 6 5 4 3 2 1 0
Figure 6-16: EEPROM Control Register
EEPROM Control Register (EECR)
 The When you set EEMPE to one, the hardware clears the bit to zero after four
clock cycles. This prevents unwanted write operations on EEPROM contents.
 Notice that you cannot start read or write operations before the last
write(program) operation is finished. You can check for this by polling the EEPE
bit. If EEPE is zero it means that EEPROM is ready to start a new read or
write(program) operation.
 EEPROM Ready Interrupt Enable (EERIE): This will be explained later on. In
Figure 6-16, bit number 6 and 7 of EECR are unused at the present time and
are reserved.
EEPROM Control Register (EECR)
 EEPROM Programming Mode Bits (EEPM1:EEPM0): These bits define which
programming action that will be triggered when writing EEPE.
 While EEPE is set, any write to EEPMn will be ignored.
 During reset, the EEPMn bits will be reset to 0b00 unless the EEPROM is busy
programming.
Programming the AVR to Write on EEPROM
 To write on EEPROM, the following steps should be followed.
1. Wait until EEPE becomes zero.
while(EECR & (1<<EEPE));
2. Write new EEPROM address to EEAR (optional).
EEAR = Address;
3. Write new EEPROM data to EEDR (optional).
EEDR = Data;
4. Set EEMPE bit to one.
EECR |= (1<<EEMPE);
5. Within four clock cycles after setting EEMPE, set EEPE to one.
EECR |= (1<<EEPE);
Programming the AVR to Write on EEPROM
void EEPROM_Write(unsigned int Address, byte Data)
{
// Wait for completion of previous write
while(EECR & (1<<EEPE));

// Set up address and Data Registers


EEAR = Address; EEDR = Data;

// Write logical one to EEMPE


EECR |= (1<<EEMPE);

// Start EEPROM write by setting EEPE


EECR |= (1<<EEPE);
}
Programming the AVR to Read from EEPROM
 To read from EEPROM, the following steps should be followed.

1. Wait until EEPE becomes zero.


while(EECR & (1<<EEPE));
2. Write new EEPROM address to EEAR
EEAR = Address;
3. Set EERE bit to one.
EECR |= (1<<EERE);
4. Read EEPROM data from EEDR.
return EEDR;
Programming the AVR to Read from EEPROM
byte EEPROM_Read(unsigned int Address){

// Wait for completion of previous write


while(EECR & (1<<EEPE));

// Set up address register


EEAR = Address;

// Start eeprom read by writing EERE


EECR |= (1<<EERE);

// Return data from Data Register


return EEDR;
}
Example 27
// Write a program to store ‘a' into location Ox005F of EEPROM.

/*** SOLUTION ***/

void EEPROM_Write(unsigned int Address, byte Data){


while(EECR & (1<<EEPE)); // Wait for completion of previous write
EEAR = Address; EEDR = Data; // Set up address and Data Registers
EECR |= (1<<EEMPE); // Write logical one to EEMPE
EECR |= (1<<EEPE); // Start EEPROM write by setting EEPE
}

void setup(){
EEPROM_Write(0x5F, 'a');
}

void loop(){

}
67
Example 28
// Write a program to read the content of location 0x005F of EEPROM into PORTD.

/*** SOLUTION ***/

byte EEPROM_Read(unsigned int Address){


while(EECR & (1<<EEPE)); // Wait for completion of previous write
EEAR = Address; // Set up address register
EECR |= (1<<EERE); // Start EEPROM read by writing EERE
return EEDR; // Return data from Data Register
}

void setup(){
DDRD = 0xFF; // Set PORTD as Output Port
PORTD = EEPROM_Read(0x5F);
}

void loop(){

}
68
Example 29
/* Write a program to write two bytes byte EEPROM_Read(unsigned int Address){
at address 0x10 and 0x12 of EEPROM and // Wait for completion of previous write
then read the data from these two while(EECR & (1<<EEPE));
addresses and then show this data on EEAR = Address; // Set up address
PORTD with one sec delay. */ register
// Start EEPROM read by writing EERE
/*** SOLUTION ***/ EECR |= (1<<EERE);
return EEDR; // Return data from Data
void EEPROM_Write(unsigned int Register
Address, }
byte Data) void setup(){
{ DDRD = 0xFF; // Set PORTD as Output Port
// Wait for completion of previous EEPROM_Write(0x10, 'a');
write EEPROM_Write(0x12, 'b');
while(EECR & (1<<EEPE)); }
// Set up address and Data Registers
EEAR = Address; EEDR = Data; void loop(){
// Write logical one to EEMPE PORTD = EEPROM_Read(0x10);
EECR |= (1<<EEMPE); delay(1000);
// Start EEPROM write by setting EEPE PORTD = EEPROM_Read(0x12);
Page Page
69
EECR |= (1<<EEPE); delay(1000);
Example 29

70
Example 30
/* Write a program to write a string byte EEPROM_Read(unsigned int Address){
"9876543210 Aa" to EEPROM starting // Wait for completion of previous write
from address 0x100. */ while(EECR & (1<<EEPE));
// Set up address register
/*** SOLUTION ***/ EEAR = Address;
// Start EEPROM read by writing EERE
void EEPROM_Write(unsigned int EECR |= (1<<EERE);
Address, return EEDR; // Return data from Data
byte Register
Data) }
{ void EEPROM_Write_Str (unsigned int Address,
// Wait for completion of previous byte Data[])
write {
while(EECR & (1<<EEPE)); int i = 0;
// Set up address and Data Registers // loop until we find NULL in the string
while(Data[i])
EEAR = Address; EEDR = Data; // Write first then increment
// Write logical one to EEMPE // both address and index number of array
EECR |= (1<<EEMPE); EEPROM_Write(Address++, Data[i++]);
// Start EEPROM write by setting // Write NULL also
EEPROM_Write(Address, 0);
EEPE }
Page Page
71
EECR |= (1<<EEPE);
Example 30
void setup() void loop()
{ {
// Set Port D as output port byte aByte;
DDRD = 0xFF; for( unsigned int adr =0x100 ; ; adr++)
// Write a string in EEPROM {
// starting from address 0x100 // Read One Byte from EEPROM
EEPROM_Write_Str(0x100,"9876543210 aByte = EEPROM_Read(adr);
Aa");
} // if it is NULL then break the loop
if(aByte == 0)
break;
else
// else show it on PORTD
PORTD = aByte;
// delay of 1 second
delay(1000);
}
}

Page Page
72
Using EEPROM Library in Arduino
 You can Store data in EEPROM memory instead of SRAM using the keyword
EEMEM.
 the keyword EEMEM tells the compiler "put this information into EEPROM",
instead of into SRAM.
#include <avr/eeprom.h>
 Syntax: dataType variableName[] EEMEM = {data0, data1, data3…​};
 EEMEM can also be used on a single variable.
 Using EEMEM is also a two-step procedure.
 After getting the data into EEPROM, it requires special methods (functions),
also defined in the eeprom.h library, to read the data from EEPROM back
into SRAM, or to write data to EEPROM.
List of Functions in EEPROM Library
uint8_t eeprom_read_byte (const uint8_t* __p)
uint16_t eeprom_read_word (const uint16_t* __p)
uint32_t eeprom_read_dword (const uint32_t* __p)
Float eeprom_read_float (const float* __p)
void eeprom_read_block(void* __dst, const void* __src,size_t
__n)
void eeprom_write_byte (uint8_t* __p, uint8_t
__value)
void eeprom_write_word (uint16_t* __p, uint16_t
__value)
void eeprom_write_dword (uint32_t* __p, uint32_t
__value)
void eeprom_write_float (float* __p, float
__value)
void eeprom_write_block (const void* __src, void* __dst,
size_t __n)
Example 31
// Write a program to write a byte to EEPROM then read it and show it on PORTD.

/*** SOLUTION ***/

#include <avr/eeprom.h>
// Reserve a location in EEPROM
byte EEMEM myByte;

void setup() {
DDRD = 0xFF; // Set Port D as output port
// Write to EEPROM
eeprom_write_byte(&myByte,'G');

// Read from EEPROM


PORTD = eeprom_read_byte(&myByte);
}

void loop() {

}
75
Assignment # 1
1. Write a program to find number of 1s in a byte.
2. Write a program to find the average of the following numbers.
byte No[] = {'8','9','4','7','6','2','5'}; Notice that they are ASCII and must be
converted to BCD (or binary) before the average is calculated.
3. Write a program to calculate y where y = x2 + 2x + 1. x is between 0 and 9 and
the look-up table for x2 is located in Flash Memory. Take the values of x from
PORTB and Show the answer in binary at PORTD.
4. Write a program to read 8-bit number (234) from PORTD, Separate each digit,
convert digits to ASCII, store them in character array in the form of string
"234" and Finally store this string in EEPROM starting from address 0x100.
5. Write a program to read a string "234" from EEPROM starting from address
0x100, convert the string back to 8-bit number and show this number on
PORTD.

You might also like