You are on page 1of 63

HỌC VIỆN HÀNG KHÔNG VIỆT NAM

KỸ THUẬT VI XỬ LÝ – VI ĐIỀU KHIỂN

Khoa: Điện – Điện tử


GV: Th.S Phương Hữu Công

1
4.1. Timer
4.1.1. Timer0 (8-bit)
4.1.2. Timer1 (16-bit)
4.1.3. Timer2 (8-bit)
Các Timer có thể hoạt động như một bộ định thời, bộ đếm hoặc bộ
điều rộng xung PWM.

2
4.1. Timer
Một số thuật ngữ:
• Prescaler là tên cho một phần của bộ vi điều khiển phân chia xung
nhịp bộ dao động trước khi nó đạt đến mức logic làm tăng trạng
thái bộ định thời. Phạm vi của Prescaler là từ 1-256 và giá trị của
Prescaler có thể được cài đặt bằng cách sử dụng thanh ghi
OPTION_REG.

3
4.1. Timer
Một số thuật ngữ:
• Khi bộ định thời tăng lên và khi nó đạt đến giá trị lớn nhất là 255
(Timer 8 bit) hoặc 65536 (Timer 16 bit), nó sẽ kích hoạt ngắt và tự
khởi tạo trở lại 0. Ngắt này được gọi là ngắt bộ định thời (Timer
Interrupt). Ngắt này thông báo cho vi điều khiển một thời gian cụ
thể đã kết thúc.
• Fosc (Frequency of the Oscillator) là tần số của thạch anh được sử
dụng. Thời gian thực hiện cho thanh ghi Timer phụ thuộc vào giá
trị của Prescaler và giá trị của Fosc.

4
4.1. Timer
TIMER0 TIMER1 TIMER2
Thanh ghi 8-bit 16-bit 8-bit
Nguồn xung clock nội Fosc/4 Fosc/4 Fosc/4
Nguồn xung clock Chân T1CKI hoặc bộ
Chân T0CKI
ngoại dao động của TIMER1

Prescaler 8-bit Prescaler 3-bit Prescaler (1:1, 1:4, 1:16)


Bộ chia
(1:2 => 1:256) (1:1, 1:2; 1:4, 1:8) Postscaler (1:1 => 1:16)

Tràn từ FFh => 00h


Tràn từ FFFFh => 0000h TMR2 = PR2
Ngắt và cờ báo ngắt TMR0IF trong
TMR1IF trong PIR1 TMR2IF trong PIR2
INTCON

Thoát khỏi chế độ Sleep Không Có Không

5
4.1.1. Timer0
Đặc điểm:
• 8-bit timer/counter
• Có thể đọc và ghi
• 8-bit Prescaler có thể lập trình bằng phần mềm
• Có thể lựa chọn xung clock nội hoặc ngoại
• Xung clock nội có chu kỳ đều đặn do đó có thể tính được thời gian
rất chính xác => Chức năng Timer.
• Xung clock bên ngoài là các tín hiệu logic thay đổi giữa mức 0 và 1.
Thường dùng để đếm các sự kiện bên ngoài: đếm sản phẩm trên
băng chuyền, đế xe ra vào bãi… => Chức năng Counter.

6
4.1.1. Timer0
Đặc điểm:
• Ngắt tràn từ FFh – 00h: Nhảy đến chương trình ngắt nếu ngắt
được cho phép sử dụng.
• Lựa chọn cạnh từ xung clock ngoài.

7
4.1.1. Timer0
Nguồn ngắt: TMR0: Thanh ghi
CLKO: xung clock nội lưu trữ giá trị đếm.
RA4: xung clock ngoại Có thể đọc hoặc
ghi dữ liệu

T0CS: bit chọn nguồn ngắt


T0SE: bit chọn cạnh xung clock
PSA: bit gán Prescaler Bit TMR0IF: đặt lên
1 khi TMR0 tràn. Bit
này nằm trong thanh
ghi INTCON. Cần
xóa bit này sau khi
ngắt xảy ra

PS2:PS0: các bit


chọn tỉ lệ Prescaler

8
4.1.1. Timer0
Các thanh ghi được sử dụng cho Timer0

