NGẮT (TIMER) CÁC BIT CHO PHÉP GIE Cho phép ngắt toàn cục Phải được đặt để sử dụng BẤT KỲ ngắt nào của PIC PEIE Cho phép ngắt ngoại vi Phải được đặt để sử dụng các ngắt ngoại vi T0IE Cho phép ngắt. Sử dụng ngắt ngoài lập trình điều khiển led theo yêu cầu sau Bình thường: Led đếm 0→7 theo mã nhị phân Ngắt: led chớp tắt 3 lần viết chương trình đọc giá trị điện áp (0 → 5V) từ biến trở nối với chân RB2, chuyển đổi ADC và hiển thị kết quả chuyển đổi trên 10 LED. Sử dụng modul ADC, led nối với PORTD và PORTC viết chương trình điều khiển đọc giá trị điện áp từ cảm biến nhiệt độ LM35, chuyển đổi ADC thành giá trị số nhị phân 10 bit và hiển thị giá trị nhiệt độ lên LED.
Trang 1NGẮT (TIMER) CÁC BIT CHO PHÉP
GIE: Cho phép ngắt toàn cục
* Phải được đặt để sử dụng BẤT KỲ ngắt nào của PIC
PEIE: Cho phép ngắt ngoại vi
* Phải được đặt để sử dụng các ngắt ngoại vi
T0IE: Cho phép ngắt Timer0 tràn
INTE: Cho phép ngắt ngoài INT
RBIE: Cho phép ngắt Port B thay đổi
CÁC BIT CỜ
T0IF: Cờ ngắt Timer0 tràn
INTF: Cờ ngắt ngoài INT
RBIF: Cờ ngắt Port B thay đổi
Ví dụ: Thiết lập thứ tự ưu tiên từ cao xuống thấp cho cácngắt: Port B, Timer 2 và Timer 1
void interrupt isr(void)
b Các bit liên quan:
- Nguồn ngắt : RB0 (khi có xung kích theo cạnh lên hay xuống)
Trang 2- Cho phép ngắt:
+ Cho phép ngắt ngoài: INTIE = 1
+ Cho phép ngắt toàn cục: GIE = 1
- Chọn xung tác động theo cạnh lên/xuống: INTEDG = 1/0
- Cờ ngắt: INTIF được tự động set lên 1 khi có sự kiện ngắt ngoài xảy
ra Cờ INTIF phải được xóa bằng chương để vi điều khiển quản lý chính xác các lần ngắt kế tiếp
Bài tập:
1 Sử dụng ngắt ngoài lập trình điều khiển led theo yêu cầu sau
Bình thường: Led đếm 0→7 theo mã nhị phân
Ngắt: led chớp tắt 3 lần
Trang 3void interrupt isr(void)
PORTE = 0X00;
delay_ms(500); PORTE = 0X07;
delay_ms(500); }
}
}
void main(void)
{ unsigned char i; ANSEL = 0X00; ANSELH = 0X00; TRISE = 0X00;
}
}
Trang 42 Sử dụng ngắt ngoài lập trình điều khiển led bảy đoạn theo yêu cầu sau Bình thường: Led hiển thị số đếm từ 00 → 12
{ unsigned char CH,DV,i;
const unsigned char a[]=
Trang 53 Ngắt PORTB:
b Các bit liên quan:
- Nguồn ngắt : PORTB (khi các chân RB0→RB7 thay đổi mức logic)
- Cho phép ngắt:
+ cho phép ngắt PORTB: RBIE = 1
+ cho phép ngắt ở chân thứ x của PORTB: IOCBx= 1
+ cho phép ngắt toàn cục: GIE = 1
- Cờ ngắt: RBIF được tự động set lên 1 khi có sự kiện ngắt PORTB xảy ra Cờ RBIF phải được xóa để vi điều khiển quản lý chính xác các lần ngắt kế tiếp
BÀI TẬP
Ví dụ 3: Sử dụng ngắt portB lập trình điều khiển led theo yêu cầu sau Bình thường: Led tắt hết
Ngắt portB :
+ nhấn RB0: led chop tat 3 lan
+ nhấn RB1: led sang trong 2s
Trang 6RBIF = 0; // xoa co ngat
RBIE = 1; // cho phep ngat PORTB GIE = 1; // cho phep ngat toan cuc IOCB0 = 1; // cho phep ngat tai RB0 IOCB1 = 1; // cho phep ngat tai RB1 IOCB2 = 1; // cho phep ngat tai RB2
Trang 7+ nhấn RB0: led hiển thi số 12 trong 2s
+ nhấn RB1: led hiển thi số 24 trong 2s
unsigned char i,a;
for (i=0; i<24; i++)
Trang 8void interrupt isr()
Trang 9+ cho phép ngắt toàn cục: GIE = 1
- Cờ ngắt: TMR0IF được tự động set lên 1 khi có sự kiện ngắt ngoài
xảy ra Cờ TMR0IF phải được xóa để vi điều khiển quản lý chính xác
các lần ngắt kế tiếp
b Các bit liên quan
T0CS: bit lựa chọn nguồn xung cho TMR0
T0CS = 1 → chọn xung ngoài từ chân T0CKI
T0CS = 0 → chọn xung bên trong (ftimer = fosc/4)
- T0SE: chọn cạnh kích cho xung ngoài từ chân T0CKI
T0SE = 0 → chọn cạnh lên
T0SE = 1 → chọn cạnh xuống
- PSA: bit gán bộ chia trước
PSA = 1→ gán bộ chia cho WDT
PSA = 0→ gán bộ chia Timer0
- PS2, PS1, PS0: các bit lựa chọn tỉ lệ bộ chia trước
- TMR0: thanh ghi chứa giá trị đếm của timer 0
- TMR0IF: cờ báo tràn timer0
Trang 10T0_delay_max = 65ms = 65000us
▪ B2:Ghi vào thanh ghi TMR0 giá trị tương ứng với thời gian cần định thời
▪ B3: Xóa cờ báo tràn( cờ ngắt) TMR0IF
▪ B4: Chọn chế độ hoạt động của Timer 0
- Chế độ định thời gian (Timer)
- Kích hoạt hoặc vô hiệu hóa ngắt (tùy chọn)
- Gán Prescaler cho Timer và chọn giá trị tỉ lệ của Prescaler (tùy chọn)
▪ B5: Xác định thời điểm Timer 0 bị tràn bằng cách:
- Kiểm tra cờ TMR0IF( nếu dùng thăm dò)
- Xử lý ISR của Timer 0 (nếu dùng ngắt)
BÀI TẬP
VÍ DỤ 1 : Viết chương trình con tạo trễ tdelay =100μs dùng
Timer 0, fOSC = 4MHZ, chọn prescaler = 2
Trang 11VÍ DỤ 2 : Viết chương trình con tạo trễ tdelay = 4ms dùng Timer 0, fOSC = 8MHZ, chọn prescaler = 32
Tính giá trị thanh ghi TMR0:
VÍ DỤ 3 : Viết chương trình con tạo trễ tdelay = 500ms dùng Timer 0, fOSC = 4MHZ
nên ko thể tạo delay trực tiếp
➔ ta viết code tạo delay 100us
dùng TIMER0 và cho lặp 5000
lần
Trang 12- Led chớp tắt với f = 1Hz → chọn Ton = Toff = 500ms = 500 000us
- Do 500 000us > t0_delay_max nên ko thể làm trực tiếp ➔ ta tạo
delay 100us và cho lặp 5000 lần
Giải:
- Tạo delay 100us (như VD1):
Tính các giá trị thanh ghi
Ta có:
tdelay = 100us, pre = 2, fosc = 4MHz → TMR0 = 206
- Cho lặp 5000 lần → tdelay = 100x5000 = 500 000us = 500ms
Trang 13void delay100us(unsigned int n)
Trang 142.2 Các bước lập trình timer 0 chế độ đếm sự kiện
• BƯỚC 1: Xóa giá trị trong thanh ghi TMR0
(hoặc đặt giá trị ban đầu của bộ đếm)
• BƯỚC 2: Xóa cờ báo tràn (cờ ngắt) TMR0IF
• BƯỚC 3: Chọn chế độ hoạt động của Timer0
- Chế độ đếm sự kiện (Counter)
- Kích hoạt hoặc vô hiệu hóa ngắt (tùy chọn)
- Gán Prescaler cho Timer và chọn giá trị tỉ lệ của Prescaler (tùy chọn)
- Chọn loại cạnh kích của nguồn xung đếm bên ngoài
• BƯỚC 4: Đọc về và xử lý số xung đếm được
trong thanh ghi TMR0
Dựa vào cờ báo tràn TMR0IF để xử lý các trường
hợp số xung đếm
vượt quá 255
Ví dụ 5: viết chương trình đếm số lần nhấn–nhả
nút SW0 và hiển thị giá trị này trên 8 LED đơn
SW0 được nối với ngõ vào của Counter 0
Trang 15const unsigned char a[]=
Trang 18Ví dụ 10: Sử dụng ngắt ngoài lập trình điều khiển led bảy đoạn theo yêu cầu sau,
sử dụng TIMER1 để tạo delay
Bình thường: Led hiển thị số đếm từ 00 đến 12, mỗi số hiển thị trong 500ms Ngắt: led tắt trong 2s
Trang 19PWM
4 Các bước lập trình modul CCP1 chế độ PWM:
Bước 1: Tính toán các giá trị thanh ghi
Áp dụng công thức tính giá trị thanh ghi PR2, CCPR1L và 2 bit
DC1B1, DC1B0
Trang 20Bước 2: Cấm xuất xung PWM
Cấu hình chân CCP1/RC2 là ngõ vào: TRISC2 = 1
Bước 3: Đặt giá trị chu kỳ PWM
ghi giá trị đã tính vào thanh ghi PR2
Bước 4: Đặt giá trị độ rộng xung PWM
ghi giá trị đã tính vào thanh ghi CCPR1L và 2 bit DC1B1,
DC1B0
Bước 5: Cấu hình modul CCP ở chế độ PWM
CCP1CON = 0x0C
Bước 6: Cấu hình và kích hoạt Timer 2
• Xóa cờ ngắt/tràn Timer 2: TMR2IF = 0
• Đặt giá trị prescaler của Timer 2
• Kích hoạt Timer 2 hoạt động: TMR2ON = 1
Bước 7: Cho phép xuất xung PWM
• Chờ cho đến khi Timer 2 tràn TMR2IF = 1
• Cho phép xuất xung:
Cấu hình chân CCP1/RC2 là ngõ ra TRISC2 = 0
5 Các bước lập trình modul CCP2 chế độ PWM:
Bước 1: Tính toán các giá trị thanh ghi
Áp dụng công thức tính giá trị thanh ghi PR2, CCPR2L và 2 bit
DC2B1, DC2B0
Bước 2: Cấm xuất xung PWM
Cấu hình chân CCP2/RC1 là ngõ vào: TRISC1 = 1
Bước 3: Đặt giá trị chu kỳ PWM
ghi giá trị đã tính vào thanh ghi PR2
Bước 4: Đặt giá trị độ rộng xung PWM
ghi giá trị đã tính vào thanh ghi CCPR2L và 2 bit DC2B1,
DC2B0
Bước 5: Cấu hình modul CCP ở chế độ PWM
CCP2CON = 0x0C
Trang 21Bước 6: Cấu hình và kích hoạt Timer 2
• Xóa cờ ngắt/tràn Timer 2: TMR2IF = 0
• Đặt giá trị prescaler của Timer 2
• Kích hoạt Timer 2 hoạt động: TMR2ON = 1
Bước 7: Cho phép xuất xung PWM
• Chờ cho đến khi Timer 2 tràn TMR2IF = 1
• Cho phép xuất xung:
Cấu hình chân CCP2/RC1 là ngõ ra TRISC1 = 0
BÀI TẬP
Ví dụ 1: viết chương trình điều khiển tạo xung PWM có fPWM = 8KHz, D = 50% tại chân CCP1 (RC2) Sử dụng modul CCP ở chế độ PWM để tạo xung, fosc=4MHz
Trang 22void main (void)
Trang 23VD2: viết chương trình điều khiển tạo xung PWM có fPWM = 10KHz, D1 = 80% tại chân CCP1 và D2 = 50% tại chân CCP2 Sử dụng modul CCP ở chế
Trang 24void main (void)
{
ANSEL = 0X00;
ANSELH = 0X00;
TRISC2 = 1; //cam xuat xung
TRISC1 = 1; //cam xuat xung
CCP1CON = 0x0C; //chon che do PWM
CCP2CON = 0x0C; //chon che do PWM
PR2 = 99 ; //dat chu ky cho PWM
Trang 25TRISC2 = 0; //xuat xung
TRISC1 = 0; //xuat xung
while (1);
}
VD3 : viết chương trình điều khiển motor quay thuận, với
fosc=4MHz Sử dụng xung PWM tại chân CCP1 có f = 8KHz, D= 50%
void main (void)
TRISC2 = 1; //cam xuat xung
PR2 = 124; //dat chu ky cho PWM
CCP1CON = 0x0C; //chon che do PWM
CCPR1L = 62; //do rong xung
DC1B1 = 1; //CCP1CON5
DC1B0 = 0; //CCP1CON4
TMR2IF = 0;
T2CKPS1 = 0; T2CKPS0 = 0; //chon pre = 1
Trang 28ADCS1 ADCS0 Tần số chuyển đổi
Trang 296 Các bước lập trình ADC
BƯỚC 1: Cấu hình Port
• Cấu hình chân PIC là ngõ vào (TRISx)
• Cấu hình chân PIC là tương tự (ANSLH, ANSEL)
BƯỚC 2: Cấu hình modul ADC
• Chọn xung clock chuyển đổi ADC (ADCSx)
• Chọn điện áp tham chiếu (VCFGx)
• Chọn kênh vào ADC (CHSx)
• Chọn định dạng kết quả (ADFM)
• Bật modul ADC (ADON)
BƯỚC 3: Cấu hình ngắt ADC (tùy chọn)
• Xóa cờ ngắt ADC (ADIF)
• Cho phép ngắt ADC (ADIE)
• Cho phép ngắt ngoại vi (PEIE)
• Cho phép ngắt toàn cục (GIE)
•BƯỚC 4: Chờ một khoảng thời gian (khoảng 6s) để
modul ADC ổn định (tACQ)
•BƯỚC 5: Đặt bit GO/DONE để bắt đầu quá trình chuyển
đổi
BƯỚC 6: Chờ quá trình chuyển đổi AD hoàn tất bằng một
trong các cách sau:
• Kiểm tra bit GO/DONE (GO/DONE = 0) → Polling
• Chờ ngắt ADC (nếu ngắt được cho phép) → Interrupt
BƯỚC 7: Đọc kết quả ADC
BƯỚC 8: Xóa cờ ngắt ADC (bỏ qua bước này nếu ngắt
không được cho phép)
Trang 30Ví dụ 1: viết chương trình đọc giá trị điện áp (0 → 5V) từ biến trở nối với
chân RA0, chuyển đổi ADC và hiển thị kết quả chuyển đổi trên 10 LED Sửdụng modul ADC, led nối với PORTD và PORTC
Trang 31CHS3= 0; CHS2 = 0; CHS1 = 0; CHS0 = 0; //chon kenh AN0
ADFM = 1; //canh phai
ADON = 1; //cho phep ADC
ADIF = 0; // xoa co ngat
GIE = PEIE = ADIE =0; //cam ngat
while(1) {
delay_us(6);
GO = 1; while(GO); PORTD = ADRESH; PORTC = ADRESL; } }
Trang 32Ví dụ 2: viết chương trình đọc giá trị điện áp (0 → 5V) từ biến trở nối với chân RB2, chuyển đổi ADC và hiển thị kết quả chuyển đổi trên 10 LED Sử dụng modul ADC, led nối với PORTD và PORTC
Trang 33VCFG1 = 0; VCFG0 = 0; // Vref+ = 5v; Vref- = 0V
CHS3= 1; CHS2 = 0; CHS1 = 0; CHS0 = 0; //chon kenh AN12
ADFM = 1; //canh phai
ADON = 1; //cho phep ADC
ADIF = 0; // xoa co ngat
GIE = PEIE = ADIE =0; //cam ngat
while(1)
{
delay_us(6);
GO = 1; while(GO);
PORTD = ADRESH; PORTC = ADRESL; } }
Ví dụ 3: viết chương trình điều khiển đọc giá trị điện áp từ cảm biến nhiệt độ
LM35, chuyển đổi ADC thành giá trị số nhị phân 10 bit và hiển thị giá trị
nhiệt độ lên LED
Trang 34unsigned long doc_adc(void)
ADON = 1; //cho phep ADC
ADIF = 0; // xoa co ngat
GIE = PEIE = ADIE =0; //cam ngat
Trang 35Timer 0,1= PWM / Counter 0 (T0KI)