Sei sulla pagina 1di 9

Plug an LED (and resistor in series, say 470 ohms) between D9 and Gnd, and you will see

it toggle every
320 mS. (1/(16000000 / 1024) * 5000).

Table of pins -> pin change names / masks

D0 PCINT16 (PCMSK2 / PCIF2 / PCIE2)


D1 PCINT17 (PCMSK2 / PCIF2 / PCIE2)
D2 PCINT18 (PCMSK2 / PCIF2 / PCIE2)
D3 PCINT19 (PCMSK2 / PCIF2 / PCIE2)
D4 PCINT20 (PCMSK2 / PCIF2 / PCIE2)
D5 PCINT21 (PCMSK2 / PCIF2 / PCIE2)
D6 PCINT22 (PCMSK2 / PCIF2 / PCIE2)
D7 PCINT23 (PCMSK2 / PCIF2 / PCIE2)
D8 PCINT0 (PCMSK0 / PCIF0 / PCIE0)
D9 PCINT1 (PCMSK0 / PCIF0 / PCIE0)
D10 PCINT2 (PCMSK0 / PCIF0 / PCIE0)
D11 PCINT3 (PCMSK0 / PCIF0 / PCIE0)
D12 PCINT4 (PCMSK0 / PCIF0 / PCIE0)
D13 PCINT5 (PCMSK0 / PCIF0 / PCIE0)
A0 PCINT8 (PCMSK1 / PCIF1 / PCIE1)
A1 PCINT9 (PCMSK1 / PCIF1 / PCIE1)
A2 PCINT10 (PCMSK1 / PCIF1 / PCIE1)
A3 PCINT11 (PCMSK1 / PCIF1 / PCIE1)
A4 PCINT12 (PCMSK1 / PCIF1 / PCIE1)
A5 PCINT13 (PCMSK1 / PCIF1 / PCIE1)

ntreruperile externe Digital230 pot fi declanate i soft cu scrieri pe pini.

CCR1A
Bit 7 6 5 4 3 2 1 0 TCCR1A
080 COM1A1 COM1A0 COM1B1 COM1B0 - - WGM11 WGM10
ReadWrite RW RW RW RW R R RW RW
Initial Value 0 0 0 0 0 0 0 0

TCCR1B
Bit 7 6 5 4 3 2 1 0 TCCR1B
081 ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
ReadWrite R/W R/W R R/W R/W R/W R/W R/w
Initial Value 0 0 0 0 0 0 0 0

CS12 CS11 CS10 Description


0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clki/o/1 (No prescaling)
0 1 0 clki/o/8 (From Prescaler)
0 1 1 clki/o/64 (From Prescaler)
1 0 0 clki/o/256 (From Prescaler)
1 0 1 clki/o/1024 (From Prescaler)
1 1 0 External clock source on T1 pin. Clock on falling edge
1 1 1 External clock source on T1 pin. Clock on rising edge
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0;
// enable Timer1 overflow interrupt:
TIMSK1 = (1 << TOIE1);
// Set CS10 bit so timer runs at clock speed:
TCCR1B |= (1 << CS10);
// enable global interrupts:
sei();