TMR0: Lưu giữ giá trị đếm, khi tràn thì đặt bit cờ ngắt TMR0IF = 1
INTCON: Là thanh ghi quản lý ngắt, chứa bit cờ ngắt tràn (TMR0IF),
và bit cho phép ngắt tương ứng (TMR0IE), bit cho phép ngắt toàn cục
(GIE), bit cho phép ngắt ngoại vi (PEIE)
OPTION_REG: Sử dụng để cấu hình Prescaler, lựa chọn nguồn xung
clock, nguồn cạnh xung clock…
9
4.1.1. Timer0
Luồng làm việc của Timer0:
• Timer0 có thể hoạt động như một bộ định thời và bộ đếm
• Timer0 lưu trữ các giá trị thanh ghi TMR0
• Thanh ghi OPTION_REG (điều khiển Timer 0) được sử dụng để lập
trình bộ định thời và bao gồm các bit: T0CS, PSA, v.v.
• Nguồn xung nhịp có thể là nguồn xung nội hoặc ngoại và được điều
khiển bởi bit T0CS

10
4.1.1. Timer0
Luồng làm việc của Timer0:
• Trong một số trường hợp, xung clock đến từ bộ dao động có thể quá
nhanh đối với các ứng dụng: chúng ta có thể hạ thấp nó bằng cách sử
dụng bộ chia trước (prescaler) tần số.
• Prescaler là mạch chia tần số tín hiệu cho 2, 4, 8, 16, 32, 64, 128, 256
• Prescaler được kích hoạt bởi bit PSA. Giá trị Prescaler được ghi vào
thanh ghi OPTION_REG.

11
4.1.1. Timer0
Bit cờ ngắt TMR0IF (trong thanh ghi INTCON) được đặt bằng 1 khi
thanh ghi TMR0 tràn. Bit TMR0IF này phải được xóa bằng phần mềm
sau khi xảy ra ngắt.
Các hàm cấu hình Timer0 trong CCS:
• setup_timer_0(int8 mode);
• mode: T0_INTERNAL, T0_EXT_L_TO_H…, T0_DIV_1, T0_DIV_2…
VD: setup_timer_0(T0_INTERNAL|T0_DIV_32);
//Sử dụng xung clock nội + bộ chia trước Prescaler = 32

12
4.1.1. Timer0
• set_timer0(int8 value); Cài đặt giá trị đặt
trước cho thanh ghi TMR0
VD: set_timer0(100); Thì sau 156 lần timer0
đếm giá trị thanh ghi TMR0 sẽ quay về 0 và sẽ
xảy ra một ngắt. Lúc này: TMR0=0 và
TMR0IF=1
Vì vậy, sau mỗi lần xảy ra ngắt cần đặt lại giá
trị value này và xóa cờ ngắt tràn TMR0IF.

13
4.1.1. Timer0
• get_timer0(); Trả về giá trị của thanh ghi TMR0
• setup_counters(int8 mode, int8 prescaler); Cấu hình Timer0 hoạt
động ở chế độ counter.
• mode: T0_EXT_L_TO_H, T0_EXT_H_TO_L
• prescaler: T0_DIV_1,…, T0_DIV_16

14
4.1.1. Timer0
Xóa cờ ngắt TMR0IF bằng hàm:
• clear_interrupt(INT_TIMER0);
Chú ý: Bit cờ ngắt phải được xóa trước khi cho phép ngắt.
Cho phép ngắt Timer0 bằng 2 hàm sau:
• enable_interrupts(INT_TIMER0);
• enable_interrupts(GLOBAL);

15
4.1.1. Timer0
Tính thời gian xảy ra ngắt, thông số Prescaler, giá trị đặt trước cho
thanh ghi TMR0 và số lần ngắt:

Chu kỳ thời gian


1 Tần số ngắt Timer0
ngắt Timer0 TTimer 0 =
FTimer 0
Fosc
FTimer 0 =
4* Prescaler *(256 − value) * count
Giá trị bộ chia trước
Giá trị đặt trước Số lần ngắt
thanh ghi TMR0 16
4.1.1. Timer0
VD: Thời gian mong muốn để xảy ra ngắt là 0.5s
1 1
𝑇𝑇𝑖𝑚𝑒𝑟0 = = 0.5 𝑠 => 𝐹𝑇𝑖𝑚𝑒𝑟0 = = 2 𝐻𝑧
𝐹𝑇𝑖𝑚𝑒𝑟0 0.5

Chọn bộ chia trước là 32. Giá trị đặt trước cho thanh ghi TMR0:
value = 100. Sử dụng thạch anh 20 𝑀𝐻𝑧
Số lần ngắt:
𝐹𝑜𝑠𝑐 20,000,000
𝑐𝑜𝑢𝑛𝑡 = = = 500.8
𝐹𝑇𝑖𝑚𝑒𝑟0 ∗4∗𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟∗(256−100) 2∗4∗32∗(256−100)

