3.2 Các loại ngắt
3.2.3 Ngắt ADC, SPI, TWI, AC
Hoạt động ngắt ADC, SPI, TWI (I2C), AC xảy ra khi các hoạt động này hoàn thành 3.2.4 BÀI TẬP VÍ DỤ
Ví dụ 1: Sử dụng ngắt ngoài để đếm sản phẩm
Hình 3.3 Sơ đồ nguyên lý mạch đếm sản phẩm sử dụng ngắt ngoài Chương trình được viết như sau:
Sử dụng ngắt INT0, tác động cạnh xuống. #include <mega16.h>
#include <delay.h>
unsigned char flash MaledAnot[10] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; // External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void) { index++; if(index>99) index = 0; } void hienthi() { PORTB = 0xfe; PORTA = MaledAnot[donvi]; delay_ms(2); PORTB = 0xfd; PORTA = MaledAnot[chuc]; delay_ms(2); } void giaima() { donvi = index%10; chuc = index/10; } void main(void) { PORTA=0x00; DDRA=0xFF; PORTB=0x00; DDRB=0xFF; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x00;
// External Interrupt(s) initialization GICR|=0x40;
MCUCR=0x02; MCUCSR=0x00; GIFR=0x40;
// Global enable interrupts #asm("sei")
while (1) {
// Place your code here giaima();
hienthi(); }
Ví dụ 2: Sử dụng ngắt timer để hiển thị số đếm từ 00 đến 99 và lặp lại Sơ đồ nguyên lý tương tự như hình 3.3
Chương trình được viết như sau:
Sử dụng ngắt tràn timer/counter0, bộ chia 1024, mode Normal #include <mega16.h>
#include <delay.h>
unsigned char index, donvi, chuc; unsigned char flash MaledAnot[10] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; // Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void) { index++; if(index>99) index = 0; } void hienthi() { PORTB = 0xfe; PORTA = MaledAnot[donvi]; delay_ms(2); PORTB = 0xfd; PORTA = MaledAnot[chuc]; delay_ms(2); } void giaima() { donvi = index%10; chuc = index/10; } void main(void) { PORTA=0x00; DDRA=0xFF; PORTB=0x00; DDRB=0xFF; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 0,977 kHz // Mode: Normal top=0xFF TCCR0=0x05;
TCNT0=0x00; OCR0=0x00;
TIMSK=0x01; ACSR=0x80;
// Global enable interrupts #asm("sei")
while (1) {
// Place your code here giaima();
hienthi(); }
}
3.3. CÂU HỎI ÔN TẬP HẾT CHƯƠNG
1. Viết chương trình đếm lên và đếm xuống sử dụng 2 ngắt của vi điều khiển? 2. Viết chương trình đếm tự động từ 00 đến 99, khi nhấn nút trên chân 16 thì vi điều
khiển dừng đếm, khi nhấn tiếp thì vi điều khiển chạy tiếp tục 3. Viết chương trình hiển thị số ngẫu nhiên từ 00 đến 99
Chương 4
HOẠT ĐỘNG
4.1 GIỚI THIỆU:
Bộ timer/counter hoạt động dựa trên nguyên tắc sau: bộ timer/counter (bộ đếm) nhận xung clock và đếm số lượng xung này, vi điều khiển nhận biết được số lượng xung này có bằng với giá trị cho trước hay không hoặc đã đạt tới giá trị TOP (0xFF) hoặc BOTTOM (0x00), dựa vào sự nhận biết này mà ta có các cách cư xử khác nhau cho phù hợp với từng ứng dụng của mình.
Ứng dụng của bộ timer/counter: Dùng đếm sự kiện, định thời, tạo tần số, hoặc được sử dụng trong ứng dụng điều chế độ rộng xung PWM (điều khiển tốc độ động cơ, mạch ổn áp…)
Atmega16 có 3 bộ timer/counter: 2 bộ 8 bit (timer0, timer2) và 1 bộ 16 bit (timer1).
Hình 4.1 Sơ đồ khối của bộ timer/ Counter
Qua hình vẽ trên ta nhận thấy khối Control Logic nhận tín hiệu xung clock (clkTn) từ chân Tn hoặc từ bộ chia (prescaler), việc lựa chọn này tùy thuộc vào thanh ghi TCCR. Nếu clkTn là Tn thì bộ timer/counter sẽ thành bộ counter (đếm sự kiện), vi điều khiển sẽ nhận tín hiệu từ chân T0 (chân 1), T1 (chân 2).
Nếu clkTn là prescaler thì bộ timer/counter sẽ thành bộ timer (định thời), tùy theo việc cài đặt bộ chia mà tín hiệu clkTn có các tần số khác nhau.
Khối Control Logic xuất tín hiệu qua thanh ghi TCNTn bao gồm tín hiệu đếm (count), tín hiệu clear (xóa thanh ghi TCNTn về 0), và tín hiệu đếm lên/xuống (direction), nếu giá trị trong bộ counter và OCRn bằng nhau thì nó sẽ báo trên chân OCn, hoặc phát sinh ra tín hiệu ngắt.
Tần số tín hiệu phát ra bên trong của vi điều khiển cấp cho bộ chia (prescaler) được gọi là chu kì máy (CKM) và được tính như sau:
(4.1) Với fosc là tần số thạch anh được gắn vào chân 12 và 13 của vi điều khiển
Các mode hoạt động của bộ timer/counter, có 4 chế độ làm việc tùy thuộc vào thanh ghi TCCR đó là:
Chế độ bình thường (normal), thường được sử dụng trong hoạt động tạo hàm delay, ngắt timer định kỳ.
Chế độ điều xung, 2 chu kỳ đếm lên và xuống (PWM, phase correct) dùng để điều khiển tốc độ động cơ, DAC.
Chế độ xóa bộ counter (CTC, Clear Timer on Compare Match Mode) dùng để tạo tần số.
Chế độ điều xung 1 chu kỳ đếm lên (Fast PWM) dùng để điều khiển tốc độ động cơ, DAC.
4.2 CÁC THANH GHI LIÊN QUAN (TCCR, TCNT, OCR, TIMSK, TIFR) 4.2.1 THANH GHI TCCRn 4.2.1 THANH GHI TCCRn
Thanh ghi điều khiển TCCR dùng để xác định các Mode làm việc của bộ timer/counter, kiểu hoạt động ngõ ra chân OCn và bộ chia của bộ phát xung.
Hình 4.2 Thanh ghi TCCR0
Bit7 – FOC0: bit này chỉ có tác dụng trong hoạt động không sử dụng điều xung PWM, và bit này nên được viết 0 khi sử dụng trong hoạt động PWM. Khi bit này được viết lên mức 1 một hoạt động so sánh bằng sẽ xảy ra theo cài đặc của 2 bit COM00 và COM01.
Hoạt động này không phát sinh ra ngắt và không xóa giá trị thanh ghi OCR0 trong hoạt động CTC. Hoạt động này thích hợp trong việc tạo tần số với duty cycle thay đổi.
Bit6 – WGM00: bit này kết hợp với bit 3 sẽ qui định các chế độ hoạt động của bộ timer (Normal, CTC, Fast PWM, phase correct PWM).
Mode WGM01 Bit 3 WGM00 Bit 6 Chế độ hoạt động cực đại Giá trị Thời điểm cập nhật OCR0 tràn bậc lên 1 Thời điểm cờ
0 0 0 Normal 255 Ngay tức thời 255
1 0 1 PWM, Phase correct 255 255 0
2 1 0 CTC OCR0 Ngay tức thời OCR0
3 1 1 Fast PWM 255 255 255
Bảng 4.1 Các mode làm việc của bộ timer/counter0
Bit5 – COM01: Bit này kết hợp với bit 4 để điều khiển chân OC0, lưu ý phải khai báo chân OC0 là ngõ ra trước khi sử dụng, tùy thuộc vào các mode hoạt động khác nhau mà ta có bảng kết nối chân OC0 khác nhau.
Bit4 – COM00: xem bit 5
Bit3 – WGM01:xem bit 6
Bit2.1.0 – CS02.01.00: 3 bit này dùng để xác định nguồn tạo xung đưa vào bộ counter.
Hình 4.3 Bộ chia và bộ chọn kênh cho hoạt động timer/counter
(2) Thời gian để timer/counter tràn là 255 xung cho timer/counter0,2 (8bit) và 65535 xung cho timer/counter1 (16 bit)
Stt CS02 CS01 CS00 Description (mô tả)
1 0 0 0 Timer/counter không hoạt động
2 0 0 1 clkI/O (không chia tần số, bộ chia = 1)
3 0 1 0 clkI/O/8 (bộ chia = 8)
4 0 1 1 clkI/O/64 (bộ chia = 64) 5 1 0 0 clkI/O/256 (bộ chia = 256) 6 1 0 1 clkI/O/1024 (bộ chia = 1024)
7 1 1 0 Nhận xung ngoài từ chân T0, tác động cạnh xuống 8 1 1 1 Nhận xung ngoài từ chân T0, tác động cạnh lên
Bảng 4.2 Chọn nguồn xung cho bộ timer/counter
Chú ý: Dựa vào hình vẽ 4.3 và bảng 4.2 trên ta nhận thấy rằng khi sử dụng bộ timer/counter là bộ đếm thì bộ chia luôn bằng 1.
Xem bài tập ví dụ 1.
4.2.2 Thanh ghi TCNT: Lưu giá trị đang đếm ta cũng có thể gọi đây là bộ counter.
4.2.3 Thanh ghi OCR: Lưu trữ giá trị mong muốn (giá trị đặt)
4.2.4 Thanh ghi TIMSK
Bit 7 6 5 4 3 2 1 0
OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0
Read/ Write RW RW RW RW RW RW RW RW
Giá trị ban
đầu 0 0 0 0 0 0 0 0
Hình 4.4 Thanh ghi TIMSK Bit7 – 2: không sử dụng
Bit1 – OCIE0: bit này kết hợp với bit I trong thanh ghi trạng thái (status register) để cho phép hoạt động ngắt khi giá trị trong thanh ghi TCNT0 và OCR0 bằng nhau.
Bit0 – TOIE0: bit này kết hợp với bit I trong thanh ghi trạng thái (status register) để cho phép hoạt động ngắt khi hiện tượng tràn xảy ra.
4.2.5 Thanh ghi TIFR
Bit 7 6 5 4 3 2 1 0
OCF2 TOV2 ICF1 OCIF1A OCIF1B TOV1 OCF0 TOV0
Read/ Write RW RW RW RW RW RW RW RW
Giá trị ban đầu 0 0 0 0 0 0 0 0
Hình 4.5 Thanh ghi TIFR Bit7 – 2: không sử dụng
Bit1 – OCF0: (Cờ ngắt OCF0) cờ ngắt xảy ra khi bộ counter bằng với giá trị cài đặc trong OCR0, cờ này sẽ được tự động xóa bởi phần cứng khi sử dụng ngắt và xóa bởi phần mềm khi viết logic cao vào cờ này.
Bit0 – TOV0: (cờ tràn TOV0) cờ tràn sẽ ở mức cao khi bộ counter tràn (từ MAX về BOTTOM) và được tự động xóa bởi phẩn cứng khi sử dụng ngắt và xóa bởi phần mềm khi viết logic cao vào cờ này.
4.3 CÁC CHẾ ĐỘ HOẠT ĐỘNG CỦA TIMER/COUNTER 4.3.1 CHẾ ĐỘ BÌNH THƯỜNG (NORMAL) 4.3.1 CHẾ ĐỘ BÌNH THƯỜNG (NORMAL)
Đây là chế độ hoạt động đơn giản nhất, bộ counter sẽ đếm từ BOTTOM (0x00) tới MAX (0xFF) và lặp lại từ BOTTOM. Cờ tràn TOV0 sẽ tự động bật lên 1 khi bộ counter đếm từ 255 về 0, muốn xóa cờ tràn này ta phải viết logic 1 vào nó, khi sử dụng ngắt thì cờ tràn sẽ tự động xóa về 0, thời gian đếm phụ thuộc vào bộ chia (prescaler) được cài đặt bởi thanh ghi TCCR0, có thể bằng 1, 8, 64, 256 hoặc 1024.
Hình 4.6 Giản đồ thời gian trong hoạt động NORMAL
Bài tập ví dụ: Viết chương trình định thời thời gian là 10 giây, tần số thạch anh là 2Mhz.
Bài giải:
Chu kì máy: = = . = 0.5
Vậy số CKM để chạy trong 10 giây là: ∗
. = 2 ∗ 10 CKM Vậy ta phải chọn bộ chia là 1024 để có được số xung tối thiểu, Số xung tối thiểu = ∗ = 19531.
Vậy ta cần 19531 xung để có được bộ định thời 10 giây.
Nếu sử dụng bộ định thời 8 bit (timer0/timer2) thì ta có: = 76 Vậy cờ tràn TOV0 sẽ có 76 lần bật lên 1.
Vậy ta chọn biến đếm là unsigned char. Chương trình được viết như sau
#include <mega16.h>
unsigned char index;
bit key;
// Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
// Place your code here
index++; PORTD++; if(index == 76) { PORTC.0 = 1; PORTD = 0; index = 0; key = 1; } }
void main(void) {
PORTA=0x00;
DDRA=0x00; //PORTA là ngõ vào
PORTB=0x00; DDRB=0x00; //PORTB là ngõ vào PORTC=0x00; DDRC=0xFF; //PORTC là ngõ ra PORTD=0x00; DDRD=0xff; //PORTD là ngõ ra TIMSK=0x01; //Cho phép ngắt tràn
ACSR=0x80; //Không sử dụng mode so sánh // Global enable interrupts
#asm("sei")
while (1) {
// Place your code here
TCCR0 = 0; while(PINA.0); TCCR0 = 0x05; //chế độ là normal, bộ chia 1024 PORTC.0 = 0; while(!PINA.0); //chờ nhã phím } }
4.3.2. Chế độ CTC: (xóa khi so sánh bằng) bộ timer/counter sẽ đếm lên, khi giá trị trong thanh ghi counter (TCNT0) bằng với thanh ghi OCR0 (đã cài đặc trước) thì bộ counter thanh ghi counter (TCNT0) bằng với thanh ghi OCR0 (đã cài đặc trước) thì bộ counter sẽ bị xóa về 0 và tiếp tục đếm lên, cờ ngắt OCF0 nếu có sẽ xảy ra khi bộ counter đạt giá trị Max (bằng với OCR0).
Hình 4.8 Giản đồ thời gian trong hoạt động CTC
Tín hiệu OC0 sẽ không được xuất ra trên chân OC0 (PB3) nếu ta không cài đặt chức năng Ouput cho chân này (xem thanh ghi DDRB), các trạng thái của OC0 trong mode này được mô tả trong bảng sau:
COM01 COM00 Description (Mô tả)
0 0 Chân OC0 không kết nối, hoạt động như chức năng I/O 0 1 Chân OC0 đảo trạng thái khi TCNT0 = OCR0 (toggle)
1 0 Chân OC0 = 0 khi bằng
1 1 Chân OC1 = 1 khi bằng
Bảng 4.3 Ngõ ra OC0 trong hoạt động CTC
Tần số trên chân OC0 được tính bởi công thức sau:
(3) Với N là giá trị được xác định bởi thanh ghi TCCR0 N = (1, 8, 64, 256 hoặc 1024). Xem bài tập ví dụ 2
4.3.3 Chế độ PWM PHASE CORRECT
Chu kỳ hoạt động của bộ counter là hoạt động kép nghĩa là bộ counter sẽ đếm từ BOTTOM (0x00) đến MAX (0xFF) sau đó đếm từ MAX về BOTTOM và quá trình này lặp lại bất chấp bộ counter lớn hơn, nhỏ hơn hay bằng với OCR0.
Đối với hoạt động ngõ ra không đảo: khi bộ counter (thanh ghi TCNT0) bằng với thanh ghi OCR0 thì OC0 sẽ được xóa về 0, nếu bộ counter đang đếm lên, khi bộ counter đếm xuống thì OC0 sẽ bằng 1.
Đối với hoạt động đảo thì OC0 sẽ hoạt động ngược lại.
Hình 4.9 Giản đồ thời gian trong hoạt động PWM – PHASE CORRECT
Tín hiệu OC0 sẽ không được xuất ra trên chân OC0 (PB3) nếu ta không cài đặt chức năng ouput cho chân này (xem thanh ghi DDRB), các trạng thái của OC0 trong mode này được mô tả trong bảng 4.1.
COM01 COM00 Description (Mô tả)
0 0 Chân OC0 không kết nối, hoạt động như chức năng I/O
0 1 Không sử dụng
1 0 OC0 = 0 khi TCNT0 = OC0 trong khi đếm lên OC0 = 1 khi TCNT0 = OC0 trong khi đếm xuống 1 1 OC0 = 1 khi TCNT0 = OC0 trong khi đếm lên OC0 = 0 khi TCNT0 = OC0 trong khi đếm xuống
Bảng 4.4 Ngõ ra OC0 trong hoạt động PWM – PHASE CORRECT
Tần số trên chân OC0 được tính bởi công thức sau:
(4) Với N là giá trị được xác định bởi thanh ghi TCCR0 N = (1, 8, 64, 256 hoặc 1024). Bài tập ví dụ: cho biết thanh ghi OCR0 = 145 và thanh ghi TCCR0 = 0x01100010
4.3.4 Chế độ Fast PWM
Chu kỳ hoạt động của bộ counter sẽ là hoạt động đơn, nghĩa là bộ counter sẽ đếm từ BOTTOM đến MAX sau đó reset về BOTTOM và đếm lên tiếp, quá trình này lặp lại bất chấp bộ counter lớn hơn, nhỏ hơn hay bằng với OCR0.
Ở chế độ không đảo OC0 sẽ bị xóa về 0 khi bộ counter trùng với OCR0, và bằng 1 khi bộ counter bằng BOTTOM.
Ở chế độ đảo thì ngược lại.
Hình 4.10 Giản đồ thời gian cho hoạt động FAST PWM
Tín hiệu OC0 sẽ không được xuất ra trên chân OC0 (PB3) nếu ta không cài đặt chức năng ouput cho chân này (xem thanh ghi DDRB), các trạng thái của OC0 trong mode này được mô tả trong table 40.
COM01 COM00 Mô tả (Description)
0 0 Chân OC0 không kết nối, hoạt động như chức năng I/O
0 1 Không sử dụng
1 0 OC0 = 0 khi TCNT0 bằng OCR0, OC0 = 1 khi TCNT0 = 0 OC0 = 1 khi TCNT0 bằng OCR0, OC0 = 0 khi TCNT0 = 0 1 1 OC0 = 1 khi TCNT0 bằng OCR0, OC0 = 0 khi TCNT0 = 0 OC0 = 0 khi TCNT0 bằng OCR0, OC0 = 1 khi TCNT0 = 0
Bảng 4.5 Ngõ ra oc0 trong hoạt động FAST PWM
Tần số trên chân OC0 được tính bởi công thức sau:
(5) Với N là giá trị được xác định bởi thanh ghi TCCR0 N = (1, 8, 64, 256 hoặc 1024).
4.4 Bài tập ví dụ
Ví dụ 1: Trong chế độ Normal, tần số thạch anh là 1 Mhz, sử dụng bộ chia là 64, hỏi trong 1 giây timer tràn bao nhiêu lần.
Giải: Dựa vào hình vẽ 4.3 ta nhận thấy rằng, 1 xung ngõ ra của bộ chia bằng 64 chu kì máy (CKM).
Ta có 1CKM = 1/fosc = 1 (us) 1 xung = 64 CKM = 64us
Thời gian tràn là 255 xung = 255.64 = 16.320 us Vậy số lần tràn trong 1 giây là: 61 lần
Ví dụ 2: Viết chương trình tạo tần số 5Khz trên chân PB.3, thạch anh 4Mhz
Giải: Vì yêu cầu mạch thiết kế tần số nên ta chọn mode CTC, OC0 ngõ ra dạng toggle.
Mode CTC: WGM01 = 1; WGM00 = 0 (xem bảng 4.1)
Ngõ ra dạng toggle: COM00 = 1; COM01 = 0. (xem bảng 4.3)
Hình 4.11 Dạng xung cho tần số 5Khz
Chu kì máy = = 1
Để thực hiện 100us ta phải mất 100CKM < 255 nên ta chọn bộ chia = 1 Vậy
Thanh ghi TCCR0 = 0b00011001 = 0x19; Thanh ghi OCR0 = 100;
Ví dụ 3: Hãy xác định thanh ghi TCCR2, biết rằng vi điều khiển sử dụng bộ chia 64, chế độ hoạt động Fast PWM, ngõ ra OC2 = 0 khi bằng.
Giải: Sử dụng bộ chia 64 nên: CS02, CS01, CS00: 011 (xem bảng 4.2) Chế độ hoạt động Fast PWM: WGM01,00 = 11 (xem bảng 4.1)
4.4 CÂU HỎI ÔN TẬP HẾT CHƯƠNG
Câu 1: Hãy nêu các thời điểm xảy ra hoạt động ngắt (ngắt bằng và ngắt tràn) trong hoạt động Timer/Counter.
Câu 2: Vi điều khiển có bao nhiêu chân điều xung, kể tên các chân đó. Câu 3: Khi sử dụng đếm sự kiện tín hiệu vào phải ở chân nào?
Câu 4: Hãy cho biết sự khác nhau và giống nhau giữa 2 mode Fast PWM và Phase correct PWM.
Câu 5: Hãy viết chương trình tạo tần số 20 Khz trên chân OC0 (PB3) với duty cycle là 50%, tần số thạch anh là 2Mhz.
Câu 6: Viết chương trình tạo bộ định thời chính xác 10 giây, tần số thạch anh là 1Mhz (gợi ý: sử dụng chế độ CTC)
Câu 7: Hãy viết chương trình tạo tần số 8 Khz trên chân OC0 (PB3) với duty cycle là 75%.
Câu 8: Hãy viết chương trình đếm sản phẩm trên chân T0 sử dụng chức năng timer/counter (tác động cạnh lên), khi đếm đến 100 sản phẩm thì sẽ xuất tín hiệu trên chân PORTD.7 = 1 trong khoảng 5 giây, sau đó lặp lại từ đầu.