NGẮT VÀ CẤU TRÚC CỦA MỘT CHƯƠNG TRÌNH NGẮT

Một phần của tài liệu Báo cáo Vi điều khiển.pdf (Trang 120 - 124)

CHƯƠN G4 MỘT SỐ ỨNG DỤNG CỤ THỂ CỦA PIC16F877A

4.4 NGẮT VÀ CẤU TRÚC CỦA MỘT CHƯƠNG TRÌNH NGẮT

Ngắt và các loại ngắt đã được trình bày cụ thể trong chương 2. Ở đây ta chỉ tóm tắt lại một số đặc điểm quan trọng của ngắt và thông tin mang tính ứng dụng.

Có thể nói đây là một khái niệm mang tính trừu tượng cao nhưng cũng được thiết lập dựa trên các hiện tượng và tình huống có thực trong thực tế. Chẳng hạn như trong cuộc sống hằng ngày, đôi khi ta phải tạm ngưng một công việc nào đó để làm một công việc khác cần thiết hơn, chẳng hạn như tạm ngưng một công việc nào đó đang làm để nghe điện thoại. Sự tạm ngưng này cần được báo hiệu bởi một tín hiệu (trong trường hợp trên là chuông điện thoại chẳng hạn) và phải được ta cho phép trước đó (nếu ta không cho phép điện thoại reo thì điện thoại sẽ không reo). Từ ví dụ thực tế trên ta có thể liên tưởng đến ngắt và cách xử lí ngắt của một vi điều khiển. Một ngắt là một tín hiệu điều khiển bắt buộc vi điều khiển tạm ngưng công việc đang làm để tiến hành các thao tác mà ngắt đó qui định thông qua chương trình ngắt. Tín hiệu điều khiển này được báo hiệu bởi cờ ngắt (tương ứng với chuông điện

thoại ở ví dụ trên) và phải được ta cho phép trước đó thông qua các bit điều khiển cho phép hoặc không cho phép ngắt. Một chương trình ngắt thông thường sẽ được tách riêng với chương trình chính để bảo đảm tính độc lập của chương trình ngắt.

Đối với vi điều khiển PIC16F877A, khi một ngắt (đã được cho phép trước đó) xảy ra thì “phản ứng” của nó là quay về địa chỉ 0004h và thực hiện các lệnh bắt đầu tại địa chỉ này. Thông thường đối với chương trình viết cho vi điều khiển PIC, chương trình ngắt sẽ được đặt tại đây và chương trình chính sẽ được bắt đầu ở một địa chỉ cách đó một đoạn “an toàn” sao cho chương trình chính và chương trình ngắt không bi chồng lên nhau. Nếu ta sử dụng trình biên dịch MPLAB, trình biên dịch sẽ báo lỗi khi hiện tượng trên xảy ra và ta có thể khắc phục bằng cách dời chương trình chính đi một đoạn xa hơn.

Một điểm cần lưu ý nữa là trong quá trình thực hiện chương trình ngắt, nội dung của một số thanh ghi quan trọng có khả năng bị thay đổi (thanh ghi W chẳng hạn). Do đó trước khi thực hiện chương trình ngắt ta cần thực hiện một thao tác là “cất” một số thanh ghi quan trọng vào một vài ô nhớ nào đó và phải trả lại giá trị ban đầu cho các thanh ghi đó trước khi thoát khỏi chương trình ngắt bằng lệnh RETFIE.

Nếu sử dụng trình biên dịch MPLAB, cấu trúc chương trình này đã được viết sẵn, ta chỉ việc đưa chương trình ngắt và chương trình chính vào các vị trí thích hợp được chú thích trong chương trình, tuy nhiên dựa vào các nhận định như trên ta hoàn toàn có thể tự định ra một câú trúc chương trình cho riêng mình như sau:

;--- ; Một số thông tin cần ghi chú về chương trình

;--- TITLE "tên chương trình"

processor 16f877a

include <p16f877a.inc>

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF

; Ví dụ về cách khai báo một vi điều khiển

;--- ; Định nghĩa phần cứng

;--- ; định nghĩa các chân xuất nhập để dễ dàng sử dụng

; ví dụ

#DEFINE DEN1 PORTB,0 #DEFINE DEN2 PORTB,1 #DEFINE DEN3 PORTB,2

;--- ; Định nghĩa các biến, các thanh ghi các tham số

;--- ;Nên đặt tất cả các biến trong BANK0

; ví dụ ORG 0x020

REGAD1 RES 1 ; biến này có độ lớn 1 byte, địa chỉ

; bắt đầu là 0x20

Variables RES 32 ; biến này có độ lớn 32 byte, địa chỉ

; bắt đầu là 0x21

;--- ; Chương trình ngắt

;--- ; Chú ý là tuyệt đối không thay đổi cấu trúc đoạn chương trình bắt đầu và thoát ra ; khỏi chương trình ngắt

; Nếu thay đổi chương trình sẽ chạy không đúng ORG 0X0004

;--- ; Bắt đầu chương trình ngắt

; Đoạn chương trình bắt buộc và không được thay đổi ; có tác dụng lưu lại một số thanh ghi quan trọng

;--- MOVWF W_SAVE ; W_SAVE(bank unknown!) = W

SWAPF STATUS,W

CLRF STATUS ; force bank 0 for remainder of handler MOVWF STAT_SV ; STAT_SV = swap_nibbles( STATUS ) ; STATUS = 0 MOVF PCLATH,W MOVWF PCH_SV ; PCH_SV = PCLATH CLRF PCLATH ; PCLATH = 0 MOVF FSR,W MOVWF FSR_SV ; FSR_SV = FSR

; 12 cycles from interrupt to here!

;--- ; Đoạn chương trình ngắt bắt đầu tại đây

;--- ; Kiểm tra xem ngắt nào đã xảy ra

; Xóa cờ ngắt trước khi thực hiện các lệnh trong ngắt ; Bắt đầu các lệnh cho chương trình ngắt

;--- ; Kết thúc chương trình ngắt

; Đoạn chương trình bắt buộc và không được thay đổi

; có tác dụng phục hồi giá trị ban đầu cho một số thanh ghi quan trọng

;--- ENDINT

MOVF FSR_SV,W

MOVWF FSR ; FSR = FSR_SV MOVF PCH_SV,W

MOVWF PCLATH ; PCLATH = PCH_SV SWAPF STAT_SV,W

MOVWF STATUS ; STATUS = swap_nibbles( STAT_SV ) SWAPF W_SAVE,F

SWAPF W_SAVE,W ; W = swap(swap( W_SAVE )) (no change Z bit) RETFIE ; RETURN!

; 1 cycle to resumption of code (branch penalty) ;--- ; Chấm dứt chương trình ngắt

; Bắt đầu các bước khởi tạo cho toàn bộ chương trình

;--- ORG 0X0000

GOTO START ORG 0X0050

; Phải cách ra một đoạn để tránh đè lên chương trình ngắt START

;--- ; Khởi tao cac PORT

; Khởi tạo các biến

; Khởi tạo các khối chức năng (Timer, CCP, PWM,……)

;--- ; Bắt đầu vòng lặp chính MAIN ; Các thao tác trong vòng lặp chính ; Các chương trình con END

So với các chương trình trước đây thì bắt đầu từ giai đoạn này, các chương trình sẽ trở

Một phần của tài liệu Báo cáo Vi điều khiển.pdf (Trang 120 - 124)

Tải bản đầy đủ (PDF)

(173 trang)