Timer Counter

41
timer/counter: dùng để đếm thời gian hay sự kiện.ngoài ra nó còn dùng nhiều chức năng khác. Khi tìm hiểu sâu bạn sẽ biết. ví dụ bạn đếm sản phẩm hoặc xung encoder đưa về, khi đếm đủ thì bạn làm gí dó tùy bạn lập trình. Nó còn có thể ngắt, so sánh, pwm... ======================================================================== Cho bạn mt ví dụ đơn giản nh : với CPU AT90S2313 (Atmega8 không khác gì); hãy lập trình cho Timer0 phát xung tần số do mình tự đặt ,còn Timer1 phát xung PWM #include <90s2313.h> #define XUNG PORTD.0 //Xung đầu ra // Ngắt T0 interrupt [TIM0_OVF] void timer0_ovf_isr(void) { XUNG=!XUNG; } // Declare your global variables here void main(void) { PORTB=0x00; DDRB=0x08; PORTD=0x00; DDRD=0xFF; // Port D có chiều ra // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 500,000 kHz đầu vào xung 500.000khz TCCR0=0x02; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 500,000 kHz // Mode: CTC top=OCR1A // OC1 output: Toggle // Noise Canceler: Off // Input Capture on Falling Edge TCCR1A=0x40; TCCR1B=0x0A; TCNT1H=0x00; TCNT1L=0x00; OCR1H=0x00;

Transcript of Timer Counter

Page 1: Timer Counter

timer/counter: dùng để đếm thời gian hay sự kiện.ngoài ra nó còn dùng nhiều chức năng khác. Khi tìm hiểu sâu bạn sẽ biết.ví dụ bạn đếm sản phẩm hoặc xung encoder đưa về, khi đếm đủ thì bạn làm gí dó tùy bạn lập trình. Nó còn có thể ngắt, so sánh, pwm...========================================================================Cho bạn môt ví dụ đơn giản nhe : với CPU AT90S2313 (Atmega8 không khác gì); hãy lập trình cho Timer0 phát xung tần số do mình tự đặt ,còn Timer1 phát xung PWM

#include <90s2313.h>#define XUNG PORTD.0 //Xung đầu ra// Ngắt T0interrupt [TIM0_OVF] void timer0_ovf_isr(void){XUNG=!XUNG;}

// Declare your global variables here

void main(void){PORTB=0x00;DDRB=0x08;PORTD=0x00;DDRD=0xFF; // Port D có chiều ra

// Timer/Counter 0 initialization// Clock source: System Clock// Clock value: 500,000 kHz đầu vào xung 500.000khzTCCR0=0x02;TCNT0=0x00;

// Timer/Counter 1 initialization// Clock source: System Clock// Clock value: 500,000 kHz// Mode: CTC top=OCR1A// OC1 output: Toggle// Noise Canceler: Off// Input Capture on Falling EdgeTCCR1A=0x40;TCCR1B=0x0A;TCNT1H=0x00;TCNT1L=0x00;OCR1H=0x00;OCR1L=0xFF; // mức so sánh PWM

// External Interrupt(s) initialization// INT0: Off// INT1: OffGIMSK=0x00;MCUCR=0x00;

Page 2: Timer Counter

// Timer(s)/Counter(s) Interrupt(s) initializationTIMSK=0x02;

ACSR=0x80;

// Global enable interrupts#asm("sei")

while (1){// Place your code here

};}

và sau đây là sơ đồ kết nối và dạng sóng tạo ra.Nói chung là bạn nên kiếm sách để học qua về Timer trước khi làm tiếp vì chưa có cơ bản thì khó nói lắm. chúc thành công. có thể lấy quyển VDK của Thầy Tống Văn On

http://dientuvietnam.net/forums/showthread.php?p=67457#post67457File gửi kèm

Page 4: Timer Counter

Bài 4 AVR - Cách dùng Timer trong vi điều khiển AVRNgười gửi: bmnhy

Sử dụng bộ định thời là nhu cầu của nhiều lập trình viên. Thông thường mỗi loại vi điều khiển đều có bộ định thời. Hôm nay VAGAM xin giới thiệu tới các bạn bài viết về cách dùng Timer trong vi điều khiển AVR.

Đặc tính:

- Bao gồm các bộ timer 8bit 16 bit, thường có từ 3 – 4 bộ Timer- Có các kênh PWM (từ 4 đến 8 kênh tuỳ loại )- Bao gồm nhiều chế độ ngắt và PWM …- Có thể là một kênh đếm riêng biệt- Tự động xoá Timer trong chế độ so sánh(tự động nạp lại)- Có chế độ PWM- Tạo ra tần số- Đếm các dự kiện ngắt ngoài- Tạo ra các ngắt tràn và ngắt so sánh....

Introduction

Các chế độ hoạt động của timer:

Chế Độ Thông Thường:Đây là chế độ hoạt động đơn giản nhất của Timer .Bộ đếm sẽ liên tục đếm tăng lên cho đến khi vượt quá giá trị lớn nhất TOP và sau đó sẽ được khởi động lại tại giá trị Bottom.Trong các hoạt động thông thường thì cờ tràn sẽ được thiết lập khi giá trị trong Timer đạt giá trị không và không bị xoá đi.Tuy nhiên nếu mà ngắt tràn được chấp nhận thì cờ ngắt sẽ tự động bị xoá khi ngắt được thực hiện.Giá trị trong Timer có thể được viết vào bất cứ lúc nào

Chế Độ So Sánh (CTC): Đấy là chế độ mà giá trị trong Timer luôn được so sánh với giá trị trong thanh ghi ORC .Khi giá trị trong Timer bằng giá trị trong thanh ghi ORC thì giá trị trong Timer sẽ bị xoá đi.Giá trị trong ORC đóng vai trò là giá trị TOP cho bộ đếm.Chế độ này cũng cho phép tạo ra tần số so sánh ở đầu ra.Tuy nhiên trong chế độ này nếu giá trị mới ghi vào thanh ghi ORC mà nhỏ hơn giá trị tức thời của bộ đếm thì thì 1 so sánh sẽ bị lỡ, khi đó bộ đếm sẽ đếm đến giá trị lớn nhất sau đó rơi xuống giá trị 0 trước khi so sánh tiếp theo xuất hiện.

Page 5: Timer Counter

Sơ đồ thời gian của chế độ CTC

Chế Độ Fast PWM: Cho phép tạo ra sóng với tần số cao.Sự khác biệt cơ bản giữa Fast PWM với các loại PWM khác là nó chỉ sử dụng 1 sườn dốc.Bộ đếm sẽ đếm từ Bottom đến Max sau đó khởi động lại từ bottom. Trong chế độ không đảo đầu ra của chân so sánh OCx sẽ bi xoá khi có phép toán so sánh giữa TCNTx và thanh ghi ORC là bằng nhau. Và sẽ được sét lên 1 khi giá trị đạt Bottom. Trong chế độ đảo ,đầu ra đảo sẽ được set lên 1 khi sự so sánh giữa thanh ghi ORC và giá trị trong Timer bằng nhau và sẽ bị xoá khi giá trị đạt Bottom.Trong cả hai trường hơp này tần số của chế đô Fast PWM đều gấp đôi so với chế độ phase correct PWM sử dụng hai sườn dốcVới tần số cao này chế độ độ Fast PWM rất tốt cho các ứng dụng như ADC hay chỉnh lưu.Ngoài ra với tần số cao giúp làm giảm kích thước của thiết bị ngoài như cuộn dây tụ từ đó giúp làm giảm toàn bộ chi phí cho hệ thốngSơ đồ dưới đây mô tả chu kỳ thời gian của chế độ:

Biều đồ thời gian chế độ Fast PWM

Page 6: Timer Counter

Chế độ Phase correct PWM: Chế độ này hoạt động dựa trên hai sườn lên xuống.Bộ đếm sẽ đếm liên tục từ giá trị BOTTOM đến giá trị MAX và sau đó từ giá trị MAX đến giá trị BOTTOM.Trong chế độ so sánh không đảo chân so sánh (OCx) sẽ bị xóa khi giá trị TCNTx bằng giá trị OCRx trong quá trình đếm lên và sẽ được set bằng 1 khi giá trị so sánh xuất hiện trong quá trình đếm xuống.Chế độ so sánh đảo thì các giá trị là ngược lại.Với hoạt động hai sườn xung này thì chế độ này không tạo ra được tần số nhỏ như chế độ một sườn xung .Nhưng do tính cân đối của hai sườn xung thì nó tốt hơn cho điều khiển động cơChế độ phase correct PWM hoạt động cố định là 8 bít.Trong chế độ này bộ đếm sẽ tăng cho đến khi đạt giá trị MAX ,khi đó nó sẽ đổi chiều đếm.Biểu đồ thời gian đây mô tả hoạt động của toàn bộ quá trình:

Từ biểu đồ thời gian ta nhận thấy việc thay đổi tần số trong hoạt động của phase correct PWM có thể thay thế bằng hai giá trị là MAX và BOTTOM. Nó linh hoạt hơn so với chế độ Fast PWM.Tần số có thể tính theo công thức như sau:

f=fc/N*510

Trong đó N tạo ra bởi bộ chia nó có các giá trị là:1,8,64,256 hoặc 1024

Các thanh ghi trong bộ Timer/ Counter:

Thanh ghi điều khiển - TCCRx:

Page 7: Timer Counter

Bít 3,6 –WG00-WG01: Đây là các bít chọn chế độ trong Timer.Các giá trị được mô tả trong bảng sau.

Bảng chọn chế độ Timer:

Bít 5-4 : COM00-COM01: Quy định giá trị đầu ra trong các phép so sánhBít 2: 0 – CS2:0 :Đây là các bít quy định xung cấp cho hoạt động của Timer.Bảng dưới đây mô tả toàn bộ các giá trị

Chọn chế độ cho xung Clock

Thanh ghi cờ ngắt-TIFR:

Bít 1-OCFx : Khi hai giá trị bằng nhau bít này được set lên bằng 1Bít 1-TVOx : Khi bộ đếm vượt quá giá trị Top thì bít này được set bằng 1

Thanh ghi mặt nạ ngắt-TIMSK:

Bít 1 – OCIEx: khi bít này được set lên bằng 1 thì cho phép ngắt so sánhBít 0 –TOIEX : Khi bít này được set lên bằng 1 thì cho phép ngắt tràn

Page 8: Timer Counter

đoạn chương trình trên dùng timer1. Timer này là bộ đếm 16bit nên giá trị đếm được tối đa là FFFF. Trong phần khởi tạo Timer ta khởi tạo xung clock cho bộ đếm là 125Khz = 125000 có nghĩa là bộ đếm sẽ đếm được 125000 giá trị trong 1 giây. Ta làm phép tính như sau:

125000 số ----1 giây? số----- 0,02 giây (20ms)ta tính được trong 20ms bộ timer sẽ đếm được là: 125000x0.02= 2500 số.Ta cần là làm sao cho timer1 đếm được 2500 số sẽ tràn có nghĩa là cần phải nạp vô nó một giá trị xác định trước (mặc định nó sẽ đếm từ 0000>FFFF và bị tràn) giá trị này sẽ nhỏ hơn 65535(FFFF) là 2500 (9C4 Hexa) vậy ta tính được giá trị cần nạp lại sau mỗi lần tràn là FFFF- 9C4 = F63B.

#include  

unsigned  char  count=0;

interrupt  [TIM1_OVF]  void  timer1_ovf_isr(void)  //ngat  xay  ra  sau  20ms{TCNT1H=0xF6;  //giá  trị  nạp  lại  TCNT1L=0x3B;//  goi  ham  can  xu  li  sau  20mscount++;if  (count>10){count=0;//goi  ham  can  xu  li  sau  2s  }}

voidmain(void){//Timer/Counter1initialization//Clocksource:SystemClock//Clockvalue:125.000 kHz// Mode: Normal top=FFFFh//OC1A output:Discon.//OC1Boutput: Discon.//Noise Canceler: Off// InputCaptureon Falling Edge// Timer1Overflow Interrupt: On// Input Capture Interrupt: Off//Compare A Match Interrupt:Off//Compare B Match Interrupt: OffTCCR1A=0x00;TCCR1B=0x03;TCNT1H=0xF6;TCNT1L=0x3B;ICR1H=0x00;ICR1L=0x00;OCR1AH=0x00;OCR1AL=0x00;OCR1BH=0x00;OCR1BL=0x00;#asm("sei")  //bat  co  cho  phep  ngat  toan  cuc  neu  khong  thi  khong  co  ngat  xay  rawhile  (1)

Page 9: Timer Counter

{..........................};}===========================================================================

Co hai khai niem ve bo dinh thoai va counter.

1. Trong AVR tuy theo cac loai ma cac bo dinh thoi khac nhau, co bo dinh thoi 8 bit, co bo dinh thoi 16 bit. Bo dinh thoi nay dua tren co so cua clock ma ban su dung de dem, tan so cua bo dinh thoi hoan toan co the biet duoc tuy theo gia tri cua xung clock ban dung. Ta co the dung voi tan so cua xung clock, hoac clk/2, clk/4 ......... Khi bo dinh thoi tran (over flow) no se tro ve 0. binh thuong gia tri tran defalut la gia tri maximum cua bo dinh thoi, tuy nhien ta co the thiet lap gia tri tran cho bo dinh thoi. Neu su dung Codevision avr, ban co the thiet lap gia tri nay trong Codewizard khi khoi tao chuong trinh.

2. Couter: ve ban chat thi counter cung khong khac so voi bo dinh thoi lam. Tuy nhien ve dinh nghia thi counter la mot bo dem, nghia la no dem gia tri cua mot su kien nao do. Nhu vay ve nguyen tac thi counter co the co tan so khac nhau!!Neu ban su dung timer giong nhu mot bo dem, thi ban phai de y khi bo dinh thoi bi tran, phai co viec xu ly de cho counter ko bi reset.

ta co the xay dung bo dem thoi gian su dung bo dinh thoi trong AVR, truoc tien ta phai xac dinh tan so ca abo dinh thoi, gia tri tran cua bo dinh thoi de sao cho khi no tran thi thoi gian tu diem xuat phat den luc tran la 0.1 giay chang han (vi du the), bang viec dem so lan tran (vi du 10 lan) ban co duoc 1 giay, tu do ban se dem duoc phut va gio tuong ung dua tren viec tran cua bo dinh thoi.

=============================================================================

Timer bắt đầu đếm khi bạn cấp clock cho nó.Tức là ngay sau câu lệnh set bit CS00, CS01, CS02 của thanh ghi TCCR

===============================================================

Ban co the dung ngat Input Capture Interrupt (ICP) cua timer1 de lam viec dem tan so. Tren atmega co mot Pin ICP, ban tim xem voi atmega8535 no la chan nao. Noi chan ICP nay voi tien hieu ma ban can dem.

Chu y:- kich hoat ngat ICP- xac dinh dem suon len hay suon xuong

Sử dụng codevision la tốt nhất. chỉ cần khai báo là xong!Khai báo Timerx làm bô đếm ngoàikhai báo sườn lên hay xuốngtrong đó có các ngắt ví dụ như tràn TOV so sánh với A,B...bạn viết với codevision rất tiện

Page 10: Timer Counter

Atemega8 có thể dùng với cả dao đông trong lẫn dao đông ngoài. Nguồn dao đông bạn co thể xem trong datasheet (page 24).

Nếu dùng dao đông trong, bạn nên để ý:- Set Fusebit- Khi nạp chương trình, bạn vẫn cần mot dao đông ngoài để nap. ( môt dạng như là kích hoạt dao đông nôi)- gia trị lớn nhất có thể là 8 MHz với Atmega8=======================================================================

Đặc tính:

- Bao gồm các bô timer 8bit 16 bit, thường có từ 3 – 4 bô Timer - Có các kênh PWM (từ 4 đến 8 kênh tuỳ loại ) - Bao gồm nhiều chế đô ngắt và PWM … - Có thể là môt kênh đếm riêng biệt - Tự đông xoá Timer trong chế đô so sánh(tự đông nạp lại) - Có chế đô PWM - Tạo ra tần số - Đếm các dự kiện ngắt ngoài - Tạo ra các ngắt tràn và ngắt so sánh ....

==========================================Introduction

--Các chế đô hoạt đông của timer:--

--Chế Đô Thông Thường:-- Đây là chế đô hoạt đông đơn giản nhất của Timer .Bô đếm sẽ liên tục đếm tăng lên cho đến khi vượt quá giá trị lớn nhất TOP và sau đó sẽ được khởi đông lại tại giá trị Bottom.Trong các hoạt đông thông thường thì cờ tràn sẽ được thiết lập khi giá trị trong Timer đạt giá trị không và không bị xoá đi.Tuy nhiên nếu mà ngắt tràn được chấp nhận thì cờ ngắt sẽ tự đông bị xoá khi ngắt được thực hiện.Giá trị trong Timer có thể được viết vào bất cứ lúc nào

--Chế Đô So Sánh (CTC): -- Đấy là chế đô mà giá trị trong Timer luôn được so sánh với giá trị trong thanh ghi ORC .Khi giá trị trong Timer bằng giá trị trong thanh ghi ORC thì giá trị trong Timer sẽ bị xoá đi.Giá trị trong ORC đóng vai trò là giá trị TOP cho bô đếm.Chế đô này cũng cho phep tạo ra tần số so sánh ở đầu ra.Tuy nhiên trong chế đô này nếu giá trị mới ghi vào thanh ghi ORC mà nhỏ hơn giá trị tức thời của bô đếm thì thì 1 so sánh sẽ bị lỡ, khi đó bô đếm sẽ đếm đến giá trị lớn nhất sau đó rơi xuống giá trị 0 trước khi so sánh tiếp theo xuất hiện.

Page 11: Timer Counter

///Sơ đồ thời gian của chế đô CTC///

--Chế Đô Fast PWM: -- Cho phep tạo ra sóng với tần số cao.Sự khác biệt cơ bản giữa Fast PWM với các loại PWM khác là nó chỉ sử dụng 1 sườn dốc.Bô đếm sẽ đếm từ Bottom đến Max sau đó khởi đông lại từ bottom. Trong chế đô không đảo đầu ra của chân so sánh OCx sẽ bi xoá khi có phep toán so sánh giữa TCNTx và thanh ghi ORC là bằng nhau. Và sẽ được set lên 1 khi giá trị đạt Bottom. Trong chế đô đảo ,đầu ra đảo sẽ được set lên 1 khi sự so sánh giữa thanh ghi ORC và giá trị trong Timer bằng nhau và sẽ bị xoá khi giá trị đạt Bottom.Trong cả hai trường hơp này tần số của chế đô Fast PWM đều gấp đôi so với chế đô phase correct PWM sử dụng hai sườn dốc Với tần số cao này chế đô đô Fast PWM rất tốt cho các ứng dụng như ADC hay chỉnh lưu.Ngoài ra với tần số cao giúp làm giảm kích thước của thiết bị ngoài như cuôn dây tụ từ đó giúp làm giảm toàn bô chi phí cho hệ thống Sơ đồ dưới đây mô tả chu kỳ thời gian của chế đô:

--Biều đồ thời gian chế đô Fast PWM --

-- Chế đô Phase correct PWM: --

Page 12: Timer Counter

Chế đô này hoạt đông dựa trên hai sườn lên xuống.Bô đếm sẽ đếm liên tục từ giá trị BOTTOM đến giá trị MAX và sau đó từ giá trị MAX đến giá trị BOTTOM.Trong chế đô so sánh không đảo chân so sánh (OCx) sẽ bị xóa khi giá trị TCNTx bằng giá trị OCRx trong quá trình đếm lên và sẽ được set bằng 1 khi giá trị so sánh xuất hiện trong quá trình đếm xuống.Chế đô so sánh đảo thì các giá trị là ngược lại.Với hoạt đông hai sườn xung này thì chế đô này không tạo ra được tần số nhỏ như chế đô môt sườn xung .Nhưng do tính cân đối của hai sườn xung thì nó tốt hơn cho điều khiển đông cơ Chế đô phase correct PWM hoạt đông cố định là 8 bít.Trong chế đô này bô đếm sẽ tăng cho đến khi đạt giá trị MAX ,khi đó nó sẽ đổi chiều đếm.Biểu đồ thời gian đây mô tả hoạt đông của toàn bô quá trình:

Từ biểu đồ thời gian ta nhận thấy việc thay đổi tần số trong hoạt đông của phase correct PWM có thể thay thế bằng hai giá trị là MAX và BOTTOM. Nó linh hoạt hơn so với chế đô Fast PWM. Tần số có thể tính theo công thức như sau:

f=fc/N*510

Trong đó N tạo ra bởi bô chia nó có các giá trị là:1,8,64,256 hoặc 1024

--Các thanh ghi trong bô Timer/ Counter:--

-- Thanh ghi điều khiển - TCCRx:--

Page 13: Timer Counter

Bít 3,6 –WG00-WG01: Đây là các bít chọn chế đô trong Timer.Các giá trị được mô tả trong bảng sau.

-- Bảng chọn chế đô Timer:--

Bít 5-4 : COM00-COM01: Quy định giá trị đầu ra trong các phep so sánh Bít 2: 0 – CS2:0 :Đây là các bít quy định xung cấp cho hoạt đông của Timer.Bảng dưới đây mô tả toàn bô các giá trị

--Chọn chế đô cho xung Clock--

--Thanh ghi cờ ngắt-TIFR:--

Bít 1-OCFx : Khi hai giá trị bằng nhau bít này được set lên bằng 1 Bít 1-TVOx : Khi bô đếm vượt quá giá trị Top thì bít này được set bằng 1

--Thanh ghi mặt nạ ngắt-TIMSK:--

Bít 1 – OCIEx: khi bít này được set lên bằng 1 thì cho phep ngắt so sánh Bít 0 –TOIEX : Khi bít này được set lên bằng 1 thì cho phep ngắt tràn

Page 14: Timer Counter

===========================đoạn chương trình trên dùng timer1. Timer này là bô đếm 16bit nên giá trị đếm được tối đa là FFFF. Trong phần khởi tạo Timer ta khởi tạo xung clock cho bô đếm là 125Khz = 125000 có nghĩa là bô đếm sẽ đếm được 125000 giá trị trong 1 giây. Ta làm phep tính như sau:

125000 số --------------------1 giây ? số----------------------- 0,02 giây (20ms) ta tính được trong 20ms bô timer sẽ đếm được là: 125000x0.02= 2500 số. Ta cần là làm sao cho timer1 đếm được 2500 số sẽ tràn có nghĩa là cần phải nạp vô nó môt giá trị xác định trước (mặc định nó sẽ đếm từ 0000-->FFFF và bị tràn) giá trị này sẽ nhỏ hơn 65535(FFFF) là 2500 (9C4 Hexa) vậy ta tính được giá trị cần nạp lại sau mỗi lần tràn là FFFF- 9C4 = F63B.

#include <mega8.h>

unsigned char count=0;

interrupt [TIM1_OVF] void timer1_ovf_isr(void) //ngat xay ra sau 20ms { TCNT1H=0xF6; //giá trị nạp lại TCNT1L=0x3B; // goi ham can xu li sau 20mscount++; if (count>10) { count=0; //goi ham can xu li sau 2s } }

void main(void) { // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 125.000 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: On // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: OffTCCR1A=0x00; TCCR1B=0x03; TCNT1H=0xF6; TCNT1L=0x3B; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; #asm("sei") //bat co cho phep ngat toan cuc neu khong thi khong co ngat xay ra while (1)

Page 15: Timer Counter

{ .......................... }; }

Sau đây xin giới thiệu mọi người cách điều khiển đông cơ PWM(Pulse Width Modulator) bằng AVR . c ó khá nhiều loại mạch cầu trong bài viết này mình giới thiệu mọi người cầu IRF – RELAY. Ưu điểm là rẻ , đơn giản chỉ cần băm xung 1 kênh . Tuy nhiên nó có nhược điểm rất lớn là khả năng , tần số đảo chiều thấp. Sơ đồ mạch điện :

Với sơ đồ như trên chân đk IRF được nối trực tiếp với chân PORTD.5 hay chân OC1A . Với Atmega 16L có 4 kênh băm xung nếu các bạn xem datasheet sẽ thấy timer 0 và timer 2 chỉ có

Page 16: Timer Counter

1 bô PWM 8 bit và có đầu ra ở chân OC0 và OC2 trong khi đó timer1 có 2 bô băm xung 16 bit và có đầu ra là OC1A và OC1B .Tuỳ loại avr mà số kênh PWM nhiều hay ít khác nhau .Atmega88 có tới 6 kênh băm xung , Atmega128 có tới 8 kênh băm xung. Với cách mắc như sơ đồ để đông cơ chạy ta cho giá trị ra ở portD.5 là logic 0 , hay trong phần chọn Out A : inverted

Trong tiện ích codeWizardAVR ta chọn như sau :

Chọn chế đô Phase Correct 8 bit , khi đó để điều khiển tốc đô của đông cơ ta chỉ cần đổi các giá trị trong thanh ghi OCR1AL từ 0 -> 255 . #include <mega16.h>

// Declare your global variables here #define V_DC OCR1AL #define RELAY PORTD.6 void main(void) { // Declare your local variables here

// Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T

Page 17: Timer Counter

PORTA=0x00; DDRA=0x00;

// Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00;

// Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00;

// Port D initialization // Func7=In Func6=Out Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=1 State5=1 State4=T State3=T State2=T State1=T State0=T PORTD=0x60; DDRD=0x60; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 3.906 kHz // Mode: Normal top=FFh // OC0 output: Disconnected TCCR0=0x05; TCNT0=0x00; OCR0=0x00;

// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 500.000 // Mode: Ph. correct PWM top=00FFh // OC1A output: Inverted // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0xC1; TCCR1B=0x02; //bam xung voi tan so gan 1KHz TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;

Page 18: Timer Counter

// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00;

// External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00; MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;

// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00;

// Global enable interrupts #asm("sei") while (1) { // Place your code here V_DC=0; delay_ms(10); RELAY=1; V_DC=255;//quay thuan toi da delay_ms(2000); V_DC=0; delay_ms(10); //khi dao chieu ban phai tat IRF neu khong se hong relay RELAY=0; //dao chieu dong co V_DC=125; // Chay 50% toc do toi da Delay_ms(5000); }; }

Hiện tại em đang thử xuất xung PWM đk đông cơ DC qua chân PD7 của con Atmega 8535.Thạch anh em xài là 11,0592MHz. Nhưng em mới vừa chuyển qua AVR nên ko bít cơ chế xuất xung PWM của AVR

như thế nào(đọc tiếng Anh tệ quá nên vẫn chưa hiểu rõ lắm ).Qua bên diendandientu.com thì thấy có

Page 19: Timer Counter

mấy bác nói về việc này,nhưng em đọc code vẫn thắc mắc không bít có phải OCR2 là quy định cái duty cycle của PWM ko nữa,còn cái TCNT2 dùng làm gì nhỉ ?Các anh gúp em với !CẢm ơn anh trc nghen!

OC2 (PD7) là tín hiệu đầu ra của khối PWM trong Atmega8535. Tín hiệu này làm việc với bô định thời Timer2.

Bạn phải khởi tạo bô định thời timer 2 trước tiên bằng cách thiết lập thanh ghi TCCR2 (3 bit: CS20, CS21, CS22). Giá trị của 3 bit này xác định tần số làm việc của Timer2.

Sau đó bạn phải thiết lập PD7 là đầu ra của PWM thông qua thanh ghi TCCR2 (bit WGM20 = 1, WGM21 = 1: fast PWM)

Xác định chế đô đầu ra là Non-inverted PWM: thônng qua các bít sau trong TCCR2 (COM2.1 =1, COM2.0 = 0 )

Như vậy đầu ra đã sẵn sàng. Để thay đổi đô rông xung, bạn chỉ cần thay đổi giá tri của thanh ghi OCR2. Chú y là giá trị này phải nhỏ hon 256 vì chế đô làm việc ở trường hợp này là PWM 8 bit. Nói cách khác OCR2 quy định cái duty cycle của PWM.

Nếu làm việc với fast PWM, giá trị TCNT2 nên đặt bằng 0. Nếu làm việc ở chế đô so sánh thì OCR2 sẽ so sánh với giá trị TCNT2 để tạo ra đầu ra.

Vi dụ :

Code:

interrupt [USART1_RXC] void usart1_rx_isr(void){data=UDR1; if(data == 'a'){ count +=5; if(count >=30000) count = 30000;} else if(data == 'd'){ count -=5; if(count <=0) count = 0;}}void main(void){char receive_char;UCSRA=0x00;UCSRB=0x18;UCSRC=0x86;UBRRH=0x00;UBRRL=0x33;while (1){OCR1AH = count>>8;OCR1AL = count;

Page 20: Timer Counter

};}

Ví dụ trên tôi viết cho atmega8, nên co lẽ ko chạy dc với 8535, tuy nhiên về nôi dung thi như nhau. đô rông xung thay đổi khi ân kí tư 'a' hoac 'd' tu bàn phím, bạn có thể nhìn thấy sự thay đổi nếu dùng đông cơ hoặc oscilloscope

Anh jindo_vn nói thật rõ ràng!EM cám ơn anh nhiều lắm!Anh cho em hỏi thêm cái này nghen,em đọc trong datasheet của Atmega8535 thấy nó bảo : trong chế đô Phase correct PWM,ở Non-inverting Compare output mode, OC2 sẽ clear khi có compare match giữa TCNT2 và OCR2(khi đếm lên) và set khi có compare match giữa TCNT2 và OCR2 (khi đếm xuống),nó có cả cái diagram,nhưng trên diagram em không hiểu từ period 1 chuyển qua period 2 tại sao OC2 lại bị clear. Những mũi tên từ cái OCR2 update lại không phải tại thời điểm OC2 thay đổi trạng thái??Em mới tập tành về VXL nên khả năng đọc mấy cái diagram này không tốt lắm,anh giúp giùm em nhe

! Thanks anh nhiều nhiều!!!!

Đồng ý với bạn là cái diagram đó thiếu, trên giản đồ thời gian cua TCNT, nhung chỗ có gạch ngang phải là những chỗ OCR2 update.

Điều khác biệt cua Phase corect PWM la ở chỗ TCNT đếm đến giá trị MAX rồi nó sẽ đếm ngược mà ko quay trở lại giá trị MIN như ở fast PWM. Chính vì vạy mới nảy sinh ra việc clear hay set khi đếm ngược và đếm xuôi.

====================PWM sử dụng bô định thời trong AVR kết hợp với môt bô so sánh để tạo đầu ra PWM.

giả sử bô định timer đếm từ 0 -> 255giả sủ giá trị đặt để so sánh là 128, giá trị này quan hệ tuyến tính với đô rông cua xung PWM

khi timer đếm tu 0 -> 128, đẩu ra cua PWM ơ mức cao128 -> 255 đầu ra cua PWM ở mức thấp

Vi vặy nếu thay đổi giá trị đặt, đô rông của tin hiệu PWM ở mức cao và mức thấp sẽ thay đổi.

Đo là nguyen tắc hoạt đông cua PWM, tất nhiên là còn nhiều chế đô PWM khác, tuy nhiên cơ bản là vậy.

Ở đây là thiếu hay sai?Thiếu cái jì?.Nguyên tắc vầy là sai.Mọi người xem lại đi.Bạn nào có thể giải đáp 1 số thắc mắc của mình với:+Điểm khác Phase and frequency correct PWM so với chế đô phase correct PWM mode là thời gian thanh ghi OCR1x được updated bởi thanh ghi đệm OCR1x.(mình dịch ra là vậy)Mình chưa hiểu rõ ý này?+bạn nào có thể nói rõ hơn về hoạt đông đồng bô của Timer2 được ko?ứng dụng khi nào?Mình mới bắt đầu dịch datasheet.bạn nào biết chỉ giáo nheHy vọg 4rum này sẽ sôi đông hơn.

Mình mới biết sơ qua như datasheet nói: phase correct PWM mode dùng cho đk đông cơ vì nó đối xứng, còn fast PWM thì phù hợp cho tính toán mạnh, chp DAC và lọc, cũng làm cho các thiết bị vật lý kích thước nhỏ hơn.Chỉ là lý thuyết datasheet.Bạn Jinđo_vn có thể nói rõ hơn thực tế dùng các chế đô đó như thế nào ko?hay dùng chế đô nào nhất?nếu có thế cho đoạn code tham khảo thì càng tốt.thanks

Page 21: Timer Counter

tổng quan về DAC :Khi nói tới DAC có lẽ trongchungs ta khong ai là không nghĩ tới đó là chip DAC !!! Hê hê hê (ví như có lần tôi tranh luận với Fallear bên dientuvietnam.net khi tôi nói tới DAC thì F chụp đầu tôi là con chip DAC hô hô - !!! )Thực chất đối với tôi và quan điểm của tôi DAC xet về mặt toán học đây là môt phet biến đổi từ không gian số học rời rạc sang không gian tương tự. Và để thực hiện phep biến đổi này chúng ta có 2 kĩ thuật gần đúng đó là kĩ thuật DAC và kĩ thuật PMW (mà tôi biết).Xet về mặt toán học mà nói thì hai phương pháp này đều là phuêong pháp xấp xỉ xong với đô chính xác khác nhau.(như vậy khi nói tới DAC chúng ta hãy nghĩ tới khâu DAC đừng nghĩ ngay tới chip DAC-PMW cũng có thể coi là DAC)Phương pháp DAC có đô chính xác tiệm cận cao và thưong f được sử dung trong các hệ xử lý tín hiệu.Phương pháp PMW có sai số tiệm cận lớn hơn và nó phù họp trong cacmachj công suất .AVR có trang bị các bô PMW với số lượng và số bít khác nhau.Để tạo môt chip DAC từ bô PMW thì chúng ta có thể mắc nối tiếp chúng với môt mạch lọc thông thấp LC (có thể thông qua môt transistor đệm hoặc 1 con IRF) nhưng đô chính xác không cao.Để điều khiển các bô PMW chúng ta cũng làm các bước sau:bước 1: Khởi tạo trạn thái cho bô PMW bao gồm các thông số điều khiển,các thông số dữ liệu ,,,,,,,,buồn

ngủ quá !!!!!!!!!!!!! mai viết tiếp !!!

Lập trình đa nhiệm cho vi điều khiển

Cái này trước đây tớ viết cho DTVN hôm nay Copy lại sang đây !!!Lập trình đa nhiệm cho hệ thống nhúng khác với lập trình có cấu trúc và lập trình tuyến tính là.Chúng không thực hiện môt khối lệnh môt cách liên tục (hàm) mà khối lệnh đó được chia nhỏ và thức hiện sen kẽ với các đoạn lệnh trong các khối lệnh khác.Về cấu trúc chương trình thì lập trình đa nhiệm không có môt chương trình chính (hay hàm main trong C) mà chúng chia thành các task.Các task này được đặt trong bô nhớ ,và có môt câu hoỉ được đặt ra là vậy thì các task này sẽ hoạt đông như thế nào ?Đúng vậy chúng phải có môt chương trình để điều khiển chúng và có tên rất quen thuôc là Kernel.Kernet có nhiệm vụ quản lý sự hoạt đông của các task bao gồm các công việc : Phân hạch thời gian,quản lý tài nguyên …

Như vậy để có thể xây dựng được môt hệ thống đa nhiệm trên VĐK thì các bạn cần có những yêu cầu gì về phần cứng và phần mềm?

Về phần cứng:Môt điều không thể thiết đó là môt bô timer tích hợp trong VĐK.Nó có nhiệm vụ tạo đơn vị thời gian.(Có nghĩa là môt chu kì hoạt đông của hệ thống được chia nhỏ thành các đơn vị thời gian).Bô nhớ chương trình đủ lớn để chứa các mã lệnh .Ngoài mã lệnh của các task cong mã lệnh của Kernel .Bô nhớ RAM cũng là môt vấn đề rất hạn chế của VĐK vì mỗi lần chuyển ngữ cảnh thì toàn bô ngữ cảnh của môt Task được lưu vào môt ngăn xếp trong RAM.Chúng ta có càng nhiều task thì cần cành nhiều ngăng xếp kiểu này (Các bạn đừng nhầm ngăn xếp này với ngăn xếp cứng nhe ! đây là ngăng xếp do phần mềm chúng ta phải tạo ra)Cụ thể chúng là bao nhiêu thì tùy vào các ứng dụng mà các bạn mới có thể xác định được.Về phần mềm:Các bạn hiện gời có hai công cụ để lập trình cho VĐK đó là ngôn ngữ bậc thấp (Assembly) và ngôn ngữ bậc cao (C ,basic…,nhưng tôi chỉ dùng C) và ở hai ngôn ngữ này các bạn đều có thể lập trình đa nhiệm cho VĐK được.Với Assembly đây là ngôn ngữ mà các bạn có thể làm mọi chuyên được với VĐK nhưng thực sự nó chỉ dành cho những người quá chuyên nghiệp.Để lập trình đa nhiệm cho VĐK bằng ngôn ngữ này thì các bạn phải bắt đẩu từ con số 0 !!! bạn phải xây dụng toàn bô Kernel cho ứng dụng của bạn và nó chỉ phù hợp với các ứng dụng rất nhỏ (Đối với tôi và không giám nói tới các cao nhân).Nếu bạn nào đam mê có thể đọc quyển sách :”Real time system and programming languages” Có gần như tất cả các thuật toán tối ưu để các bạn có thể xây dựng Kernel. Song thế mạnh của Assembly là bạn có thể xác định được chính xác thời gian mà môt task của bạn thực hiện và tất nhiên điều đó đồng nghĩa với việc hệ thống của các bạn sẽ tố ưu.(Thế mạnh của Assembly mà).

Page 22: Timer Counter

