You are on page 1of 35

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 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;
OCR1L=0xFF; // mức so sánh PWM

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

MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=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#post67457
File gửi kèm

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

Khi giá trị trong Timer bằng giá trị trong thanh ghi ORC thì giá trị trong Timer sẽ bị xoá đi. Có các kênh PWM (từ 4 đến 8 kênh tuỳ loại ) .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.Bài 4 AVR .Chế độ này cũng cho phép tạo ra tần số so sánh ở đầu ra. Tự động xoá Timer trong chế độ so sánh(tự động nạp lại) .. Đếm các dự kiện ngắt ngoài . . Bao gồm nhiều chế độ ngắt và PWM … . 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.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. Tạo ra tần số . Thông thường mỗi loại vi điều khiển đều có bộ định thời. Bao gồm các bộ timer 8bit 16 bit.Giá trị trong ORC đóng vai trò là giá trị TOP cho bộ đếm. Có chế độ PWM . Đặc tính: . Tạo ra các ngắt tràn và ngắt so sánh .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 .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...Cách dùng Timer trong vi điều khiển AVR Ngườ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 có từ 3 – 4 bộ Timer . 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 . Có thể là một kênh đếm riêng biệt .

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.đầ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.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.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 .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. 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. Trong chế độ đảo . Và sẽ được sét lên 1 khi giá trị đạt Bottom.

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 .256 hoặc 1024 Các thanh ghi trong bộ Timer/ Counter: Thanh ghi điều khiển . Nó linh hoạt hơn so với chế độ Fast PWM.8.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ế độ 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. 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.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.64.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.Chế độ Phase correct PWM: Chế độ này hoạt động dựa trên hai sườn lên xuống.Trong chế độ này bộ đếm sẽ tăng cho đến khi đạt giá trị MAX .khi đó nó sẽ đổi chiều đếm.Chế độ so sánh đảo thì các giá trị là ngược lại. TCCRx: .

6 –WG00-WG01: Đây là các bít chọn chế độ trong Timer.Bít 3. 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á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.Các giá trị được mô tả trong bảng sau.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 phép ngắt so sánh Bít 0 –TOIEX : Khi bít này được set lên bằng 1 thì cho phép ngắt tràn .

đoạn chương trình trên dùng timer1. interrupt [TIM1_OVF] void timer1_ovf_isr(void) //ngat xay ra sau 20ms { TCNT1H=0xF6. TCNT1H=0xF6. OCR1BL=0x00. TCNT1L=0x3B. 9C4 = F63B. #asm("sei") //bat co cho phep ngat toan cuc neu khong thi khong co ngat xay ra while (1) . 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. // goi ham can xu li sau 20mscount++. Timer này là bộ đếm 16bit nên giá trị đếm được tối đa là FFFF. OCR1BH=0x00. ICR1H=0x00.02= 2500 số. ICR1L=0x00. 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. if (count>10) { count=0. #include unsigned char count=0.02 giây (20ms) ta tính được trong 20ms bộ timer sẽ đếm được là: 125000x0. OCR1AH=0x00. //giá trị nạp lại TCNT1L=0x3B. 0. Ta làm phép tính như sau: 125000 số ----1 giây ? số----. //OC1Boutput: Discon.000 kHz // Mode: Normal top=FFFFh //OC1A output: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. OCR1AL=0x00. //goi ham can xu li sau 2s } } voidmain(void) { //Timer/Counter1initialization //Clocksource:SystemClock //Clockvalue:125.

