avr timer/counter · การทางานเบ้ืองตน้ของ timer/counter...
TRANSCRIPT
Overview
Introduction
Basic Component
Operation
ATmega168 Timer
Overview
Related Registers
Operation
Programming Language
C Language
C Language with Arduino
2
หลกัการเบือ้งตน้
Timer การวดัคาบเวลา หรือการจบัเวลาCounter การนบัจ านวนสญัญาณ ถา้สญัญาณนั้นมีคาบเวลาคงท่ี การนบัก็จะเป็นการนบัจ านวนเวลา นัน่คือ Timer
ส่วนประกอบเบ้ืองของ Timer/Counter ในระบบ Microcontroller: แหล่งจ่ายสัญญาณท่ีจะใชน้บั วงจรนบั รีจิสเตอร์ควบคุม Optional prescaler ของสัญญาณท่ีจะใชน้บั
ทั้ง Timer และ Counter บางคร้ังกเ็รียกรวมๆกนัวา่ Timer
3
แหล่งจ่ายสญัญาณท่ีจะใชน้บั (Timer Clock Source)แหล่งจ่ายสัญญาณมาจาก : ภายใน Internal ภายนอก External
ปกติแลว้ Microcontroller จะใชส้ัญญาณนาฬิกาเพื่อการท างานของระบบ สัญญาณนาฬิกาน้ี อาจจะมาจากภายนอกชิพ เช่น ใช ้XTAL หรือเป็นวงจรสร้างสัญญาณภายในชิพเองกไ็ด ้ สัญญาณนาฬิกาของระบบน้ี ยงัใชเ้ป็นสัญญาณนาฬิกาของวงจรต่างๆดว้ย เช่น
CPU clock (clkcpu) I/O clock (clkI/O) ADC clock (clkADC) Timer/Counter clock
4
วงจรนบั (Timer/Counter Registers) วงจรนบั ใชส้ าหรับการนบัสัญญาณ และการจบัเวลา ขนาดของวงจรนบั 8 บิต 16 บิต บางคร้ังใชว้งจรนบัขนาด 8 บิต 2 ตวัมาท าเป็นวงจรนบัขนาด 16 บิต
5
รีจิสเตอร์ควบคุม (Timer Control Registers)ท าหนา้ท่ีควบคุมการท างาน เช่น รูปแบบการท างาน (Operating mode) เช่น Normal, PWM,
compare/capture สร้างสัญญาณอินเตอร์รัพท ์ เลือกแหล่งจ่ายสญัญาณ เลือกรูปแบบการทริก (Trigger)
รีจิสเตอร์ควบคุมน้ีอาจมีหลายตวั
6
Timer PrescalerController บางตวัมีความยดืหยุน่สูง สามารถเลือกใชส้ญัญาณนาฬิกาท่ีความถ่ีต่างๆกนัได ้ ซ่ึงความถ่ีเหล่าน้ีไดม้าจากวงจร prescaler. วงจร Prescaler อาจเป็นวงจร คูณหรือวงจรหารความถ่ีกไ็ด ้ การคูณหรือหารความถ่ีน้ีกเ็พื่อใหไ้ดค้วามถีสัญญาณท่ีตอ้งการ โดยปกติจะเป็นวงจรหารความถ่ีตวัอยา่งเช่น ถา้สัญญาณนาฬิกาของระบบมี Prescaler เป็น 64 กห็มายความวา่ความถ่ีสัญญาณท่ีไดจ้ะเป็น fsys/64
7
การท างานเบ้ืองตน้ของ Timer/Counter วงจรนบั เร่ิมการนบัจากค่าตั้งตน้ (ปกติเป็น 0) เม่ือมีสัญญาณเขา้มา วงจรนบัจะเพ่ิมค่า (หรือลดค่า) ทีละ 1 เม่ือนบัมาถึงค่าท่ีก าหนดใว ้ จะเกิดสัญญาณ Overflow ในสัญญาณลกูถดัไป วงจรนบั เร่ิมการนบัจากค่าตั้งตน้ใหม่
9
ATmega168 Timer/CounterATmega168 มี Timer 3 ตวั Timer/Counter 0 : 8 bit with PWM Timer/Counter 1 : 16 bit with PWM Timer/Counter 2 : 8 bit with PWM and Asynchronous Operation
11
External counter input
PD4/ T0 Timer/Counter 0 external counter input
PD5/ T1 / Timer/Counter 1 external counter input
12
External counter Output
13
PD6/OC0A Timer/Counter 0 output compare match A output
PD5/OC0B Timer/Counter 0 output compare match B output
PB1/OC1A Timer/Counter 1 output compare match A output
PB2/OC1B Timer/Counter 1 output compare match B output
PB3/OC2A Timer/Counter 2 output compare match A output
PD3/OC2B Timer/Counter 2 output compare match B output
The 8-bit Timer block diagram
14
Timer/Counter 0/2
output compare match B output
Timer/Counter 0/2
output compare match A output
Timer/Counter 0/2
external counter input
รีจิสเตอร์ส ำหรับควบคุม Timer 8 บิต
Counter0 Counter2 Description
TCCR0A TCCR2A Timer/Counter Control Register A
TCCR0B TCCR2B Timer/Counter Control Register B
TCNT0 TCNT2 Timer/Counter Register
OCR0A OCR2A Output Compare Register A
OCR0B OCR2B Output Compare Register B
TIMSK0 TIMSK2 Timer/Counter Interrupt Mask Register
TIFR0 TIFR2 Timer/Counter Interrupt Flag Register
19
รีจิสเตอร์ส ำหรับควบคุม Timer 16 บิต
20
Counter1 Description
TCCR1A Timer/Counter 1 Control Register A
TCCR1B Timer/Counter 1 Control Register B
TCCR1C Timer/Counter 1 Control Register C
TCNT1H Timer/Counter 1 High Register
TCNT1L Timer/Counter 1 Low Register
OCR1AH Output Compare Register 1 A High
OCR1AL Output Compare Register 1 A Low
OCR1BH Output Compare Register 1 B High
OCR1BL Output Compare Register 1 B Low
ICR1H Input Capture Register 1 High
ICR1L Input Capture Register 1 Low
TIMSK1 Timer/Counter Interrupt Mask Register
TIFR1 Timer/Counter Interrupt Flag Register
นิยาม
MAX ค่าสูงสุดท่ี Counter นบัได ้กรณีเป็นแบบ 8 บิต นบัได ้255 ถา้เป็น 16 บิตจะนบัได ้65535
BOTTOM ค่าต ่าสุดท่ีนบัได ้ปกติคือ 0 TOP ค่าสูงสุดท่ีก าหนดให ้Counter นบั
21
การท างานของ Timer/Counter Normal CTC (Clear Timer on Compare Match) Fast PWM (Single Slope PWM) Phase Correct PWM (Double Slope PWM)
22
การท างานแบบ Normal
นบัจากค่าท่ีตั้งใวใ้น Counter ไปจนถึงค่า MAX จะเกิดการ Overflow ซ่ึงใชไ้ปอินเตอร์รัพท ์CPU ได ้
วิธีกาหนดการท างาน ก าหนดให ้WGM ในรีจิสเตอร์ TCCRnA และ TCCRnB เท่ากบั 000 ก าหนดค่า Prescale CSn2 – CSn0 ในรีจิสเตอร์ TCCRnB ก าหนดค่าเร่ิมตน้ส าหรับการนบั ในรีจิสเตอร์ TCNTn ก าหนดสถานการณ์อินเตอร์รัพทข์อง Timer บิต TOIEn ในรีจิสเตอร์ TIMSKn ก าหนดบิต Global ใน SREG
23
การท างานของ Timer 0 : TCCR0A and TCCR0B
Mode WGM02 WGM01 WGM00 Description
0 0 0 0 Normal
1 0 0 1 PWM, Phase Correct
2 0 1 0 Clear Timer on Compare (CTC)
3 0 1 1 Fast PWM
4 1 0 0 Reserved
5 1 0 1 PWM, Phase Correct
6 1 1 0 Reserved
7 1 1 1 Fast PWM
25
รีจิสเตอร์ส าหรับนบั Timer/Counter Register Timer 0 : TCNT0 Timer1 : TCnT1 = TCNT1H (8-bit) + TCNT1L (8-bit) Timer2 : TCNT2
30
ตวัอยา่งโปรแกรม Timer 0 mode 0 (Normal)#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER0_OVF_vect)
{
PORTB = ~PORTB; //Complement PortB
TCNT0 = 55; //Preload Counter
}
32
ตวัอยา่งโปรแกรม Timer 0 mode 0 (Normal)// ***********************************************************
// Main program
//
int main(void) {
DDRB = 0b11111111; // All outputs
TCCR0A = 0; // initialize timer1
TCCR0B = 0; // mode 0
TCCR0B |= (1 << CS02); // prescaler 256
TCNT0 = 55; // preload timer 60000
TIMSK0 |= (1 << TOIE0); // enable timer overflow interrupt
PORTB = 0xff; // Set port B =1111 1111
sei(); // Global Interrupt
while(1)
{
}
}
33
การค านวณค่าความถ่ี
จากตวัอยา่ง จะไดส้ญัญาณส่ีเหล่ียม ออกทางพอรท ์ B ซ่ึงสามารถ์ค านวณหาค่าความถ่ีไดด้งัน้ี
34
HzF
Fin
escaler
n
TCNT
Max
MHzspeedClock
TCNTMaxn
escaler
speedClockFin
n
FinF
47.155402
62500
62500256
16000000
256Pr
402
550
256
16
2*)0(
Pr
ตวัอยา่งโปรแกรม Timer 1 mode 0 (Normal)#include <avr/io.h>
#include <avr/interrupt.h>
int main (void)
{
DDRB = 0b11111111; // All outputs
TCCR1A = 0; // initialize timer1
TCCR1B = 0; //mode 0
TCCR1B |= (1 << CS10); // no prescaler
TCNT1 = 60000; // preload timer 60000
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
PORTB = 0xff; // Set port B =1111 1111
sei(); //Global Interrupt
35
ตวัอยา่งโปรแกรม Timer1 mode 0 (Normal) (ต่อ)while(1)
{
}
}
ISR(TIMER1_OVF_vect)
{
PORTB = ~PORTB; //Complement PortB
TCNT1 = 60000; //Preload Counter
}
36
การค านวณคาบเวลา Interrupt fclk = 16MHz Prescale = 1 ความถ่ีท่ีใชใ้นการนบั = fclk/prescale = 16MHz/1 = 16MHz การนบัแต่ละคร้ังใชเ้วลา = 1/16MHz = 0.0625 uS Preload Counter = 60000 ค่า MAX ของ Timer 1 = 65536 ดงันั้นตอ้งนบั = MAX – Preload = 65536 – 60000 = 5536 จึงจะ Overflow คาบเวลาการอินเตอร์รัพท ์= 5536 * 0.0625 uS = 346 uSec
37
การท างานแบบ Clear timer on compare match (CTC) mode
รีจิสเตอร์ TCNT เร่ิมนบัจากนบัจาก 0 ไปจนเท่ากบัค่า TOP ท่ีตั้งใวใ้น OCRA จะเกิดการ Overflow ซ่ึงใชไ้ปอินเตอร์รัพท ์CPU ได ้ และ Timer จะ Clear ค่า ใน TCNT ใหเ้ป็น 0 ใหม่
วิธีกาหนดการท างาน ก าหนดให ้WGM ในรีจิสเตอร์ TCCRnA และ TCCRnB เท่ากบั 010 ก าหนดค่า Prescale CSn2 – CSn0 ในรีจิสเตอร์ TCCRnB ก าหนดค่า TOP ส าหรับการนบั ในรีจิสเตอร์ OCRnA ก าหนดสถานการณ์อินเตอร์รัพทข์อง Timer บิต OCIEnA ในรีจิสเตอร์ TIMSKn ก าหนดบิต Global ใน SREG
38
ตวัอยา่งโปรแกรม Timer 0 mode 2 (CTC)#include <avr/io.h>
#include <avr/interrupt.h>
int main (void)
{
DDRB = 0b11111111; // All outputs
TIMSK0 = _BV(OCIE0A); // Enable Interrupt
TCCR0A = _BV(WGM01); // Mode = CTC
TCCR0B = _BV(CS02) | _BV(CS00); // Clock/1024
OCR0A = 40; // Set Top value
PORTB = 0xff;
sei();
39
การค านวณคาบเวลา Interrupt fclk = 16MHz Prescale = 1024 ความถ่ีท่ีใชใ้นการนบั = fclk/prescale = 16MHz/1024 = 15.625 KHz การนบัแต่ละคร้ังใชเ้วลา T = 1/15.625 KHz = 0.064 uS ค่า TOP ท่ีตั้งของ Timer 0 = OCR0A = 40 คาบเวลาการอินเตอร์รัพท ์= TOP*T = 40* 0.064 uS = 2.56 mSec
41
Phase correct PWM mode การท างานโหมดน้ี เร่ิมตน้ Counter TCNT จะนบั
ข้ึน เม่ือนบัถึงค่าสูงสุด MAX ของ Counter (เช่น Timer 0 = 255) วงจรนบัจะเปล่ียนทิศทางการนบั กลายเป็นนบัลง และเม่ือนบัถึงค่าต ่าสุด BOTTOM วงจรนบักจ็ะเปล่ียนทิศทางการนบัอีกคร้ัง การนบัจะเป็นเช่นน้ีตลอดไป
สัญญาณเอาทพ์ทุ จะออกทางขา Ocnx เช่น Timer 0 ช่อง A จะออกท่ีขา PD6 โดยสญัญาณจะถกูก าหนดดว้ยค่า COM0A1 COM0A0 (Timer 0 ช่อง A) และ COM0B1 COM0B0 COM0A0 (Timer 0 ช่อง B) ในรีจิสเตอร์ TCCR0A
43
Compare output mode, phase correct PWM mode
45
ตวัอยา่ง ถา้ให ้COM0A1-COM0A0 = 10 เม่ือ Counter นบัข้ึน สัญญาณ OC0A เป็น 1 และจะกลายเป็น 0 เม่ือ ค่า Counter เท่ากบัค่าท่ีตั้งใวใ้น OCR0A เม่ือนบัถึงค่าสูงสุด Counter เปล่ียนเป็นนบัลง ขณะน้ี สัญญาณ OC0A ยงัเป็น 0 อยู ่แต่ม่ือนบัมาเท่ากบัค่า OCR0A จะเปล่ียนเป็น ลอจิก 1 อีกคร้ังถา้ให ้COM0A1-COM0A0 = 11 สัญญาณจะกลบัเฟสกนั
ตวัอยา่งโปรแกรม สร้าง PWM ออกท่ี PD6 Duty cycle 25% #include <avr/io.h>
#include <avr/interrupt.h>
int main (void)
{
DDRD = 0b11111111; // All outputs
TCCR0A = 0b10000001; // Mode = PWM
TCCR0B = 0b00000011; // Clock/64, Normal phase
OCR0A = 51; // Duty cycle 20%
PORTD = 0xff; //PWM Output on PD6 = OC0A
while(1)
{
}
}
46
การค านวณคาบเวลา fclk = 16MHz Prescale = 64 ความถ่ีท่ีใชใ้นการนบั = fclk/prescale = 16MHz/64 = 250 KHz การนบัแต่ละคร้ังใชเ้วลา T = 1/250 KHz = 4 uS ค่าคาบเวลาของสญัญาณ PWM = 4uS*255*2 = 2040 uS ค่าความถ่ีของสญัญาณ PWM = 1/2040 uS = 490 Hz ค่า TOP ท่ีตั้งของ Timer 0 = OCR0A = 51 ความกวา้งของพลัส์ = 4uS*51*2 = 408 uS Duty Cycle = ค่าคาบเวลาของสญัญาณ PWM / ความกวา้งของพลัส์ = 408uS/2040uS = 20%
หมายเหตุ 2 มาจากการท่ี Counter นบัข้ึนและนบัลง
47
TimerONE ท าอะไรไดบ้า้ง
void initialize(long microseconds=1000000);
void start();
void stop();
void restart();
unsigned long read();
void setPeriod(long microseconds);
void pwm(char pin, int duty, long microseconds=-1);
void setPwmDuty(char pin, int duty);
void disablePwm(char pin);
void attachInterrupt(void (*isr)(), long microseconds=-1);
void detachInterrupt();
48
หมายเหตุ โปรแกรมท่ีเก่ียวกบั Timer0 มกัจะจ าลองการท างานบน
VMLAB ไม่ได ้ ตอ้งใชเ้ขียน บน Arduino แทน
49
ตวัอยา่งให ้Interrupt ทุกๆ 1000 uSec#include <TimerOne.h> //เรยีกใช ้ไลบรารี ่TimerOne
unsigned char a = 0;
//--------------------------------------------------------------------------------
void setup() {
pinMode(8, OUTPUT);
//ก าหนดระยะเวลาการอนิเตอรรั์พทข์อง timer 1 ใหเ้ป็นทกุๆ 1000 uS
Timer1.initialize(1000);
// ก าหนดต าแหน่งโปรแกรมรองรับการอนิเตอรรั์พท ์
Timer1.attachInterrupt( timerIsr );
}
50
ตวัอยา่งให ้Interrupt ทุกๆ 1000 uSec (ต่อ) void timerIsr(){
if(a==0) {
digitalWrite(8, LOW);
a = 1;
}else{
digitalWrite(8, HIGH);
a = 0;
}
}
Loop ()
{
}
51
Arduino PWM#include "TimerOne.h"
void setup(){
pinMode(10, OUTPUT);
Timer1.initialize(1000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 256); // setup pwm on pin 9, 25% duty cycle
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
}
void callback(){
digitalWrite(10, digitalRead(10) ^ 1);
}
void loop(){
// your program here...
}
52
สญัญาณท่ีขา 10 T = 2 mSDuty = 50%
สญัญาณท่ีขา 9 T = 1 mSDuty = 25%
การใช ้ Library Timer 1 บน Arduinoใน Arduino มี Library เก่ียวกบั Timer TimerOne TimerThreeดูไดจ้าก http://playground.arduino.cc/code/timer1
53
โปรแกรมเม่ือเขียนบน Arduino#include <avr/io.h>
#include <avr/interrupt.h>
void setup() {
DDRD = 0b11111111; // All outputs
TCCR0A = 0b10000001; // Mode = PWM
TCCR0B = 0b00000011; // Clock/64, Normal phase
OCR0A = 51; // Duty cycle 20%
PORTD = 0xff; //PWM Output on PD6 = OC0A
}
void loop() {
}
54
โปรแกรมเม่ือเขียนบน Arduino#include <avr/io.h>
#include <avr/interrupt.h>
void setup() {
DDRB = 0b11111111; // All outputs
// initialize timer1
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 60000; // preload timer
TCCR1B |= (1 << CS10); // no prescaler
// enable timer overflow interrupt
TIMSK1 |= (1 << TOIE1);
PORTB = 0xff;
sei();
}
55
void loop() {
}
ISR(TIMER1_OVF_vect)
//ISR(TIMER0_OVF_vect)
{
PORTB = ~PORTB;
TCNT1 = 60000;
}
โปรแกรมเม่ือเขียนบน Arduino#include <avr/io.h>
#include <avr/interrupt.h>
void setup() {
DDRB = 0b11111111; // All outputs
TIMSK0 = _BV(OCIE0A); // Enable Interrupt
TCCR0A = _BV(WGM01); // Mode = CTC
TCCR0B = _BV(CS02) | _BV(CS00); // Clock/1024
OCR0A = 40; // Top Value
PORTB = 0xff;
sei();
}
56
void loop() {
}
ISR(SIG_OUTPUT_COMPARE0A)
{
PORTB = ~PORTB;
}
โปรแกรมสร้าง PWM 2 ช่อง ท่ี OC0A กบั OC0B เม่ือเขียนบน Arduino#include <avr/io.h>
#include <avr/interrupt.h>
void setup() {
DDRD = 0b11111111; // All outputs
TCCR0A = 0b10100001; // Mode = PWM 2 channel
TCCR0B = 0b00000010; // Clock/8, Normal phase
OCR0A = 51; // Duty cycle 20% : ch A = PD6
OCR0B = 128; //Duty cycle 50% : ch B = PD5
PORTD = 0xff; //PWM Output on PD6 = OC0A
}
void loop() {
}
57