=> Lựa chọn 𝑐𝑜𝑢𝑛𝑡 = 500

17
4.1.1. Timer0
Giải thích cơ sở lựa chọn Prescaler = 32 và giá trị value = 100
Giá trị chắc chắn biết trước: 𝐹𝑜𝑠𝑐 = 20 𝑀𝐻𝑧
𝐹𝑜𝑠𝑐
 𝐹𝑇𝑖𝑚𝑒𝑟0 = = 5,000,000 𝐻𝑧 => 1s vi điều khiển thực hiện được
4
5,000,000 lệnh
 1ms: 5,000 lệnh
 Timer0 cần đếm 5,000 lần để xảy ra ngắt. Vượt quá 8-bit (256 lần)
 Vì vậy cần bộ chia trước Prescaler để giảm số lần đếm của Timer0

18
4.1.1. Timer0
Prescaler Số lần đếm của Timer0
1:2 5000/2 = 2500 Prescaler: 1:2 – 1:16 vượt quá 8-bit
1:4 5000/4 = 1250  Loại những bộ chia này (Vì đang
xét trường hợp cụ thể là 1ms)
1:8 5000/8 = 625
Lựa chọn bộ chia càng nhỏ thì
1:16 5000/16 = 312.5 càng chính xác.
1:32 5000/32 = 156.25 Vì vậy, chọn Prescaler = 32
1:64 5000/64 = 78.125
1:128 5000/128 = 39.0625
1:256 5000/256 = 19.53125

19
4.1.1. Timer0
Thời gian xảy ra ngắt: 1ms
Giá trị đặt trước cho thanh ghi TMR0:
1𝑚𝑠 ∗ 𝐹𝑜𝑠𝑐 1 ∗ 10−3 ∗ 20,000,000
𝑣𝑎𝑙𝑢𝑒 = 256 − = 256 − = 99.75
4 ∗ 𝑃𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 4 ∗ 32
𝑣𝑎𝑙𝑢𝑒 là số nguyên nên chọn bằng 100.
Vì vậy, nếu muốn sau 500ms mới thực hiện lệnh điều khiển nào đó,
thì số lần ngắt count = 500 lần.

20
4.1.1. Timer0
VD: Thời gian xảy ra ngắt là 100ms (0.1s)
1 1 1
TTimer 0 = = 0.1 = FTimer 0 = = = 10 ( Hz )
FTimer 0 TTimer 0 0.1
Fosc
FTimer 0 =
4* Prescaler *(256 − value) * count
Fosc Chọn prescaler = 2,
count =
4* Prescaler *(256 − value) * FTimer 0 value = 0
20, 000, 000
= = 976.5625 Cần khoảng 976 lần xảy ra ngắt
4* 2*(256 − 0) *10
để tạo được thời gian 0.1s
21
4.1.1. Timer0
Ứng dụng: Điều khiển Led
chớp/tắt với chu kỳ 500ms sử
dụng ngắt Timer0.

22
4.1.1. Timer0
Chương trình:

23
4.1.1. Timer0
Bài tập: Led đơn được kết nối với chân RB0. Dùng ngắt Timer0 điều
khiển Led chớp tắt. Bộ chia và giá trị đặt trước cho thanh ghi TMR0
tự chọn.

GIÁ TRỊ THẠCH


CHU KỲ
ANH
4MHz 200ms

8MHz 350ms

20MHz 1000ms

24
4.1.1. Timer0
Ứng dụng: Nút nhấn
được nối với nguồn
xung clock ngoại ở chân
RA4. Đếm số lần nhấn
nút và hiển thị lên LCD.

25
4.1.1. Timer0
Chương trình:

26
4.1.1. Timer0
Bài tập: Áp dụng sơ đồ mạch như trên. Viết chương trình sau mỗi
10 lần nhấn nút thì hiển thị chuỗi “Full box” lên LCD và cài đặt lại
bộ timer/counter.

27
4.1.2. Timer1
Đặc điểm:
• 16-bit timer/counter với hai thanh ghi 8-bit TMR1H/TMR1L
• Có thể đọc và ghi
• Prescaler có thể lập trình: tỉ lệ 1:1, 1:2, 1:4, 1:8
• Lựa chọn xung clock nội hoặc ngoại
• Ngắt tràn từ FFFFh – 0000h
• Chọn cạnh cho xung clock ngoài