1. thi ban phai de y khi bo dinh thoi bi tran. tuy nhien ta co the thiet lap gia tri tran cho bo dinh thoi... }... Tren atmega co mot Pin ICP... 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. co bo dinh thoi 16 bit. Khi bo dinh thoi tran (over flow) no se tro ve 0.B..... phai co viec xu ly de cho counter ko bi reset. truoc tien ta phai xac dinh tan so ca abo dinh thoi. ============================================================================= Timer bắt đầu đếm khi bạn cấp clock cho nó.... Nhu vay ve nguyen tac thi counter co the co tan so khac nhau!! Neu ban su dung timer giong nhu mot bo dem... Bo dinh thoi nay dua tren co so cua clock ma ban su dung de dem...... CS02 của thanh ghi TCCR =============================================================== Ban co the dung ngat Input Capture Interrupt (ICP) cua timer1 de lam viec dem tan so. bang viec dem so lan tran (vi du 10 lan) ban co duoc 1 giay. nghia la no dem gia tri cua mot su kien nao do. Ta co the dung voi tan so cua xung clock. ban tim xem voi atmega8535 no la chan nao. } =========================================================================== Co hai khai niem ve bo dinh thoai va counter.{ . Neu su dung Codevision avr. clk/4 .. binh thuong gia tri tran defalut la gia tri maximum cua bo dinh thoi...1 giay chang han (vi du the). tu do ban se dem duoc phut va gio tuong ung dua tren viec tran cua bo dinh thoi..... Tuy nhien ve dinh nghia thi counter la mot bo dem. Couter: ve ban chat thi counter cung khong khac so voi bo dinh thoi lam..xac dinh dem suon len hay suon xuong Sử dụng codevision la tốt nhất. ta co the xay dung bo dem thoi gian su dung bo dinh thoi trong AVR.... hoac clk/2. tan so cua bo dinh thoi hoan toan co the biet duoc tuy theo gia tri cua xung clock ban dung. 2. chỉ cần khai báo là xong! Khai báo Timerx làm bộ đếm ngoài khai báo sườn lên hay xuống trong đó có các ngắt ví dụ như tràn TOV so sánh với A. Chu y: . ban co the thiet lap gia tri nay trong Codewizard khi khoi tao chuong trinh.. co bo dinh thoi 8 bit.kich hoat ngat ICP .. Noi chan ICP nay voi tien hieu ma ban can dem.. bạn viết với codevision rất tiện . Trong AVR tuy theo cac loai ma cac bo dinh thoi khac nhau.. Tức là ngay sau câu lệnh set bit CS00. CS01.

bạn nên để ý: .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.Khi nạp chương trình..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.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. ( một dạng như là kích hoạt dao động nội) .Bao gồm nhiều chế độ ngắt và PWM … ...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 .Đếm các dự kiện ngắt ngoài . Nếu dùng dao động trong. bạn vẫn cần mot dao động ngoài để nap. 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.Bao gồm các bộ timer 8bit 16 bit. .Có thể là một kênh đếm riêng biệt . Nguồn dao động bạn co thể xem trong datasheet (page 24).Tạo ra tần số .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ỡ.Giá trị trong ORC đóng vai trò là giá trị TOP cho bộ đếm.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.Chế độ này cũng cho phép tạo ra tần số so sánh ở đầu ra. thường có từ 3 – 4 bộ Timer .Có các kênh PWM (từ 4 đến 8 kênh tuỳ loại ) .gia trị lớn nhất có thể là 8 MHz với Atmega8 ======================================================================= Đặc tính: .Tự động xoá Timer trong chế độ so sánh(tự động nạp lại) .Có chế độ PWM .Set Fusebit .Atemega8 có thể dùng với cả dao động trong lẫn dao động ngoài.

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.đầ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.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 -- -. Trong chế độ đảo .Bộ đếm sẽ đếm từ Bottom đến Max sau đó khởi động lại từ bottom.///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.Chế độ Phase correct PWM: -- .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.

Chế độ so sánh đảo thì các giá trị là ngược lại.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. 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.256 hoặc 1024 --Các thanh ghi trong bộ Timer/ Counter:-- -. Nó linh hoạt hơn so với chế độ Fast PWM.8.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.TCCRx:-- .64.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.Thanh ghi điều khiển .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 .Trong chế độ này bộ đếm sẽ tăng cho đến khi đạt giá trị MAX .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.khi đó nó sẽ đổi chiều đếm.Chế độ này hoạt động dựa trên hai sườn lên xuống.

Bít 3. -.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á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.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 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 phép ngắt so sánh Bít 0 –TOIEX : Khi bít này được set lên bằng 1 thì cho phép ngắt tràn .

ICR1L=0x00. OCR1BL=0x00. #include <mega8.=========================== đoạn chương trình trên dùng timer1. OCR1BH=0x00. OCR1AL=0x00. //giá trị nạp lại TCNT1L=0x3B. Timer này là bộ đếm 16bit nên giá trị đếm được tối đa là FFFF. TCNT1H=0xF6. Ta làm phép tính như sau: 125000 số --------------------1 giây ? số----------------------.02= 2500 số. // goi ham can xu li sau 20mscount++. TCNT1L=0x3B. 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. 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. //goi ham can xu li sau 2s } } void main(void) { // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 125.02 giây (20ms) ta tính được trong 20ms bộ timer sẽ đếm được là: 125000x0.9C4 = F63B. TCCR1B=0x03.000 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. interrupt [TIM1_OVF] void timer1_ovf_isr(void) //ngat xay ra sau 20ms { TCNT1H=0xF6.h> unsigned char count=0. // 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.0. OCR1AH=0x00. ICR1H=0x00. #asm("sei") //bat co cho phep ngat toan cuc neu khong thi khong co ngat xay ra while (1) . if (count>10) { count=0.

. }. 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. Ưu điểm là rẻ .....{ .... 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...... đơn giản chỉ cần băm xung 1 kênh ....5 hay chân OC1A ..... } 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 . tần số đảo chiều thấp. 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ó . Tuy nhiên nó có nhược điểm rất lớn là khả năng ......

