### null 8557451

2/7/14 Physics 120B: Lecture 12 Timers and Scheduled Interrupts Timer Basics •  The Arduino Uno/Nano (ATMega 328) has three Hmers available to it (Arduino Mega has 6) –  max frequency of each is 16 MHz, (as assembled) –  TIMER0 is an 8-­‐bit Hmer, with 1, 8, 64, 256, 1024 prescaler opHons –  TIMER1 is a 16-­‐bit Hmer, with 1, 8, 64, 256, 1024 prescaler opHons –  TIMER2 is an 8-­‐bit Hmer with 1, 8, 32, 64, 128, 256, 1024 prescaler opHons •  These Hmers, recall, are used for PWM pins 5&6, 9&10, 3&11, respecHvely –  we saw that we could change the PWM frequency by messing with the frequency prescaler values –  but PWM frequency is not the same as clock frequency Lecture 12 2 1 2/7/14 Prescaling & Frequency •  The Arduino boards run the ATMega chip at 16 MHz –  so a prescaler of 1 results in a 16 MHz clock –  a prescaler of 1024 results in 15.625 kHz •  Recall the PWM table: PWM pins Register scaler values frequencies (Hz) 5, 6 TCCR0B 1, 2, 3, 4, 5 62500, 7812, 977, 244, 61.0 9, 10 TCCR1B 1, 2, 3, 4, 5 31250, 3906, 488, 122, 30.5 3, 11 TCCR2B 1, 2, 3, 4, 5, 6, 7 31250, 3906, 977, 488, 244, 122, 30.5 –  the top frequency is not 16 MHz, oﬀ by 256× and 512× –  this is because PWM is (presumably) counHng a certain number of clock cycles (256 or 512) between acHons Lecture 12 3 Prescaling ImplementaHon on-­‐chip •  From ATMega full datasheet –  CS bits decide which tap to output (note orig. clock in pos. 1) Lecture 12 4 2 2/7/14 Prescaling for TIMER2: more taps CSn0:CSn2 = 0 selects this: no clock out Lecture 12 5 Wrap Times •  TIMER0 is 8-­‐bit (0−255) –  when prescaler = 1, reaches full count in 16 µs –  when prescaler = 1024, full count in 16.384 ms •  TIMER1 is 16-­‐bit (0−65536) –  when prescaler = 1, reaches full count in 4.096 ms –  when prescaler = 1024, full count in 4.194 seconds •  TIMER2 is 8-­‐bit (0−255) –  when prescaler = 1, reaches full count in 16 µs –  when prescaler = 1024, full count in 16.384 ms •  These wrap Hmes set limits on Hmed interrupts –  makes TIMER1 abracHve, for its 16 bits Lecture 12 6 3 2/7/14 Timed Interrupts •  Really handy to have Hmed acHon, despite whatever loop() is doing –  could check for serial or other input on a regular basis –  could read analog signal for regular sampling –  could produce custom signal at speciﬁc frequency •  Idea is to set up Hmer so when it reaches speciﬁed count, it creates an interrupt –  and also resets counter to zero so cycle begins anew •  Interrupt Service RouHne (ISR) should be short and sweet –  performs whatever periodic task you want Lecture 12 7 CAUTION •  Messing with Hmer conﬁguraHons can compromise other Hmer-­‐based funcHons like –  PWM outputs: analogWrite() (diﬀ. pins  diﬀ. Hmers) –  delay() (uses Hmer0, depends on counter wrap)!
–  millis() and micros() (uses Hmer0, dep. on wrap) –  Servo library (uses Hmer1)!
–  tone() (uses Hmer2) –  but delayMicroseconds() is okay (not Hmer-­‐based) –  others? •  Be cognizant of which Hmer each funcHon uses –  see hbp://letsmakerobots.com/node/28278 Lecture 12 8 4 2/7/14 TIMER1 as Example •  Relevant registers for sefng up Hmer: –  TCCR1A: Timer/Counter1 Control Register A •  sets up mode of operaHon –  TCCR1B: Timer/Counter1 Control Register B •  more mode control, and prescaler –  OCR1A: Output Compare Register 1 A (there’s also a B) •  value against which to compare –  TIMSK1: Timer1 Interrupt MaSK register •  selects which OCR to use –  TIFR1: Timer1 Interrupt Flag Register •  contains info on tripped interrupt status –  TCNT1: actual 16-­‐bit count –  TCNT1 and OCR1A break into, e.g., TCNT1H and TCNT1L high and low bytes (registers) to accommodate 16 bits Lecture 12 9 Timer 1 Registers •  From short datasheet –  page reference is for full datasheet •  Note 16-­‐bit quanHHes need two registers apiece –  H and L for high and low Lecture 12 10 5 2/7/14 TCCR1A •  Upper bits are Compare Output Mode –  sets behavior of Compare Match condiHon –  can toggle, clear or set OCR bits on Compare Match condiHon •  Lower bits are 2/4 Waveform GeneraHon Mode controls –  other two are in TCCR1B –  16 possibiliHes, the ones we’re likely interested in: •  CTC is Clear Timer on Compare match (so starts count all over) Lecture 12 11 TCCR1B •  We’ve seen this before, for prescaling –  two bits for Input Capture (noise cancel and edge sense) –  has upper two bits of WGM1 –  has three CS (Clock Select) bits for prescaling, or ext. clock Lecture 12 12 6 2/7/14 OCR1A and TIMSK1 •  This is the value against which TCNT1 (L & H) is compared (also a OCR1B for alternate value) •  TIMSK1 controls what generates interrupts –  ICIE: Input Capture Interrupt Enable –  OCIE A/B Output Compare Match Interrupt Enable –  TOIE: Timer Overﬂow Interrupt Enable: when counter wraps Lecture 12 13 Finally, TIFR1 •  Timer1 Interrupt Flag Register –  ICF1 set if Internal Capture interrupt has occurred –  OCF1B set if Output Compare match occurs on OCR1B –  OCF1A set if Output Compare match occurs on OCR1A –  TOV1 set if OVerﬂow (wrap) occurs on counter (in certain modes) Lecture 12 14 7 2/7/14 What Do We Do with this Power? •  Let’s set up an interrupt Hmer to change the state of an LED every 1.5 seconds •  Need TIMER1 if we want to reach beyond 16 ms –  prescale by 1024, so frequency is 15625 Hcks/sec –  thus 1.5 seconds corresponds to 23437 Hcks •  Set up registers: –  TCCR1A to 0 (ignore COM1A; WGM10=WGM11=0 for CTC) –  TCCR1B: set WGM12 (for CTC), CS12, CS10 –  OCR1A to 23437 (OCR1AH = 91, OCR1AL to 141) –  TIMSK1: set OCIE1A •  Make ISR funcHon: ISR(TIMER1_COMPA_vect){} Lecture 12 15 Example: Interrupt-­‐Driven LED blink const int LED=13; !
!
volatile int state=0;!
!// use on-board LED!
void setup(){!
pinMode(LED,OUTPUT);!
!//
TCCR1A = 0; !
!
!
!//
TCCR1B = 0; !
!
!
!//
TCCR1B |= (1 << WGM12); !//
TCCR1B |= (1 << CS12); !//
TCCR1B |= (1 << CS10); !//
OCR1A = 23437; !
!
!//
TIMSK1 |= (1 << OCIE1A);!//
TCNT1 = 0; !
!
!
!//
}!
void loop(){!
delay(10000);
}!
!
!
set up LED for OUTPUT!
clear ctrl register A!
clear ctrl register B!
set bit for CTC mode!
set bit 2 of prescaler for 1024x!
set bit 0 of prescaler for 1024x!
set L & H bytes to 23437 (1.5 sec)!
enable interrupt on OCR1A!
reset counter to zero!
!// provide lengthy task to interrupt!
ISR(TIMER1_COMPA_vect){ !// results in interrupt vector in asm code!
state += 1;!
state %= 2; !
!
!
!// toggle state 1 --> 0; 0 --> 1!
digitalWrite(LED,state);!// export value to pin!
}!
Lecture 12 16 8 2/7/14 Comments on Code •  The bit values WGM12, CS10, etc. are deﬁned in, e.g., iom328p.h –  in hardware/tools/avr/avr/include/avr/ –  for example: #define
#define
#define
#define
#define
#define
#define
CS10 0!
CS11 1!
CS12 2!
WGM12 3!
WGM13 4!
ICES1 6!
ICNC1 7!
#define OCR1A _SFR_MEM16(0x88)!
#define OCR1AL _SFR_MEM8(0x88)!
#define OCR1AH _SFR_MEM8(0x89)!
#define TIMER1_COMPA_vect _VECTOR(11)
// Timer1 Compare Match A!
Lecture 12 17 Handling the Interrupt •  The command ISR(TIMER1_COMPA_vect) creates a “vector” poinHng to the program memory locaHon of the piece that is meant to service the interrupt –  near beginning of assembly code lisHng: 2c:
0c 94 80 00
jmp
0x100
; 0x100 <__vector_11>!
–  vector 11 is specially deﬁned in ATMega 328 to correspond to a comparison match to OCR1A on Hmer 1 –  when this parHcular sort of interrupt is encountered, it’ll jump to program locaHon 0x100, where: •  various working registers are PUSHed onto the STACK –  so the service funcHon can use those registers for itself •  the interrupt service funcHons are performed •  the STACK contents are POPped back into registers •  the program counter is reloaded with the pre-­‐interrupHon value •  The vector approach allows use of mulHple interrupts Lecture 12 18 9 2/7/14 A Custom PWM ISR(TIMER1_COMPA_vect)!
{!
if (state) OCR1A = 31248;
else OCR1A = 15624; ! !
state += 1;!
state %= 2;!
digitalWrite(LED,state);!
}!
!// two seconds for OFF!
!// one second for ON!
•  When Hme is up: –  if state == 1 (LED ON), set compare register to 2 seconds –  otherwise (LED OFF), set compare register to 1 second •  In this way, you can customize a PWM-­‐like signal arbitrarily –  preby sure this is what the Servo library is doing with TIMER1 Lecture 12 19 Nested Interrupts •  Imagine you want to respond to an external interrupt, and perform some follow-­‐up acHon 2 seconds later –  external interrupt arranged via attachInterrupt()!
–  within service funcHon, set up TIMER1 counter for Hmed interrupt –  in Hmer ISR, reset TIMER1 to normal mode •  disable interrupt condiHon, or you’ll keep coming back Lecture 12 20 10 2/7/14 References and Announcements •  For more on Hmer interrupts: –  hbp://www.instructables.com/id/Arduino-­‐Timer-­‐
Interrupts/ –  hbp://letsmakerobots.com/node/28278 •  Announcements –  Will review proposals over weekend –  Oﬀer feedback, redirect, order parts (some) early in week –  New Lab Hmes: •  M 12−6; T 2−6; W 1−6; Th 2−6, F 12−5 •  will have someone there, oqen two out of the three of us –  Light tracker demo/code/paragraphs due 2/11 or 2/12 –  Midterm on Wednesday 2/19 in class Hme Lecture 12 21 11