4.1.1. Lý thuyết liên quan:
- Giới thiệu ngắt:
Ngắt(interrupt) là quá trình tạm thời dừng chương trình chính, để thực thi một chương trình khác, chương trình này còn được gọi là chương trình thực thi ngắt. Hoạt động ngắt giúp hệ thống của chúng ta đặc tả tốt hơn các đặc tính thời gian thực.
Quá trình hoạt động của ngắt được tóm tắt thông qua sơ đồ sau:
Hình 4.1 - Quy trình hoạt động của ngắt trong VĐK - Chế độ ngắt:
Mỗi dòng VDK có số lượng nguồn ngắt ngắt khác nhau : PIC 14 có 14 ngắt, PIC 18 có 35 ngắt.
Muốn biết CCS hỗ trợ những ngắt nào cho VDK của bạn, mở file *.h tương ứng, ở cuối file là danh sách các ngắt mà CCS hỗ trợ nó. Cách khác là vào CCS -> View -> Valid interrupts, chọn dòng PIC muốn xem, danh sách ngắt sẽ hiển thị.
Sau đây là danh sách 1 số ngắt với chức năng tương ứng:
#INT_GLOBAL : ngắt chung, nghĩa là khi có ngắt xảy ra, hàm theo sau chỉ thị này được thực thi, bạn sẽ không được khai báo thêm chỉ thị ngắt nào khác khi sử dụng chỉ thị này. CCS không sinh bất kỳ mã lưu nào, hàm ngắt bắt đầu ngay tại vector ngắt. Nếu bật nhiều cờ cho phép ngắt, có thể bạn sẽ phải hỏi vòng để xác định ngắt nào. Dùng chỉ thị này tương đương viết hàm ngắt 1 cách thủ công mà thôi, như là viết hàm ngắt với ASM vậy.
#INT_AD : chuyển đổi A /D đã hoàn tất, thường thì không nên dùng
#INT_BUSCOL : xung đột bus
#INT_BUTTON : nút nhấn( không biết hoạt động thế nào)
#INT_CCP1 : có Capture hay compare trên CCP1
#INT_CCP2 : có Capture hay compare trên CCP2
#INT_COMP : kiểm tra bằng nhau trên Comparator
#INT_EEPROM : hoàn thành ghi EEPROM
#INT_EXT : ngắt ngoài
#INT_EXT1 : ngắt ngoài 1
#INT_EXT2 : ngắt ngoài 2
#INT_I2C : có hoạt động I 2C
#INT_LCD : có hoạt động LCD
#INT_LOWVOLT : phát hiện áp thấp
#INT_PSP : có data vào cổng Parallel slave
#INT_RB : bất kỳ thay đổi nào trên chân B4 đến B7
#INT_RC : bất kỳ thay đổi nào trên chân C4 đến C7
#INT_RDA : data nhận từ RS 232 sẵn sàng
#INT_RTCC : tràn Timer 0
#INT_SSP : có hoạt động SPI hay I 2C
#INT_TBE : bộ đệm chuyển RS 232 trống
#INT_TIMER0 : một tên khác của #INT_RTCC
#INT_TIMER1 : tràn Timer 1
#INT_TIMER2 : tràn Timer 2
#INT_TIMER3 : tràn Timer 3
#INT_TIMER5 : tràn Timer 5
#INT_OSCF : lỗi OSC
#INT_PWMTB : ngắt cuả PWM time base
#INT_IC3DR : ngắt đổi hướng( direct) của IC 3
#INT_IC2QEI : ngắt của QEI
#INT_IC1 : ngắt IC 1
Hàm đi kèm phục vụ ngắt không cần tham số vì không có tác dụng.
Sử dụng NOCLEAR sau #int_xxx để CCS không xoá cờ ngắt của hàm đó.
Để cho phép ngắt đó hoạt động phải dùng lệnh enable_interrupts(
int_xxxx) và enable_interrupts(global).
Khoá FAST theo sau #int_xxxx để cho ngắt đó là ưu tiên cao, chỉ được 1 ngắt, chỉ có ở PIC18 và dsPIC.
VD : #int_timer0 FAST NOCLEAR
-Các hàm thiết lập hoạt động ngắt : - enable_interrupts( level)
+ level là tên các ngắt là GLOBAL để cho phép ngắt ở cấp toàn cục.
+ Mọi ngắt của VDK đều có 1 bit cờ ngắt, 1 bit cho phép ngắt. Khi có ngắt thì bit cờ ngắt bị set =1, nhưng ngắt có họat động được hay không tuỳ thuộc bit cho phép ngắt. enable_interrupts(int_xxx) sẽ bật bit cho phép ngắt.
Nhưng tất cả các ngắt đều không thể thực thi nếu bit cho phép ngắt toàn cục = 0, enable_interrupts( global) sẽ bật bit này.
Ví dụ: để cho phép ngắt timer0 và timer1 hoạt động:
enable_interrupts(int_timer0);
enable_interrupts(int_timer1) ;
enable_interrupts( global); // chỉcần dùng 1 lần ngoại trừcó thayđổiđặc biệt
- disable_interrupts( level)
+ level là tên các ngắt là GLOBAL để cho phép ngắt ở cấp toàn cục.
+ Hàm này vô hiệu 1 ngắt bằng cách set bit cho phép ngắt = 0.
+ disable_interrupts( global) set bit cho phép ngắt toàn cục =0, cấm tất cả các ngắt.
+ Không dùng hàm này trong hàm phục vụ ngắt vì không có tác dụng, cờ ngắt luôn bị xoá tự động.
- clear_interupt( level)
+ level không có GLOBAL.
+ Hàm này xoá cờ ngắt của ngắt được chỉ định bởi level.
- ext_int_edge( source, edge)
+ Hàm này thiết lập nguồn ngắt ngoài EXTx là cạnh lên hay cạnh xuống.
+ source: nguồn ngắt. Trên PIC 18 có 3 nguồn ngắt trên 3 chân EXT0, EXT1, EXT2 ứng với source = 0, 1, 2. Các PIC khác chỉ có 1 nguồn EXT nên source = 0.
+ edge: chọn cạnh kích ngắt, edge = L_TO_H nếu chọn cạnh lên(từ mức thấp chuyển lên mức cao) hay H_TO_L nếu chọn cạnh xuống.
- Quản lý ngắt Timer 0 trong chương trình CCS
* Trong chương trình chính, cài đặt ngắt:
- Gán giá trị ban đầu cho thanh ghi TMR0, tùy thuộc vào thời gian mà người lập trình muốn: SET_TIMER0(giá trị)
- Cho phép ngắt timer 0: ENABLE_INTERRUPTS(INT_TIMER0) - Cho phép ngắt toàn cục: ENABLE_INTERRUPTS(GLOBAL)
* Chương trình con phục vụ ngắt đặt sau chỉ định biên dịch #INT_TIMER0:
#INT_TIMER0 //Định nghĩa chương trình con
* Trong chương trình con phục vụ ngắt:
- Xóa cờ ngắt: CLEAR_INTERRUPT(INT_TIMER0)
- Cấm ngắt toàn cục, đề phòng lúc đang xử lý ngắt, lại có ngắt xảy ra:
DISABLE_INTERRUPTS(GLOBAL)
- Xử lý ngắt đó: tùy thuộc vào ý đồ của người lập trình, chú ý đến số lần ngắt
- Gán lại giá trị ban đầu cho thanh ghi TMR0(tùy thuộc vào ý đồ của người lập trình):
SET_TIMER0(giá trị);
4.1.2. Trình tự thực hiện:
- Bước 1:Xác định loại ngắt sẽ thực hiện Sử dụng ngắt Timer 0
- Bước 2:Viết chương trình tạo ngắt
#include <18f4550.h>
#fuses NOWDT,PUT,HS,NOPROTECT
#use delay(clock=20000000) int16 count;
int8 a;
int16 dv,chuc,tram,nghin;
int16 so,i;
//Chuong trinh ngat TMR0
#int_timer0 void ngat0() {
set_timer0(46595);
so++;
chuc=so/10;
dv=so%10;
}
// CHUONG TRINH CON void led_A0()
{ output_low(PIN_E0);//E0=0 output_low(PIN_E1);//E1=0 }
void led_A1()
{ output_high(PIN_E0);//E0=1 output_low(PIN_E1);//E1=0 }
void led_A2()
{ output_low(PIN_E0);//E0=0 output_high(PIN_E1);//E1=1 }
void led_A3()
{ output_high(PIN_E0);//E0=1 output_high(PIN_E1);//E1=1 }
void chon_ma(int16 maled) { switch(maled)
{
case 0 :output_low (PIN_E2) ;output_low (PIN_C0) ; output_low (PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 1 :output_high(PIN_E2) ;output_low (PIN_C0) ; output_low (PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 2 :output_low (PIN_E2) ;output_high(PIN_C0) ; output_low (PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 3 :output_high(PIN_E2) ;output_high(PIN_C0) ; output_low (PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 4 :output_low (PIN_E2) ;output_low (PIN_C0) ; output_high(PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 5 :output_high(PIN_E2) ;output_low (PIN_C0) ; output_high(PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 6 :output_low (PIN_E2) ;output_high(PIN_C0) ; output_high(PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 7 :output_high(PIN_E2) ;output_high(PIN_C0) ; output_high(PIN_C1) ; output_low (PIN_A4);delay_ms(1);break;
case 8 :output_low (PIN_E2) ;output_low (PIN_C0) ; output_low (PIN_C1) ; output_high(PIN_A4);delay_ms(1);break;
case 9 :output_high(PIN_E2) ;output_low (PIN_C0) ; output_low (PIN_C1) ; output_high(PIN_A4);delay_ms(1);break;
} }
//--- //Chuong trinh chinh void main(void) {
enable_interrupts(int_timer0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
enable_interrupts(global);
so = 0;
while(true) {
led_A0();
chon_ma(dv);
led_A1();
chon_ma(chuc);
} }
- Bước 3:Kiểm tra và nạp chương trình - Bước 4:Vận hành, quan sát và chỉnh sửa 4.1.3. Thực hành:
Người học thực hiện viết chương trình hiển thị theo yêu cầu kỹ thuật như trên, nạp vào vi điều khiển PIC 18F4550.
Thiết bị thực hành:
- Máy vi tính;
- Mạch nạp PIC KIT 2
- Môn đun thực hành PIC Traning KIT 4.1.4. Câu hỏi ôn tập:
Câu 1: IC PIC 18F4550 có bao nhiêu nguồn ngắt?