Atmega128 có tới 8 kênh băm xung. 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 .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 . #include <mega16.Atmega88 có tới 6 kênh băm xung . Với cách mắc như sơ đồ để động cơ chạy ta cho giá trị ra ở portD. 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 .5 là logic 0 .Tuỳ loại avr mà số kênh PWM nhiều hay ít khác nhau .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 .h> // Declare your global variables here #define V_DC OCR1AL #define RELAY PORTD.

// 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. OCR1BL=0x00. DDRD=0x60. correct PWM top=00FFh // OC1A output: Inverted // OC1B output: Discon. TCNT1L=0x00.000 // Mode: Ph. // 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.PORTA=0x00. OCR0=0x00. ICR1H=0x00. OCR1BH=0x00. OCR1AH=0x00. DDRA=0x00. . ICR1L=0x00. // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 3. // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 500. DDRB=0x00. DDRC=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. // 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.906 kHz // Mode: Normal top=FFh // OC0 output: Disconnected TCCR0=0x05. TCNT0=0x00. //bam xung voi tan so gan 1KHz TCNT1H=0x00. OCR1AL=0x00. TCCR1B=0x02.

// Global enable interrupts #asm("sei") while (1) { // Place your code here V_DC=0. //khi dao chieu ban phai tat IRF neu khong se hong relay RELAY=0. 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 . }. SFIOR=0x00. V_DC=0. delay_ms(10).//quay thuan toi da delay_ms(2000). // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80.// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00. TCCR2=0x00.0592MHz. OCR2=0x00.Thạch anh em xài là 11. V_DC=255. // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00. delay_ms(10). RELAY=1. MCUCSR=0x00. } Hiện tại em đang thử xuất xung PWM đk động cơ DC qua chân PD7 của con Atmega 8535. // Chay 50% toc do toi da Delay_ms(5000). TCNT2=0x00. //dao chieu dong co V_DC=125. // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00.