TCNT1
The Timer Counter Something Timer is a register that is automatically increased or decreased. In other
words, it is the current value of the timer. Depending on the mode, it may count up until it reaches the
special value TOP and then roll over to 0; or it may count up until TOP and then back down to 0.
OCR1A
The Output Compare Register (Channel A) is the register whose value is compared to the current value of
TCNT1. Depending on the wave generation mode and the compare output mode, this may be used as the
threshold after which one of the physical output pins is set to HIGH. See COM and WGM.
TCCR1
The Timer Counter/Control Register has two parts: TCCR1A and TCCR1B. Depending on which bits are
set on this register, Timer 1 will behave differently. You can set the compare output mode (COM), the
wave generation mode (WGM), and select a clock (CS).
// Here's some sample code showing how to set various bits on the TCCR1
registers.
TCCR1A |= (1 << COM1A1) | (1 << COM1A0); // Set COM to 3
TCCR1A |= (1 << WGM11) | (0 << WGM10); // Set lower two bits of WGM to 2.
TCCR1B |= (1 << WGM13) | (1 << WGM12); // Set higher two bits of WGM to 8 +
4. Total WGM = 14.
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10); // CS = 2.
COM
I mentioned compare output mode. You can use these two bits to determine for what portions of TCNT's
cycle the OC1A pin is on. For example, when COM = 3, the OC1A pin is set to HIGH when TCNT1 is
greater than OCR1A.
WGM
Wave Generation Mode. This lets you choose between Non-PWM, PWM, and Fast-PWM modes; what
the value of TOP is; and more. This four bit number is made up of two bits in the TCCR1A register and
two bits in the TCCR1B register.
TOP
This is the MAX value of TCNT1. This can be a value between 0 and 0xFFFF because Timer 1 is a 16-bit
timer. An 8-bit timer would have a maximum value of TOP equal to 0xFF. Lower values of TOP mean a
higher frequency.
CS
The Clock Select lets you choose a "pre-scaler" for the timer. For example, CS = 2 means that the timer
operates at the speed of the CPU; CS = 3 means that the timer operates at FCPU/4; etc. This is another
way to vary the frequency of the pulse.
Below is a plot of TCNT1 values over time, as a function of the TCCR1 registers and the values of the
OCR1A and ICR1 registers. It will only display visualizations for Fast PWM modes. You can toggle the
values of various bits in the registers to see what they affect in the graph. The diagram will also generate
code for you.
COM1A1 COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
COM1A1 COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
TCCR1A 1 1 0 1
ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
TCCR1B 0 1 0 1 0
Clock Select 2
Wave Generation Mode 5
OCR1A 0x7f

TCCR1A |= (1 << COM1A1) | (1 << COM1A0) | (1 << WGM10);


TCCR1B |= (1 << WGM12) | (1 << CS11);
OCR1A = 127;
ICR1 = 100;