28
4.1.2. Timer1

29
4.1.2. Timer1
Các thanh ghi được sử dụng cho Timer1:

30
4.1.2. Timer1
Các thanh ghi được sử dụng cho Timer1:
INTCON: Chứa bit cho phép ngắt ngoại vi và ngắt toàn cục
PIR1: Chứa bit cờ ngắt tràn TMR1 (TMR1IF)
PIE1: Chứa bit cho phép ngắt tràn TMR1 (TMR1IE)
TMR1L: Chứa giá trị đếm byte thấp của thanh ghi TMR1
TMR1H: Chứa giá trị đếm byte cao của thanh ghi TMR1
T1CON: Là thanh ghi điều khiển Timer1

31
4.1.2. Timer1
Luồng làm việc của Timer1:
• Bit nguồn xung clock (TMR1CS) của bộ định thời được sử dụng để
chọn nguồn xung nhịp.
• Nếu TMR1CS là 0, thì xung nhịp nội bên trong được cấp cho đầu vào
của bộ định thời. Nếu TMR1CS là 1, nó sẽ lấy nguồn xung nhịp từ
nguồn bên ngoài. Nguồn bên ngoài đó có thể là T1CKI hoặc một bộ
dao động thạch anh.
• Khi là một bộ dao động thạch anh, thì T1OSCEN = 1 nếu nó được cho
phép, nó sẽ nhận xung clock từ bộ dao động thạch anh. Nếu nó bị cấm
thì nó sẽ lấy xung clock trực tiếp từ chân T1CKI.

32
4.1.2. Timer1
Luồng làm việc của Timer1:
• Các bit Prescaler được sử dụng để chia xung nhịp (có thể là 1,2,4,8)
• Bit T1SYNC là 1 nó sẽ không được đồng bộ. Xung clock bên ngoài sẽ
không được đồng bộ với xung clock dao động bên trong. Nếu
TISYNC là 0, nó sẽ được đồng bộ và nó sẽ được cấp cho cổng AND.
• Một bit khác của cổng AND là bit TMR1ON. Bit TMR1ON là bit cho
phép Timer1 hoạt động hay không. TMR1ON = 1 thì Timer1 được
phép hoạt động, TMR1ON = 1 thì Timer1 không hoạt động.

33
4.1.2. Timer1
Các hàm cấu hình Timer1 trong CCS:
• clear_interrupt(INT_TIMER1);
• enable_interrupt(INT_TIMER1);
• enable_interrupt(GLOBAL);
• setup_timer_1(int16 mode);
• mode: T1_DISABLED, T1_INTERNAL, T1_EXTERNAL, T1_DIV_BY_1
(2,4,8)…

34
4.1.2. Timer1
Các câu lệnh cấu hình Timer1 trong CCS:
• get_timer1(); Trả về giá trị của thanh ghi TMR1 (một số int16)
• set_timer1(int16 value); Cài đặt giá trị đặt trước cho thanh ghi
TMR1

35
4.1.2. Timer1
Công thức tính toán:

Chu kỳ thời gian 1


ngắt Timer1 TTimer1 = Tần số ngắt Timer1
FTimer1

Fosc
FTimer1 =
4* Prescaler *(65536 − value) * count
Giá trị bộ chia trước
Giá trị đặt trước Số lần ngắt
thanh ghi TMR1
36
4.1.2. Timer1
Bài tập:
1. Viết chương trình tạo một ngắt Timer1 với chu kỳ 100ms
(500ms, 650ms, 1000ms) để điều khiển Led sáng/tắt.
2. Viết chương trình để đếm xung ngoài từ chân RC1/T1CKI và
hiển thị lên LCD.

37
4.1.3. Timer2
Đặc điểm:
• 8-bit timer/counter
• Có thể đọc và ghi
• Prescaler và Postscaler có thể lập trình được bằng phần mềm
• Ngắt khi tràn từ FFh – 00h

38
4.1.3. Timer2

39
4.1.3. Timer2
Các thanh ghi được sử dụng cho Timer2:

40
4.1.3. Timer2
Các thanh ghi được sử dụng cho Timer2:
• INTCON: Chứa bit cho phép ngắt ngoại vi và ngắt toàn cục
• PIR1: Chứa bit cờ ngắt tràn TMR2 (TMR2IF)
• PIE1: Chứa bit cho phép ngắt tràn TMR2 (TMR2IE)
• TMR2: Chứa giá trị đếm. Khi thanh ghi này bằng thanh ghi PR2
thì ngắt sẽ được tạo ra và TMR2 được reset về 00h.
• T2CON: Sử dụng để cấu hình Prescaler, nguồn xung clock…
• PR2: Thanh ghi chu kỳ

