[go: up one dir, main page]

0% found this document useful (0 votes)
2 views61 pages

Bit Fiddling and Arduino Digital IO

The document provides an overview of using microcontrollers, specifically Arduino, to manipulate digital I/O through bitwise operations. It explains how to set, clear, and check individual bits within a byte using logical operations such as AND, OR, and XOR. Additionally, it emphasizes the importance of using masks and shift operations for effective bit manipulation in programming.

Uploaded by

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

Bit Fiddling and Arduino Digital IO

The document provides an overview of using microcontrollers, specifically Arduino, to manipulate digital I/O through bitwise operations. It explains how to set, clear, and check individual bits within a byte using logical operations such as AND, OR, and XOR. Additionally, it emphasizes the importance of using masks and shift operations for effective bit manipulation in programming.

Uploaded by

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

1

Microcontrollers (Arduino) Overview


Digital I/O

These slides use the resources online from Prof. Murali Annavaram,
Prof. Mark Redekopp, and Prof. Allan Weber,
School of Engineering, USC Viterbi.
2

Introduction
• The primary way that software controls hardware is
by manipulating individual bits
• We need to learn how to:
– Set a bit to a1
– Clear a bit to a0
– Check the value of a given bit (is it 0 or 1)
• Because computers do not access anything smaller
than a byte (8-bits) we must use logic operations to
manipulate individual bits within abyte
3

Using software to perform logic on individual (or groups) of bits

BIT FIDDLING
4

Numbers in Other Bases in C/C++