Timer1 are multe moduri de lucrui: pn la o tranziie MAX0, pn la o valoare prestabilit, intrare
analogic, PWM, generator de funcii.
Modul normal
Wgm13_0 = 0. Numr de la valoarea curent la maim, apoi cnd cade la 0, Timer/Counter Owerflow
Flag TOV1 devine 1.
Timer1, ncrcare cu o valoare, numr nainte pn la maxim 0 = ntr
void setup() {
TIMSK1 = 0x01; // activare intreruperi globale si timer overflow;
TCCR1A = 0x00; // mod normal de operare (mode0);
TCNT1 = 0x0BDC; // setarea valorii initiale pentru a elimina eroarea
(16bit counter register) Poate fi rescris oricnd
TCCR1B = 0x04; // start timer / set clock 1 0 0
}
La ntrerupere se apeleaz funcia
ISR(TIMER1_OVF_vect) {...
Timer1, ClearTimerOnCompareMatch CTC. Se numr pn la valoarea de comp din OCR
http://maxembedded.com/2011/07/14/avr-timers-ctc-mode/
Program care merge
// Intreruperi cu CTC, bun
#define myOutputPin 13
int toggle = 0;
void setup()
{
pinMode(myOutputPin, OUTPUT);
cli();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 5000;
TCCR1B |= (1 << WGM12); // Mod CTC
TCCR1B |= (1 << CS10); // prescalar = 1024
TCCR1B |= (1 << CS12);
TIMSK1 |= (1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(myOutputPin, toggle == 0 ? HIGH : LOW);
toggle = ~toggle;
}
void loop(){}

Nu neleg urmtorul registru, TIMSKx deoarece am verificat i pe normal, i pe MEGA i el are


biii descrii mai sus, nu ca mai jos!
The Timer/Counter Interrupt Mask Register TIMSK Register is as follows.

The Timer/Counter Interrupt Flag Register TIFR is as follows.

This bit is set to 1 whenever the timer overflows. It is cleared (to zero) automatically as soon as the
corresponding Interrupt Service Routine (ISR) is executed. Alternatively, if there is no ISR to execute, we
can clear it by writing 1 to it.

// set up 1 second interrupt on Timer/counter1


TCCR1A = 0;
TCCR1B = 1<<WGM13 | 1<<WGM12 | 1<<CS12 | 1<<CS10; // clock = F_CPU / 1024 = 15625 Hz
ICR1 = 15625;
bitSet(TIMSK1, ICIE1); // enable capture event interrupt
// set up ~240Hz interrupt on Timer/Counter2
TCCR2A = 0;
TCCR2B = 6; // select CK/256
bitSet(TIMSK2, TOIE2); // enable overflow interrupt

#include <avr/io.h>
02.#define F_CPU 1600000UL
03.#include <util/delay.h>
04.#include <avr/interrupt.h>
05./* method to initialise the timer*/
06.void timer_init()
07.{
08./*Set Timer/counter register with prescale value 1024 */
09.TCCR1B |= (1 << WGM12)|(1 << CS12)|(1 << CS10);
10./* Set Timer interrupt mask register*/
11.TIMSK |= (1 << OCIE1A);
12./* initialise timer counter value to 0*/
13.TCNT1 = 0;
14.}
15./* method to set time*/
16.void timer_set(int time)
17.{
18.int max;
19.max = (time/1000)*(16000000/1024)-1;
20./* assign the max value to the output compare register*/
21.OCR1A = max;
22./* Enable global interrupts*/
23.sei();
24.
25.}
26.
27./* method to flash an LED for every 1 minute*/
28.ISR(TIMER1_COMPA_vect )
29.{
30.counter++;
31.if(counter == 60){
32.DDRB = 0x01;
33.PORTB |= 0x01;
34._delay_ms(600);
35.PORTB &amp;= ~0x01;
36._delay_ms(600);
37.counter = 0;
38.}
39.
40.}
41./*main method*/
42.int main()
43.{
44.
45.timer_init(); //initialise timer
46.timer_set(1000); // time in milliseconds
47.while(1);
48.}
- See more at: http://www.bredboard.com/blog/?p=641#sthash.iwASXzqL.dpuf

How to Enable Interrupts on ANY pin


7/8/2010
Louis Van Blarigan
Every pin on the ATMEGA 328 (Heart of Arduino) is capable of registering
a pin change interrupt. The arduino board is only set up to register external
interrupts on digital pins 2 and 3. To get around this limitation, it is
necessary to speak directly to the ATMEGA chip through the arduino
interface.
A pin change interrupt is triggered by the state of a pin rising, falling,
changing, or being low.
To enable this feature on the arduino, we must identify the pins that we
want to enable this feature on, and direct the chip what it needs to do when
the interrupt is called. Since arduino uses its own chip assignments, there
is a map we will use to find the arrays and pin assignments that the
ATMEGA uses to control these pins. The best source for this information is
the datasheet for the ATMEGA 328 (Linked on webpage). Upon
examination, we find:
We are familiar with the pins on the arduino, so the first column will be our
starting place. Decide which pin you want to add an interrupt on. Usually it
would be wise to avoid D2 and D3 since these are pre-set with external
interrupts. Use the table to find the associated pin PCINT#. Notice that
each set of pins is associated with a different number for PCIE, PCMSK,
and PCINT. Each of these is associated with a
separate pin change interrupt. They are labeled 0, 1, 2. This would indicate
that there are three additional interrupts that can be handled by our Arduino
board. Each PCINT is capable of being caused by any of the pins
associated with it. This would indicate that you could have 6+ switches that
all trigger the same interrupt. However, each of these pins would have to
be attached to the interrupt routine separately.
To incorporate this information into your arduino code, we only need to
consider the setup and ISR routines. An ISR routine is called whenever an
interrupt is called and the parameter defines which PCINT triggers the ISR.
For instance:
ISR ( PCINT#_void ) {
Do some stuff.
}
This format is valid for each of the three PCINTs. Note that the _void is
always necessary and this is the main PCINT from the table above.
In the setup of your Arduino sketch, there are several lines of code that
must be included to attach the interrupts. We must first tell the chip that we
want to enable an interrupt:
PCICR |= (1<<PCIE#); Enable una din cele trei ntreruperi.
This changes the interrupt enable bit (PCIE) to on in the interrupt register
(PCICR). 1 turns the interrupt on, 0 turns the interrupt off.
PCMSK# |= (1<<PCINT#); Spune numrul pinului folosit
This tells the pin change mask (PCMSK#) that it needs to watch for a
change on pin (#). Use the table above to find the # for both the PCMSK
and the PCINT (this will be the pin PCINT).
MCUCR = (1<<ISC1#) | (1<<ISC0#); low, cresctor, desc, svhimbare
This line of code tells the chip which type of change triggers the interrupt.
ISC0 is the value we are modifying. Inputting a 1 or a 0 at the # will
determine the state. 0 0 triggers at any low level. 01 triggers at any change.
1 0 triggers at a falling edge. 1 1 triggers at a rising edge.
These are all of the commands that are necessary for implementing a
switch as an interrupt on any available pin on the Arduino. There are other
complication which will be left up to the end user, such as switch bounce
etc..
Attached Below is an example code that uses two switches (default set to
digital pins 7 and 8) to switch the LCD display between displaying HIGH
and LOW
/* How to set up additional interrupts in Arduino (ATMEL 328)
7/7/2010
Louis Van Blarigan
This code uses Pin Change interrupts to switch between two display states.

#include <SoftwareSerial.h> //(Include the needed libraries (pentru LCD serial)


#define interrupt_pin 7
//Define Analog Pin (analog pins are 16-21)
#define interrupt_pin2 8 //Define Analog Pin (analog pins are 16-21)
volatile int bump = 0;
SoftwareSerial mySerial = SoftwareSerial(13, 13); //Change LCD Tx and Rx Pins to pins of our
choosing
void setup() {
PCICR |= (1<<PCIE2);
PCMSK2 |= (1<<PCINT23);
MCUCR = (1<<ISC01) | (1<<ISC00);
PCICR |= (1<<PCIE0);
PCMSK0 |= (1<<PCINT0);
//LCD Configuration
pinMode(13, OUTPUT);
mySerial.begin(9600);
mySerial.print("?f");
//Sends clear screen command to LCD
pinMode(interrupt_pin, INPUT); //Make pin an input
pinMode(interrupt_pin2, INPUT); //Make pin an input
digitalWrite(interrupt_pin,HIGH); //Enable pullup resistor on Analog Pin
digital Daca se scrie 1 pe intrare se activeaz rezistenele pull Up.
Write(interrupt_pin2,HIGH); //Enable pullup resistor on Analog Pin
bump = 0;
interrupts(); Cred c activeaz ntreruperile
}

mySerial.print("?f");
mySerial.print("LOW");
}
else {
mySerial.print("?f");
mySerial.print("HIGH");
}
}
ISR(PCINT2_vect) {
bump = 1;
}
ISR(PCINT0_vect) {
bump = 0;
}

Aprind i sting un LED


Folosesc biblioteca TimerOne. Atenie, Obiectul este Timer1
/*
* Timer1 library example
* June 2008 | jesse dot tane at gmail dot com
*/

#include "TimerOne.h"
#define LED 13
int valLed=1;

void setup()
{
pinMode(LED, OUTPUT);
Timer1.initialize(50000);
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
}

void callback()
{
if (valLed==1)
{
digitalWrite(LED,LOW);
valLed=0;
}
else
{
digitalWrite(LED,HIGH);
valLed=1;
}
}

void loop()
{

Probabil adaug
#include <avr/interrupt.h>

Jordan McConnell
int ledPin = 13; // LED is attached to digital pin 13
int x = 0; // variable to be updated by the interrupt

void setup() {
//enable interrupt 0 (pin 2) which is connected to a button
//jump to the increment function on falling edge
attachInterrupt(0, increment, FALLING);
Serial.begin(9600); //turn on serial communication
}

void loop() {
digitalWrite(ledPin, LOW);
delay(3000); //pretend to be doing something useful
Serial.println(x, DEC); //print x to serial monitor
}

// Interrupt service routine for interrupt 0


void increment() {
x++;
digitalWrite(ledPin, HIGH);
}

Potrebbero piacerti anche