41
4.1.3. Timer2
Luồng làm việc của Timer2:
• Lấy xung clock từ 𝐹𝑜𝑠𝑐 /4 và sau đó đi đến Prescaler. Prescaler chia
tần số xung nhịp (có thể là 1, 4, 16)
• Sau đó tần số xung nhịp này được đưa cho thanh ghi TMR2, nó sẽ
đếm các xung clock đến.
• Khi nó đang đếm xung clock, giá trị có trong thanh ghi TMR2 cũng
được so sánh với thanh ghi PR2.
• Nếu thanh ghi TMR2 và PR2 bằng nhau, ngõ ra của bộ so sánh sẽ
đặt lại thanh ghi TMR2.

42
4.1.3. Timer2
Luồng làm việc của Timer2:
• Sau đó, ngõ ra bằng nhau này được cấp cho ngõ vào của Postscaler.
Nó không tạo ra ngắt ngay lập tức.
• Khi các bit Postscaler được đặt giá trị chia sau, nó sẽ tạo ra một độ
trễ bằng giá trị chia này và đặt bit TMR2IF lên 1.

43
4.1.3. Timer2
Các hàm cấu hình Timer2 trong CCS:
clear_interrupt(INT_TIMER2);
enable_interrupt(INT_TIMER2);
enable_interrupt(GLOBAL);
setup_timer_2(int8 mode, int8 period, int8 postscaler);
• mode: T2_DISABLED, T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
• period: giá trị thanh ghi PR2
• Postscaler: có thể từ 1-16

44
4.1.3. Timer2
Các câu lệnh cấu hình Timer2 trong CCS:
get_timer2(): trả về giá trị của thanh ghi TMR2 (một số int8)
set_timer2(int8 value): cài đặt giá trị đặt trước cho thanh ghi TMR2

45
4.1.3. Timer2
Công thức tính toán:

Chu kỳ thời gian 1 Tần số ngắt Timer2


ngắt Timer2 TTimer 2 =
FTimer 2

Fosc
FTimer 2 =
4* Prescaler *( PR 2 − value) * Postscaler * count
Giá trị bộ
chia trước Giá trị thanh ghi PR2 và giá Giá trị bộ
Số lần ngắt
trị đặt trước thanh ghi TMR2 chia sau
46
4.1.3. Timer2
Ví dụ: Tạo thời gian ngắt là 0.1s

1 1 1
TTimer 2 = = 0.1 = FTimer 2 = = = 10 ( Hz )
FTimer 2 TTimer 2 0.1
Fosc
FTimer 2 =
4* Prescaler *( PR 2 − value) * Postscaler * count Prescaler = 1
Fosc PR2 = 0xff
count = Value = 0
4* Prescaler *( PR 2 − value) * Postscaler * FTimer 2 Postscaler = 1
20, 000, 000
= = 1953.125 Cần khoảng 1953 lần xảy ra
4*1*(256 − 0) *1*10 ngắt để tạo được thời gian 0.1s
47
4.1.3. Timer2
Bài tập:
Tạo một ngắt Timer2 với chu kỳ 0.15s (0.3s, 0.8s) để điều khiển Led
sáng/tắt.

48
4.2. Ngắt
Ngắt là một sự kiện đặc biệt cần được thực hiện ngay lập tức, nó
dừng vi điều khiển khỏi các tác vụ đang chạy và phục vụ tác vụ đặc
biệt tại trình xử lý ngắt.
PIC16f877A có 15 nguồn ngắt:
Ngắt ngoài, ngắt Timer0, ngắt Timer1, thay đổi ở PORTB, đọc ghi
port song song, ADC, USART Receive, USART Transmit, Port nối
tiếp đồng bộ, CCP1, CCP2, TMR2=PR2, bộ so sánh, hoạt động ghi
EEPROM, va chạm bus.

49
4.2.1. Ngắt ngoài
Đặc điểm:
• PIC16F877A có 1 ngắt ngoài ở chân RB0/INT
• Có thể lựa chọn cạnh lên hoặc cạnh xuống
Thanh ghi được sử dụng cho ngắt ngoài:
• INTCON: Chứa bit cho phép ngắt toàn cục (GIE), bit cho phép
ngắt ngoài (INTE), bit cờ ngắt ngoài (INTF)
Ứng dụng: Đọc xung từ encoder cho các ứng dụng điều khiển tốc
độ động cơ…

