Đại Học Giao Thông Vận Tải Tp.HCM Đại Học Giao Thông Vận Tải Tp.HCM
Khoa Điện – Điện Tử Viễn Thông Khoa Điện – Điện Tử Viễn Thông
Học phần: Vi Xử Lý Học phần: Vi Xử Lý
Chương 4: Các chức năng họ 8051 Chương 4: Các chức năng họ 8051
Giảng viên: TS. Giảng viên:
NGUYỄN HỮU CHÂN THÀNH TS. NGUYỄN HỮU CHÂN THÀNH
Chương 4 bao gồm 3 nội dung:
1. Timer.
2. Port nối tiếp.
3. Interrupt.
I. Timer
1. Giới thiệu
4
-Một bộ định thời (timer) là một chuỗi các Flip Flop (FF) với mỗi FF là một mạch chia 2. Chuỗi này nhận một tín hiệu ngõ vào làm xung clock kích cho tầng đầu tiên, ngõ ra của tầng đầu lại trở thành nguồn xung clock cho tầng kế tiếp. Ngõ ra của tầng cuối cùng làm xung clock cho một FF báo tràn timer hay còn gọi là cờ tràn (overflow flag). Cờ tràn này sẽ được kiểm tra bởi phần mềm hay tạo ra một ngắt (interrupt). Hình dưới minh họa một timer đơn giản 3-bit.
- Giá trị nhị phân trong các FF của timer được dùng để tính số xung clock (số chu kì) của tín hiệu ngõ vào từ khi timer bắt đầu đếm.
- 8051/8031 có 2 timer 16 bit:
+ Timer 0: số đếm chứa trong thanh ghi TH0 (byte
cao) và TL0 (byte thấp)
+ Timer 1: số đếm chứa trong thanh ghi TH1 (byte
cao) và TL1 (byte thấp)
Ngoài ra, các chip 8032/8052 còn có thêm timer 2.
5
- Các timer chỉ đếm lên (0000H ÷ FFFFH). Khi số đếm tràn từ FFFFH xuống 0000H, cờ tràn sẽ được đặt lên 1.
1. Giới thiệu
2. Các thanh ghi của timer
a. Thanh ghi chế độ định thời (TMOD):
- Không được định địa chỉ bit. - Được dùng để định chế độ hoạt động cho các timer. - Chức năng từng bit:
6
+ M1, M0: chọn chế độ hoạt động.
+ C/T: bit chọn chức năng đếm hoặc định thời cho timer. + Gate: bit điều khiển cổng cho bộ định thời.
2. Các thanh ghi của timer
b. Thanh ghi điều khiển định thời (TCON):
- Chứa các bit điều khiển và trạng thái của timer 0 và 1 ở 4 bit cao, 4
bit thấp được dùng cho chức năng ngắt (interrupt).
- Được định địa chỉ bit. - Chức năng từng bit:
7
+ TFx: cờ tràn của timer x (x là 0 hay 1) + TRx = 0: không cho phép timer chạy.
+ TRx = 1: cho phép timer chạy.
8
3. Điều khiển các bộ định thời
3. Điều khiển các bộ định thời
- (Counter/Timer):
+ C/T= 0: timer nhận xung clock từ bộ dao động nội (sau khi
qua bộ chia 12). (cid:0) Ứng dụng: thường dùng cho việc định thời một khoảng thời gian (mỗi số đếm tương ứng với 1 chu kỳ máy).
+ C/T = 1: timer nhận xung clock từ chân Tx (P3.4 đối với
timer 0 và P3.5 đối với timer 1).
9
(cid:0) Ứng dụng: thường dùng để đếm sự kiện bên ngoài. Mỗi sự kiện tạo
ra một xung kích vào chân Tx (tích cực cạnh xuống). Số các sự kiện được xác định trong phần mềm bằng cách đọc các thanh ghi định thời (THx/TLx), giá trị 16-bit trong các thanh ghi này tăng theo mỗi sự kiện.
3. Điều khiển các bộ định thời
- Gate:
+ Gate = 0: việc điều khiển timer x chỉ phụ thuộc vào
TRx.
TRx = 0: không cho phép timer x chạy. TRx = 1: cho phép timer x chạy.
+ Gate = 1: việc điều khiển timer x phụ thuộc vào TRx
và /INTx.
TRx = 1 và /INTX= 1: cho phép timer chạy. Ứng dụng: thường dùng để đo độ rộng xung (thời gian xung ở mức cao) đưa vào ở chân . Độ rộng xung tương ứng với số đếm trong THx/TLx. 10
(cid:0)
4. Các chế độ định thời
a. Chế độ 0
- Xác lập bit M1M0 = 00
- Là chế độ định thời 13-bit tương thích với bộ vi điều khiển 8048 trước đó. Chế độ này thường ít dùng.
11
4. Các chế độ định thời
b. Chế độ 1
- Xác lập bit M1M0 = 01
- Là chế độ định thời 16-bit: số đếm 16-bit chứa trong cặp thanh ghi THx/TLx (cid:0) khoảng đếm tối đa là 65536 chu kì máy.
12
- Giá trị bắt đầu đếm được nạp vào THx và TLx. Khi timer tràn, để nạp lại giá trị bắt đầu đếm cần phải dừng timer.
4. Các chế độ định thời
Ví dụ 1: Viết 1 đoạn chương trình khởi động timer 0 ở chế độ 1 và dùng timer 0 để tạo ra 1 xung mức cao rộng 1ms ở chân P1.0. Giả sử dùng thạch anh 12MHz.
13
4. Các chế độ định thời
; 8051 code
MOV TMOD,#00000001B CLR P1.0 MOV TH0,#HIGH(-1000) MOV TL0,#LOW(-1000) SETB TR0 SETB P1.0 JNB TF0,$ CLR P1.0 CLR TF0
; khởi động timer 0 ở chế độ 1 ; xóa P1.0 ; nạp byte cao của -1000 (FCH) vào TH0 ; nạp byte thấp của -1000 (18H) vào TL0 ; cho timer 0 chạy ; đặt P1.0 lên mức cao ; chờ cho đến khi timer tràn (TF0 = 1) ; xóa P1.0 ; xóa cờ tràn TF0 để dùng cho các lần sau
14
4. Các chế độ định thời
Ví dụ 2: Viết chương trình con tạo trễ 200ms dùng timer 1.
Giả sử fOSC = 12MHz.
Hướng dẫn: fOSC = 12MHz (cid:0)
chu kỳ máy TM= 1(cid:0) s. Nếu dùng timer 1 ở chế độ 1 thì thời gian định thời tối đa là 65536(cid:0) s < 200.000(cid:0) s = 200ms (cid:0) phải dùng thêm vòng lặp ngoài. Để đơn giản, mỗi vòng lặp sẽ delay 50.000(cid:0) s (cid:0) số lần lặp là 4.
15
4. Các chế độ định thời
; 8051 code
DELAY_200MS:
MOV TMOD,#10H MOV R7,#4
LOOP:
MOV TH1,#HIGH(-50000) MOV TL1,#LOW(-50000) SETB TR1 JNB TF1,$ CLR TR1 CLR TF1 DJNZ R7, LOOP
16
RET
4. Các chế độ định thời
Ví dụ 3: Viết chương trình dùng timer tạo sóng vuông đối xứng
có tần số 1KHz trên chân P1.0.
Hướng dẫn:
f = 1KHz (cid:0)
T=1000 (cid:0) s (cid:0)
tH = tL = 500(cid:0) s
17
Tần số thạch anh: fOSC = 12MHz (cid:0)
chu kỳ máy TM=1(cid:0) s (cid:0)
tH = tL = 500TM
4. Các chế độ định thời
; 8051 code, using TIMER 0
ORG 0
MOV TMOD,#01H
LOOP:
MOV TH0,#HIGH(-500) MOV TL0,#LOW(-500) SETB TR0 JNB TF0,$ CLR TR0 CLR TF0 CPL P1.0 SJMP LOOP
18
END
4. Các chế độ định thời
c. Chế độ 2
- Xác lập bit M1M0 = 10
- Là chế độ định thời 8 bit tự động nạp lại.
khoảng đếm tối đa là 256 chu kì máy.
+ TLx: bộ đếm 8 bit (cid:0) + THx: lưu giá trị bắt đầu đếm được cài đặt.
- Mỗi khi timer tràn từ FFH xuống 00H, không chỉ cờ tràn được đặt lên 1 mà giá trị lưu trong THx còn được tự động nạp vào cho TLx (không cần dừng timer) và việc đếm sẽ tiếp tục từ giá trị này cho đến khi xảy ra lần tràn kế tiếp rồi lặp lại… 19
4. Các chế độ định thời
Ví dụ 4: Viết chương trình con delay 100(cid:0) s dùng timer. Giả
sử fOSC = 12MHz.
Hướng dẫn:
Do khoảng thời gian tạo trễ là 100 (cid:0) s = 100 TM < 256 (cid:0) có thể dùng timer ở chế độ 2.
20
4. Các chế độ định thời
; 8051 code, using TIMER 0 ;note: timer initial usually put in main program
DELAY_100US:
; nạp giá trị bắt đầu đếm –100 vào TH0
MOV TMOD,#02H ; khởi động timer 0 ở chế độ 2 MOV TH0,#-100 MOV TL0,TH0 SETB TR0 JNB TF0,$ CLR TR0 CLR TF0
RET
21
4. Các chế độ định thời
Ví dụ 5: Viết chương trình dùng timer 1 để tạo sóng vuông đối xứng, tần số f = 10KHz tại chân P1.7 (giả sử fOSC = 6MHz).
Hướng dẫn:
f = 10KHz (cid:0)
chu kỳ T=100(cid:0) s (cid:0)
tH = tL = 50(cid:0) s
Tần số thạch anh: fOSC = 6MHz (cid:0)
chu kỳ máy TM=2(cid:0) s (cid:0)
tH = tL = 25TM
22
4. Các chế độ định thời
; 8051 code, using TIMER 1
ORG 0
MOV TMOD,#20H MOV TH1,#-25 SETB TR1
LOOP:
JNB TF1,$ CPL P1.7 CLR TF1 SJMP LOOP
23
END
4. Các chế độ định thời
d. Chế độ 3
- Xác lập M1M0 = 11
- Là chế độ tách timer: timer 0 16-bit được chia thành 2 timer 8-bit riêng lẽ TL0 và TH0 với cờ tràn tương ứng là TF0 và TF1 (TF1 lúc này không còn là cờ tràn của timer 1 nữa).
24
- Timer 1 không hoạt động ở chế độ 3 nhưng có thể được dùng trong các chế độ khác (không sử dụng cờ tràn TF1).
4. Các chế độ định thời
Chú ý: Các kỹ thuật thường được dùng để tạo các khoảng
thời gian định thời khác nhau
25
II. Port nối tiếp
1. Giới thiệu
- Chức năng cơ bản của port nối tiếp là chuyển đổi dữ liệu từ song song thành nối tiếp khi phát và từ nối tiếp thành song song khi thu.
- Truy xuất port nối tiếp thông qua 2 chân:
+ RxD (P3.0): chân thu của port nối tiếp. + TxD (P3.1): chân phát của port nối tiếp.
27
- Có khả năng hoạt động song công (full duplex), tức là thu và phát đồng thời. Ngoài ra port nối tiếp còn có chức năng đệm dữ liệu khi thu cho phép một ký tự được nhận và lưu giữ trong bộ đệm thu trong khi ký tự tiếp theo được nhận vào. Nếu vi điều khiển đọc ký tự thứ nhất trước khi ký tự thứ hai được thu đầy đủ, dữ liệu sẽ không bị mất.
- Các thanh ghi liên quan đến port nối tiếp:
+ SCON: chứa các bit trạng thái và các bit điều khiển
port nối tiếp.
+ SBUF: là bộ đệm của port nối tiếp. Thực tế, port nối
tiếp gồm 2 bộ đệm riêng cho phát và thu.
- Tần số hoạt động của port nối tiếp, hay còn gọi là tốc độ baud (baud rate), có thể cố định hoặc thay đổi. Khi dùng tốc độ baud thay đổi, timer 1 được lập trình để cung cấp xung clock tốc độ baud phù hợp.
28
1. Giới thiệu
29
1. Giới thiệu
2. Thanh ghi điều khiển port nối tiếp SCON
30
- Địa chỉ 99H. - Định địa chỉ bit.
2. Thanh ghi điều khiển port nối tiếp SCON
31
SM0, SM1: chọn chế độ hoạt động của port nối tiếp
2. Thanh ghi điều khiển port nối tiếp SCON
+ SM2: chọn chế độ hoạt động của port nối tiếp.
SM2 = 1: cho phép truyền thông đa xử lý ở các chế độ 2 và
3; bit RI sẽ không được tích cực nếu bit thứ 9 nhận được là 0.
+ REN: bit cho phép thu.
32
REN = 1: cho phép thu. REN = 0: không cho phép thu.
+ TB8: bit phát thứ 9 (ở chế độ 2 và 3), có thể đặt và xóa bằng phần mềm. + RB8: bit thu thứ 9 (ở chế độ 2 và 3), có thể đặt và xóa bằng phần mềm. + TI: cờ ngắt phát. Cờ này được đặt lên 1 bằng phần cứng khi phát xong 1 ký tự (để báo bộ đệm phát đã rỗng), được xóa bằng phần mềm. + RI: cờ ngắt thu. Cờ này được đặt lên 1 bằng phần cứng khi thu xong 1 ký tự (để báo bộ đệm thu đã đầy), được xóa bằng phần mềm.
33
2. Thanh ghi điều khiển port nối tiếp SCON
3. Các chế độ hoạt động của port nối tiếp
a. Chế độ 0 (thanh ghi dịch 8 bit)
-Xác lập bit SM0 SM1 = 0 0
-Dữ liệu nối tiếp được thu/phát thông qua chân RxD.
-Chân TxD phát xung clock để dịch bit.
-Khi thu/phát dữ liệu 8 bit, bit LSB được thu/phát trước tiên.
34
- Tốc độ baud cố định và bằng 1/12 tốc độ dao động trên chip (f = fM = fOSC /12).
3. Các chế độ hoạt động của port nối tiếp
35
Một ứng dụng khả thi của chế độ 0 là mở rộng thêm các ngõ ra cho 8051. Một vi mạch thanh ghi dịch nối tiếp-song song có thể được nối với các chân TxD và RxD của 8051 để cung cấp thêm 8 đường xuất. Các thanh ghi dịch khác có thể ghép cascade với thanh ghi dịch đầu tiên để mở rộng thêm nữa.
3. Các chế độ hoạt động của port nối tiếp
b. Chế độ 1 (UART 8 bit tốc độ baud thay đổi)
36
- Xác lập SM0 SM1 = 0 1 - Port nối tiếp hoạt động như một bộ thu/phát bất đồng bộ (universal asynchronous receiver/transmitter) UART 8 bit có tốc độ baud thay đổi được. -Truyền 10 bit:
Tốc độ baud = (tốc độ tràn của timer 1) / 32 (nếu bit SMOD = 0) = (tốc độ tràn của timer 1) /16 ( nếu bit SMOD = 1)
3. Các chế độ hoạt động của port nối tiếp
•Khi phát:
- Trước tiên, dữ liệu được ghi vào SBUF (phát).
- Dữ liệu được dịch bit để xuất ra trên đường TxD sẽ bắt đầu bằng bit Start , tiếp theo là 8 bit dữ liệu với LSB phát trước và cuối cùng là bit Stop. Bit Start và Stop do phần cứng tự động chèn vào. Thời gian của mỗi bit là nghịch đảo của tốc độ baud.
- Cờ ngắt TI sẽ được tự động đặt bằng 1 bởi phần cứng ngay
37
khi bit Stop xuất hiện trên đường TxD (tức là đã phát xong 1 ký tự dữ liệu) để báo bộ đệm phát đã rỗng.
3. Các chế độ hoạt động của port nối tiếp
•Khi thu:
- Việc thu được khởi động bởi sự chuyển trạng thái từ 1 xuống
0 trên đường RxD (bắt đầu bit Start).
- Khi 1 bit Start hợp lệ được phát hiện, bit Start được bỏ qua và 8 bit dữ liệu được nhận tuần tự vào thanh ghi dịch bit của port nối tiếp. Sau khi thu xong cả 8 bit, các điều sau sẽ xảy ra:
+ Bit thứ 9 (bit Stop) được đưa đến bit RB8 trong
SCON.
38
+ 8 bit data được nạp vào SBUF (thu). + Cờ ngắt thu RI được đặt lên 1 bởi phần cứng.
•Khi thu:
Tuy nhiên các điều trên chỉ xảy ra nếu tồn tại các điều
kiện sau:
+ REN = 1 + RI = 0 (báo bộ đệm thu chưa đầy). + SM2 = 0 hoặc SM2 = 1 và bit Stop nhận được
bằng 1.
39
3. Các chế độ hoạt động của port nối tiếp
3. Các chế độ hoạt động của port nối tiếp
c. Chế độ 2 (UART 9 bit, tốc độ baud cố định)
- Xác lập SM0 SM1 = 1 0 - Port nối tiếp hoạt động ở chế độ UART 9 bit có tốc độ baud cố định. - Truyền 11 bit:
- Tốc độ baud = fOSC / 64 (nếu bit SMOD = 0) hay fOSC / 32 (nếu bit SMOD = 1)
- Khi phát, bit data thứ 9 là bit bất kỳ đặt ở TB8 trong thanh ghi SCON. - Khi thu, bit data thứ 9 nhận được sẽ đặt vào RB8 trong thanh ghi
40
SCON.
3. Các chế độ hoạt động của port nối tiếp
d. Chế độ 3 (UART 9 bit, tốc độ baud thay đổi được)
- Xác lập SM0 SM1 = 1 1
- Port nối tiếp hoạt động ở chế độ UART 9 bit có tốc độ baud thay đổi được, tương tự như chế độ 2 nhưng tốc độ baud được lập trình và được cung cấp bởi timer 1.
- Tốc độ baud = (tốc độ tràn của timer 1) / 32 (nếu
bit SMOD = 0)
= (tốc độ tràn của timer 1) / 16 (nếu
41
bit SMOD = 1)
3. Các chế độ hoạt động của port nối tiếp
42
* Giải thuật chương trình con thu và phát một byte:
3. Các chế độ hoạt động của port nối tiếp
•Chương trình:
INCHAR: ; CT con thu 1 byte
JNB RI,$ CLR RI MOV A,SBUF RET
43
OUTCHAR: ; CT con phát 1 byte
JNB TI,$ CLR TI MOV SBUF,A RET
Ở chế độ 1 và 3, tốc độ baud cho port nối tiếp được lập trình bởi timer 1:
Tốc độ baud = (tốc độ tràn timer 1) / 32 (SMOD = 0) / 16 (SMOD = 1)
4. Tốc độ baud cho port nối tiếp
(cid:0)
tốc độ tràn timer 1 (ftràn) = tốc độ baud x 32 (hay x16) thời gian tràn timer 1 (Ttràn) = 1 / (tốc độ tràn timer 1)
44
(cid:0)
4. Tốc độ baud cho port nối tiếp
Ví dụ: Viết 1 đoạn chương trình tạo tốc độ baud 2400 (với fOSC = 12MHz, SMOD = 0)
Ttràn timer 1 = 1/76800 =
ftràn timer 1 = 2400 x 32 = 76800 Hz (cid:0) 13,021(cid:0) s fOSC = 12MHz (cid:0) TM = 1(cid:0) s
(cid:0) 13(cid:0) s
(cid:0) Thời gian tràn timer 1 = 13,021/1 (cid:0) sai số: (13,021 – 13)/13 = 0,16%
45
; thời gian tràn là 13TM
MOV TMOD,#00100000B ; khởi động timer 1 ở mode 2 MOV TH1,#-13 SETB TR1
4. Tốc độ baud cho port nối tiếp
Ví dụ: Tạo tốc độ baud 9600 (với fOSC = 12MHz, SMOD = 0)
46
(cid:0) sai số: (3,255 – 3) / 3 = 8,5% : khá lớn.
4. Tốc độ baud cho port nối tiếp
Ví dụ: Tạo tốc độ baud 1200 (với fOSC = 12MHz, SMOD = 0)
47
(cid:0) sai số: (26,042 – 26) / 26 = 0,16%
4. Tốc độ baud cho port nối tiếp
Bảng tóm tắt một số tốc độ baud
48
Cần truyền với tốc độ chính xác thì sử dụng thạch anh 11,059MHz.
(cid:0)
5. Các ví dụ
Ví dụ 1: Viết chương trình phát 1 chuỗi mã ASCII kết thúc bằng ký tự null (có mã ASCII là 00H) ra port nối tiếp (không gởi ký tự null). Biết rằng chuỗi mã ASCII nằm trong RAM ngoài bắt đầu tại địa chỉ 2000H. Giả sử truyền UART 8 bit, tốc độ baud 2400, fOSC = 12MHz.
49
ORG 0
; khởi động port nối tiếp MOV SCON,#01010010B
MOV TMOD,#20H MOV TH1,#-13 SETB TR1
; port nối tiếp ở ; mode 1 ; timer 1 ở mode 2 ; tốc độ baud = 2400 ; cho phép timer 1
; chạy để tạo xung
; clock tốc độ baud
50
5. Các ví dụ
5. Các ví dụ
; trỏ đến địa chỉ RAM ngoài 2000H
; phát chuỗi mã ASCII MOV DPTR,#2000H LOOP:
MOVX A,@DPTR ; lấy nội dung ô nhớ RAM ngoài vào A CJNE A,#00H,CONT ; kiểm tra xem có phải ký tự null không SJMP EXIT
; nếu đúng, kết thúc chương trình ; nếu không, phát ký tự đó CONT:
51
ACALL OUTCHAR ; gọi chương trình con OUTCHAR INC DPTR SJMP LOOP ; tăng nội dung con trỏ ; lặp lại việc phát ký tự
5. Các ví dụ
; chương trình con OUTCHAR phát 1 byte dữ liệu (1 ký tự) OUTCHAR:
; chờ cờ TI bằng 1 báo bộ đệm phát rỗng ; xóa cờ TI
JNB TI,$ CLR TI MOV SBUF,A ; chuyển nội dung thanh ghi A ra SBUF RET
EXIT:NOP
; thêm lệnh NOP do END không phải là lệnh ; của 8051
52
END
5. Các ví dụ
Ví dụ 2: Viết chương trình nhập 1 chuỗi mã ASCII từ port nối tiếp và cất vào RAM nội bắt đầu từ địa chỉ 30H. Chuỗi mã ASCII kết thúc bằng ký tự CR (có mã ASCII là 13H). Cất cả ký tự CR vào RAM nội và kết thúc chuỗi bằng cách thêm ký tự null. Giả sử truyền UART 8 bit, tốc độ baud 2400, fOSC = 12MHz, bit SMOD = 0.
53
5. Các ví dụ
ORG 0 ; khởi động port nối tiếp
MOV SCON,#01010010B MOV TMOD,#20H MOV TH1,#-13 SETB TR1
54
; port nối tiếp ở mode 1 ; timer 1 ở mode 2 ; tốc độ baud = 2400 ; cho phép timer 1 chạy để tạo ; xung clock tốc độ baud
5. Các ví dụ
; trỏ đến ô nhớ RAM nội 30H
; nhập chuỗi mã ASCII MOV R0,#30H LOOP:
; nhập 1 byte từ port nối tiếp vào A ; cất byte ký tự vào ô nhớ RAM nội ; tăng nội dung con trỏ
ACALL INCHAR MOV @R0,A INC R0 CJNE A,#13H,LOOP ; kiểm tra ký tự thu được có phải là CR
; không, ; nếu không thì lặp lại
MOV @R0,#0; nếu đúng, kết thúc và chèn thêm ký tự
; null
55
SJMP EXIT
5. Các ví dụ
; chương trình con INCHAR nhận 1 byte dữ liệu (1 ký tự) INCHAR:
JNB RI,$ CLR RI MOV A,SBUF RET
56
EXIT:NOP END
5. Các ví dụ
Ví dụ 3: Viết chương trình con gởi liên tục các ký tự chữ thường ra port nối tiếp.
- Phần khởi động port nối tiếp được viết ở chương
trình chính.
- Sử dụng chương trình con OUTCHAR đã trình bày
ở trên để xuất 1 btye ra port nối tiếp.
57
5. Các ví dụ
SEND:
MOV A,#‘a’
; chuyển mã ASCII của ký tự ‘a’ vào ; thanh ghi A
LOOP:
ACALL OUTCHAR ; xuất ký tự từ thanh ghi A ra port nối
; tiếp ; tăng lên mã ASCII của ký tự kế
INC A CJNE A,#‘z’+1,LOOP ; so sánh (A) với mã ASCII của ‘z’+1 RET
58
; nếu chưa bằng thì lặp lại, nếu bằng thì ; thoát
5. Các ví dụ
Ví dụ 4: Viết chương trình nhập các ký tự từ port nối tiếp rồi xuất ra port nối tiếp liên tục. Nếu ký tự nhập vào là ký tự điều khiển (có mã ASCII từ 00H ÷ 1FH và 7FH) thì xuất ra ký tự ‘.’để thay thế. Giả sử tốc độ baud = 1200, UART 8 bit, fOSC = 12MHz.
59
5. Các ví dụ
ORG 0
; khởi động port nối tiếp MOV SCON,#01010010B MOV TMOD,#20H MOV TH1,#-26 SETB TR1 ; port nối tiếp ở mode 1 ; timer 1 ở mode 2 ; tốc độ baud = 1200 ; cho phép timer 1 chạy để tạo xung
60
; clock tốc độ baud
; nhập ký tự và so sánh LOOP:
ACALL INCHAR CJNE A,#7FH,CONT SJMP CTRL
CONT:
CJNE A,#20H,CONT1
; nhập ký tự từ port nối tiếp ; so sánh với 7FH ; nếu bằng, nhảy đến nhãn xuất CTRL ; nếu không, so sánh tiếp ; ký tự có bằng 20H
CONT1:
JC CTRL SJMP OUT
; nếu nhỏ hơn 20H thì nhảy đến nhãn CTRL ; nếu không, xuất ký tự ra port nối tiếp
CTRL:
MOV A,#‘.’
61
OUT: ACALL OUTCHAR SJMP LOOP
; chuyển mã ASCII của ký tự ‘.’ vào thanh ghi ; A ; xuất ký tự ra port nối tiếp ; lặp lại
5. Các ví dụ
5. Các ví dụ
INCHAR:
JNB RI,$ CLR RI MOV A, SBUF RET
OUTCHAR:
62
JNB TI,$ CLR TI MOV SBUF,A RET
END
III. Interrupt
-Interrupt (Ngắt): là việc ngưng thực hiện chương trình hiện hành do sự tác động của bên ngoài hay bên trong để nhảy tới thực hiện 1 chương trình khác, được gọi là chương trình phục vụ ngắt ISR (Interrupt Service Routine). Khi thực hiện xong chương trình ISR, chương trình trước đó được tiếp tục thực thi tại nơi bị tạm dừng.
- 8031/8051 có 5 nguồn ngắt:
+ 2 ngắt ngoài:
ngắt ngoài 0: qua chân (P3.2) ngắt ngoài 1: qua chân (P3.3)
+ 3 ngắt trong:
64
ngắt timer 0 ngắt timer 1 ngắt port nối tiếp
1. Giới thiệu
2. Các thanh ghi liên quan đến ngắt
a. Thanh ghi cho phép ngắt IE (Interrupt Enable) - Được định địa chỉ bit. - Chức năng từng bit:
65
EA: cho phép toàn bộ ET2: cho phép ngắt timer 2 (nếu có) ES: cho phép ngắt port nối tiếp ET1: cho phép ngắt timer 1 EX1: cho phép ngắt ngoài 1 ET0: cho phép ngắt timer 0 EX0: cho phép ngắt ngoài 0 - Để cho phép 1 nguồn ngắt, cần phải có:
+ EA = 1 + Bit cho phép ngắt tương ứng bằng 1.
Ví dụ: Khởi động thanh ghi IE cho phép ngắt timer 0 và ngắt ngoài 0
MOV IE, #10000011B
Hay:
SETB EA SETB ET0 SETB EX0
66
2. Các thanh ghi liên quan đến ngắt
2. Các thanh ghi liên quan đến ngắt
b. Thanh ghi ưu tiên ngắt IP (Interrupt Priority)
- Được định địa chỉ bit. - Bit = 1: mức ưu tiên cao Bit = 0: mức ưu tiên thấp Mặc nhiên sau khi reset, tất cả các ngắt ở mức ưu tiên thấp. - Nếu 2 ngắt với mức ưu tiên khác nhau xuất hiện đồng thời, ngắt có mức ưu tiên cao sẽ được phục vụ trước. Đồng thời, ngắt có mức ưu tiên cao cũng có thể tạm dừng chương trình phục vụ ngắt của ngắt có mức ưu tiên thấp. - Nếu các ngắt có cùng mức ưu tiên xuất hiện đồng thời, việc xác định ngắt nào được phục vụ trước sẽ theo thứ tự: ngoài 0, timer 0, ngoài 1, timer 1, port nối tiếp, timer 2 (đối với 8032/8052). 67
2. Các thanh ghi liên quan đến ngắt
c. Thanh ghi TCON
- Định địa chỉ bit. - Chức năng các bit liên quan đến ngắt (interrupt):
tạo ngắt ngoài x)
68
+ IEx: cờ ngắt ngoài x (IEx = 1 (cid:0) + ITx: bit xác định loại tác động ngắt ngoài x
ITx = 0 : tác động mức 0 ITx = 1 : tác động cạnh xuống (thường dùng)
3. Các ngắt của 8031/8051
a. Các ngắt ngoài (ngoài 0 và ngoài 1):
vi điều khiển thực hiện chương
- Khi có xung cạnh xuống (bit ITx = 1) hay mức 0 (bit ITx = 0) tác động vào chân /INTx (chân P3.2 hoặc P3.3) của 8051, cờ ngắt IEx tương ứng sẽ được đặt bằng 1 (cid:0) trình phục vụ ngắt của ngắt ngoài tương ứng.
- Khi một ngắt ngoài được tạo ra, cờ ngắt sẽ được tự động xóa bởi
69
phần cứng khi vi điều khiển chuyển đến chương trình phục vụ ngắt nếu ngắt thuộc loại tác động cạnh xuống. Còn nếu ngắt thuộc loại tác động mức, nguyên nhân ngắt ngoài sẽ điều khiển mức của cờ thay vì phần cứng.
3. Các ngắt của 8031/8051
b. Các ngắt timer (timer 0 và timer 1)
- Khi timer x tràn, cờ TFx được đặt lên 1(cid:0)
vi điều khiển
thực hiện chương trình phục vụ ngắt của timer x.
- Cờ TFx được tự động xóa về 0 bởi phần cứng khi vi điều
khiển chuyển đến chương trình phục vụ ngắt.
70
3. Các ngắt của 8031/8051
c. Các ngắt port nối tiếp
- Khi TI = 1 (phát xong 1 byte) hay RI = 1 (thu xong 1 vi điều khiển thực hiện chương trình phục vụ
byte)(cid:0) ngắt của port nối tiếp.
- Cờ TI hay RI không được xóa tự động bởi phần cứng khi
người lập trình
chuyển đến chương trình phục vụ ngắt (cid:0) phải xóa cờ TI hay RI về 0 bằng phần mềm.
71
* Vector ngắt (Interrupt vector): là địa chỉ bắt đầu của 1 chương trình phục vụ ngắt. Mỗi loại ngắt khác nhau được dành riêng một vector ngắt. Khi một ngắt được chấp nhận, địa chỉ vector ngắt tương ứng được nạp vào thanh ghi PC.
72
4. Thiết kế chương trình dùng các ngắt
4. Thiết kế chương trình dùng các ngắt
Bảng các vector ngắt:
73
Lưu ý: việc reset hệ thống cũng được xem như là một ngắt với địa chỉ vector tương ứng là 0000H.
4. Thiết kế chương trình dùng các ngắt
a. Chương trình phục vụ ngắt có kích thước nhỏ
((cid:0)
8 byte)
Chương trình phục vụ ngắt có thể được viết ngay tại địa chỉ vector ngắt nếu nó có kích thước không quá 8 byte. Khuôn mẫu chương trình sau có thể được sử dụng:
74
ORG 0000H
; điểm nhập sau khi reset
LJMP MAIN ; nhảy đến chương trình chính, bỏ qua vùng vector ngắt ; điểm nhập của trình phục vụ ngắt ngoài 0
ORG 0003H
; thoát khỏi trình phục vụ ngắt, quay về chương trình chính ; điểm nhập của trình phục vụ ngắt timer 0
EXT0_ISR: …… RETI ORG 000BH T0_ISR: …… RETI
; thoát khỏi trình phục vụ ngắt, quay về chương trình chính
; bắt đầu CT chính tại 0030H để tránh đè lên vùng vector ngắt
75
…… ORG 0030H MAIN: …… END
; kết thúc chương trình
4. Thiết kế chương trình dùng các ngắt
4. Thiết kế chương trình dùng các ngắt
b. Chương trình phục vụ ngắt có kích thước lớn (> 8 byte)
Nếu chương trình phục vụ ngắt có kích thước dài hơn 8
byte, cần phải di chuyển chương trình này đến một nơi khác trong bộ nhớ chương trình hay có thể lấn qua vùng của ngắt khác nếu ngắt đó không dùng. Thông thường, ISR được bắt đầu với một lệnh nhảy đến một vùng khác của bộ nhớ chương trình, ở đó chương trình được trải rộng nếu cần. Khuôn mẫu chương trình sau có thể được sử dụng:
76
ORG 0000H
LJMP MAIN
ORG 0003H
; nhảy đến chương trình chính ; điểm nhập của trình phục vụ ngắt ngoài 0
LJMP EXT0_ISR ; nhảy đến chương trình phục vụ ngắt
ORG 000BH
;ngoài 0 ; điểm nhập của trình phục vụ ngắt timer 0 ; nhảy đến chương trình phục vụ ngắt timer 0
LJMP T0_ISR
…… ORG 0030H
; bắt đầu chương trình chính tại 0030H ; Thường là các khởi động ban đầu, các lệnh gọi
;chương trình con, …
77
MAIN: …… ;SJMP $
4. Thiết kế chương trình dùng các ngắt
; các chương trình con CTCON_1:
…… RET
CTCON_2:
…… RET
…… ; các chương trình phục vụ ngắt EXT0_ISR:
…… RETI
T0_ISR:
…… RETI
78
…… END
4. Thiết kế chương trình dùng các ngắt
5. Các ví dụ
Ví dụ 1: Viết chương trình sử dụng ngắt timer 0 để tạo một sóng vuông đối xứng tần số 10KHz trên chân P1.0. Giả sử fOSC = 12 MHz.
T = 0,1ms = 100(cid:0) s (cid:0) cho tL = tH = 50(cid:0) s (cid:0)
sử dụng timer 0, chế độ 2 (8 bit tự động nạp lại).
sử dụng
79
Hướng dẫn: - Sóng vuông f = 10KHz (cid:0) timer đếm 50(cid:0) s (cid:0) - Mỗi lần tràn, timer 0 tạo ra một ngắt (TF0 = 1). Chương trình phục vụ ngắt chỉ cần lấy bù giá trị ở chân P1.0 (do đối xứng) (cid:0) chương trình phục vụ ngắt có kích thước nhỏ.
ORG 0
LJMP MAIN
ORG 000BH T0_ISR:
CPL P1.0 RETI ORG 0030H MAIN:
; điểm nhập khi reset ; nhảy đến chương trình chính ; vector ngắt timer 0 ; chương trình phục vụ ngắt timer 0 ; lấy bù chân P1.0 ; trở về chương trình chính ; điểm nhập chương trình chính ; chương trình chính ; khởi động timer 0, chế độ 2
MOV TMOD,#02H MOV TH0,#-50; cho timer 0 đếm 50(cid:0) s SETB TR0 MOV IE,#82H SJMP $
; cho phép timer 0 chạy ; cho phép ngắt timer 0 ; không làm gì, chỉ chờ ngắt
80
END
5. Các ví dụ
5. Các ví dụ
Ví dụ 2: Viết chương trình sử dụng các ngắt timer để tạo đồng thời 2 sóng vuông đối xứng có tần số là 7KHz và 500Hz trên các chân P1.7 và P1.6. Giả sử fOSC = 12 MHz. Hướng dẫn: - Hai sóng vuông có tần số khác nhau:
+ f1 = 7KHz (cid:0)
T1 (cid:0) 142(cid:0) s (cid:0)
dùng timer 0, chế
tL1 = tH1 = 71(cid:0) s (cid:0)
T2 = 2ms = 2000(cid:0) s (cid:0)
+ f2 = 500Hz (cid:0)
dùng
độ 2 (8 bit tự động nạp lại) tạo ngắt lấy bù giá trị trên chân P1.7. tL2 = tH2 = 1000(cid:0) s (cid:0)
timer 1, chế độ 1 (16 bit) tạo ngắt lấy bù giá trị trên chân P1.6.
chương trình sẽ vượt quá 8 byte.
81
- Sử dụng chương trình phục vụ ngắt kích thước lớn vì khi dùng timer 1 ở chế độ 1, trong chương trình phục vụ ngắt phải nạp lại giá trị cho các thanh ghi TH1 và TL1 (cid:0)
ORG 0
LJMP MAIN
ORG 000BH
; vector ngắt timer 0
LJMP T0_ISR
ORG 001BH
; vector ngắt timer 1
LJMP T1_ISR
ORG 0030H MAIN:
; cho phép ngắt timer 0 và timer 1
82
MOV TMOD,#12H ; khởi động timer 0 ở chế độ 2 và timer 1 ở chế độ 1 MOV TH0,#-71 MOV TH1,#HIGH(-1000) MOV TL1,#LOW(-1000) SETB TR0 SETB TR1 MOV IE,#8AH SJMP $
5. Các ví dụ
5. Các ví dụ
T0_ISR: ; chương trình phục vụ ngắt timer 0
CPL P1.7 RETI
T1_ISR: ; chương trình phục vụ ngắt timer 1
CLR TR1 MOV TH1,#HIGH(-1000) MOV TL1,#LOW(-1000) SETB TR1 CPL P1.6 RETI
83
END
5. Các ví dụ
Ví dụ 3: Viết chương trình sử dụng ngắt để liên tục phát đi tập mã ASCII (bỏ qua các mã điều khiển) đến 1 thiết bị đầu cuối nối với 8051 qua port nối tiếp. Giả sử truyền UART 8 bit, tốc độ baud là 1200, bit SMOD = 1. Hướng dẫn:
- Có 128 mã ASCII 7-bit trong bảng mã ASCII. Các mã này bao
gồm 95 mã đồ hoạ (từ 20H đến 7EH) và 33 mã điều khiển (từ 00H đến 1FH và 7FH). Ở đây ta chỉ xuất các mã đồ họa (từ 20H đến 7EH).
- Sử dụng ngắt port nối tiếp để phát ký tự: khi có ngắt TI = 1 (báo bộ đệm phát đã rỗng) (cid:0) vào chương trình phục vụ ngắt để gởi mã đồ họa tiếp theo ra bộ đệm phát. Trước khi gởi, cần phải kiểm tra xem đã hết tập mã ASCII chưa, nếu hết thì phát lại từ đầu.
84
ORG 0
LJMP MAIN
ORG 0023H
LJMP SP_ISR
; vector ngắt port nối tiếp
ORG 0030H MAIN:
; chương trình chính ; khởi động timer 1, chế độ 2 ; tốc độ baud của port nối tiếp là 1200
; cho timer 1 chạy để tạo xung clock tốc độ baud
MOV TMOD,#20H MOV TH1,#-26 SETB TR1 MOV SCON,#42h ; port nối tiếp ở chế độ 1 (UART 8 bit, tốc độ thay
; đổi), ; cho TI = 1: buộc ngắt để gởi ký tự đầu tiên
; ký tự đầu tiên là 20H ; cho phép ngắt port nối tiếp
85
MOV A,#20H MOV IE,#90H SJMP $
5. Các ví dụ
SP_ISR:
CJNE A,#7FH,SKIP
; chương trình phục vụ ngắt port nối tiếp ; nếu chưa hết tập mã đồ họa ASCII thì
; phát ký tự kế
MOV A,#20H
; nếu hết thì phát lại từ mã đồ họa đầu tiên ; (20H)
SKIP:
MOV SBUF,A INC A CLR TI
; gởi ký tự đến bộ đệm phát ; tăng lên ký tự kế ; xóa cờ ngắt phát, chuẩn bị cho lần phát ; kế tiếp
RETI
86
END
5. Các ví dụ
5. Các ví dụ
Ví dụ 4: Điều khiển lò nung Giả sử có một bộ cảm biến nhiệt được nối với chân (P3.2) và (P3.3) cung cấp hai tín hiệu và như sau:
/HOT = 0 nếu nhiệt độ > 210C /COLD= 0 nếu nhiệt độ < 190C
Lò được điều khiển bật/tắt thông qua chân P1.7 : P1.7 = 1 bật lò, P1.7 = 0 tắt lò.
87
Viết chương trình sử dụng các ngắt để điều khiển lò nung sao cho nhiệt độ lò được duy trì ở 200C (cid:0) 10C.
5. Các ví dụ
88
Chương trình sẽ bật lò (P1.7 = 1) khi nhiệt độ < 190C và tắt lò (P1.7 = 0) khi nhiệt độ >210C. Khi nhiệt độ trong [190C, 210C], các ngõ vào /HOT và /COLD đều là 1. Khi nhiệt độ < 190C, /HOT= 0 hay nhiệt độ > 210C, /COLD= 0 (cid:0) tạo xung cạnh xuống kích vào chân ngắt ngoài hay . Như vậy trong chương trình phục vụ các ngắt ngoài này chỉ cần đặt hay xóa bit P1.7.
ORG 0
LJMP MAIN
ORG 0003H EXT0_ISR:
; tắt lò
CLR P1.7 RETI
EXT1_ISR:
; bật lò
SETB P1.7 RETI
ORG 0030H MAIN:
; cho phép ngắt ngoài 0 và 1 ; tác động cạnh xuống
SKIP:
; ban đầu, bật lò ; nếu nhiệt độ > 210C ; thì tắt lò ; không làm gì
89
MOV IE,#85H SETB IT0 SETB IT1 SETB P1.7 JB P3.2,SKIP CLR P1.7 SJMP $ END
5. Các ví dụ
Questions ???
Bài tập chương 4
Bài tập chương 4: Timer (Xtal 12MHz)
4.1 Viết chương trình con dùng timer tạo trễ 200(cid:0) s.
4.2 Viết chương trình con dùng timer tạo trễ 50ms.
4.3 Viết chương trình con dùng timer tạo một xung mức cao trên chân P1.7 trong 1s.
92
4.4 Viết chương trình dùng timer tạo sóng vuông đối xứng có tần số f = 500Hz trên chân P1.0.
4.5 Viết chương trình dùng timer tạo sóng vuông trên chân P1.0 có tần số f = 500Hz, duty cycle = 30% (thời gian mức cao = 30% thời gian của chu kì xung).
4.6 Giả sử có một hệ thống đếm số người đi vào một siêu thị như trong hình vẽ B4.6. Bộ cảm biến sẽ tạo ra 1 xung (kích cạnh xuống) đưa vào chân T1 của 8051 (P3.5) khi có 1 người đi vào siêu thị. Một bóng đèn được điều khiển bởi chân P1.7 sẽ sáng khi P1.7 = 1 và tắt nếu P1.7 = 0. Hãy viết chương trình dùng timer để đếm số người và bật đèn báo hiệu khi có người thứ 10.000 đi vào siêu thị.
8051
Đèn báo
Bộ cảm biến
T1
P1.7
93
4.7 Viết chương trình dùng timer 0 đo thời gian mức cao của xung đưa vào chân (P3.2) của 8051. Thời gian đo được (tính bằng (cid:0) s) được lưu vào ô nhớ 30H (byte thấp) và 31H (byte cao).
Bài tập chương 4: Timer (Xtal 12MHz)
Bài tập chương 4: Serial port
4.8 Viết một đoạn chương trình khởi động port nối tiếp để thu dữ liệu ở chế độ UART 8 bit, tốc độ baud là 4800. Giả sử hệ thống dùng thạch anh 12MHz và bit SMOD = 0.
94
4.9 Viết chương trình nhập một chuỗi mã ASCII dài 80 byte từ port nối tiếp và cất vào RAM ngoài bắt đầu từ địa chỉ 2000H. Giả sử truyền ở chế độ UART 8 bit, tốc độ baud là 2400, fOSC=12MHz và bit SMOD = 0.
4.10 Viết chương trình gởi liên tiếp các ký tự hiển thị được trong tập mã ASCII (có mã từ 20H đến 7EH) đến thiết bị gắn với port nối tiếp của 8051. Giả sử truyền ở chế độ UART 8 bit, tốc độ baud là 1200, fOSC =12MHz và bit SMOD = 0.
Bài tập chương 4: Serial port
4.11 Viết chương trình nhập các ký tự từ bàn phím vào port nối tiếp và xuất ra thiết bị gắn với port nối tiếp, chuyển các ký tự thường thành ký tự hoa. Giả sử truyền ở chế độ UART 8 bit, tốc độ baud là 1200, fOSC =12MHz và bit SMOD = 0.
95
4.12 Tương tự bài 11 nhưng chuyển các ký tự hoa thành ký tự thường.
4.13 Giả sử có một chuỗi mã ASCII 20 byte chứa trong RAM nội bắt đầu từ ô nhớ 30H. Hãy viết chương trình phát chuỗi dữ liệu này ra port nối tiếp với điều kiện chỉ truyền các ký tự hoa. Giả sử truyền ở chế độ UART 8 bit, tốc độ baud là 2400, fOSC = 8MHz và bit SMOD = 0.
Bài tập chương 4: Interrupt
4.14 Viết chương trình dùng ngắt tạo sóng vuông đối xứng có tần số f = 400Hz trên chân P1.7. Giả sử hệ thống dùng thạch anh 12MHz.
4.15 Viết chương trình dùng ngắt để phát liên tiếp các ký tự hoa ra port nối tiếp. Giả sử truyền ở chế độ UART 8 bit, tốc độ baud là 2400, fOSC = 12MHz và bit SMOD = 0.
4.16 Làm lại bài 4.9 của phần port nối tiếp nhưng dùng ngắt.
96
4.17 Làm lại bài 4.13 của phần port nối tiếp nhưng dùng ngắt.
Bài tập chương 4: Interrupt
4.18 Làm lại bài 4.6 của phần timer nhưng dùng ngắt, lúc này
xung từ bộ cảm biến đưa vào chân (P3.4) thay vì chân T1.
97
4.19 Viết chương trình dùng ngắt để phát liên tiếp các ký tự hiển thị được trong tập mã ASCII (mã từ 20H đến 7EH) ra port nối tiếp, mỗi lần phát cách nhau 50ms. Giả sử truyền ở chế độ UART 8 bit, tốc độ baud là 2400, fOSC = 12MHz và bit SMOD = 0.
Bài tập chương 4: Interrupt
8051
Bộ cảm biến
P1.7
INT0
98
4.20 Giả sử có một hệ thống đếm sản phẩm như hình B4.20. Cứ mỗi sản phẩm chạy qua bộ cảm biến sẽ tạo ra một xung vuông (kích cạnh xuống) đưa vào chân /INT0 (P3.2) của 8051. Hãy viết chương trình dùng các ngắt để đếm số sản phẩm, mỗi khi đủ 100 sản phẩm thì xóa bộ đếm và tạo một xung mức cao trên chân P1.7 trong thời gian 1 giây, sau đó lặp lại.
Bài tập chương 4: Interrupt
8051
74LS04
Bộ cảm biến cửa mở
P1.7
INT0
99
4.21 Giả sử có một hệ thống báo động như hình B4.21. Bộ cảm biến cửa mở sẽ tạo ra một xung vuông (kích cạnh xuống) đưa vào chân /INT0 (P3.2) của 8051. Hãy viết chương trình dùng các ngắt để tạo ra âm hiệu có tần số 400Hz trên loa (nối với chân P1.7) trong thời gian 3 giây nếu cửa bị mở. Giả sử hệ thống dùng thạch anh 12MHz.