Với C và các ngôn ngữ bậc cao khác thì sao nhỉ ?bạn đã được cung cấp môt Kernel rồi và vấn đề của các bạn là sử dụng chúng mà thôi .Nếu như phần mềm các bạn sử dụng mà chưa có thì các bạn vào các trang Web của bản hãng để mua về !!!(Vấn đề là mất tiền) tôi xin thí dụ như để viết cho 8051 Keil C có môt nhân đó là RTX51.Với AVR là ….Trời tôi quên mất rồi vì hôm trước chỉ xem trên Web thôi họ không cho free nên không có (!!! Bác nào có thì share cho em nhe) Vấn đề sd nhân RTX51 thì cũng không có gì khó cả .Các bạn có thể xem phần hướng dẫn của Keil C là có hết.Tôi xin tóm tắt đôi chut :Các cú pháp của chương trình C thì hoàn toàn không có gì khác cả chỉ có khác về mặt cấu trúc.Các bạn không cần hàm “main” mà thay vào đó là hàm khởi tạo các task Ví dụ :void init (void) _task_ 0 { /* sau khi Reset chương trình sẽ chạy từ đây */os_create_task (1); /* Bắt đầu task 0 hoạt đông */os_create_task (2); /* task 1 hoạt đông */os_create_task (3); /* */os_delete_task (0); /*dừng khởi tạo các task */}Các bạn sẽ nói chaẻng khác gì các chương trình C khác cả nhưn sự thật là cúng sẽ được thực hiện “đồng thời” và thời điểm mỗi task bắt đầu là khác nhau mà thôi. Và các bạn khai báo các task “như”(theo nghĩa hình thức) các chương trình con mà các bạn cần thực hiện.Ví dụ:void readADC (void) _task_ 1 {

// nôi dung

}….Vậy Task này có mã hiệu là 1 và là tham số cho hàm os_create_task (má hiệu của task muốn khởi tạo.);Sau đay tôi xin gửi tới các bạn môt chương trình mẫu của Keil C rất hay và cụ thể để các bạn tham khảo:

Lập trình đa nhiệm cho VĐK dùng Assembly

Chào các bạn !

Hôm trước tôi đã nói sơ về lập trình đa nhiệm cho VĐK và hướng dẫn chó các bạn dùng Keil C .Hôm nay tôi sẽ hướng dẫn cho các bạn các sử dụng Asembly (vì nó không mất tiền , và có tư duy trong sáng để các bạn hiểu hơn về lập trình đa nhiệm cho VĐK) .

Do tôi không có nhiều thời gian và cũng không thể nói hết tất cả được với các bạn nên tôi chỉ có thể giới thiệu cho các bạn những gì trung nhất và môt ví dụ cụ thể đơn giản nhất và phần còn lại đi sâu thì các bạn phải tự tìm hiểu từ các tài liệu tôi đã giới thiệu ở bài viết trước cho các bạn.

Vậy để lập trình đa nhiệm được cho VĐK bằng Assembly thì bạn cần những gì ?Trước hết bạn phải là người đã lập trình thành thạo Assembly cho VĐK (đây là điều khiên quyết).Bạn hiểu sâu sắc về cấu trúc phần cứng mà VĐK của bạn sử dụng. Cụ thể là :Bạn cần nắm được cách mà ngăn xếp của bạn hoạt đông như thế nào.Làm thế nào để bạn có thể quản lý được ngăn xếp và bô nhớ môt cách hợp lý.

Các khái niệm cơ bản các bạn cần nắm được:

1.Ngữ cảnh:Là trạng thái tại môt thời điểm nào đó của hệ thống bao gồm giá trị của các thanh ghi

Page 23: Timer Counter

chung,thanh ghi tích lũy và thanh ghi trạng thái cùng thanh ghi chương trình(con trỏ chương trình PC)

2.Chuyển ngữ cảnh :Là hoạt đông chuyển quyền sử dụng CPU từ task này sang task khác,Nó bao gồm các công việc:Lưu ngữ cảnh đang thực hiện(Lư PC,PSW,B,A,Rn,DPTR với 8051 và các thanh ghi tương tự với AVR…)và khôi phục trạng thái của ngữ cảnh mới(Khôi phục các thanh ghi trên).

3.Task:Với Assembly thì task hoàn toàn là môt đoạn mã lệnh đơn thuần và khác với cách nhìn của các phương pháp lập trình trước của các bạn.Task gồm tên task và kết thúc của môt task là môt lệnh nhảy vô điều kiện trở về đầu chương trình.

Ví dụ:

ReadADC:

;ReadADC là tên của task và chính xác hơn nó là môt nhãn.

;đọang mã lệnh

Ljmp ReadADC

;lệnh nhả về đầu của task kết thúc môt chu kỳ của task

4.Tài nguyên: Tài nguyên bao gồm các thiết bị ngoại vi như bô nhớ ,các Port,ADC ,DAC(Được ghep thêm)…

5.Ưu tiên: Là phương thức mà ta gán cho các task các quyền ưu tiên sử dụng CUP và tài nguyên.

Bài viết này tôi không tham vọng nói được hết những gì mà các nhà kinh điển đã viết và những gì tôi ngô được.Tôi chỉ có thể hướng dẫn các bạn cách thiết kế cho môt chương trình đa nhiệm đơn giản không có tranh chấp tài nguyên ,không có ưu tiên (các task bình đẳng).

Chúng ta sẽ bắt đầu với môt ví dụ nhe:

Lập trình cho 8051 với hai công việc là đọc cổng P1 và đưa dữ liệu ra cổng P2

Như vậy với tư duy lập trình cấu trúc hoặc lập trình tuyến tính thì các bạn sẽ lấy dữ liệu từ ADC (cổng P1) sau đó sẽ chuyển ra cổng P2(DAC).

Với tư duy lập trình đa nhiệm các bạn có thể thiết kế 2 task với task1 lấy dữ liệu và task2 chuyển dữ liệu ra cổng P2 (Ở đây tôi lấy ví dụ đơn giản cho các bạn dễ hiểu còn nếu bài toán thế này thì tất nhiên là dùng phương pháp lập trình tuyến tính thì hiệu quả hơn)

Cấu trúc của chương trình hoàn toàn như môt chương trình Assembly bình thường.

Chúng ta sẽ sử dung timer 0 để là xung nhịp chia thời gian đơn vị.Và mỗi lần ngắt của timer là môt lần chuyển ngữ cảnh (chuyển giữa các task).Như vậy chúng ta có 2 task đồng nghĩa với 2 vùng nhớ làm ngăn xếp để lưu trạng thái(ngũ cảnh).Môt vùng để lưu dữ liệu dùng chung cho các task.Và các vùng nhớ này bạn caanf chú ý và bảo vệ không được phá hủy trong các task đặc biệt là các ngăn xếp vì điều đó sẽ làm hỏng toàn bô chương trình hay cụ thể là CPU sẽ chạy loạn xạ các lệnh lên (Đây cũng là điểm yếu của Assembly-bạn phải tự quản lý tất cả).

Bước 1:Thiết kế Kernel hay viết chương trình cho ngắt timer 0(hoặc timer nào đó mà bạn chọn)Kernel này là môt nhân cơ bản nhất chỉ có hai nhiệm vụ:Định thời và chuyển các ngữ cảnh.Phần định thời ở

Page 24: Timer Counter

đây ta sẽ chọn thời gian là sau 10uS sẽ ngắt môt lần (chuyển ngữ cảnh)như vậy ta chọn timer0 chế đô tự load và giá trị các thanh ghi sẽ được thiết lập ở chương trình khi khởi tạo.Để chuyển ngữ cảnh và khôi phục ngữ cảnh bạn cần có môt biến để nhận ra task đang thực hiện để quyết định chuyển sang môt task nào đó khác.

Int_Timer0:

;Lưu ngữ cảnh đang thực hiện

Push psw

Push acc

Push b

Push dpl

Push dph

Push r7

Push r5

Push r4

Push r3

Push r2

Push r1

Push r0

Mov a,cpc

Cjne a,#2 exits

Mov stack2,sp;lưu gữ ngăn xếp

Sjmp exits

Mov stack1,sp

Exits:

;Lưu xong ngữ cảnh

;Xác định task để trả lại ngữ cảnh

Mov a,cpc

;cpc là biến trạng thái lư giữ tên của task đabg chạy (0,1,2,3…)

Cjne a,#0 task0_run

Page 25: Timer Counter

Mov cpc,#2 ;tăng con trỏ trạng thái lên 2 để báo task 2 đang ;chạy

;đây là lần chạy đầu tiên của task1 ngay sau khi khởi đông

Mov psw,#0

Mov a,0

Mov dptr,#task2

Mov sp,stack2

;với stack2 là môt ô nhớ lưu vị trí khởi tạo đầu của ngăn xếp ;cho task2 và được khởi tạo khi bắt đầu chạy

Push dpl

Push dph

;Lưu vị trí của task2

Sjmp exit

task0_run: Cjne a,#1,task2_run

;nếu cpc =1 thì task1 đang chạy

;khôi phục lại task2

Mov sp,Stack2 ;trở lại ngăn xếp của task2 ở đây thì stack2 lại là ;đỉnh ngăn xếp rồi

Pop r0

Pop r1

Pop r2

Pop r3

Pop r4

Pop r5

Pop r6

Pop r7

Pop dph

Pop dpl

Pop b

Pop acc

Page 26: Timer Counter

Pop psw

Inc pcp;tăng con trỏ chương trình lên 2 (task2 chiếm CPU)

Sjmp exit

;đây là trường hợp cpc=2

;task2 đang chiếm CPU thì bị ngắt

;khôi phục lại task1

Mov sp,stack1

Pop r0

Pop r1

Pop r2

Pop r3

Pop r4

Pop r5

Pop r6

Pop r7

Pop dph

Pop dpl

Pop b

Pop acc

Pop psw

Mov cpc,#1