bạn chỉ cần thay đổi giá tri của thanh ghi OCR2.1 =1. Nếu làm việc với fast PWM. UBRRL=0x33. UBRRH=0x00. CS21. if(count <=0) count = 0. COM2. Giá trị của 3 bit này xác định tần số làm việc của Timer2. if(count >=30000) count = 30000. 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. Để thay đổi độ rông xung.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. 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. UCSRC=0x86. while (1) . } } void main(void) { char receive_char. } else if(data == 'd') { count -=5.com thì thấy có mấy bác nói về việc này. Nói cách khác OCR2 quy định cái duty cycle của PWM.như thế nào(đọc tiếng Anh tệ quá nên vẫn chưa hiểu rõ lắm ). 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. 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. if(data == 'a') { count +=5. UCSRB=0x18.0 = 0 ) Như vậy đầu ra đã sẵn sàng. UCSRA=0x00. Tín hiệu này làm việc với bộ định thời Timer2. giá trị TCNT2 nên đặt bằng 0. 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. Vi dụ : Code: interrupt [USART1_RXC] void usart1_rx_isr(void) { data=UDR1.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. CS22).Qua bên diendandientu.

nên co lẽ ko chạy dc với 8535.anh giúp giùm em nhé ! Thanks anh nhiều nhiều!!!! Đồng ý với bạn là cái diagram đó thiếu. Ở đây là thiếu hay sai?Thiếu cái jì?. đẩu ra cua PWM ơ mức cao 128 -> 255 đầu ra cua PWM ở mức thấp Vi vặy nếu thay đổi giá trị đặt. giá trị này quan hệ tuyến tính với độ rộng cua xung PWM khi timer đếm tu 0 -> 128. tuy nhiên về nội dung thi như nhau. Chính vì vạy mới nảy sinh ra việc clear hay set khi đếm ngược và đếm xuôi.bạn nào biết chỉ giáo nhé Hy vọg 4rum này sẽ sôi động hơn.{ OCR1AH = count>>8.(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. ==================== 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 -> 255 giả sủ giá trị đặt để so sánh là 128. 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. OCR1AL = count.Nguyên tắc vầy là sai.ở Non-inverting Compare output mode. trên giản đồ thời gian cua TCNT. tất nhiên là còn nhiều chế độ PWM khác. tuy nhiên cơ bản là vậy.em đọc trong datasheet của Atmega8535 thấy nó bảo : trong chế độ Phase correct PWM.nó có cả cái diagram. nhung chỗ có gạch ngang phải là những chỗ OCR2 update.Mọi người xem lại đi.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. 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). . 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. Đ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. Đo là nguyen tắc hoạt động cua PWM. độ rộng xung thay đổi khi ân kí tư 'a' hoac 'd' tu bàn phím. độ rộng của tin hiệu PWM ở mức cao và mức thấp sẽ thay đổi. 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. } Ví dụ trên tôi viết cho atmega8.

Ngoài mã lệnh của các task cong mã lệnh của Kernel . chp DAC và lọ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 .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.Để 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.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.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.basic….. AVR có trang bị các bộ PMW với số lượng và số bít khác nhau.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. Chỉ là lý thuyết datasheet. còn fast PWM thì phù hợp cho tính toán mạnh..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...!!! )Thực chất đối với tôi và quan điểm của tôi DAC xét về mặt toán học đây là một phét biến đổi từ không gian số học rời rạc sang không gian tương tự..(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.. cũng làm cho các thiết bị vật lý kích thước nhỏ hơn.net khi tôi nói tới DAC thì F chụp đầu tôi là con chip DAC hô hô .Bộ nhớ chương trình đủ lớn để chứa các mã lệnh .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à.thanks 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.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 nhé ! đâ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.Xét 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.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.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 ..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.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.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).Các task này được đặt trong bộ nhớ .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. . Và để thực hiện phép 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). Để đ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.

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. 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.Với AVR là ….). 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 . . 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 . 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) . /*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.Các bạn có thể xem phần hướng dẫn của Keil C là có hết.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).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.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. 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. /* Bắt đầu task 0 hoạt động */ os_create_task (2).(Thế mạnh của Assembly mà).Để 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).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 nhé) Vấn đề sd nhân RTX51 thì cũng không có gì khó cả .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í 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. /* task 1 hoạt động */ os_create_task (3). 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.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 . /* */ os_delete_task (0).

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) .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 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.PSW. Các khái niệm cơ bản các bạn cần nắm được: 1.đọang mã lệnh Ljmp ReadADC .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.Rn.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.lệnh nhả về đầu của task kết thúc một chu kỳ của task 4.ReadADC là tên của task và chính xác hơn nó là một nhãn.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).Nó bao gồm các công việc:Lưu ngữ cảnh đang thực hiện(Lư PC.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ý.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 . 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.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. 3.A.B. Chúng ta sẽ bắt đầu với một ví dụ nhé: 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).không có ưu tiên (các task bình đẳng).các Port. .Ư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.Tài nguyên: Tài nguyên bao gồm các thiết bị ngoại vi như bộ nhớ .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ậ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à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.ADC .DAC(Được ghép thêm)… 5. Ví dụ: ReadADC: .

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ả).Để 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.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).cpc Cjne a.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. 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 ở đâ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.Một vùng để lưu dữ liệu dùng chung cho các task.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).sp. Int_Timer0: . Chúng ta sẽ sử dung timer 0 để là xung nhịp chia thời gian đơn vị.lưu gữ ngăn xếp Sjmp exits .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.#2 exits Mov stack2.

