Arduino Esplora
ATMega32u4
ISP programming
Bootloader 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.
Arduino Esplora board
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 Low power crystal oscillator crystal External oscillator Low frequency crystal oscillator Used for real time clock
Clock systems
Digital devices Diodes External switch
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 0b00000010 = 0x02 0b00000100 = 0x04 0b00001000 = 0x08 0b00001100 = 0x0C 0b11110001 = 0xF1 0b10001000 = 0x88 ~0x01 = 0xfe ~0x02 = 0xfd ~0x04 = 0xfb Makro _BV(x): _BV(0) = 0b00000001 _BV(1) = 0b00000010 _BV(2) = 0b00000100 _BV(3) = 0b00001000 _BV(4) = 0b00010000 _BV(5) = 0b00100000 _BV(6) = 0b01000000 _BV(7) = 0b10000000 ~_BV(0) = 0b11111110 ~_BV(0) = 0b11111101 ~_BV(0) = 0b11111011 ~_BV(0) = 0b11110111 ~_BV(0) = 0b11101111 ~_BV(0) = 0b11011111 ~_BV(0) = 0b10111111 ~_BV(0) = 0b01111111
Shifted numbers _BV(0) = 0b00000001 = (1<<0) _BV(1) = 0b00000010 = (1<<1) _BV(2) = 0b00000100 = (1<<2) _BV(3) = 0b00001000 = (1<<3) _BV(4) = 0b00010000 = (1<<4) _BV(5) = 0b00100000 = (1<<5) _BV(6) = 0b01000000 = (1<<6) _BV(7) = 0b10000000 = (1<<7) ~ (1<<0) = 0b11111110 ~ (1<<1) = 0b11111101 ~ (1<<2) = 0b11111011 ~ (1<<3) = 0b11110111 ~ (1<<4) = 0b11101111 ~ (1<<5) = 0b11011111 ~ (1<<6) = 0b10111111 ~ (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 Pullup transistor Output to pin Input from pin
Port D registers
Using PORT names Using Arduino library 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; PORTB = PORTB 0x20; PORTB = PORTB & 0xDF; pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Using PORT names Using Arduino library Pin 2 as input internally pulled up pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ _BV(2); (input) PORTD = PORTD _BV(2) ; (pullup) pinmode(2, INPUT_PULLUP); Pin 2 as input floating (high Z) pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ _BV(2); (input) PORTD = PORTD & ~ _BV(2); (floating) pinmode(2, INPUT); Pin 13 as output pin 13 = PORTB, 5 (Uno) DDRB = DDRB _BV(5); PORTB = PORTB _BV(5); PORTB = PORTB & ~ _BV(5); pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Using PORT names Using Arduino library Pin 2 as input internally pulled up pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ (1<<DDD2); (input) PORTD = PORTD (1<<PORTD2); (pullup) pinmode(2, INPUT_PULLUP); Pin 2 as input floating (high Z) pin 2 = PORTD, 2 (Uno) DDRD = DDRD & ~ (1<<DDD2); (input) PORTD = PORTD & ~ (1<<PORTD2); (floating) pinmode(2, INPUT); Pin 13 as output pin 13 = PORTB, 5 (Uno) DDRB = DDRB (1<<DDD5); PORTB = PORTB (1<<PORTD5); PORTB = PORTB & ~ (1<<PORTD5)); pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Cod in AtmelStudio: int main(void) { setup(); while (1) loop(); return 0; Cod in Arduino setup(); loop(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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
Example: blinking LED Using Arduino library void setup() { pinmode(13, OUTPUT); void loop() { digitalwrite(13, HIGH); delay(1000); // wait for a second digitalwrite(13, LOW); delay(1000); Using PORT names (Uno) void setup() { DDRB = DDRB 0x20; void loop() { PORTB = PORTB 0x20; delay(1000); // wait for a second PORTB = PORTB & 0xDF; delay(1000);
Example: serial monitor Serial monitor is an application on PC connected to USART via USB 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);
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++;
Example: button (Esplora) const int buttonpin = 3; const int ledpin = 13; int buttonstate = 0; // PORTD0 // PORTC7 // 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) { // turn LED on: digitalwrite(ledpin, HIGH); else { // turn LED off: digitalwrite(ledpin, LOW); // check if the pushbutton is pressed.
Example: button (Esplora) const int buttonpin = 3; const int ledpin = 13; int buttonstate = 0; // PORTD0 // PORTC7 // 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
Interrupt vectors
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). ISR (INT0_vect) example LOW level #define ledpin 13 void setup() { pinmode(ledpin, OUTPUT); void loop() { digitalwrite(13, LOW); ISR (INT0_vect) { digitalwrite(13, HIGH);
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). #define ledpin 13 void setup() { pinmode(ledpin, OUTPUT); attachinterrupt(digitalpintointerrupt(3), blink, FALLING); void loop() { Attachinterrupt void blink () { int state = digitalread(ledpin); digitalwrite (ledpin, state^1); //toggle state example
Przewania zewnętrzne wybór źródła przerwania Przerwania zewnętrzne maska przerwania
Stany nieustalone przycisku Rejestr flagowy przerwań zewnętrznych
Program, który radzi sobie ze stanami nieustalonymi przycisku #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;
Przerwania zewnętrzne przykład ISR (INT0_vect) { PORTC = _BV(7); //zapalenie diody void setup() { DDRD &= ~_BV(0); PORTD = _BV(0); DDRC = _BV(7); PORTC &= ~_BV(7); EICRA = EIMSK = sei(); void loop() { PORTC &= ~_BV(7); //linia 0 portu D jako wejście //podwieszenie wejścia // linia 7 portu C jako wyjście //wyjście low // Odblokowanie przerwań //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.
Example: PCINT vectors 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() {