mua vé xem phim, ai đến trước sẽ được mua vé trước, nhưng lại có 1 kẻ to con không thích phải xếp hàng và đi thẳng lên trước và mua vé trước vậy, đây là một Interrupt. Hay là việc mình đang viết chuỗi blog về LED 7 SEGMENT (005-006) bỗng nhiên lại chuyển sang 007.Interrupt vậy. Vậy nên thay vì như thông thường vi xử lý sẽ nhận các lệnh lần lượt và xử lý lần lượt (First in- First out [FIFO]), trong một số trường hợp đặc biệt sau khi nhận một số thông tin đặc biệt từ dữ liệu phần mềm (Timer Interrupts) hay thông tin từ phần cứng (External Interrupt), nó sẽ dừng công việc hiện tại rồi ưu tiên thực hiện những lệnh đặc biệt trước. Bây giờ, chúng ta sẽ tìm hiểu kĩ hơn về ngắt trong 8051 nhé. Sẽ hơi đau đầu đấy. Nhưng chỉ cần làm những ví dụ sau là bạn sẽ hiểu ngay thôi ^^
Cơ chế ngắt trong 8051:
1.Phân loại ngắt:
Thực tế chỉ có 5 ngắt dành cho người dùng trong 8051 nhưng các nhà sản xuất nói rằng có 6 ngắt vì họ tính cả lệnh RESET. Sáu ngắt của 8051 được phân bố như sau:
1. RESET: Khi chân RESET được kích hoạt từ 8051, bộ đếm chương trình nhảy về địa chỉ 0000H. Đây là địa chỉ bật lại nguồn.
2. 2 ngắt dành cho các bộ Timer: 1 cho Timer0 và 1 cho Timer1. Địa chỉ tương ứng của các ngắt này là 000BH và 001BH.
3. 2 ngắt dành cho các ngắt phần cứng bên ngoài: chân 12 (P3.2) và 13 (P3.3) của cổng P3 là các ngắt phần cứng bên ngoài INT0 và INT1 tương ứng. Địa chỉ tương ứng của các ngắt ngoài này là 0003H và 0013H.
4. Truyền thông nối tiếp: có 1 ngắt chung cho cả nhận và truyền dữ liệu nối tiếp. Địa chỉ của ngắt này trong bảng vector ngắt là 0023H.
Nói tóm lại, 8051 chỉ có một số lượng khá ít các nguồn ngắt (interrupt source). Mỗi ngắt có một vector ngắt riêng, đó là một địa chỉ cố định nằm trong bộ nhớ chương trình, khi ngắt xảy ra, CPU sẽ tự động nhảy đến thực hiện lệnh nằm tại địa chỉ này. Ngoài RESET ra chúngta có thể tóm tắt các ngắt trong 8051 như trong bảng sau:
Việc cho phép cấm ngắt hoàn toàn có thể được điều khiển bằng phần mềm nạp trên vi điều khiển qua việc điều khiển thanh ghi IE (SFR IE) (Special Function Register Interrupt Enable ) 1 thanh ghi IE sẽ có 8 bit IE.7-IE.0 (chúng ta tạm thời bỏ qua IE.5, IE.6)
Tức là:
- Nếu EA = 0 thì không có ngắt nào được đáp ứng
- Nếu EA = 1 thì tất cả mọi ngắt đều được phép và sẽ được đáp ứng nếu các bit tương ứng của chúng trong IE có mức cao.
- Bit ES=1 Cho phép ngắt cổng kết nối trong port
- Bit EX1(EX0)=1 Cho phép ngắt INT1(INT0)
- Bit ET1(ET0)=1 Cho phép ngắt Timer1(Timer0)
Ví dụ:
- Tìm giá trị của IE để vi điều khiển cho phép ngắt Timer(0) và INT1?
Muốn cho phép ngắt Timer(0) và INT1 chúng ta phải cho EA=EX1=ET0=1 hay IE.7=IE.3=TE.1=1 hay ta có dòng bit: 10001010 hay IE=0x8A
2.Các mức ưu tiên ngắt trong 8051:
Nhìn vào bảng ta thấy ngắt INT0 là ngắt có mức ưu tiên cao nhất và ngắt timer2 là ngắt có mức ưu tiên thấp nhất trong số các ngắt. Như vậy nếu ngắt ngoài 1 và ngắt timer0 cùng xảy ra một lúc, ngắt ngoài 1 sẽ được CPU xử lý trước, sau đó mới xử lý ngắt timer0
3.Ngắt ngoài (External Interrupt)
8051 có 2 ngắt ngoài là INT0 và INT1. Ngắt ngoài xảy ra khi nhận mức Logic=0 ở chân ngắt tương ứng (P3.2 với ngắt ngoài 0 và P3.3 với ngắt ngoài 1). Việc lựa chọn kiểu ngắt được thực hiện bằng các bit IT (Interrupt Type) nằm trong thanh ghi TCON. Cũng giống như thanh ghi EA, thanh ghi TCON cũng biểu diễn 8 bit (TF1, TR1 TF0 TR0 IE1 IT1 IE0 IT0). Đây là thanh ghi điều khiển dùng chung cho cả EI và timer.
- TF0(1) là các cờ báo tràn timer, khi sự kiện tràn timer xảy ra, cờ sẽ được tự động đặt lên mức logic 1 và nếu ngắt tràn timer đang bật, ngắt sẽ xảy ra. Khi CPU xử lý ngắt tràn timer0(1), cờ ngắt TF0(1) tương ứng sẽ tự động được xóa về 0.
- TR0(1) = 1, timer0(1) sẽ đếm, ngược lại khi TR0(1) = 0, timerx sẽ không đếm . Khi dừng không đếm, giá trị của timer được giữ nguyên
- Khi bit IT0(1) = 1 thì ngắt ngoài tương ứng được chọn kiểu là ngắt theo sườn xuống, ngược lại nếu bit IT0(1) = 0 thì ngắt ngoài tương ứng được sẽ có kiểu ngắt là ngắt theo mức thấp. Các bit IE là các bit cờ ngắt ngoài, chỉ có tác dụng trong trường hợp kiểu ngắt được chọn là ngắt theo sườn xuống.
Khi kiểu ngắt theo sườn xuống được chọn thì ngắt sẽ xảy ra duy nhất một lần khi có sườn xuống của tín hiệu, sau đó khi tín hiệu ở mức thấp, hoặc có sườn lên, hoặc ở mức cao thì cũng không có ngắt xảy ra nữa cho đến khi có sườn xuống tiếp theo. Cờ ngắt IE sẽ dựng lên khi có sườn xuống và tự động bị xóa khi CPU bắt đầu xử lý ngắt. Khi kiểu ngắt theo mức thấp được chọn thì ngắt sẽ xảy ra bất cứ khi nào tín hiệu tại chân ngắt ở mức thấp. Nếu sau khi xử lý xong ngắt mà tín hiệu vẫn ở mức thấp thì lại ngắt tiếp, cứ như vậy cho đến khi xử lý xong ngắt lần thứ n , tín hiệu đã lên mức cao rồi thì thôi không ngắt nữa. Cờ ngắt IE trong trường hợp này không có ý nghĩa gì cả.
Thông thường kiểu ngắt hay được chọn là ngắt theo sườn xuống.
4.Ngắt timer
8051 có 2 timer tên là timer0 và timer1. Các timer này đều là timer 16bit, giá trị đếm max do đó bằng 2^16 = 65536 (đếm từ 0 đến 65535). Hai timer có nguyên lý hoạt động hoàn toàn giống nhau và độc lập.
Sau khi cho phép chạy, mỗi khi có thêm một xung tại đầu vào đếm, giá trị của timer sẽ tự động được tăng lên 1 đơn vị, cứ như vậy cho đến khi giá trị tăng lên vượt quá giá trị max mà thanh ghi đếm có thể biểu diễn thì giá trị đếm lại được đưa trở về giá trị min (thông thường min = 0). Khi đó xảy ra tràn timer (overflow) và có thể gây ra ngắt nếu ngắt tràn timer được cho phép (bit ETx trong thanh ghi IE=1). Việc cho timer chạy/dừng được thực hiện bởi các bit TR trong thanh ghi TCON (đánh địa chỉ đến từng bit).
Thanh ghi 16 bit của bộ Timer 0 (hay Timer 1) được truy cập như byte thấp và byte cao:
- Thanh ghi byte thấp được gọi là TL0 (Timer0 Low byte).
- Thanh ghi byte cao được gọi là TH0 (Timer0 High byte).
Các timer có thể hoạt động theo nhiều chế độ, được quy định bởi các bit trong thanh ghi TMOD (không đánh địa chỉ đến từng bit)
- Bit GATE quy định việc cho phép Timer đếm (run Timer). Nếu GATE =0, Timer sẽ đếm khi bit TR bằng 1, dừng khi bit bằng 0. Nếu GATE =1, Timer sẽ chỉ đếm khi bit TR = 1 và tín hiệu tại chân INT = 1, dừng khi một trong hai điều kiện trên không còn thỏa mãn. Thông thường người ta dùng Timer với GATE = 0, chỉ dùng timer với GATE = 1 trong trường hợp muốn đo độ rộng xung vì lúc đó Timer sẽ chỉ đếm thời gian khi xung đưa vào chân INT ở mức cao.
- Bit C/T quy định nguồn clock đưa vào đếm trong Timer. Nếu C/T = 0, timer sẽ được cấu hình là bộ Timer, nếu C/T = 1, timer sẽ được cấu hình là bộ đếm sự kiện.
- Hai bit còn lại (M0 và M1) dùng để chọn chế độ timer
M1
|
M0
|
Chế độ
|
Chế độ hoạt động
|
0
|
0
|
0
|
Bộ Timer 13 bit: 8 bit là bộ Timer/bộ đếm, 5 bit đặt trước.
|
0
|
1
|
1
|
Bộ Timer 16 bit: không có đặt trước.
|
1
|
0
|
2
|
Bộ Timer 8 bit: tự nạp lại.
|
1
|
1
|
3
|
Chế độ bộ tách Timer
|
Để sử dụng timer của 8051, chúng ta cần thực hiện các bước sau:
- Quy định chế độ hoạt động cho timer bằng cách tính toán và ghi giá trị cho các bit trong thanh ghi TMOD.
- Ghi giá trị đếm khởi đầu mong muốn vào 2 thanh ghi đếm THx và TLx. Đôi khi ta không muốn timer/counter bắt đầu đếm từ 0 mà từ một giá trị nào đó để thời điểm tràn gần hơn, hoặc chẵn hơn trong tính toán sau này. Ví dụ nếu cho timer đếm từ 15535 thì sau 50000 xung nhịp (tức 50000 ms với thạch anh 12MHz) timer sẽ tràn, và thời gian một giây có thể dễ dàng tính ra khá chính xác = 20 lần tràn của timer (đương nhiên mỗi lần tràn lại phải nạp lại giá trị 15535).
- Dùng bit TRx trong thanh ghi TCON để cho timer chạy hay dừng theo ý muốn.
Các bước lập trình cho chế độ 1
Để tạo ra một độ trễ thời gian dùng chế độ 1 của Timer thì cần phải thực hiện các bước:
1. Nạp giá trị TMOD cho thanh ghi báo độ Timer nào (Timer0 hay Timer1) được sử dụng và chế độ nào được chọn.
2. Nạp các thanh ghi TL và TH với các giá trị đếm ban đầu.
3. Khởi động Timer.
4. Duy trì kiểm tra cờ Timer TF bằng một vòng lặp để xem nó được bật lên 1 không. Thoát vòng lặp khi TF được lên cao.
5. Dừng Timer.
6. Xoá cờ TF cho vòng kế tiếp.
7. Quay trở lại bước 2 để nạp lại TL và TH.
Công thức tính độ trễ sử dụng chế độ 1 (16 bit) của Timer đối với tần số thạch anh XTAL = f (MHz):
a) Tính theo số Hex
|
b) Tính theo số thập phân
|
(FFFF – YYXX + 1)*12/f (ms) trong đó YYXX là các giá trị khởi tạo của TH, TL tương ứng. Lưu ý rằng các giá trị YYXX là theo số Hex.
|
Chuyển đổi các giá trị YYXX của TH, TL về số thập phân để nhận một số thập phân NNNNN sau đó lấy (65536 – NNNNN)*12/f (ms).
|
Các bước để tìm các giá trị của các thanh ghi TH và TL:
1. Chia thời gian trễ cần thiết cho 1.085ms2. Thực hiện 65536 – n với n là giá trị thập phân nhận được từ bước 1.
(hoặc lấy -n rồi đổi sang Hex luôn)3. Chuyển đổi kết quả ở bước 2 sang số Hex: ta có YYXX là giá trị Hexa ban đầu cần phải nạp vào các thanh ghi Timer.4. Đặt TL = XX và TH = YY.
Chế độ 0 hoàn toàn giống chế độ 1 chỉ khác là Timer 16 bit được thay bằng13 bit. đếm 13 bit có thể giữ các giá trị giữa 0000 đến 1FFFF trong TH - TL. Do vậy khi Timer đạt được giá trị cực đại của nó là 1FFFH thì nó sẽ quay trở về 0000và cờ TF được bật lên.
Để tạo ra một thời gian trễ sử dụng chế độ 2 của Timer cần thực hiện các bước sau:1. Nạp thanh ghi giá trị TMOD để báo Timer gian nào (Timer0 hay Timer1) được sử dụng và chế độ làm việc nào của chúng được chon.2. Nạp lại thanh ghi TH và TL với giá trị đếm ban đầu.3. Khởi động Timer.4. Duy trì kiểm tra cờ Timer TF bằng cách sử dụng một vòng lặp để xem nó đã được bật chưa. Thoát vòng lặp khi TF lên cao.5. Dừng Timer.6. Xoá cờ TF.7. Quay trở lại bước 3. Vì chế độ 2 là chế độ tự nạp lại.
Trong bài viết sau, chúng ta sẽ thử làm một vài ví dụ, thông qua đó để biết cách sử dụng một số phương pháp ngắt cơ bản.
references
INTRO TO EMBEDDED SYSTEMS 1E- Shibu K V
8051 Microcontrollers: Hardware, Software and Applications - David M Calcutt
Làm quen với vi điều khiển 8051-Nguyễn Xuân Kiên
http://dientumaytinh.com
http://duyanhxp.wordpress.com/
Thân.
Phong'S
2 comments
Chuẩn luôn
Replythanks. bài viết hữu ích và rất hay
ReplyĐăng nhận xét