cho task2 và được khởi tạo khi bắt đầu chạy Push dpl Push dph .Stack2 .sp Exits: .cpc là biến trạng thái lư giữ tên của task đabg chạy (0.task2_run .trở lại ngăn xếp của task2 ở đây thì stack2 lại là .#0 task0_run Mov cpc.chạy .cpc .với stack2 là một ô nhớ lưu vị trí khởi tạo đầu của ngăn xếp .stack2 .#1.đỉnh ngăn xếp rồi Pop r0 Pop r1 Pop r2 Pop r3 .Xác định task để trả lại ngữ cảnh Mov a.3…) Cjne a.đây là lần chạy đầu tiên của task1 ngay sau khi khởi động Mov psw.Lưu xong ngữ cảnh .nếu cpc =1 thì task1 đang chạy .1.Lưu vị trí của task2 Sjmp exit task0_run: Cjne a.0 Mov dptr.#0 Mov a.tăng con trỏ trạng thái lên 2 để báo task 2 đang .Mov stack1.#2 .2.#task2 Mov sp.khôi phục lại task2 Mov sp.

Pop r4 Pop r5 Pop r6 Pop r7 Pop dph Pop dpl Pop b Pop acc Pop psw Inc pcp.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 .task2 đang chiếm CPU thì bị ngắt .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 .khôi phục lại task1 Mov sp.

khởi tạo con trỏ task .#1 .#03Fh Mov SP.ngat int0 Org 0030H Start: . Mov Stack1.Pop psw Mov cpc.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 GenralR equ 07EH .#02Fh Mov cpc.#0h Mov Stack2.#00 .#0 .bien trang thai Cpc equ 07DH .một lần phần này các bạn tự viết.cấm các ngắt .bien du lieu dung chung Org 00h Ljmp start Org 00BH Ljmp int_timer0 .đoạn khởi tạo chương trình Mov psw.thiết lập timer 1 chế độ tự load và tính toán sao cho sau 10uS thì ngắt .bien trang thai Stack2 equ 07EH .cho phép ngắt .

. Chức năng này dùng để đo khoảng thời gian giữa các sự kiện. nó được ứng dụng làm gì thế. 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. . vv.falling. Chú ý: . Để ý là khi xảy ra sự kiện input capture thì sẽ tạo ra 1 ngắt.Kết thúc task 2 Int_timer0: . đo gia tốc. Dung khá nhiều trong giao tiếp hồng ngoại Xung được đưa trực tiếp vào chân ICP. .nếu ngắt input capture được cho phép. 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.) sẽ được cập nhật (coppy) vào thanh ghi input capture register.(Ở đây chưa tính đến thời gian tới hạn của một task ). Từ đó có thể ứng dụng làm các applications khác nhau.Để đặ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..counter bi tràn. Như vậy mỗi lần có xung thì giá trị counter sẽ tăng lên 1. chức năng này dùng để bạn đo độ rộng xung .2.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 sửa lại Kernel cho phù hợp.Lấy dữ liệu từ ADC (P1) đưa vào thanh ghi GenaralR Ljmp task1 .kết thúc task Task2: . đo vận tốc.Task1: . bạn có thể ghi lại thời điểm xảy ra ngắt.(đ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.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. Chẳng hạn đo tần số. 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.Mong bạn nào viết nhiều cho PIC thì cùng chia sẻ với anh em.. chân này nối với khối input capture.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..level) ở chân input capture thì giá trị của thanh ghi bộ định thời (1.lấy dữ liệu từ thanh ghi GenaralR dưa ra DAC qua Port P2 Ljmp task2. 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.) các bác cho em hỏi chế độ input capture trong avr hoạt động như thế nào vậy..nội dung như trên . chức năng của khối này là : Khi có sự kiện (rising.

các chế độ PWM trong Timer1.2 ? 2. ứng dụng? 4.. giá trị đếm . 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. Hy vọng Topic này sẽ được nhiều người ủng hộ.. QD.. 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.. 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. 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. 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 đó. 3. Các chế độ hoạt động của các Timer0. em mới nhập môn AVR không lâu và chọn Atmega8 làm điểm xuất phát. Timer .timer 0 thì n=0). 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. các vướng mắc. ??? chào các pác.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. nên em dám mở luồng này vì em thấy có 1 số điểm như sau: 1. Chế độ InputCapature. sau đó là đổi sườn cature.. 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 . -Timer nào thì cũng có hai chức năng là đếm xung và đếm thời gian.Khi đo độ rộng xung. 2.. Nhưng em vần thấy trong Box này vẫn thiếu cái Thread gì đó.. Rất mong các cao thủ như Sphinx. 3.. 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. 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 -. Như vậy là thoải mái rồi đúng không. Tập trung giải quyết các vấn đề liên quan. PWM.2 ???cách sử dụng các Mode trong các ứng dụng thực tế . 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 ạ. 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... để biết được là nó tràn mấy lần. Mỗi một lần tràn giá trị đếm bạn lưu vào một cái gì đó. 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). 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. UART. 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. NVT2.1. 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. 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ự. 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.