• Suppose we want toplace the binary value 00111010 into a
char variable, v [i.e. char v;]
– We could convert todecimal on our own (5810)
v =58;
– All compilers support hexadecimal using the '0x' prefix
v =0x3a;
– Our Arduino compiler supports binary using the '0b' prefix
v =0b00111010;
• Important note: Compilers convert EVERYTHINGto equivalent
binary. The 3 alternatives above are equivalent because the
compiler will take all 3 and place 00111010 inmemory.
– Use whichever base makes the most sense in any given situation
– It is your (the programmer's) choice…the compiler will end up
converting to binary once it is compiled
5

Modifying Individual Bits


• Suppose we want to change only a single bit (or a few bits)
in a variable [i.e. char v;] without changing the other bits ? ? ? ? ? ? ? ?

– Set the LSBof v to 1 w/o affecting other bits Original v


• Would this work? v = 1;
– Set the upper 4 bits of v to 1111 w/o affecting other bits ? ? ? ? ? ? ? 1
• Would this work? v = 0xf0;
Desired v
– Clear the lower 2 bits of v to 00 w/o affecting other bits (change LSB to 1)
• Would this work? v = 0;
– No!!! Assignment changes ALLbits in avariable
1 1 1 1 ? ? ? ?
• Because the smallest unit of data incomputers is usually a
Desired v
byte, manipulating individual bits requires us to use (change upper 4 bits to
BITWISEOPERATIONS. 1111)

– Use AND operations to clear individual bits to 0


– Use ORoperations to set individual bits to 1 ? ? ? ? ? ? 0 0
– Use XOR operations to invert bits Desired v
– Use AND to check a bit(s) value in a register (change lower 2 bits to
00)
6

Using Logic to Change Bits


• ANDs can be used to control whether a bit passes unchanged or results ina '0'
• ORscan be used to control whether a bit passes unchanged or results in a '1'
• XORscan be used to control whether a bit passes unchanged or isinverted
X
Bit
Bit Bit
X
X
F XOR FZ
AND F Ctrl OR Ctrl
Y
Ctrl
Y Y

Ctrl Bit F Ctrl Bit F Ctrl Bit F


Pass Force

0 0 0 0 0 0 0 0 0

Force Pass

Invert Pass
'0'

0 1 0 0 1 1 0 1 1
1 0 0 1 0 1 1 0 1
1 1 0

'1'
1 1 1 1 1 1

1 AND x = 0 1 OR x = x 1 XOR x = x
2 AND x = x 2 OR x = 1 2 XOR x = NOT x
x AND x = x x OR x = x x XOR x = 0
You already T1 X + 0 =X T1' X • 1= X
knew the above
ideas. It is just
T2 X + 1 =1 T2' X • 0= 0
T1-T3. T3 X+ X= X T3' X • X =X
7

Bitwise Operations
• The CAND, OR, XOR, NOT bitwise operationsperform
the operation on each pair of bits of 2 numbers
#include <stdio.h> // C-Library
// for printf()
0xF0 1111 0000
AND 0x3C AND 0011 1100 int main()
{
0x30 0011 0000 char a = 0xf0;
char b = 0x3c;

0xF0 1111 0000 printf("a & b = %x\n", a &b);


printf("a | b = %x\n", a | b);
OR 0x3C OR 0011 1100 printf("a ^ b = %x\n", a ^ b);
0xFC 1111 1100 printf("~a = %x\n", ~a);
return 0;
}

0xF0 1111 0000


C bitwise operators:
XOR 0x3C XOR 0011 1100
0xCC 1100 1100 & = AND
| = OR
NOT 0xF0 NOT 1111 0000 ^ = XOR
0x0F 0000 1111 ~ = NOT
8

Bitwise Operations & Masking


Bit #
• Bitwise operations are often used for "bit 7 6 5 4 3 2 1 0

fiddling" v ? ? ? ? ? ? ? ?
– Change the value of a bit in a registerw/o affecting
other bits &
• Determine appropriate constant bit patterns v ? ? ? ? ? ? ? 0
(aka masks) that will change some bits while
leaving others unchanged
• Masks can be written in binary, hex, or even decimal (it v ? ? ? ? ? ? ? ?
is the programmer's choice…whatever is easiest)
|
• Examples (Assume an 8-bit variable, v)
v 1 ? ? ? ? ? ? ?
– Clear the LSBto '0' w/o affecting otherbits
• v = v & 0xfe; or equivalently
• v = v & ~(0x01); v ? ? ? ? ? ? ? ?
– Set the MSB to '1' w/o affecting other bits
• v = v | 0x80; ^ 0 0 0 0 1 1 1 1
– Flip the LS 4-bits w/o affecting other bits v ? ? ? ? ? ? ? ?
• v = v ^ 0x0f;
9

Changing Register Bits


7 6 5 4 3 2 1 0

v ? ? ? ? ? ? ? ?
• Some practice problems:
|
– Set bit 0 of v to a ‘1’
v = v | 0x01;
– Clear the 4 upper bits in v to ‘0’s v ? ? ? ? ? ? ? ?
v = v & 0x0f;
&
– Flip bits 4 and 5 in v
v = v ^ 0b00110000;
v ? ? ? ? ? ? ? ?

Note: It is the programmer's choice of writing the "mask" constant in binary,


hex, or decimal. However, hex is usually preferable (avoids mistakesof missing
a bit in binary and easier than converting to decimal).
10

Checking Register Bits 7 6 5 4 3 2 1 0

v ? ? ? ? ? ? ? ?
• Tocheck for a given set of bits we usea
bitwise-AND to isolate just thosebits & 1 0 0 0 0 0 0 0
– The result will then have 0's in the bit locations not
of interest
– The result will keep the bit values of interest v ? ? ? ? ? ? ? ?
• Examples & 0 0 0 0 0 1 0 0
– Check if bit 7 ofv = '1'
if ( (v & 0x80) == 0x80) { code } or
if (v & 0x80) { code } v ? ? ? ? ? ? ? ?
– Check if bit 2 ofv = '0' & 0 0 0 0 0 1 1 1
if ( (v & 0x04) == 0x00) { code } or
if ( ! (v & 0x04) ) { code }
– Check if bit 2:0 ofv = "101" v ? ? ? ? ? ? ? ?
if ( (v & 0b00000111) == 0b00000101) {..}
& 0 0 1 1 0 0 0 0
– Check if bit 5-4 ofv = "01"
if ( (v & 0x30) == 0x10) { code }
11

Short Notation for Operations


• In C, assignment statements of the form
x = x op y;
• Can be shortened to
x op= y;
• Example:
x = x + 1; can be written as x += 1;
• The preceding operations can be written as
v|= 0x01;
v &= 0x0f;
v ^= 0b00110000;
12

Logical vs. Bitwise Operations


• The C language has two types of logicoperations
– Logical and Bitwise
• Logical Operators (&&, | | , !)
– Operate on the logical value of a FULLvariable (char, int, etc.)
interpreting that value as either True (non-zero) or False(zero)
– char x = 1, y = 2, z = x && y; 00000001=T
• Result is z = 1; Why? && 0000 0010=T
– char x = 1; T
if(!x) { /* w i l l NOT execute since !x = !true = false */ }
• Bitwise Operators (&, |, ^, ~) ! 0000 0001=T
F
– Operate on the logical value of INDIVIDUAL bits ina variable
– char x = 1, y = 2, z = x & y; 0000 0001
• Result is z = 0; Why? & 0000 0010
– char x = 1; F = 0000 0000
if(~x) { /* w i l l execute since ~x = 0xfe = non-zero = true */ }
~ 0000 0001
T = 1111 1110
13

Using "good" syntax/style when performing logicoperations

FIDDLING WITH STYLE!


14

Code Read-ability Tip #1


• Try to replace hex and binary constants withshifted constants
#include<avr/io.h> #include<avr/io.h>

int main() int main()


{ {
// Init. D7 to output // Init. D7 to output This syntax tells us
DDRD |= 0x80; DDRD |= (1 << 7); we are putting a '1' in
bit 7 or bit 4…
// Enable pull-up on PD4 // Enable pull-up on PD4
PORTD |= 0x10; PORTD |= (1 << 4);

// Repeat forever // Repeat forever


while(1){ while(1){
// Is PD4 pressed? // Is PD4 pressed?
if( (PIND & 0x10) == 0){ if( (PIND & (1 << 4)) == 0){
// PD7 = 1 (LED on) // PD7 = 1 (LED on)
PORTD |= 0x80; PORTD |= (1 << 7);
} }
else { else { We will teach you
// PD7 = 0 (LED off) // PD7 = 0 (LED off) what all this meansin
PORTD &= ~(0x80); PORTD &= ~(1 << 7);
} } the next slides…
} }
// Never reached // Never reached
return 0; return 0;
} }
15

Shift Operations
• In C, operators '<<' and '>>' are the shift operators
<< = Left shift
>> = Right shift
• Format: data << bit_places_to_shift_by
• Bits shifted out and dropped on oneside
• Usually (but not always) 0’s are shifted in on the other side
x = x >> 2; x = x << 2;
Right Shift by 2 bits: Left Shift by 2 bits:
x 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 x
Original x Original x
0’s shifted in… 0’s shifted in…
0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0
x x
x Shifted by 2 bits x Shifted by 2 bits
16

Another Example
• To get a 1 in a particular bit location it is easier to
shift the constant 1 some number of places thantry
to think of the hex or binary constant
0x01
0 0 0 0 0 0 0 1 = +1

1 << 3 1 << 5
0’s shifted in… 0’s shifted in…
0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0
0x08 0x20
Suppose we want a 1 in bit Suppose we want a 1 in bit
location 3. Just take the value location 5. Shift 1 5 spots to
1 and shift it 3 spots to the left the left. Easier than coming
up with 0x20…
17

Putting it AllTogether
• Values for working with bits can be made using the ‘<<‘ shift operator
– OK: PORTB |= 0x20; Better: PORTB|= (1 <<5) ;
– OK: DDRD|= 0x04; Better: DDRD|= (1 <<2);
• This makes the code more readable and your intention easierto
understand…
• More examples
– Set DDRC,bit 5: DDRC|= (1 <<5)
– Invert PORTB,bit 2: PORTB^= (1 << 2)
? ? ? ? ? ? ? ? PORTD
– Clear PORTD,bit 3: PORTD&= (1 << 3) 0 0 0 0 1 0 0 0
&
• WRONG! Why?
0 0 0 0 ? 0 0 0
? ? ? ? ? ? ? ? PORTD
– Clear PORTD,bit 3: PORTD &= (0 <<3)
& 0 0 0 0 0 0 0 0
• WRONG! Why?
0 0 0 0 0 0 0 0

– Clear PORTD,bit 3: PORTD &= ~(1 <<3) ? ? ? ? ? ? ? ? PORTD

• RIGHT! Why? & 1 1 1 1 0 1 1 1


? ? ? ? 0 ? ? ?
18

Clearing Bits…A Common Mistake


• When using the ‘&=‘ operation to clear bits, remember to
invert the bits.
• This won’t work to clear 3 to ‘0’
– PORTD &= (1 <<3);
– is the sameas
– PORTD &= 0b0001000;
– which clears everything but bit 3
• Use the ‘~’ operator to complement the bits.
– PORTD &= ~(1 <<3);
– is the sameas
– PORTD &=0b11110111;
– and now 3 getscleared.
• And NEVER use a mask of all 0's
– PORTD&= (0 << 3); / / 0 shifted by any amount is 0 in all bit places
19

Setting/Clearing Multiple bits


• Can combine multiple bits into one definedvalue
– PORTB|= ((1 << 3) | (1 << 4) | (1 << 5));
– is the same as PORTB |= 0b00111000

– PORTB&= ~ ((1 << 3) | (1 << 4) | (1 << 5));


– is the same as PORTB &= 0b11000111;

1 << PB3 00001000


1 << PB4 00010000
1 << PB5 | 00100000
00111000
20

ARDUINO BOARD INTRO


21

Arduino Uno
• The Arduino Uno is a Printed circuit (PC) board with
processor and other circuits for
microcomputer development programming the system and
interfacing other devices
board based on the Atmel
ATmega328P 8-bit processor.
• Most microcomputer
manufacturers (Atmel,
Freescale, etc.) produce small
PCboards with their chips on
them for engineers to
experiment with and http://arduino.cc/en/Main/ArduinoBoardUno
hopefully generate sales of
Atmega328P 8-bit
the product. processor
22

Arduino Uno
• Arduino
– An Italian company
– They make numerous boards with different processors
– Hardware and software are open source.
– Very popular with hobbyists, due in a large part to their low cost.

http://arduino.cc/en/Main/Products
23

Arduino Uno
• What’s on an Arduino Uno board?
Connectors for I/O lines D0 – D13

Reset button

USB interface

16MHz oscillator Atmel ATmega328P


(i.e. clock signal microcontroller
generator)

Power connector
(for use when not
connected to USB) Power and I/O lines A0 –A5
ground pins
24

Arduino Uno
• Arduino Unos can be stacked with "shield"
boards to add additional capabilities (Ethernet,
wireless, D/A, LCDs, sensors, motor control,etc.)
25

Controlling the pins of the Arduino to be digital inputs and outputs

ARDUINO DIGITAL I/O


26

Flashback to Week1
• Recall the computer interacts with any input or output (I/O)
device by simply doing reads/writes tothe memory locations
(often called registers) in the I/O interfaces…
• The Arduino has many of these I/O interfaces all connectedvia
the data bus
Processor Memory
0

3FF
A D C
Video
Interface 800
FE may 800 FE FE
signify a WRITE

white dot at
a particular 01
location
Keyboard
Interface

Data Bus connecting all components 400 61


27

Atmel ATmega328P
• The Arduino Uno is
based on an Atmel
Mem.
ATmega328P 8-bit
microcontroller Processor

– 32kb of FLASHROM
– 2048 bytes of RAM
– 23 I/O lines
– 3 timer/counters
– Serial/SPI/I2C interfaces
– A/D converter Data Bus
28

Arduino Digital I/O


• ATmega328P has 23 pins on the chip that can be
connected to other devices (switches, LEDs, motors, etc.)
– Other members of the ATmega family may have more or less
lines.
– The Arduino Uno can make use of only 20 of these lines.
• Each pin can be used as a digital input or a digital output
– For output pins: Your code determines what value ('1' or '0')
appears on the pin and can connect to another component
– For input pins: Your code senses/reads what value another
device is putting on the pin

Main Point: Individual pins on the Arduino can be used as inputs ORoutputs
29

Groups B, C and D
• The Arduino provides around 20
separate digital input/output bits that
we can use to interface to external
devices
• Recall computers don't access individual
bits but instead the byte (8-bits) is the

Group D Group B
smallest unit of access
• Thus to deal with our digital inputs we

Group C
will put the bits into 3 groups: Group B,
C, and D
– We often refer to these groups as"ports"
but you'll see that "port"is used in multiple
Software to Arduino Name Mapping
places so we'll generally use "group" Group B bit5-bit0 = DIG13-DIG8
Group C bit5-bit0 = A5-A0
Group D bit7-bit0 = DIG7-DIG0
30

Arduino Port/Pin Mapping


• Since computers usually deal with groups of 8-bits (a.k.a. a byte),all
of the 20 I/O pins are split into three 8-bit I/O groups (B, Cand D)
– The avr-gcc software (SW) and the Arduino hardware use different namesto
refer to the bits within each port
SW Arduino SW Arduino SW Arduino
PortB, bit0 DIG8 PortC, bit0 AN0 PortD, bit0 DIG0
PortB, bit1 DIG9 PortC, bit1 AN1 PortD, bit1 DIG1
PortB, bit2 DIG10 PortC, bit2 AN2 PortD, bit2 DIG2
PortB, bit3 DIG11 PortC, bit3 AN3 PortD, bit3 DIG3
PortB, bit4 DIG12 PortC, bit4 AN4 PortD, bit4 DIG4
PortB, bit5 DIG13 PortC, bit5 AN5 PortD, bit5 DIG5
PortB, bit6 Clock1 PortC, bit6 Reset PortD, bit6 DIG6
(don't use) (don't use)
Clock2
PortB, bit7
(don't use)
PortD, bit7 DIG7

Main Point: Each pin has a name the software uses (Portx) and a name used on the Arduino circuit board (Anx or DIGx)
31

Using Ports to Interface to HW


• The I/O ports (i.e. groups of pins) are the Code Data
middle men between your software program
and the physical devices connected to the
chip.
• Your program is responsible for managing
these ports (groups ofI/O pins) in order to
make things happen on the outside
#include <avr/io.h>
int main()
{
// check input Group C
// bit 0 value

// set output Group B


// bit 2 to Logic 1=5V
Arduino D10 ó
// ... GroupB bit 2
}

Logic 1 = 5V An LED Groups/


Logic 0 = 0V PORTs

A button
Arduino A0 ó GroupC bit 0
32

Overview
• In the next few slides you will learn
– What your software needs to do to setup
#include <avr/io.h>
the pins for use as digital inputs and/or int main()
{
outputs // check input Group C
// bit 0 value

– Toset bits (to 1) and clear bits (to0) using // set output Group B
// bit 2 to Logic 1=5V
bitwise operations (AND, OR, NOT) to // ...
control individual I/O pins }

– How to do it in a readable syntax using shift What is the actual code


we would write to
operators (<<, >>) accomplish these
tasks?
• Don't be worried if it doesn't make We'll answer that
sense the first time…listen, try to make through the next few
slides.
sense of it, and ask a lot of questions.
33

Controlling I/O Groups/Ports


• Each group (B, C, and D) has 3 registers in the µC associated with it
that control the operation
– Each bit in the register controls something about the corresponding I/O bit.
– Data Direction Register (DDRB, DDRC,DDRD)
– Port Output Register (PORTB, PORTC,PORTD)
– Port Input Register (PINB, PINC,PIND)
• You'll write a program that sets these bitsto What you store in the register
bits below affect how the pins
1's or 0's asnecessary on the chip operates
DDRD DDRB
DDRD7 DDRD6 DDRD5 DDRD4 DDRD3 DDRD2 DDRD1 DDRD0 DDRB5 DDRB4 DDRB3 DDRB2 DDRB1 DDRB0

PORTD PORTB
PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT
D7 D6 D5 D4 D3 D2 D1 D0 B5 B4 B3 D2 D1 D0

PIND PINB
PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0 PINB5 PINB4 PINB3 PIND2 PIND1 PIND0
34

Register 1: Data Direction Register


• DDRx (Data direction register) [x=B,C,D…DDRB, DDRC, DDRD]
– Controls whether pins on the chip act as inputs or outputs.
– Example: If DDRB5 = 0 -> Group B bit 5 = DIG13 pin) will be used as aninput
– Example: If DDRB5 = 1 -> Group B bit 5) will be used as an output
– All I/O lines start out as inputs when the µC is reset orpowered up.
DDRD DDRB
DDRD7 DDRD6 DDRD5 DDRD4 DDRD3 DDRD2 DDDR1 DDRD0 DDRB5 DDRB4 DDRB3 DDRB2 DDRB1 DDRB0
0 0 0 0 1 1 1 1 1 0 0 0 0 0

PD[7:4] = INPUT PD[3:0] = OUTPUT PB[5] = OUTPUT PB[4:0] = INPUT


Notation: [7:4] means bit7-bit4 Consider a leaf BLOWER / VACCUM.
and is shorthand, not C code. There must be a switch to select if you
want it to blow (output) or produce
Don't use it in your programs. suction (input)…DDR register is that
"switch"

http://www.toro.com/en-
us/homeowner/yard-
PD[7:4] PD[3:0] PB[5] tools/blowers-
vacs/pages/series.aspx?sid
=gasblowervacsseries
35

Register 2: PORT (Pin-Output) Register


• PORTxn (Primarily used if group x, bit n is configured as anoutput)
– When a pin is used as an output (DDRxn = 1), the corresponding bit in PORTxn
determines the value/voltage of thatpin.
– E.g. By placing a '1' in PORTB5, pin 5 of group B will output a highvoltage
DDRD DDRB
DDRD7 DDRD6 DDRD5 DDRD4 DDRD3 DDRD2 DDRD1 DDRD0 DDRB5 DDRB4 DDRB3 DDRB2 DDRB1 DDRB0
0 0 0 0 1 1 1 1 1 0 0 0 0 0

PORTD PORTB
PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0 PORTB5 PORTB4 PORTB3 PORTB2 PORTB1 PORTB0
1 1 0 0 1 0 0 1 0 0 0 0 1 0

PD[7:4] PD[3:0] PB[5]


1001 0

Main Point: For pins configured as outputs, the values you put in the PORT register will be the outputvoltages
36

Register 3: PIN (Pin-Input) Register


• PINxn (Used if the group x, bit n is configured as aninput)
– When a bit is an input (DDRxn=0), reading bit n from the register PINx
reflects the current value at the corresponding input pin
• The program doesn’t have to do anything special to read the
digital signals into the PIN register, just use the registername
– if(PIND == 0x00) / / check if all the signals coming into port D are 0's
– char val = PINB; / / read and save all 8 signals coming into port B in
a variable 'val'.
– Referencing PINx produces a snapshot (at the instant the line of code is
execute) of the bit values coming in those 8 pins; it does not constantly
monitor the input bits
• Programs must read the full eight bits in the PIN register, but can
then use bitwise logical operations to check individualbits
Main Point: For pins configured as inputs, referencing the PINx register samples the input voltages at all the pins
37

Review of Accessing Control Registers in C


• Control registers have names and act just like variables in a C
program
• Toput values into a control register you can assign to themlike
any C variable or perform bitwiseoperations
– DDRD= 0xff; / / 0b11111111 or 255
– DDRB= 255;
– PORTD|= 0xc0; / / 0b11000000 or 192
– PORTD |= 0b01110000;
• Toread the value of a control register you can write expressions
with them
– unsigned char myvar = PIND; / / grabs all 8-inputs on the port D
– myvar = PINB & 0x0f; / / grabs the lower 4 inputs
38

Practice: Changing Register Bits


DDRB ? ? ? ? ? ? ? ?
• Use your knowledge of the bitwise |
operations to change the values of
individual bits in registers without
affecting the other bits in the register. PORTC ? ? ? ? ? ? ? ?

– Set DDRB, bit 3 to a '1' &


DDRB|= 0b00001000; / / DDRB|= 0x08;
– Clear the 2 upper bits in PORTCto ‘0’s DDRC ? ? ? ? ? ? ? ?
PORTC &= 0x3f;
/ / PORTC &= ~(0b11000000) ^

– Flip bits 7 and 1 in DDRC


DDRC^= 0b10000010; / / DDRC^= 0x82; PIND ? ? ? ? ? ? ? ?
– Check if PIND, bit 4 ='1' &
if (PIND & 0x10) { code }
39
40

EXAMPLES
41

LED Outputs Review


• Recall we can connect LEDsto the outputs of a digital signal
– The digital output value that will turn the LEDon varies based on howwe wire
the LED
• Be sure to use a current-limiting resistor (few hundred ohms
~200-500 ohms)
Can be
Option 1 Option 2
discrete
gate or
Arduino
output pin

Can be
discrete
LED is on when LED is on when gate or
gate outputs '1' gate outputs '0' Arduino
output pin
42

Switch & Button Input Review


• Recall: Switches/buttons alone do not produce 1's and 0's; they
must be connected to voltagesources
• Preferred connection:
– Connect one side of switch to GND(ground)
– Connect other side of switch to digital input AND to a pull-up resistor
(around 10Kohms) whose other side is connected to Vdd
• Switch/button will producea:
– 0 when pressed
– 1 when open (not-pressed)
Vdd
Rp
Arduino
SW input model

Vin R ≈ inf.

Preferred: Use a pullup resistor


Main Point: Buttons & switches should have GND connected to one side & a pull-up resistor on the other
43

Blinking an LED
• Hardware and software to make an LEDconnected to D7blink
#include<avr/io.h> DDRD
#include<util/delay.h>

int main() ? ? ? ? ? ? ? ?
{
// Init. D7 to output |
DDRD |= 0x80;

// Repeat forever 1 ? ? ? ? ? ? ?
while(1){
// PD7 = 1 (LED on)
PORTD |= 0x80;
PORTD
_delay_ms(500);
? ? ? ? ? ? ? ?
// PD7 = 0 (LED off)
PORTD &= ~(0x80);
_delay_ms(500);
|
}
// Never reached 1 ? ? ? ? ? ? ?
return 0;
}
&

0 ? ? ? ? ? ? ?
44

Turning an LED on/off with PB


• Hardware to turn an LEDconnected to D7 on/off when pressinga
pushbutton connected to D4

Vdd Vdd

PB Arduino + V -
PD4 PD7

LED

GND
45

Turning on an LED from aButton


• Note: When the button is pressed a '0' is produced at thePD4 input
DDRD
#include<avr/io.h> (starts at 0's on reset)
int main()
{ 0 0 0 0 0 0 0 0
// Init. D7 to output
DDRD |= 0x80; |
// All pins start as input
// on reset, so no need to
// clear DDRD bit 4 1 ? ? 0 ? ? ? ?
// Repeat forever
while(1){ PIND
// Is PD4 pressed?
if( (PIND & 0x10) == 0){ ? ? ? ? ? ? ? ?
// PD7 = 1 (LED on)
PORTD |= 0x80;
} &
else {
// PD7 = 0 (LED off) ? ? ? ? ? ? ? ?
PORTD &= ~(0x80);
}
}
// Never reached
return 0;
}
46

Pull Up Resistors
• Adding and wiring pull-up resistors for input buttons can be time
consuming…
• Thankfully, each Arduino input bit has an optional internal“pull-
up resistor” associated with it.
– If the pull-up is enabled, in the absence of an input signal, the input bit
will be “pulled” up toa logical one.
– The pull-up has no effect on the input if an active signal is attached.
This pull-up resistor can be
built separately on your
circuit board ORthere is one
on each pin of the Arduino
that can be enabled

Arduino
Arduino Arduino

1) Built Separately 2) Enabled in the Arduino


