Vector ngắt có mức ưu tiên cao của pic18f4520 là gì?

Chữ lem luốn thế kia hàng fake là phải, thấy data là 0.28 ôm. Bạn thử cho nó dẫn dòng DC 3A xem VDS bao nhiêu volt? Con 26N60-TO220 dẫn 3.4A/0.57V = 0.168R. Trước cũng mua trên mạng, 20N60 về đo tới trên 2R, không thể chạy được. E là nếu nó đúng 1.9R...

rocket42

07-10-2011, 05:21 PM

Ngắt ưu tiên thấp trong Pic18 là chương trình ngắt được lưu bắt đầu ở địa chỉ 0x18.
Ngắt ưu tiên cao trong thì chương trình ngắt được lưu bắt đầu ở địa chỉ 0x08. Tức là khi xảy ra ngắt thì con trỏ chương trình sẽ nhảy tới địa chỉ này và thực hiện lệnh.
ngắt ưu tiên cao khác so với ngắt ưu tiên thấp là khi đang thực hiện chương trình ngắt ưu tiên thấp mà xảy ra ngắt ưu tiên cao thì nó sẽ nhảy tới thực hiện chương trình ngắt ưu tiên cao. Sau khi thực hiện xong ngắt ưu tiên thấp nó sẽ trở lại hoàn thành chương trình ngắt ưu tiên thấp đang thực hiện dở.
Nhưng điều ngược lại ko được thực hiện khi đang có chương trình ngắt ưu tiên cao đang thực hiện thì nó sẽ ko bị ngắt bởi bất cứ loại ngắt nào khác. Trừ RESET [nhưng đây ko phải là ngắt]
Trong Pic18 thì mức ưu tiên ngắt có thể cài đặt cho từng loại ngắt cụ thể bằng set các bit trong thanh ghi điều khiển ngắt tương ứng. bạn có thể xem chi tiết các thanh ghi trong datasheet của loại Pic mà bạn dùng
Bạn có thể xem hình minh họa tôi gửi kèm để hiểu rõ về nó
Để xem cách lập trình ngắt trong Pic18 bằng C18 như thế nào bạn có thể xem tài liệu tiếng việt tôi đã viết xong và gửi lên diễn đàn:
//www.picvietnam.com/forum/showthread.php?t=11338
chúc vui!!!

Tai lieu tra_cuu_pic 18f4520 from Vũ Anh

Các Ngắt Trong PIC
I / CƠ CHẾ HOẠT ĐỘNG CỦA NGẮT :
1 / Ngắt 1 cấp :
+ 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, và nhiều thứ vớ vẫn khác, 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 “RETFIE” – thoát ngắt . Số chu kỳ thực thi từ chỗ ngắt đến khi nhảy vào
hàm ngắt cỡ 20 chu kỳ lệnh !, nhảy ra cũng cỡ đó .
+ Điều gì xảy ra nếu chương trình dùng nhiều ngắt và khi có ngắt thì có 2 ngắt trở lên xảy ra đồng thời ? Nghĩa là : 2 ngắt xảy ra
cùng lúc , hay khi ngắt A kích hoạt và CCS đang lưu các thanh ghi [ chưa tới hỏi vòng cờ ngắt ] thì ngắt B xảy ra , dĩ nhiên ngắt B
không thể kích vector ngắt nhảy tới 004h vì bit cho phép ngắt toàn cục [ GIE ] bị khóa tự động khi có ngắt , chỉ có cờ ngắt B bật mà
thôi. Sau khi lưu các thanh ghi , chương trình kiểm tra cờ ngắt , rõ ràng là nếu bit nào được kiểm tra trước thì phục vụ trước , dù
nó xảy ra sau . Để tránh phục vụ không đúng chỗ , bạn dùng #priority để xác định ưu tiên ngắt [ xem phần chỉ thị tiền xử lý ] . 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 . Phục vụ ngắt nào xong thì chỉ xoá cờ ngắt đó .Nếu A ưu tiên hơn B thì sau khi làm A , chương trình xoá
cờ ngắt A , nhưng cờ B không xoá [ vì đâu có phục vụ ] , nên khi thoát ra ngắt A , nó sẽ lại ngắt tiếp [ vì cờ B đã bật ], lại hỏi vòng
cờ ngắt từ đầu : nếu cờ A chưa bật thì xét B, lúc này B bật nên phục vụ B , xong thì xoá cờ B 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 , . . .
2 / Ngắt 2 cấp :
+ 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 .
+ Nếu viết hàm ngắt bình thường , không đòi hỏi ưu tiên gì thì CCS sinh mã để tất cả hàm ngắt đều là ngắt ưu tiên cao . Quy trình
thực hiện ngắt sẽ như ngắt 1 cấp trên . #priority vẫn được dùng . Số chu kỳ thực thi từ 0008h đến khi nhảy vào thực thi hàm ngắt
khoảng 30 chu kỳ , xong hàm ngắt tới khi kết thúc ngắt cũng mất khoảng 30 chu kỳ lệnh .
+ Để 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 đó .
Lưu ý : khi dùng FAST thì không nên dùng HIGH cho các ngắt khác thì mới có ý nghĩa và chỉ có duy nhất 1 ngắt được ưu tiên
FAST , nhưng có thể có nhiều ngắt đặt ở mức HIGH .
VD :