vậy là có một chú PWM. Dĩ nhiên nó cũng có ngắt cho bạn lập trình dễ dàng hơn. Ở 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. đặt cấu hình là chân vào bằng phần mềm.. + Trong bộ timer và conter của nó có nhiều chế độ lắm. + Watch dog thì nó làm đơn giản hơn. 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. 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. Anh em ở đây giải quyết cho. Bạn nào có vấn đề gì ở chỗ nào thì hỏi trực tiếp. nói ra đây không hết được đâu. Nó sẽ kiểm tra khi chíp bị treo. Sau đó dùng mấy cái bít trên xác định xem đếm sườn lên hay xuống. Còn với đếm xung thì bạn đưa xung vào chân Tn.thì các bạn về tam khảo thêm nhé. Trong chế độ này thì ngắt sẽ xảy ra khi đc cho phép 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.. Tai cái chân ICP. 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.. Đây mình chỉ nói chung chung vậy thôi. -Đó là hai mấy thứ cơ bản mà cái timer và counter nào cũng có. còn từ OCR--tràn thì đầu ra là mức đảo của i. + 2 chế độ ở trên có thể kết hợp với nhau để có được một bộ pwm rất linh hoạt. -Việc ngắt timer hay counter được cho phép qua thanh ghi TIMSK (thanh ghi dùng riêng cho bộ định thời và bộ đếm).. chả cần biết nó tên tuổi gì. TIFR. nếu được cho phép 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. +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. 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. Sau khi tràn thì lại đếm từ 0). đếm sự kiện ngoài. Cái duy nhất bạn phải làm là chọn xem sau bao lâu thì reset thôi. chỉ có vậy thôi.. Còn khi TCNTn>OCRn sẽ cho đầu ra ngược lại 1 hoặc 0. tùy theo nhu cầu của bạn.gì đó). cái Timer0 là timer 8-bit. Có vài bít trong thanh ghi này qui định. lưu giá trị lại. Timer0 gồm 4 thanh ghi là TCCR0. còn nếu bạn nào muốn thì mail cho mình cũng dc. 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 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. Được ngay cái độ rộng xung. Bạn bắt tại sườn lên một phát. VÀ nếu như bạn cho phép ngắt thì tại đây sẽ có một ngắt cho bạn ứng dụng. Ở 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. Mong mọi người góp ý làm sửa chữa làm cho luồng này tốt hơn. nói chung theo datasheet nó được sử dụng vào các ứng dụng là bộ đếm. Dĩ nhiên là lúc này bít I ở trong thanh ghi SREG được cho phép đấy nhé. Tiếp đến nhân giá trị thu đc với tần số timer là xong. TCNT0. TIMSK. 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ái này để xem bít nào cho phép thì bạn phải vào datasheet của từng con AVR thì mới rõ. nói ở đây dài lắm. Bạn đặt giá trị reset vào cái thằng ICR sau đó thì timer đếm từ 0 đến ICR thì về 0 luôn. 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. Thế là xong. bộ tạo dao động. hình như nó có tên là OC. + Về cái input capture thì nó làm việc cũng đơn giản thôi. Bắt tại sườn xuống ngay sau đó. . Đối với chế độ Phase. Để 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òn codevision thì cứ tick vào phát là xong. Có hai chế độ của PWM là FAST và phase correct. Ví dụ bạn định đo độ rộng xugn dương chẳng hạn. ------------------------------- Em nói chắc sẽ có nhiều chỗ sai lắm.