;task1 chạy

Exit:

Reti

Chương trình mẫu (để các bạn tham khảo vì lâu rồi không viết cho 8051 đôi chút cũng s

Stack1 equ 07FH ;bien trang thai

Stack2 equ 07EH ;bien trang thai

Page 27: Timer Counter

Cpc equ 07DH ;bien trang thai

GenralR equ 07EH ;bien du lieu dung chung

Org 00h

Ljmp start

Org 00BH

Ljmp int_timer0 ;ngat int0

Org 0030H

Start:

;đoạn khởi tạo chương trình

Mov psw,#00

;cấm các ngắt

;thiết lập timer 1 chế đô tự load và tính toán sao cho sau 10uS thì ngắt ;môt lần phần này các bạn tự viết.

Mov Stack1,#0h

Mov Stack2,#03Fh

Mov SP,#02Fh

Mov cpc,#0 ;khởi tạo con trỏ task

;cho phep ngắt

Task1:

;Lấy dữ liệu từ ADC (P1) đưa vào thanh ghi GenaralR

Ljmp task1 ;kết thúc task

Task2:

;lấy dữ liệu từ thanh ghi GenaralR dưa ra DAC qua Port P2

Ljmp task2;Kết thúc task 2

Int_timer0:

;nôi dung như trên

;Hết chương trình.

Chú ý rất quan trọng:Nếu như trong các task các bạn muốn sử dụng ngăn xếp thì cács bạn cần phải

Page 28: Timer Counter

sửa lại Kernel cho phù hợp.(điều này giành cho các bạn)và đặc biệt các biến trạng thái thì các bạn không được thay đổi trong các task.Để đặt mức ưu tiên và SD chung tài nguyên thì các bạn cần có các biến trạng thái tương ứng để lưu trạng thái đã bị chiếm của tài nguyên và mức ưu tiên của các task.(Ở đây chưa tính đến thời gian tới hạn của môt task ).Các thuật toán các bạn đọc tại cuốn sách mà bài viết trước tôi đã nói tới.

AVR hay các vi điều khiển khác thì nguyên tắc tương tự (Trừ PIC có ngăn xếp riêng thì hơi khác.Mong bạn nào viết nhiều cho PIC thì cùng chia sẻ với anh em.)

các bác cho em hỏi chế đô input capture trong avr hoạt đông như thế nào vậy, nó được ứng dụng làm gì thế. BÁc nào biết chỉ em phát

input capture là tên của môt chân l\lối vào (input pin) của AVR, chân này nối với khối input capture, chức năng của khối này là : Khi có sự kiện (rising,falling,level) ở chân input capture thì giá trị của thanh ghi bô định thời (1,2...) sẽ được cập nhật (coppy) vào thanh ghi input capture register. Chức năng này dùng để đo khoảng thời gian giữa các sự kiện. Để ý là khi xảy ra sự kiện input capture thì sẽ tạo ra 1 ngắt,nếu ngắt input capture được cho phep. Như vậy chức năng input capture có liên quan mật thiết tới bô định thời, nên bạn cần tìm hiểu bô định thời.

chức năng này dùng để bạn đo đô rông xung . Dung khá nhiều trong giao tiếp hồng ngoại

Xung được đưa trực tiếp vào chân ICP. Giả sử đặt ICP làm việc ở chế đô gọi ngắt khi có rising edge thì trong hàm ngăt sẽ có môt biến counter dùng để đếm số lần có xung sườn lên đưa vào pin ICP. Như vậy mỗi lần có xung thì giá trị counter sẽ tăng lên 1.

Chú ý: - counter bi tràn.- Nếu xung được tạo ra bởi các sự kiện bấm nút thì vấn đề lọc các xung nhiễu cần được xử lý trước khi đưa vào ICP

Vì ICP nó làm việc cùng với các bô định thời nên khi có ngắt ICP, bạn có thể ghi lại thời điểm xảy ra ngắt. Từ đó có thể ứng dụng làm các applications khác nhau. Chẳng hạn đo tần số, đo vận tốc, đo gia tốc. vv....

Khi đo đô rông xung, chú ý là trong chương trình ngắt nên đọc giá trị của ICR sớm nhất có thể nếu không sẽ bị các giá trị capture lần sau ghi đè lên, sau đó là đổi sườn cature. Cuối cùng làm gì thì làm

không phải nó lưu khoảng thời gian đâu bạn ạ. Cứ mỗi môt lần có sự thay đổi mức ở trên chân inputcapture thì nó copy giá trị của timer vào trong thanh ghi (hình như là ICR). mình dựa vào các giá trị đó và tần số đếm của timer để mình tính toán thời gian thôi. Chúc thành công

bạn có thể nói rõ hơn dc ko?có phải nó có khả năng bắt giá trị thời gian và lưu giá trị đó vào thanh ghi ICR như bạn nói đó.nhưng nếu khoảng thời gian mình bắt là thuôc vào 2 chu kì liên tiếp của Timer thì tính sao đây ?bạn có thể post cho mình code ví dụ dc ko? mình đang rất cần.

Trong trường hợp mà khoảng thời gian mình bắt rơi vào 2 chu kỳ liên tiếp của timer thì khi đó bạn sẽ sử dụng ngắt tràn timer. Mỗi môt lần tràn giá trị đếm bạn lưu vào môt cái gì đó, để biết được là nó tràn mấy lần. Như vậy là thoải mái rồi đúng không. ???

chào các pác.em mới nhập môn AVR không lâu và chọn Atmega8 làm điểm xuất phát. Trong quá trình học tập trên diễn đàn em đã học được nhiều từ các anh đi trước. Nhưng em vần thấy trong Box này vẫn thiếu cái Thread gì đó.

Page 29: Timer Counter

Nếu nhìn ngay bên anh em PIC thì chúng ta có thể thấy ngay họ có những Thread rất hay,các Thread đó đánh đúng vào 1 vấn đề gì đó của con VĐK mà mình đang sở hữu như: ADC, UART, PWM, Timer ... nên em dám mở luồng này vì em thấy có 1 số điểm như sau:1. Để các bạn vào đây cùng thảo luận về 1 vấn đề gì đó mà chúng ta quan tâm để chúng ta học tập và trao đổi kĩ về 1 vấn đề gì đó và luồng này chúng ra sẽ thảo luận về Timer của AVR.2. Thuận tiện trong quá trình quản lí của MOD để những câu hỏi của chúng ta không phải trùng lặp lại hay ở đâu đó có những câu hỏi tương tự.3. Tập trung giải quyết các vấn đề liên quan, các vướng mắc...

Với những gì mình đã nói ở trên mình muốn đưa ra 1 số câu hỏi mở màn như sau mong anh em giúp đỡ và cũng là cho các bạn mới học AVR có những cái nhìn tổng quan hơn khi tiếp xúc với bất kì 1 loại AVR nào dù nó là Atmega hay bất kì loại nào ...1. Các chế đô hoạt đông của các Timer0,1,2 ?2. các chế đô PWM trong Timer1,2 ???cách sử dụng các Mode trong các ứng dụng thực tế ...3. Chế đô InputCapature, ứng dụng?4. Timer định thời như thế nào? Tần số? Khi nào bô định thời làm việc như 1 bô đếm, nó đếm như thế nào?

Mình hỏi vậy không là phải hỏi cho mình mà là vấn đề chung cho những ai mới học AVR.Hy vọng Topic này sẽ được nhiều người ủng hô.Rất mong các cao thủ như Sphinx, NVT2, QD... hạ sơn giảng giải giúp cho chúng em được thỏa lòng với "nàng tiên AVR" xinh đẹp.

mình bắt đầu từ đâu đây chú hùng. Cái timer này thì mình cũng biết đc vài đường cơ bản. -Timer nào thì cũng có hai chức năng là đếm xung và đếm thời gian. Việc mà bạn chọn đếm xugn hay đếm thời gian thì vào trong thanh ghi TCCRn (n là chỉ số của timer -- timer 0 thì n=0), giá trị đếm được thì được ghi vào thanh ghi TCNTn (Lưu ý là nếu thanh ghi TCNTn được ghi giá trị nào đó !=0 trước khi khởi đông thì sau khi khởi đông T/C (timer/counter) sẽ bắt đầu đếm từ giá trị đó lên. Sau khi tràn thì lại đếm từ 0). Có vài bít trong thanh ghi này qui định, nếu là đếm thời gian thì đem tần số thạch anh chia cho bao nhiêu để dc tần số đếm. Còn với đếm xung thì bạn đưa xung vào chân Tn, đặt cấu hình là chân vào bằng phần mềm. Sau đó dùng mấy cái bít trên xác định xem đếm sườn lên hay xuống. Thế là xong.

-Việc ngắt timer hay counter được cho phep qua thanh ghi TIMSK (thanh ghi dùng riêng cho bô định thời và bô đếm).Cái này để xem bít nào cho phep thì bạn phải vào datasheet của từng con AVR thì mới rõ. Đây mình chỉ nói chung chung vậy thôi. Dĩ nhiên là lúc này bít I ở trong thanh ghi SREG được cho phep đấy nhe. -Đó là hai mấy thứ cơ bản mà cái timer và counter nào cũng có. Ở AVR thì timer còn có thêm vài chức năng nữa mình xin nói thêm môt tí về nó:+ Về cái PWM để điều khiển đông cơ thì timer vẫn đếm như bình thường. Có điều khi nó đếm nó vác cái giá trị của TCNTn ra đem so sánh với cái giá trị đặt ở tại thanh ghi OCRn để quyết định đô rông xung ở chân đầu ra (chân đầu ra ở đây được cấu hình cứng ở trên chip và bạn phải tra datasheet. hình như nó có tên là OC..gì đó). Có hai chế đô của PWM là FAST và phase correct. Ở cái FAST thì nếu mà giá trị TCNTn<OCRn sẽ cho đầu ra là 0 hoặc 1 tùy chọn ở phần mềm. Còn khi TCNTn>OCRn sẽ cho đầu ra ngược lại 1 hoặc 0. Như vậy thì trong môt chu kì đếm của timer thì trong khoảng thời gian timer đếm từ 0-->OCRn thì đầu ra là mức i, còn từ OCR--tràn thì đầu ra là mức đảo của i, vậy là có môt chú PWM. Đối với chế đô Phase..thì các bạn về tam khảo thêm nhe. nói ở đây dài lắm, còn nếu bạn nào muốn thì mail cho mình cũng dc. Trong chế đô này thì ngắt sẽ xảy ra khi đc cho phep và tại các thời điểm timer tràn và hoặc có thể ngắt tại thời điểm TCNTn=OCRn cũng được.+Nếu như bạn có môt ứng dụng nào đó muốn timer đếm từ 0 đến môt giá trị nào đó thì bị reset về 0 (giá trị này dĩ nhiên có thể khác giá trị tràn) thì có thể sử dụng chế đô CTC mode. Bạn đặt giá trị reset

Page 30: Timer Counter

vào cái thằng ICR sau đó thì timer đếm từ 0 đến ICR thì về 0 luôn. VÀ nếu như bạn cho phep ngắt thì tại đây sẽ có môt ngắt cho bạn ứng dụng.+ 2 chế đô ở trên có thể kết hợp với nhau để có được môt bô pwm rất linh hoạt. tùy theo nhu cầu của bạn.+ Về cái input capture thì nó làm việc cũng đơn giản thôi. Tai cái chân ICP, nếu được cho phep thì mỗi lần có sự thay đổi sườn xung ở trên ICP thì nó làm công việc là copy thằng TCNTn vào ICRn, chỉ có vậy thôi. Dĩ nhiên nó cũng có ngắt cho bạn lập trình dễ dàng hơn. Ví dụ bạn định đo đô rông xugn dương chẳng hạn. Bạn bắt tại sườn lên môt phát, lưu giá trị lại. Bắt tại sườn xuống ngay sau đó. Sau đó lấy giá trị mới trừ đi cái cũ và sử lý thêm cái ngắt tràn timer nữa. Tiếp đến nhân giá trị thu đc với tần số timer là xong. Được ngay cái đô rông xung....+ Watch dog thì nó làm đơn giản hơn. Nếu vì môt lý do gì đó mà chíp bị rơi vào vòng lặp vô hạn không thể tiếp tục công việc của mình được (kiểu như là bị treo ấy) thì lúc này WDog sẽ làm việc. Nó sẽ kiểm tra khi chíp bị treo, nó sẽ tính ra môt khoảng thời gian nào đó mà ko thoát ra dc thì nó sẽ tự đôgn reset chip. Cái duy nhất bạn phải làm là chọn xem sau bao lâu thì reset thôi. Vào datasheet xem thanh ghi nào qui định thời gian này nếu bạn lập trình dùng ASM. Còn codevision thì cứ tick vào phát là xong. chả cần biết nó tên tuổi gì. + Trong bô timer và conter của nó có nhiều chế đô lắm, nói ra đây không hết được đâu. Bạn nào có vấn đề gì ở chỗ nào thì hỏi trực tiếp. Anh em ở đây giải quyết cho.-------------------------------Em nói chắc sẽ có nhiều chỗ sai lắm. Mong mọi người góp ý làm sửa chữa làm cho luồng này tốt hơn.

Để em nói qua môt chút về Timer vậy Uhm hum nay vừa đọc lại xem cái timer của AVR, cái Timer0 là timer 8-bit, nói chung theo datasheet nó được sử dụng vào các ứng dụng là bô đếm, bô tạo dao đông, đếm sự kiện ngoài. Timer0 gồm 4 thanh ghi là TCCR0, TCNT0, TIMSK, TIFR.TCCR0 - thanh ghi cho phep lựa chọn nguồn clock của Timer, thông qua việc đặt cho các bit của nó là CS00, CS01, CS02. Cụ thể đặt như thế nào thì đọc thêm Datasheet sẽ biết. Nếu là sử dụng Timer/Counter0 như môt Timer thì trong CodeVision có phần Clock Value trong tab Timers-Timer0 nó đặt sẵn cho rùi , phần Clock Source chọn là System clock, ko phải lo config Timer0 nữa cứ chọn là xong. Hoặc nếu làm bô Counter thì chọn Clock Source là T0 pin Falling Edge (sườn xuống) hoặc T0 pin Raising Edge (sườn lên) để làm bô Counter với sự kiện ngoài.TCNT0 - thanh ghi cho phep đọc và ghi giá trị của Timer0, nó là thanh ghi 8-bit.TIMSK - bit 0 TOIE0 là bit cho phep tràn Timer0, khi bit này đc set là 1 và bit I trong SREG dc set thì lúc đó ngắt Tràn Timer0 mới được thực hiện.TIFR - bit 0 TOV0 đc set khi xảy ra tràn Timer/Counter0.

Nói chung là phần Timer/Counter0 thì Codevision đã config hô mình gần hết, chỉ việc viết code của mình làm tác vụ gì vào phần interrupt của nó thôi.

Bạn chèn đoạn code sau vào nhe :

// Timer/Counter 0 initialization// Clock source: System Clock// Clock value: 4000.000 kHz // dùng thạch anh 4MHz, PWM tốc đô cao nhất// Mode: Fast PWM top=FFh // chon chế đô fast PWM 8bit// OC0 output: Inverted PWM // lối ra đảo !TCCR0=0x79;TCNT0=0x00;OCR0=0x00;

Page 31: Timer Counter

DDRB.3=1 // Portb3 là lối ra PWM

//Để tạo ra điện áp lối ra PWM theo ý muốn, bạn đặt giá trị cho OCR0

OCR0=0x7f ; //qua bô lọc RC tạo ra điện áp Vcc/2 .

//Nếu lối ra đảo, nếu OCR0=0xff -> V tạo ra là 0V, ngược lại OCR0=0x0 V tạo ra là Vcc.Bạn có thể chọn lối ra không đảo( trong Wizard của CV hoặc nếu dùng ASM thì xem lại trong datasheet để set các bit WGM00,WGM01,COM00,COM01)

Chúc thành công !

Trước tiên bạn phải khởi tao timer0 (vd ta dung Timer0 de dieu che xung) sang chế đô PWM Bạn mo datasheet xem thanh ghi dieu khien timer0 la TCCR0 gom co 8 bit saubit 7 : FOCObit 6 : WGM01bit 5 : COM00bit 4 : COM01bit 3 : WGM00bit 2 den bit0 : la cac bit chon tan so hoat dong cho timer0+de chon che do hoat dong cho timer0 ban dung 2 bit WGM00 va WGM01+để chọn kiểu thay đổi mức ( cao sang thap -hay - thap sang cao) o chan dieu che OC0 ban dung 2 bit COM00va COM01time0 se so sanh lien tuc thanh ghi gia tri timer0 (TCNTO) voi thanh ghi OCCR0 .khi timer dem len bang OCR0 thi se xay ra sự đổi mức logic o chan OC0 (chan ngo ra cua xung duoc dieu che boi timer0)do vay muon dieu che xung tai chan OC0 ban phai lam la :--thiet lập chân port tuong ung voi chan OC0 la ngo ra --dat gia tri cho thanh ghi OCCR0--thiet lap timer0 sang che đô dieu chế xung (Fast hoac PhaseCorrect,xem datasheet)--ket noi chan OC0 voi mach dieu khien (chang han dieu khien do sang toi cua 1 con led)the la xong, ban lam thu di nhe .

Có vài điều cơ bản về chức năng Compare trong AVR như sau:

Q: Thế nào là chức năng Compare?A: Đây là môt trong những chức năng thường thấy và gắn liền với các timer của các vi điều khiển, bên cạnh chức năng Capture. Nguyên lý hoạt đông là: giá trị đếm của timer sẽ liên tục được so sánh với môt giá trị đặt trước, khi hai giá trị này bằng nhau (chính là sự kiện compare match) thì sẽ có thể thực hiện môt tác đông nào đó (ngắt, set/clear hoặc đảo chân OCx tương ứng, hoặc thậm chí là không làm gì cả...) tùy người lập trình chọn lựa. Giá trị đặt trước ấy do người lập trình ghi trong thanh ghi OCRnx (ví dụ: OCR0A, OCR0B, OCR1A, OCR1B...)

Q:"If one or both of the COMnA1:0 bits are written to one, the OCnA output overrides the normal port functionality of the I/O pin it is connected to." nghĩa là gì?A: Mỗi kênh Output Compare liên quan đến môt hay vài đầu ra, tên là các chân OCnx (ví dụ OC0A, OC1A, OC1B..). Các chân này được dùng chung với các chân cổng vào ra thông thường, khi dùng cho chức năng Compare thì không dùng làm chức năng vào ra được nữa. Khi xảy ra sự kiện compare match thì các đầu ra OCxn này có thể thực hiện tác đông nào đó (set/clear/toggle...) tùy ý người sử dụng. Việc chọn tác đông loại nào là do các bit COMnx trong thanh ghi TCCR tương ứng quy định. Với câu tiếng Anh bạn hỏi, dịch ra có nghĩa là nếu môt hoặc hai bit COMnA0 và COMnA1 được ghi giá trị 1 vào thì tác đông đầu ra sẽ được chọn là set/clear hay toogle (tùy tổ hợp là 01,10 hay 11), đè lên chức năng hoạt

Page 32: Timer Counter

đông vào/ra thông thường của chân cổng tương ứng (chân cổng đó không còn dùng làm cổng vào ra được nữa).

Q: "Toggle OCnA/OCnB/OCnC on compare match." có nghĩa là gì?A: Khi xảy ra sự kiện compare match (tạm dịch là so sánh thấy khớp), có 04 kiểu tác đông mà người lập trình có thể chọn để tác đông lên chân đầu ra OCnx: set = 1, clear = 0, toogle = đảo giá trị, và không làm gì cả (vẫn dùng làm cổng vào ra bình thường). Bạn hãy nhớ môt điều rằng, các tác đông này khi đã chọn đều được thực hiện môt cách hoàn toàn tự đông môt khi sự kiện compare match xảy ra.

Chức năng Compare trong timer chủ yếu liên quan đến các ứng dụng về điều chế đô rông xung PWM. Theo ý kiến chủ quan của bản thân tôi, timer của AVR là ngoại vi phức tạp nhất trong số các ngoại vi onchip của nó, cũng có thể nói đó là timer khó nắm bắt nhất trong các timer của các loại vi điều khiển 8 bit, với nhiều chế đô hoạt đông phức tạp. Để nắm bắt được bạn cần có thời gian và sự kiên trì.

Hy vọng đã phần nào giúp được bạn.

Q: Input capture là gì thế?A: Mỗi kênh Input Capture liên quan đến 1 chân tín hiệu đầu vào. Khi có sự kiện bên ngoài xảy ra, thể hiện ở việc tín hiệu đưa vào chân này thay đổi mức (tức là có sườn lên hoặc sườn xuống) thì giá trị của timer liên quan sẽ được ghi lại đúng vào thời điểm đó. Cụ thể là ghi vào thanh ghi Capture tương ứng (tên là ICRxn, ví dụ: ICR1A...). Kiểu tích cực của sườn có thể lựa chọn được (sườn lên, sườn xuống hoặc cả sườn lên và sườn xuống).

Q: Ứng dụng của Input Capture?A: Có môt số. Có thể kể ra như:- đo đô rông xung: đo thời gian giữa sườn lên và sườn xuống gần nhất.- đo chu kỳ: đo thời gian giữa hai sườn lên hoặc hai sườn xuống liên tiếp.- ngắt ngoài: dùng như môt ngắt ngoài (vì cũng có thay đổi mức tín hiệu)- ...

Thông thường ATMEGA nạp qua ISP bằng cách sử dụng các chân của cổng SPI là MOSI, MISO, SCK. Tuy nhiên đến đời ATMEGA128, ko hỉu vì seo mà bác ATMEL lại sử dụng các chân RxD0, TxD0 và SCK. Phải rất chú ý điểm này chứ hàn vào rồi là dễ toi 150k lắm đấy

Mạch nạp và sơ đồ kít bạn hãy tìm ở http://www.olimex.com/, đây là môt địa chỉ được rất nhiều người biết. Ngoài AVR các bạn có thể tìm được nhiều thông tin hữu ích khác về các dòng VDK. Link cụ thể cho bác đây, bác cứ làm giống hệt như nó là ổn (tôi cũng đang dùng ATMEGA128):Đây là mạch nạp, tôi đã làm môt sợi giống hệt thế và đang dùnghttp://www.olimex.com/dev/avr-pg1.html

Đây là mạch phát triển:http://www.olimex.com/dev/avr-mt128.htmlvàhttp://www.olimex.com/dev/avr-h128.html

Để cấu hình sử dụng thạch anh ngoài, bootloader, Watchdog, JTAG, bạn nên bật PonyProg lên, chọn ATMEGA128 rồi nhất Ctrl-S để có bảng Configuration and Security Bits.

Lần lượt search trong Datasheet tác dụng của từng fuse môt. Bạn sẽ biết cần cấu hình như thế nào. làm thế bạn sẽ hiểu và nhớ lâu hơn là tớ trả lời trực tiếp câu hỏi của cậu . Và với các chíp ATMEGA

Page 33: Timer Counter

khác cậu có thể làm hoàn toàn tương tự.

À, mà tớ khuyên cậu nên sử dụng Bootloader của http://www.microsyl.com/, tên là Megaload. Đã được đề cậu đến trong 1 luồng ở Box này. Hiện đã có phiên bản mới hơn.

Sử dụng Bootloader sẽ tiết kiệm được thời gian hơn, dễ dàng hơn trong việc nạp chương trình, và còn nạp rất nhanh nữa . Bạn hoàn toàn có thể nạp qua cổng USB (dùng Laptop ko có cổng COM chẳng hạn ) với 1 sợi cáp USB to COM hoặc USB Data Cable của điện thoại di đông như DKU5 (giá chỉ 50k) chẳng hạn.

Những j tớ nói đều đã được tớ thử qua (tớ đang dùng bootloader cho board ATMEGA128, nạp qua cáp

USB2COM, cáp được chế từ cable nạp của Samsung E400 thì phải )

- Tôi cũng đang tìm hiểu về Timer và cũng xin hỏi các bác: Nếu tạo môt timer bằng codewizard như sau:+ Chip: Atmega8515L - Clock 8MHz+ Timers: tab Timer0 : Clock Source = System ClockClock Value = 8000.0kHzMode: Normal Top = 0xFFOutput: Toggle on compare matchTime Value = 0hCompare = 0hthì nó có tạo ra xung vuông f = 4MHz ở chân OC0 (PORTB.0) không? Nếu không thì các bác cho em biết hình thù nó ra sao nhe?(Cái này mà có con oxilồ thì tốt quá).

Có xung vuông ra, nhưng ... không phải là xung có tần số = 4MHz.

Nào, cùng xem tần số ra là bao nhiêu nhe:1 - Normal mode: đếm từ 0 lên 255 lại về 0, mãi như thế... Chu kỳ tràn là 256 clock. Clock là 8MHz suy ra chu kỳ tràn là 256*125ns = 32,000ns = 32us.2 - Output toggle on compare match: cứ khi so sánh timer và OCR0 thấy bằng nhau sẽ đảo đầu ra chân OC0.3 - OCR0 = 0h (hay bằng bao nhiêu đi nữa trong dải từ 0 đến 255) thì cũng chỉ so sánh khớp với timer tại môt điểm trong quá trình timer đếm từ 0 đến 255. Như vậy chu kỳ của sự kiện so sánh khớp (compare match) bằng với chu kỳ tràn timer (vì trong mỗi chu kỳ tràn chỉ so sánh khớp có môt lần). Tuy nhiên mỗi lần khớp lại đảo trạng thái OC0 môt lần, vậy phải có hai lần so sánh khớp mới tạo ra môt xung vuông hoàn chỉnh.

Tóm lại, khi ở normal mode, bất kể Compare value bằng bao nhiêu, xung vuông tạo ra có tần số bằng 1/2 tần số tràn của timer. Trong trường hợp này, timer là 8bit, clock = 8MHz ---> tần số tràn của timer = 1/32us = 31,250Hz ---> tần số xung vuông tạo ra là 31,250/2 = 15,625Hz!

Nếu muốn tạo xung bằng timer, không nên dùng normal mode.

Tôt nhất là tạo xung = PWM. Chính xác, đỡ tốn tài nguyên xử lý của chip.

Toán tử << là toán tử dịch trái. Lệnh của các hạ đưa ra phân tích chi tiết thì là thế này:- dịch trái bit 1 (bit = 1 chứ không phải bit 1 trong 8bit từ 0 đến 7!!!) đi int0 lần ---> kết quả thu được là môt byte có môt bit = 1 (tại số thứ tự = int0). Ví dụ nếu int0 = 5 thì sẽ thu được byte có giá trị là 00100000b.

Page 34: Timer Counter

- tương tự có được byte có môt bit = 1 (tại số thứ tự = int1).- OR hai byte đó với nhau thu được môt byte có 02 bit = 1 tại số thứ tự int0 và int1 (các bit có số thứ tự khác đều bằng 0). Đó chính là giá trị người lập trình muốn đưa vào biến temp.Tóm lại, lệnh trên có nghĩa là nạp môt hằng số 8bit có giá trị bằng 1 ở các bit có cùng số thứ tự với các bit int0, int1 vào biến temp.Tại hạ đoán sau đó là lệnh nạp temp vào thanh ghi cho phep ngắt của AVR. Kiến trúc của AVR không cho phep nạp trực tiếp giá trị tức thời vào các thanh ghi thuôc vùng I/O.Giang hồ hiểm ác, bảo trọng.

Capture là môt hình thức ngẳt ngoài! Trong AVR chips, có môt số chân ICPs, khi có môt sự kiện xảy ra trên các chân này (chuyen tu trạng thái thấp lên cao, hoặc ngược lại) thì sẽ có môt ngắt được gọi.

Ưu điểm của loại ngắt này là nó làm việc với các bô đinh thời, chính vì vậy khi có ngắt xảy ra, các bạn có thể biết thời điểm ngắt. Môt ứng dụng quan trọng là làm decoder. Ví dụ tính toán tốc đô của đông cơ. Nếu bạn biết thời gian giữa 2 xung nhận, bạn sẽ tính được vận tốc quay của đông cơ thông qua công thức toán học đơn giản (ko nhớ là gì :-) )

Về ví dụ về phần này, tôi đang cố gắng để viết môt giáo trình cơ bản cho các module trong AVR, vậy bạn chờ thêm chút nữa nhe. Tuy nhiên nếu bạn có môt bài toán cụ thể nào sử dụng ICP, bạn hãy thử viết code trước, nếu có những vấn đề cụ thể thi có thể bàn luận tại đây.