#int_timer1 FAST
Void xu_ly [ ]
{ . . .
}
#int_timer2 HIGH
Void dinh_thi []
{ . . .
}
#int_timer5 HIGH
Void vong_lap[]
{ . . .
}
+ Cơ chế sinh mã như sau : có ngắt thấp thì nhảy tới 0018h , sao lưu W, STATUS , FSR0/1/2 ,. . . rồi mới hỏi vòng cờ ngắt thấp .
chạy xong hàm ngắt thì phục hồi tất cả và “RETFIE 0 “ .
+ Riêng ngắt cao đánh dấu FAST không sinh mã sao lưu gì cả mà nhảy thẳng vào hàm ngắt chạy luôn . PIC 18 và dsPIC có cơ chế
lưu siêu tốc là FAST STACK REGISTER [ xem datasheet ] . Khi xảy ra ngắt bất kỳ, W, S , BSR tự động lưu vào thanh ghi trên , PC
counter lưu vào stack . xong ngắt thì pop ra . Vấn đề ở chỗ : khi ngắt thấp xảy ra , FAST STACK REGISTER tự động lưu W ,S ,
BSR , PC -> stack . Trong khi thực hiện hàm phục vụ ngắt thì trường hợp W, S , BSR thay đổi là có thể [ vì vậy mới sao lưu chứ ] .
nhưng nếu xảy ra ngắt cao vào thời điểm đó ? FAST STACK REGISTER sẽ bị ghi đè => mất data . Do đó , cơ chế sinh mã của
CCS cần phải luôn đúng , nghĩa là : luôn tự sao lưu riêng W ,S , BSR, và các thanh ghi FSR nữa , khi thực thi ngắt thấp . Còn ngắt
cao FAST khi chạy xong sẽ “RETFIE 1 “ – tự động phục hồi W, S , BSR từ FAST STACK REGISTER . Có 2 trường hợp : 1 là chỉ
có ngắt cao , thì không có vấn đề gì . 2 là ngắt cao ngắt 1 ngắt thấp đang chạy . Phân tích sẽ thấy rằng cho dù bị ngắt trong khi
đang sao lưu ,hay chưa kịp sao lưu , hay đã sao lưu vào các biến riêng rồi , cuối cùng chương trình cũng quay ra đúng địa chỉ ban
đầu với các thanh ghi W, S , BSR như cũ .
+ Tuân thủ nguyên tắc ngắt cao thực thi tức thời nên CCS chỉ cho 1 ngắt cao FAST duy nhất bất kỳ hoạt động , nên không sinh mã
hỏi vòng , sao lưu thêm gì cả .
+ Nếu bạn muốn có nhiều ngắt ưu tiên cao , thì dùng HIGH , chương trình sao lưu bình thường như với ngắt thấp , nhưng khi đó
ngắt đánh dấu FAST cũng mất tác dụng , CCS xem như là HIGH và xử lý bình thường .
_Như vậy dùng FAST hay HIGH đều có ý nghĩa riêng của nhà lập trình .
II / KHAI BÁO 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
VDK muốn xem , nó sẽ hiển thị danh sách ngắt có thể có cho VDK đó .
_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_ADOF : I don’t know
#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 thôi , chỉ có ở PIC 18 và dsPIC .
VD : #int_timer0 FAST NOCLEAR
III / CÁC HÀM THIẾT LẬP HOẠT ĐỘNG NGẮT :
1 / enable_interrupts [ level ]
+ level là tên các ngắt đã cho ở trên hay 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 .
VD : để 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 trừ phi muốn có thay đổi đặc biệt
2 / 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 .
3 / 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 .
4 / 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 .
IV / CÁC CHƯƠNG TRÌNH VD VỀ NGẮT :
1 / #INT_RB :
+ Sau đây là 1 chương trình điển hình về sử dụng ngắt khi có sự thay đổi trên chân B4-B7 .
+ Mô tả : mỗi khi nhấn nút bất kỳ trên B4-B7 , sẽ kích ngắt RB , hàm phục vụ ngắt có tên RB_LED được thực thi , hàm này đơn
giản là xuất ra LED ở vị trí tương ứng nhưng trên portD từ D4 – D7 .
+ VDK là 16F877 .
#include < 16F877.h >
#device PIC16F877 *=16
#use delay [clock = 20000000 ] //thêm khai báo này nếu ctrình có dùng hàm delay,OSC=20 Mhz
#byte portb = 0x06 //tạo tên danh định portb thay thế địa chỉ portB là 06h
#byte portd = 0x08 //tạo tên danh định portd thay thế địa chỉ portD là 08h
#INT_RB
Void RB_LED [ ] // hàm phục vụ ngắt
{
portd=portb;
}
void main [ ]
{ set_tris_b [ 0xF0 ] ; // portB = 11110000 , B4-B7 là ngõ vào , B0-B3 là ngõ ra
set_tris_d [ 0x00 ] ; // portD = 00000000 , D0-D7 đều là ngõ ra
enable_interrupts [ INT_RB ] ; // cho phép ngắt RB

enable_interrupts [ GLOBAL ] ; // cho phép ngắt toàn cục
// do chương trình không làm gì khác ngoài việc chờ ngắt nên vòng while này trống không
while[ true ]
{ //có thể thêm mã xử lý ở đây . . .
}
} //main
[Nguồn: TRẦN XUÂN TRƯỜNG]

Chủ Đề