Cụ thể đặt như thế nào thì đọc thêm Datasheet sẽ biết. CS01. 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) . TIMSK .thanh ghi cho phép đọc và ghi giá trị của Timer0. nó là thanh ghi 8-bit. ngược lại OCR0=0x0 V tạo ra là Vcc. nếu OCR0=0xff -> V tạo ra là 0V.000 kHz // dùng thạch anh 4MHz. //qua bộ lọc RC tạo ra điện áp Vcc/2 .3=1 // Portb3 là lối ra PWM //Để tạo ra điện áp lối ra PWM theo ý muốn.WGM01. Bạn chèn đoạn code sau vào nhé : // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 4000.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.bit 0 TOIE0 là bit cho phép tràn Timer0. DDRB.thanh ghi cho phép lựa chọn nguồn clock của Timer. phần Clock Source chọn là System clock.thap sang cao) o chan dieu che OC0 ban dung 2 bit COM00va COM01 time0 se so sanh lien tuc thanh ghi gia tri timer0 (TCNTO) voi thanh ghi OCCR0 . 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 .TCCR0 . thông qua việc đặt cho các bit của nó là CS00.bit 0 TOV0 đc set khi xảy ra tràn Timer/Counter0. OCR0=0x00. //Nếu lối ra đảo. 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. CS02. 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. TIFR . 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.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 sau bit 7 : FOCO bit 6 : WGM01 bit 5 : COM00 bit 4 : COM01 bit 3 : WGM00 bit 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 . ko phải lo config Timer0 nữa cứ chọn là xong. 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. TCNT0=0x00. TCNT0 . bạn đặt giá trị cho OCR0 OCR0=0x7f .COM00.

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.) Q:"If one or both of the COMnA1:0 bits are written to one. Hy vọng đã phần nào giúp được bạn. Theo ý kiến chủ quan của bản thân tôi. Cụ thể là ghi vào thanh ghi Capture tương ứng (tên là ICRxn. Với câu tiếng Anh bạn hỏi. sườn xuống ...10 hay 11). Q: "Toggle OCnA/OCnB/OCnC on compare match. 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.. 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. 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.xem datasheet) --ket noi chan OC0 voi mach dieu khien (chang han dieu khien do sang toi cua 1 con led) the la xong. OCR1B.." nghĩa là gì? A: Mỗi kênh Output Compare liên quan đến một hay vài đầu ra.. ví dụ: ICR1A. 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. OCR1A.) tùy người lập trình chọn lựa.. Khi có sự kiện bên ngoài xảy ra." 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). ban lam thu di nhe . Giá trị đặt trước ấy do người lập trình ghi trong thanh ghi OCRnx (ví dụ: OCR0A. OCR0B. OC1A.). OC1B. tên là các chân OCnx (ví dụ OC0A..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. 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.) tùy ý người sử dụng. bên cạnh chức năng Capture. Kiểu tích cực của sườn có thể lựa chọn được (sườn lên. hoặc thậm chí là không làm gì cả. clear = 0. đè lên chức năng hoạt độ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). the OCnA output overrides the normal port functionality of the I/O pin it is connected to. set/clear hoặc đảo chân OCx tương ứng.. Bạn hãy nhớ một điều rằng. 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. Để nắm bắt được bạn cần có thời gian và sự kiên trì. 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. 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. toogle = đảo giá trị. 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 đó. 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. 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.. và không làm gì cả (vẫn dùng làm cổng vào ra bình thườ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. 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. 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ó.). với nhiều chế độ hoạt động phức tạp.

