Arduino Esplora
ATMega32u4
ISP programming
The bootloader is basically a .hex file that runs when you turn on the board. It is very similar to
the BIOS that runs on your PC. It does two things. First, it looks around to see if the computer
is trying to program it. If it is, it grabs the program from the computer and uploads it into the ICs
memory (in a specific location so as not to overwrite the bootloader). That is why when you try
to upload code, the Arduino IDE resets the chip. This basically turns the IC off and back on
again so the bootloader can start running again. If the computer isn’t trying to upload code, it
tells the chip to run the code that’s already stored in memory. Once it locates and runs your
program, the Arduino continuously loops through the program and does so as long as the board
has power.
Bootloader programming
Arduino Esplora board
Low power crystal oscillator crystal
External oscillator
Low frequency crystal oscillator
Used for real time clock
Default Clock Source
The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8
programmed, resulting in 1.0MHz system clock. The startup time is set to maximum
and time-out period enabled. (CKSEL = "0010", SUT = "10", CKDIV8 = "0"). The
default setting ensures that all users can make their desired clock source setting using
any available programming interface.
Other clock sources
Clock systems
Diodes
External switch
Digital devices
Analog devices – example
Switches and multiplexer
Bitwise operators:
& AND
| OR
~ NOT
<< SHIFT LEFT
>> SHIFT RIGHT
^ EXCLUSIVE OR
Example: Bitwise AND
PORTD = 0b???????? Number= 0b11111011
???????? unknown bits & 11111011
= ?????0?? result: one bit cleared
Example: Bitwise OR
PORTD = 0b????????
Number= 0b00000100
???????? unknown bits | 00000100
= ?????1?? result: one bit set
Bitwise operators:
& AND
| OR
~ NOT
<< SHIFT LEFT
>> SHIFT RIGHT
^ EXCLUSIVE OR
Example: Bitwise NOT
PORTD = 0b10101010
~PORTD = 0b01010101
Example: Bitwise SHIFT
PORTD = 0b10101010
PORTD<<1 = 0b01010100
Example: Exclusive OR
PORTD = 0b10101010
Number = 0b110011 00
0b10101010 ^ 0b11001100 = 0b01100110
Hex numbers: 0b00000001 = 0x01 ~0x01 = 0xfe 0b00000010 = 0x02 ~0x02 = 0xfd 0b00000100 = 0x04 ~0x04 = 0xfb 0b00001000 = 0x08 0b00001100 = 0x0C 0b11110001 = 0xF1 0b10001000 = 0x88 Makro _BV(x): _BV(0) = 0b00000001 ~_BV(0) = 0b11111110 _BV(1) = 0b00000010 ~_BV(0) = 0b11111101 _BV(2) = 0b00000100 ~_BV(0) = 0b11111011 _BV(3) = 0b00001000 ~_BV(0) = 0b11110111 _BV(4) = 0b00010000 ~_BV(0) = 0b11101111 _BV(5) = 0b00100000 ~_BV(0) = 0b11011111 _BV(6) = 0b01000000 ~_BV(0) = 0b10111111 _BV(7) = 0b10000000 ~_BV(0) = 0b01111111
Shifted numbers _BV(0) = 0b00000001 = (1<<0) ~ (1<<0) = 0b11111110 _BV(1) = 0b00000010 = (1<<1) ~ (1<<1) = 0b11111101 _BV(2) = 0b00000100 = (1<<2) ~ (1<<2) = 0b11111011 _BV(3) = 0b00001000 = (1<<3) ~ (1<<3) = 0b11110111 _BV(4) = 0b00010000 = (1<<4) ~ (1<<4) = 0b11101111 _BV(5) = 0b00100000 = (1<<5) ~ (1<<5) = 0b11011111 _BV(6) = 0b01000000 = (1<<6) ~ (1<<6) = 0b10111111 _BV(7) = 0b10000000 = (1<<7) ~ (1<<7) = 0b01111111 (1<<0) = (1<<PORTD0) (1<<1) = (1<<PORTD1) (1<<2) = (1<<PORTD2) (1<<3) = (1<<PORTD3) (1<<4) = (1<<PORTD4) (1<<5) = (1<<PORTD5) (1<<6) = (1<<PORTD6) (1<<7) = (1<<PORTD7)
General purpose input/output schematic
Input from pin
Pullup transistor
Output to pin
Port D registers
Pin 2 as input internally pulled up
pin 2 = PORTD, 2 (Uno)
DDRD = DDRD & 0xFB; (input) pinMode(2, INPUT_PULLUP);
PORTD = PORTD | 0x04; (pullup)
Pin 2 as input floating (high Z)
pin 2 = PORTD, 2 (Uno)
DDRD = DDRD & 0xFB; (input) pinMode(2, INPUT);
PORTD = PORTD & 0xFB; (floating)
Pin 13 as output
pin 13 = PORTB, 5 (Uno)
DDRB = DDRB | 0x20; pinMode(13, OUTPUT);
PORTB = PORTB | 0x20; digitalWrite(13, HIGH);
PORTB = PORTB & 0xDF; digitalWrite(13, LOW);
Using Arduino library Using PORT names
Pin 2 as input internally pulled up
pin 2 = PORTD, 2 (Uno)
DDRD = DDRD & ~ _BV(2); (input) pinMode(2, INPUT_PULLUP);
PORTD = PORTD | _BV(2) ; (pullup)
Pin 2 as input floating (high Z)
pin 2 = PORTD, 2 (Uno)
DDRD = DDRD & ~ _BV(2); (input) pinMode(2, INPUT);
PORTD = PORTD & ~ _BV(2); (floating)
Pin 13 as output
pin 13 = PORTB, 5 (Uno)
DDRB = DDRB | _BV(5); pinMode(13, OUTPUT);
PORTB = PORTB | _BV(5); digitalWrite(13, HIGH);
PORTB = PORTB & ~ _BV(5); digitalWrite(13, LOW);
Using Arduino library Using PORT names
Pin 2 as input internally pulled up
pin 2 = PORTD, 2 (Uno)
DDRD = DDRD & ~ (1<<DDD2); (input) pinMode(2, INPUT_PULLUP);
PORTD = PORTD | (1<<PORTD2); (pullup)
Pin 2 as input floating (high Z)
pin 2 = PORTD, 2 (Uno)
DDRD = DDRD & ~ (1<<DDD2); (input) pinMode(2, INPUT);
PORTD = PORTD & ~ (1<<PORTD2); (floating)
Pin 13 as output
pin 13 = PORTB, 5 (Uno)
DDRB = DDRB | (1<<DDD5); pinMode(13, OUTPUT);
PORTB = PORTB | (1<<PORTD5); digitalWrite(13, HIGH);
PORTB = PORTB & ~ (1<<PORTD5)); digitalWrite(13, LOW);
Using Arduino library Using PORT names
Cod in AtmelStudio: Cod in Arduino
int main(void)
{
setup(); setup();
while (1) loop(); loop();
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup (void)
{
// the setup function runs once when you press reset or power the board
//funkcja setup jest wykonywana 1x po resecie lub podaniu zasilania
}
void loop(void)
{
// the loop function runs over and over again forever
//funkcja loop() jest wykonywana w kółko w nieskończonej pętli
}
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delay(1000); // wait for a second
digitalWrite(13, LOW);
delay(1000);
}
void setup()
{
DDRB = DDRB | 0x20;
}
void loop()
{
PORTB = PORTB | 0x20;
delay(1000); // wait for a second
PORTB = PORTB & 0xDF;
delay(1000);
}
Example: blinking LED
Using Arduino library Using PORT names (Uno)
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
Example: serial monitor
Serial monitor is an application on PC connected to USART via USB
Serial.write(33);
− Serial.write(33) gives „!"
Serial.print(33);
– Serial.print(33) gives „33"
– Serial.print(1.23456) gives "1.23"
– Serial.print('N') gives "N"
– Serial.print("Hello world.") gives "Hello world."
– Serial.print(78, BIN) gives "1001110"
– Serial.print(78, OCT) gives "116"
– Serial.print(78, DEC) gives "78"
– Serial.print(78, HEX) gives "4E"
– Serial.println(1.23456, 0) gives "1"
– Serial.println(1.23456, 2) gives "1.23"
– Serial.println(1.23456, 4) gives "1.2346"
void setup() {
Serial.begin(9600);
}
int thisByte = 33;
void loop() {
Serial.write(thisByte);
Serial.print(", dec: ");
Serial.print(thisByte);
Serial.print(", hex: ");
Serial.print(thisByte, HEX);
Serial.print(", oct: ");
Serial.print(thisByte, OCT);
Serial.print(", bin: ");
Serial.println(thisByte, BIN);
if (thisByte == 126)
{
thisByte = 33;
}
// go on to the next character
thisByte++;
}
const int buttonPin = 3; // PORTD0 const int ledPin = 13; // PORTC7 int buttonState = 0; // variable void setup() { pinMode(ledPin, OUTPUT); // initialize the LED pin as an output: pinMode(buttonPin, INPUT_PULLUP); // initialize the pushbutton pin as an input: } void loop() { buttonState = digitalRead(buttonPin); // read the state of the pushbutton value: if (buttonState == HIGH) // check if the pushbutton is pressed. { // turn LED on: digitalWrite(ledPin, HIGH); } else { // turn LED off: digitalWrite(ledPin, LOW); } }
Example: button (Esplora)
const int buttonPin = 3; // PORTD0 const int ledPin = 13; // PORTC7 int buttonState = 0; // variable void setup() { DDRC // initialize the LED pin as an output: DDRD // initialize the pushbutton pin as an input: PORTD //input pullup } void loop() { buttonState = PIND & (1<< buttonPin); // read the state of the pushbutton value: // buttonState = PIND & _BV(buttonPin); if (buttonState == HIGH) { // turn LED on: PORTC } else { // turn LED off: PORTC } }
Example: button (Esplora)
Interrupt vectors
#define ledPin 13
void setup() {
pinMode(ledpin, OUTPUT);}
void loop() {
digitalWrite(13, LOW);
}
ISR (INT0_vect)
{
digitalWrite(13, HIGH);
}
ISR (INT0_vect) example LOW level
Przerwania zewnętrzne INT0, INT1
INT0 PORTD0 linia nr 3 (Esplora)
INT1 PORTD1 linia nr 2 (Esplora)
Stan wysoki na linii jest stanem bezczynnym (IDLE state). Przerwanie może być wywołane przez:
− LOW level (poziom niski),
− FALLING edge (zbocze opadające),
− RISING edge (zbocze narastające),
− CHANGE (każda zmiana).
#define ledPin 13
void setup() {
pinMode(ledpin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(3), blink, FALLING);
void loop() {}
void blink () {
int state = digitalRead(ledPin);
digitalWrite (ledPin, state^1); //toggle state
}
Przerwania zewnętrzne INT0, INT1
Funkcja biblioteczna attachinterrupt
attachInterrupt (digitalPinToInterrupt(pin), procedura przerwania, atrybut);
Pin: 3 lub 2 numery przerwania INT0, INT1
Procedura: wykonywana w przerwaniu tu: blink()
Atrybut:
− LOW (poziom niski),
− FALLING (zbocze opadające,
− RISING (zbocze narastające),
− CHANGE (każda zmiana).
Attachinterrupt example
Przewania zewnętrzne – wybór źródła przerwania
Przerwania zewnętrzne – maska przerwania
Stany nieustalone przycisku
Rejestr flagowy przerwań zewnętrznych
#define ledPin 13
#define buttonPin 3
void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(3), blink, CHANGE );
}
void loop() {}
void blink ()
{
_delay_ms(30);
if(digitalRead(buttonPin)==1)
{
int state = digitalRead(ledPin);
digitalWrite (ledPin, state^1);
}
_delay_ms(60);
EIFR=0;
}
Program, który radzi sobie ze stanami nieustalonymi przycisku
Przerwania zewnętrzne – przykład
ISR (INT0_vect)
{ PORTC |= _BV(7); //zapalenie diody
}
void setup()
{
DDRD &= ~_BV(0); //linia 0 portu D jako wejście
PORTD |= _BV(0); //podwieszenie wejścia
DDRC |= _BV(7); // linia 7 portu C jako wyjście
PORTC &= ~_BV(7); //wyjście low
EICRA =
EIMSK =
sei(); // Odblokowanie przerwań
}
void loop()
{
PORTC &= ~_BV(7); //zgaszenie diody
}
Przerwania zewnętrzne PCINT Przerwania zewnętrzne PCINT dostępne na pinach PCINT23 - PCINT0 są objęte 3-ma wektorami przerwań, po 8 linii na jeden wektor. W rejestrze PCICR leżą bity aktywacji grup przerwań: PCINT0-7 (bit PCIE0), PCINT8-14 (bit PCIE1), PCINT15-23 (bit PCIE2). W rejestrach PCMSK0, 1, 2 leżą maski indywidualne przerwań PCINT23-0. Przerwania PCINT23-0 są aktywowane każda zmianą na pinach wejściowych.
void setup() { DDRB |= 0x20; //output digitalWrite(13, LOW); //Pin Change Interrupt enable on PCINTx (Port x) PCICR |= _BV(PCIEx); PCMSKx |= _BV(PCINTx); sei(); } ISR(PCINTx_vect) { if (……..) digitalWrite(13, HIGH); } void loop() {}
Example: PCINT vectors