TRƯỜNG ðẠI HỌC KHOA HỌC TỰ NHIÊNTRƯỜNG ðẠI HỌC KHOA HỌC TỰ NHIÊN
KHOA ðIỆN TỬ KHOA ðIỆN TỬ VIỄN THÔNGVIỄN THÔNG
PHẦN 3: LẬP TRÌNH VỚI CCS (tt)
1
ðặngðặng LêLê KhoaKhoa
CHƯƠNG 4: NGẮT VÀ ỨNG DỤNG
• Nguyên tắc hoạt ñộng của ngắt
• Các hàm dùng cho ngắt
•
Các loại ngắt
•
Các loại ngắt
• Ví dụ
2
Nguyên tắc hoạt ñộng của ngắt
• Ứng dụng trong lập trình ưu tiên
• Khi có 1 ngắt xảy ra, VðK sẽ hoàn tất lệnh
ñang thực hiện và chạy chương trình phục
vụ ngắt
vụ ngắt
• Cấp ngắt: ngắt 1 cấp và ngắt 2 cấp
3
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 .
• Khi 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 .
bị ngắt bởi 1 ngắt khác xảy ra .
• Khi ngắt xảy ra chương trình nhảy ñến ñịa chỉ
ngắt , thường là 004h , sao lưu thanh ghi W,
STATUS , PCLATCH , FSR… thì nhảy ñến hàm
• 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.
• ðể 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 theo sau chỉ thị tiền xử lý
hàm ñó.
• Chỉ có duy nhất 1 ngắt ñược ưu tiên cao.
7
Khai báo ngắt
• Mỗi dòng VDK có số lượng ngắt khác nhau :
PIC 14 có 14 ngắt , PIC 18 có 35 ngắt
• #DEVICE HIGH_INTS= Khai báo ngắt có
mức ưu tiên cao.
mức ưu tiên cao.
• #INT_XXX fast Đây là chỉ thị báo cho trình biên
dịch một ngắt có mức ưu tiên cao.
• Cách khai báo:
#INT_XXX
8
Khai báo ngắt…
• Sau ñây là danh sách 1 số ngắt với chức năng
tương ứng :
• #INT_GLOBAL : ngắt chung
• #INT_AD : chuyển ñổi A /D ñã hoàn tất
• #INT_EXT : ngắt ngoài
•
#INT_EXT1 : ngắt ngoài 1
•
being serviced.
10
• ðể 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_xxx ñể cho ngắt ñó là
•
Khoá FAST theo sau #int_xxx ñể cho ngắt ñó là
ưu tiên cao , chỉ ñược 1 ngắt thôi , chỉ có ở PIC
18 và dsPIC .
11
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 .
. 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
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
12
disable_interrupts ( level )
• level giống như trên.
function should be called whenever an interrupt is triggered.
function should be called whenever an interrupt is triggered.
This function will replace the compiler generated interrupt
dispatcher.
• #int_xxx This directive specifies that the following
function should be called whenever the xxx interrupt is
triggered. If the compiler generated interrupt dispatcher is
used, the compiler will take care of clearing the interrupt flag
bits.
16
VD: Chương trình đọc dữ liệu từ port b xuất ra port D khi có sự thay đổi từ
RB4 – RB7
#include <16F877.h>
#device *=16
#use delay (clock=20000000)
#byte portb = 0x06
#byte portd = 0x08
#INT_RB
Void RB_LED ()
{
portd=portb;
}
void main ()
{ set_tris_b(0xFF);
set_tris_d(0x00);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
while(true)
{
}
18
VD: Viết chương trình ñếm nhị phân và khi RB0 chuyển từ cao xuống thấp thì mạch ñếm sẽ reset
#include <16F877.h>
#device *=16
#use delay (clock=20000000)
#byte portc = 0x07
#byte portd = 0x08
#INT_EXT
void RB_EXT ()
{
portc=0x0;
}
void main ()
void main ()
{ set_tris_b(0xFF);
set_tris_c(0x00);
set_tris_d(0x00);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
ext_int_edge(0,H_TO_L);
portc =0;
while(true)
{
portc+=1;
delay_ms(500);
}
}
19
VD: Chương trình thực hiện công việc sau:
- Đọc dữ liệu từ port B xuất ra port D khi có sự thay đổi từ bit RB4-RB7
delay_ms(2000);
}
}
}
VD: Chương trình nhận dữ liệu từ cổng COM hiển thị lên port B và dịch Led ở
port D
#include <16F877.h>
#device *=16 ADC=8
#use delay (clock=20000000)
#byte portb = 0x06
#byte portd = 0x08
#use rs232 (uart1, baud=9600,parity=n,xmit=pin_c6, rcv=pin_c7 )
#INT_RDA
uart_handler()
{
portb=getc();
}
void main ()
{
set_tris_b(0x00);
set_tris_d(0x00);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
portd=0;
while(true)
{
portd=portd + 1;
delay_ms(1000);
}
}
{
portd=read_adc();
delay_ms(2000);
}
}
CHƯƠNG 5: TIMER VÀ ỨNG DỤNG
• Nguyên tắc hoạt ñộng của Timer
• Các hàm dùng cho Timer
•
Ứng dụng Timer
•
Ứng dụng Timer
• Ví dụ
23
• It is very easy to make a digital counter using
flip-flops. Counters can be made which count
up, count down, which can be cleared back to
zero, pre
-
loaded to a certain value, and which
zero, pre
-
loaded to a certain value, and which
by the provision of an overflow output can be
cascaded with other counters.
24
A digital counter made of eight flip-
flops
25