47

Enabling Pull Up Resistors


• When DDRxbit n is '0' (i.e. a pin is used as input), the value in the PORTxbit n
registers determines whether the internal pull-up isenabled
– Remember, the PORT register is normally used when a pin is an output, but hereits value
helps enable the internal pull-upresistor

A pin being used as an input


DDRD (DDR bits = 0) whose
DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0
corresponding PORT bit = 1 will
0 0 0 0 1 1 1 1 enable the pull up resistors on the
Inputs Outputs PIN bit

PORTD
PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0
1 1 1 1 0 0 1 1
Enable Pull-Up Resistors Actual output values from PD3-0

PIND
PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0
0 1 1 0 ? ? ? ? PD[7:4] PD[3:0]
Made-up values read from the push- (connected
buttons (which don't require you to to buttons)
0011
wire up external pull-up resistors)
48

Using Internal Pull-up Resistors


• Let's simplify our wiring and use theinternal pull-up resistors

Arduino
Arduino
Arduino
Enabled in the Arduino
Built Separately
49

Turning on an LED from aButton


• Note: When the button is pressed a '0' is produced at thePD4 input
DDRD
#include<avr/io.h>
(starts at 0's on reset)
int main()
{ 0 0 0 0 0 0 0 0
// Init. D7 to output
DDRD |= 0x80;
|
// Enable pull-up on PD4
PORTD |= 0x10; 1 ? ? 0 ? ? ? ?
// Repeat forever
while(1){ PORTD
// Is PD4 pressed?
if( (PIND & 0x10) == 0){ ? ? ? ? ? ? ? ?
// PD7 = 1 (LED on)
PORTD |= 0x80;
} |
else {
// PD7 = 0 (LED off)
PORTD &= ~(0x80);
0 0 0 1 0 0 0 0
}
}
// Never reached
return 0;
}
50

DEBOUNCING SWITCHES
51

Counting Presses
• Consider trying to build a systemthat #include<avr/io.h>
counted button presses on PC2 int main()
{

(increment once per button press) PORTC |= (1 << PC2);


int cnt = 0;
while(1){
• We can write code to check if the char pressed = (PINC & 0x04);
if( pressed == 0 ){
button is pressed (==0) and then cnt++;
}
increment 'cnt' }
return 0;
• But remember, your codeexecutes }

extremely fast…what will happen?

PC2
Arduino
PC2
cnt 0 0 1 2 3 3
52

Waiting Through a Press


• Consider trying to build a systemthat #include<avr/io.h>
counted button presses on PC2 int main()
{

(increment once per button press) PORTC |= (1 << PC2);


int cnt = 0;
while(1){
• We can write code to check if the char pressed = (PINC & 0x04);
if( pressed == 0 ){
button is pressed (==0) and then while( (PINC & 0x04) == 0 )
{}
increment 'cnt' cnt++;
}
• But remember, your codeexecutes }
return 0;
extremely fast…what will happen? }

if if if while while while if

PC2
Arduino
PC2
cnt 0 0 0 0 0 1 1
53

Interfacing Mechanical Switches/Buttons


• Mechanical switches and buttons do not make solid,steady
contact immediately after beingpressed/changed
• For a short (few ms) time, “bouncing” will ensue and can
cause spurious SWoperation (one press of a button may look
like multiple presses)
• Need to “debounce” switches withyour software
– Usually waiting around 5 ms from the first detection of a press will get
you past the bouncing and into the stable period

Stable Bouncing Stable Bouncing Stable

Arduino
Button Button
Press Release
54

Waiting Through a Press


#include<avr/io.h>
int main()
• Consider trying to build a systemthat {
PORTC |= (1 << PC2);
counted button presses on PC2 int cnt = 0;
while(1){
(increment once per button press) char pressed = (PINC & 0x04);
if( pressed == 0 ){
_delay_ms(5);
• We can write code to check if the while( (PINC & 0x04) == 0 )
{}
button is pressed (==0) and then _delay_ms(5);
cnt++;
increment 'cnt' }
}
• But remember, your codeexecutes }
return 0;

extremely fast…what will happen?

if if if while while while if


bouncing

bouncing
PC2
Arduino
PC2
cnt 0 0 0 0 0 1 1
55

What's Your Function


#include<avr/io.h>
• Because there is a fair amount of
char pc2Pressed()
work to do just torecognize a button {
char pressed = (PINC & 0x04);
press, you may want to extractthose if( pressed == 0 ){
_delay_ms(5);
to functions you can call over and while( (PINC & 0x04) == 0 ) { }
_delay_ms(5);
over again return 1;
}
else
return 0;
}
int main()
{
PORTC |= (1 << PC2);
int cnt = 0;
while(1){
if( pc2Pressed() )
cnt++;
}
return 0;
}
56

SUMMARY AND EXERCISES


57

Exercise 1
• We want to use Group C(Port C) bit 5 as an
output. Show how you should initialize your
program then write a statement to turn the
output 'ON' to 5V.
58

Exercise 2
• Now turn write a statement to turn that
same output ‘OFF’ (i.e. to output 0V)
59

Exercise 3
• We want to use Group B(Port B) bit 3 as an input connected
to a switch. You have no separate resistors available to you.
Show how you should initialize your program and then write
an if statement to checkif the input voltage isHIGH (5V).
60

Common Mistakes
// Clearing a bit to 0

• Don't make these mistakes


// Wrong
PORTD &= (0 << 3);
PORTD |= (0 << 3);

• Instead remember: // Right


PORTD &= ~(1 << 3);

– Never shift a 0 when trying to // Checking a bit


do an AND or OR (e.g. 0 <<x) // Wrong
if(PIND & (1 << 3) == 0)

– Correctly parenthesize your // Right


if( (PIND & (1 << 3)) == 0)

comparisons // Checking if a bit is 1


// Checking if a bit is 1
– To check if a bit is 1, check if // Wrong
if( (PIND & (1 << 3)) == 1)

the result of the ANDing is // Right


if( (PIND & (1 << 3)) != 0)
not-equal to 0
61

Summary – Cheat Sheet


• Refer to the cheatsheet
DigitalI/O 16-bit Timer and Pulse Width Modulation (PWM)
7 6 5 4 3 2 1 0
PORTB/ PINB PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 COM1A1COM1A0COM1B1 COM1B0 WGM11 WGM10
TCCR1A
(output / input)
7 6 5 4 3 2 1 0
PORTC/ PINC PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0 WGM13 WGM12 CS12 CS11 CS10
TCCR1B
(output / input)

in your lecture notes


7 6 5 4 3 2 1 0
PORTD/ PIND PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0 OCIE1B OCIE1A
TIMSK1
(output / input)
15 14 13 12 11 10 9 8
DDRB/ DDRC/ DDB7 DDB6 DDB5 DDB4 DDB3 DDB2 DDB1 DDB0 OCR1A
DDRD DDC7 DDC6 DDC5 DDC4 DDC3 DDC2 DDC1 DDC0 (16-bitvalue) 7 6 5 4 3 2 1 0
DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0 Timer MAX
SetPinas SetPinas or PWM
Output DDRB |= (1 << DDB4); DDRB &= ~(1 << DDB4); 15 14 13 12 11 10 9 8
Input
Set Output Check Pin OCR1B

• Below are the methods to


PORTB |= (1 << PB4); (PINB & (1 << PB4)) != 0 (16-bit value) 7 6 5 4 3 2 1 0
Value to1 is1
PWM
Clear Output PORTB &= ~(1 << PB4);
Check Pin (PINB & (1 << PB4)) == 0 15 14 13 12 11 10 9 8
Value to 0 is0
TCNT1
Analog to Digital Conversion 7 6 5 4 3 2 1 0
(16-bit current
countvalue)
7 6 5 4 3 2 1 0
REFS1 REFS0 ADLAR unused MUX3 MUX2 MUX1 MUX0
ADMUX 8-bit Timers and Pulse Width Modulation (PWM)

accomplish the 6 basic


7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
TCCR0A COM0A1 COM0A0 COM0B1 COM0B0 WGM01 WGM00
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0 WGM21 WGM20
ADCSRA TCCR2A COM2A1 COM2A0 COM2B1 COM2B0

7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
TCCR0B WGM03 WGM02 CS02 CS01 CS00
ADCH WGM23 WGM22 CS22 CS21 CS20
TCCR2B
(8-bit ADCres.)
7 6 5 4 3 2 1 0

I/O tasks
15 14 13 12 11 10 9 8 TIMSK0 OCIE0B OCIE0A
OCIE2B OCIE2A
ADC
0 0 0 0 0 0 TIMSK2
7 6 5 4 3 2 1 0
(10-bit ADCres./ OCR0A/ OCR2A
7 6 5 4 3 2 1 0
16-bit value)
(8-bitvalue)
TimerMAXor PWM
After ADCSRA |= (1 << ADSC); 7 6 5 4 3 2 1 0
initialization, while( (ADCSRA & (1 << ADSC)) != 0 ) { } OCR0B/ OCR2B
start,poll, unsigned char result = ADCH; (8-bit value)for PWM
capture // if 10-bit result (ADLAR = 0) use this
7 6 5 4 3 2 1 0
// unsigned int result = ADC; TCNT0 / TCNT2

– Memorize these, practice


result
(8-bit current count
Serial (UART / RS-232)Comm. value)

7 6 5 4 3 2 1 0
Pin Change Interrupts
RXC0 UDRE0
UCSR0A
PCICR PCIE2 PCIE1 PCIE0
7 6 5 4 3 2 1 0 (D) (C) (B)
Int. Enables

these, recite these!!!


RXEN0 TXEN0
UCSR0B
PCMSK0 PCINT7 PCINT6 PCINT5 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0
7 6 5 4 3 2 1 0 (PB7) (PB6) (PB5) (PB4) (PB3) (PB2) (PB1) (PB0)
(forPortB)
UCSZ01 UCSZ00
UCSR0C
PCMSK1 PCINT14 PCINT13 PCINT12 PCINT11 PCINT10 PCINT9 PCINT8
(PC6) (PC5) (PC4) (PC3) (PC2) (PC1) (PC0)
7 6 5 4 3 2 1 0 (forPortC)
UDR0
(RX& TXData) PCMSK2 PCINT23 PCINT22 PCINT21 PCINT20 PCINT19 PCINT18 PCINT17 PCINT16
(PD7) (PD6) (PD5) (PD4) (PD3) (PD2) (PD1) (PD0)
15 14 13 12 11 10 9 8 (forPortD)
0 0 0 0
UBRR0 7 6 5 4 3 2 1 0
Helpful C-Library Functions

Set Pinas Set Pinas


(Baud Rate)

DDRB |= (1 << DDB4); DDRB &= ~(1 << DDB4);


snprintf(char* buf, i nt max, char* frmt, . . . ) ;
<stdio.h>
Output Input <avr/io.h>
Helpful Arduino Library Functions
All register and bit position
Example:
char buf[9]; // Val= max 4-digits + null
int val;
definitions // val set to some integer
SetOutput CheckPin <util/delay.h> _delay_ms(10); // delay 10 milli(m)-sec snprintf(buf, 5, Val=%d val);

PORTB |= (1 << PB4); (PINB & (1 << PB4)) != 0


_delay_us(10); // delay 10 micro(u)-sec // to ensure fixed space (num. digits) for val
snprintf(buf, 5, Val=%4d val);
Value to 1 is1 <avr/interrupt.h>
sei(); // turn on global interrupt enable
cli(); // turn off global interrupt enable

Clear Output CheckPin


PORTB &= ~(1 << PB4); (PINB & (1 << PB4)) == 0
Value to 0 is0

You might also like