50
4.2.1. Ngắt ngoài
Các hàm cấu hình ngắt ngoài trong CCS:
clear_interrupt(INT_EXT); Xóa cờ báo ngắt ngoài
enable_interrupts(INT_EXT); Cho phép ngắt ngoài
enable_interrupts(GLOBAL); Cho phép ngắt toàn cục
ext_int_edge(); Chọn nguồn ngắt (khi có nhiều nguồn ngắt, PIC16F877A
chỉ có 1 nguồn ngắt) và cạnh ngắt
• ext_int_edge(INT_EXT,L_TO_H);
• ext_int_edge(L_TO_H);
• ext_int_edge(H_TO_L);

51
4.2.1. Ngắt ngoài
Các hàm cấu hình ngắt ngoài trong CCS:
disable_interrupts(INT_EXT); Cấm ngắt ngoài
interrupt_active(INT_EXT); Kiểm tra cờ ngắt ngoài (INTF), trả về
TRUE nếu cờ này được set (INTF = 1)
interrupt_enabled(INT_EXT); Kiểm tra cờ cho phép ngắt ngoài
(INTE), trả về TRUE nếu cờ này được set (INTE = 1)

52
4.2.1. Ngắt ngoài
VD: Ngắt ngoài thay đổi trạng thái
Led.

53
4.2.1. Ngắt ngoài
Chương trình:

54
4.2.1. Ngắt ngoài
Bài tập 1:
Thiết kế nút nhấn kết nối với ngắt ngoài RB0/INT để điều khiển
chớp tắt Led.
• Led kết nối với chân bất kỳ.
• Cạnh xung cho ngắt ngoài tùy chọn.

55
4.2.1. Ngắt ngoài
Bài tập 2:
Sử dụng ngắt ngoài để thay đổi hiệu ứng các đèn LED trong Bài tập
4 phần nút nhấn ở Chương 3.
Gợi ý: Kết nối nút nhấn vào chân ngắt ngoài.

56
4.2.2. Ngắt thay đổi ở PORTB
Đặc điểm:
Xảy ra ngắt khi 4 bit cao của PORTB thay đổi giá trị (RB4-RB7)
Thanh ghi được sử dụng cho ngắt thay đổi ở PORTB:
INTCON: Chứa bit cho phép ngắt toàn cục (GIE), bit cho phép ngắt
thay đổi ở PORTB (RBIE), bit cờ ngắt tương ứng (RBIF)
Ứng dụng: Hỗ trợ thêm cho ngắt ngoài

57
4.2.2. Ngắt thay đổi ở PORTB
Các hàm cấu hình Ngắt thay đổi ở PORTB trong CCS:
clear_interrupt(INT_RB); Xóa cờ ngắt RBIF
enable_interrupts(INT_RB); Cho phép ngắt thay đổi ở PORTB
enable_interrupts(GLOBAL); Cho phép ngắt toàn cục

58
4.2.2. Ngắt thay đổi ở PORTB
VD: Led thay đổi trạng thái khi chân
RB4 thay đổi trạng thái.

59
4.2.2. Ngắt thay đổi ở PORTB
Chương trình:

60
4.2.2. Ngắt thay đổi ở PORTB
Bài tập 1:
Dùng ngắt thay đổi ở chân RB5 PORTB để đếm số lần nhấn nút và
hiển thị lên LCD.

61
4.2.2. Ngắt thay đổi ở PORTB
Bài tập 2:
Sử dụng ngắt thay đổi ở PORT B để thay đổi hiệu ứng các đèn LED
trong Bài tập 4 phần nút nhấn ở Chương 3.
Gợi ý: Kết nối nút nhấn vào một trong 4 bit cao của PORT B.

62
4.2.2. Ngắt thay đổi ở PORTB
Bài tập 3:
Kết nối 4 nút nhấn vào các bit cao của PORT B như hình
bên, kết nối thêm LCD vào PIC. Viết chương trình:
Khi nhấn nút RB4: LCD hiển thị “UP”
Khi nhấn nút RB5: LCD hiển thị “LEFT”
Khi nhấn nút RB6: LCD hiển thị “DOWN”
Khi nhấn nút RB7: LCD hiển thị “RIGHT”

63

You might also like