bootloader. Sử dụng Bootloader sẽ tiết kiệm được thời gian hơn. SCK. dễ dàng hơn trong việc nạp chương trình.olimex. tên là Megaload.html Để cấu hình sử dụng thạch anh ngoài.. Watchdog.microsyl. cáp được chế từ cable nạp của Samsung E400 thì phải ) . 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.Clock 8MHz + Timers: tab Timer0 : Clock Source = System Clock Clock Value = 8000.olimex. Link cụ thể cho bác đây. TxD0 và SCK.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) . nạp qua cáp USB2COM. 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 . 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. chọn ATMEGA128 rồi nhất Ctrl-S để có bảng Configuration and Security Bits. 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 . . tôi đã làm một sợi giống hệt thế và đang dùng http://www.com/dev/avr-h128. MISO. 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. . và còn nạp rất nhanh nữa .0kHz . 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. Lần lượt search trong Datasheet tác dụng của từng fuse một. 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.olimex.đ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.hoặc cả sườn lên và sườn xuống).đo độ rộng xung: đo thời gian giữa sườn lên và sườn xuống gần nhất. À.com/. Tuy nhiên đến đời ATMEGA128. Bạn sẽ biết cần cấu hình như thế nào.com/dev/avr-mt128. Hiện đã có phiên bản mới hơn. đây là một địa chỉ được rất nhiều người biết. Và với các chíp ATMEGA khác cậu có thể làm hoàn toàn tương tự.com/dev/avr-pg1. bạn nên bật PonyProg lên.. Đã được đề cậu đến trong 1 luồng ở Box này. Những j tớ nói đều đã được tớ thử qua (tớ đang dùng bootloader cho board ATMEGA128. mà tớ khuyên cậu nên sử dụng Bootloader của http://www. JTAG.com/..olimex.html và http://www. Có thể kể ra như: .html Đây là mạch phát triển: http://www. Q: Ứng dụng của Input Capture? A: Có một số. ko hỉu vì seo mà bác ATMEL lại sử dụng các chân RxD0.

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 xác. Ư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. 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. 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. bất kể Compare value bằng bao nhiêu. chính vì vậy khi có ngắt xảy ra. không phải là xung có tần số = 4MHz. 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. Trong trường hợp này. các bạn có thể biết thời điểm ngắt. 2 .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). Kiến trúc của AVR không cho phép nạp trực tiếp giá trị tức thời vào các thanh ghi thuộc vùng I/O. nhưng . Toán tử << là toán tử dịch trái. bảo trọng. không nên dùng normal mode.Normal mode: đếm từ 0 lên 255 lại về 0. Đó chính là giá trị người lập trình muốn đưa vào biến temp.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. Capture là một hình thức ngẳt ngoài! Trong AVR chips. . Tôt nhất là tạo xung = PWM. Ví dụ nếu int0 = 5 thì sẽ thu được byte có giá trị là 00100000b..tương tự có được byte có một bit = 1 (tại số thứ tự = int1).. Chu kỳ tràn là 256 clock. Tóm lại. Clock là 8MHz suy ra chu kỳ tràn là 256*125ns = 32. đỡ tốn tài nguyên xử lý của chip. Tóm lại. Nào. Có xung vuông ra..250Hz ---> tần số xung vuông tạo ra là 31. cùng xem tần số ra là bao nhiêu nhé: 1 .000ns = 32us. 3 .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. mãi như thế. Tại hạ đoán sau đó là lệnh nạp temp vào thanh ghi cho phép ngắt của AVR. Giang hồ hiểm ác. . có một số chân ICPs. Một ứng dụng quan trọng là làm decoder. Ví dụ tính toán tốc độ của động .. clock = 8MHz ---> tần số tràn của timer = 1/32us = 31.250/2 = 15. Lệnh của các hạ đưa ra phân tích chi tiết thì là thế này: . xung vuông tạo ra có tần số bằng 1/2 tần số tràn của timer. hoặc ngược lại) thì sẽ có một ngắt được gọi. Mode: Normal Top = 0xFF Output: Toggle on compare match Time Value = 0h Compare = 0h thì nó có tạo ra xung vuông f = 4MHz ở chân OC0 (PORTB. timer là 8bit. Tuy nhiên mỗi lần khớp lại đảo trạng thái OC0 một lần. 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).625Hz! Nếu muốn tạo xung bằng timer. int1 vào biến temp.0) không? Nếu không thì các bác cho em biết hình thù nó ra sao nhé? (Cái này mà có con oxilồ thì tốt quá). khi ở normal mode.

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 nhé. . nếu có những vấn đề cụ thể thi có thể bàn luận tại đây. bạn hãy thử viết code trước. Tuy nhiên nếu bạn có một bài toán cụ thể nào sử dụng ICP.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.