CƠ CHẾ HOẠT ĐỘNG CỦA NGẮT : 

Ngắt hiểu theo nghĩa đơn giản là các sự kiện ngẫu nhiên làm gián đoạn quá trình của một sự kiện đang xảy ra.

interupt

Vi điều khiển cũng có ngắt. Cụ thể hoạt động của vi điều khiển khi có sự kiện ngắt xảy ra và ngắt đó đã được cho phép:
- Thực hiện nốt lệnh đang thực hiện
- Dừng chương trình đang thực hiện
- Lưu lại địa chỉ của lệnh kế tiếp trong chương trình đang thực hiện vào bộ nhớ stack
- Nhảy tới địa chỉ 0x04h trong bộ nhớ chương trình
- Tại đây, vi điều khiển sẽ thực hiện chương trình con phục vụ ngắt do người lập trình đã lập trình từ trước.
- Sau khi thực hiện xong chương trình con phục vụ ngắt, vi điều khiển lấy lại địa chỉ của lệnh kế tiếp đã được lưu và thực hiện tiếp chương trình đang thực hiện dở lúc chưa có ngắt

Trên PIC 14 , 12 ,10 ,tất cả các ngắt chỉ có 1 cấp ưu tiên . Nghĩa là ngắt nào đang được phục vụ thì không thể bị ngắt bởi 1 ngắt khác xảy ra . Cơ chế sinh mã cho ngắt của CCS như sau : nhảy đến địa chỉ ngắt , thường là 004h , sao lưu thanh ghi W,  STATUS , PCLATCH , FSR, sau đó nó mới hỏi vòng xem cờ ngắt nào xảy ra  thì nhảy đến hàm phục vụ ngắt đó . Thực hiện xong thì phục hồi tất cả thanh ghi trên , rồi mới  thoát ngắt.

Nếu chương trình dùng nhiều ngắt và có 2 ngắt trở lên xảy ra đồng thời ? Để tránh phục vụ không đúng chỗ , bạn dùng #priority để xác định ưu tiên ngắt. Ngắt ưu  tiên nhất sẽ luôn được hỏi vòng trước .Sau khi xác định cờ ngắt cần phục vụ , nó sẽ thực thi hàm ngắt tương ứng, xong thì xoá cờ ngắt đó và thoát ngắt.

Môt chương trình dùng nhiều ngắt phải lưu ý điều này , tránh trường hợp : ngắt xảy ra liên tục (tràn ngắt ) , 1 ngắt bị đáp ứng trễ  , ngắt không đúng ,... sẽ gây ra tất nhiều phiền toái và lộn xộn trong quá trình thực thi của vi điều khiển.

Chỉ có trên PIC 18 ( và dsPIC ) . Có 2 khái niệm : ngắt ưu tiên thấp (low priority) và ngắt ưu tiên cao ( high priority ) . 2 vector thực thi ngắt tương ứng thường là 0008h (high) và 0018h ( low ) . Một  ngắt thấp đang được phục vụ sẽ bị ngưng và phục vụ ngắt cao ở 0008h nếu ngắt cao xảy ra . Ngược lại , ngắt cao đang xảy ra thì không bao giờ bị ngắt bởi ngắt thấp .
Để sử dụng ngắt 2 cấp ,  khai báo #device phải có high_ints=true . Và hàm ngắt nào muốn ưu tiên cao thì thêm FAST hay HIGH theo sau chỉ thị tiền xử lý hàm đó.
Ví dụ :

#int_timer1  FAST 
 Void ngat_timer1 ( ) 
  { . . . 
  } 

 KHAI BÁO NGẮT :
Mỗi dòng VDK có số lượng tài nguyê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ó .

Ví dụ một số ngắt hay dùng :

#define GLOBAL                    0x0BC0      // Ngắt chung

#define INT_EXT                   0x000B10   // Ngắt ngoài
#define INT_AD                    0x008C40   // Chuyển đổi AD đã hoàn tất
#define INT_RDA                   0x008C20  // Ngắt nhận dữ liệu từ RS232
#define INT_TIMER1                0x008C01 // Ngắt Timer1
#define INT_TIMER2                0x008C02 // Ngắt timer2
#define INT_CCP1                  0x008C04  // có Capture hay compare trên CCP1
#define INT_CCP2                  0x008D01 // có Capture hay compare trên CCP1
#define INT_TIMER0                0x000B20 // Ngắt timer0
#define INT_RB0                   0x1010B08 // Ngắt khi có bất kì sự thay đổi nào trên PIN RB0

CÁC HÀM THIẾT LẬP HOẠT ĐỘNG NGẮT : 

enable_interrupts ( level ) 
+ level là tên các ngắt giống như ở trên.
+ Mọi ngắt của vi điều khiển đều có 1 bit cờ ngắt , 1 bit cho phép ngắt . Khi có ngắt thì bit cờ ngắt được 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 .
VD : để cho phép ngắt timer0 hoạt động:
enable_interrupts (int_timer0);
enable_interrupts ( global );

disable_interrupts ( level ) 
+ level giống như trên .
+ 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 .

Kết luận : Việc sử dụng các ngắt trong vi điều khiển đòi hỏi tính linh hoạt và mềm dẻo nếu không bạn sẽ rơi vào trạng thái xung đột các ngắt làm cho chương trình của bạn chạy loạn, điều khiển không như ý muốn.

Epicviet.com