Các phiên bản khác như 8.43, bạn có thể không chọn cấu hình ban đầu nhưng bản thân nó có thể tự động tìm kiếm các thư viện cần thiết trong quá trình biên dịch.. Tuy nhiên hầu hết các thô
Trang 1LẬP TRÌNH VĐK PIC VỚI MPLAB C18 ĐHBK TPHCM – BKIT4U
EDITTER: TRI - IUH
Trang 3Bài 1 : Cài đặt MPLAB IDE 8.36
1.1 Giới thiệu
MPLAB IDE là phần mềm được hỗ trợ bởi Microchip, dùng để soạn thảo code cho các ứng dụng của PIC Hiện tại, tháng 8/2010 MPLAB IDE đã có phiên bản 8.51 Trong tài liệu này tôi chọn phiên bản 8.36 vì nó có khá nhiều lỗi về cấu hình Các phiên bản khác như 8.43, bạn có thể không chọn cấu hình ban đầu nhưng bản thân nó có thể tự động tìm kiếm các thư viện cần thiết trong quá trình biên dịch Với phiên bản 8.36 chúng ta phải cấu hình toàn bộ cho IDE
1.2 Cài đặt MPLAB IDE 8.36
Bước 1 : Double Click vào file setup trong thư mục MPLAB IDE 8.36 Màn hình Welcome sẽ
hiện ra như sau Bạn chọn Next để tiếp tục
Hình 1.1 : Welcome to MPLAB IDE 8.36
Bước 2 : Chọn I accept the term of the license agreement và chọn Next
Trang 5Hình 1.4 : Chọn đường dẫn cài đặt
Bước 5 : Tiếp tục chọn I accept cho Maestro License và C32 License
Hình 1.5 : Maestro License
Trang 6Hình 1.6 : C32 License
Bước 6 : Giao diện sau tổng kết lại các lựa chọn của bạn, nhấn Next để tiến hành cài đặt Nếu
muốn hiệu chỉnh bạn nhấn Back
Hình 1.7 : Bắt đầu cài đặt
Trang 7Hình 1.8 : Chờ cài đặt xong
Bước 7 : Khi cài đặt xong MPLAB IDE sẽ hỏi bạn có cần cài Hi Tech không Đây là compiler C
hỗ trợ cho MPLAB IDE, tuy nhiên ta sẽ không dùng compiler này mà sẽ dùng MPLAB C18 Bạn chọn No nhấn Finish để hoàn tất việc cài đặt MPLAB IDE
Hình 1.9 : Cài đặt hoàn tất Thông báo dưới đâu xuất hiện, thống kê các tài liệu hướng dẫn đi kèm Các tài liệu này đều nằm trong thư mục cài đặt C:\Program Files\Microchip\
Trang 8Hình 1.10 : Các tài liệu hướng dẫn
Trang 9Bài 2 : Cài đặt compiler MPLAB C18
2.1 Giới thiệu
Khi cài đặt xong MPLAB IDE, compiler mặc định cho nó là MPASM, dùng để dịch project viết bằng ASM sang file HEX Muốn viết chương trình bằng C, ta cần phải cài đặt thêm 1 compiler khác có hỗ trợ cho chip PIC đang dùng Trong phần này, tôi thí nghiệm trên vi điều khiển PIC18F4520 và chọn compiler C18 để hỗ trợ cho lập trình C chuẩn
2.2 Các bước cài đặt
Bước 1 : Double Click vào file MPLAB C18 V1.0.exe để tiến hành cài đặt, màn hình welcome
của MPLAB C18 sẽ hiện ra như sau :
Trang 10Hình 2.3 : Chọn các gói cài đặt
Bước 4 : Nhấn Next để tiến hành cài đặt
Hình 2.4 : Cài đặt C18 Chờ cho đến khi cài đặt xong
Trang 12Hình 2.8 : License Agreement Các tài liệu hỗ trợ lập trình cho compiler C18 đi kèm
Hình 2.9 : Các tài liệu hướng dẫn Chọn thư mục mặc định cho việc update (giống với thư mục cài đặt C18)
Trang 13Để mặc định các thành phần sẽ được cài đặt, không cần phải check thêm
Hình 2.10 : Các gói cài đặt C18 v3.01 Check chọn thêm các option dưới đây để MPLAB IDE tự động cấu hình các thông số tương thích với phiên bản C18 v3.01
Trang 14Hình 2.11 : Chọn cấu hình update cho MPLAB IDE Chọn Next để tiến hành Update
Hình 2.12 : Tiến hành cài đặt Chờ cho đến khi hoàn tất
Trang 15Hình 2.13 : Chờ cho đến khi hoàn tất Nhấn Finish để kết thúc
Hình 2.14 : Cài đặt hoàn tất
Trang 16Bài 3 : Tạo project trên MPLAB 8.36 và C18 3.01
Tạo 1 project lần đầu trên MPLAB khá phức tạp Người sử dụng cần phải cấu hình cho MPLAB khá nhiều Tuy nhiên hầu hết các thông số cấu hình này sẽ được lưu lại cho lần sau, chúng ta chỉ cần phải thiết lập 1 lần Phần này hướng dẫn cách tạo 1 project đơn giản trên MPLAB cho chip 18F4520 và mạch nạp PICKit2 trên board BKIT PIC
3.1 Tạo mới project
Kích hoạt chương trình MPLAB IDE 8.36 từ biểu tượng Microchip trên màn hình Desktop, cửa sổ sau đây sẽ hiện ra
Hình 3.1 : Màn hình khởi động của MPLAB IDE 8.36 Chọn menu Project và chọn New
Hình 3.2 : Tạo mới project Cửa sổ sau đây hiện ra, bạn đặt tên cho project ở khung Project Name và chọn đường dẫn cho
nó ở khung Project Directory
Trang 17Hình 3.3 : Đặt tên và chọn thư mục lưu trữ Cửa sổ làm việc của project sẽ hiện ra ở bên trái như hình dưới đây Nếu cửa sổ project không hiện ra bạn sẽ chọn menu View và chọn Project
Hình 3.4 : Cửa sổ project Chọn compile C18 cho project này bằng cách chọn vào menu Project và chọn Select Language Toolsuite
Trang 18Hình 3.5 : Chọn Language ToolSuite (Compiler) Chọn Active Toolsuite là Microchip C18 Toolsuite Các đường dẫn của các chương trình trong gói compiler cho C18 đã được cấu hình trong lúc cài đặt C18 upgrade, bạn không cần phải chỉnh lại Các gói này đều nằm trong thư mục C:\mcc18
Hình 3.6 : Chọn compiler C18
3.2 Cấu hình cho chip
Phần này có ảnh hưởng đối với quá trình dịch và nạp cho chip Chọn menu Configure và chọn Select Device… để chọn chip
Trang 19Hình 3.7 : Select Device Giao diện dưới đây hiện ra và bạn chọn cho đúng chip mà mình đang dùng Ở đây tôi chọn chip PIC18F4520
Nhấn OK để đóng cửa sổ này lại Tiếp theo đó là việc lựa chọn cấu hình thạch anh và 1 số cấu hình khác Bạn vào lại menu Configure và chọn Configuration Bits…
Trang 20Hình 3.8 : Configuration Bits Màn hình để bạn cấu hình cho chế độ hoạt động của chip dưới đây hiện ra Check bỏ dấu chọn
ở Configuration Bits set in code để bạn có thể thay đổi các thông số Thông số đầu tiên là chế độ thạch anh, tùy vào mỗi loại chip và thạch anh mà chọn lựa khác nhau Ở đây tôi sử dụng thạch anh ngoài 12MHz nên sẽ chọn chế độ thạch anh là HS (High Speed) Các chế độ thạch anh của PIC18F4520 sẽ được đề cập ở các bài sau
PORTB bit 4-0 ở chế độ mặt định là các chân analog Khi không sử dụng analog bạn cần phải chỉnh sang chế độ Digital khi reset
Disable chức năng Low Voltage Programming (LVP - Nạp điện áp thấp), mạch PICKit2 không
hỗ trợ chức năng này
Sau khi hoàn thành bạn check lại Configuration Bits set in code và đóng cửa sổ này lại
Trang 21Hình 3.9 : Thiết lập thạch anh, PortB, LVP
3.3 Tạo mới file và add thư viện cho project
Bước tiếp theo là tạo file source để viết code Từ toolbar bạn có thể chọn New File hoặc và menu File và chọn New
Hình 3.10 : Tạo mới source file
Trang 22Một file mới được tạo ra với tên mặc định là Untitled như hình dưới đây
Hình 3.11 : File mới được tạo ra Bạn nhấn và menu File và chọn Save As… để lưu lại file này Cửa số dưới đây hiện ra và bạn chọn đường dẫn để lưu cho chính xác Thông thường ta sẽ lưu trong thư mục chứa project hiện tại cho dễ quản lý
Hình 3.12 : Lưu file trong thư mục chứa project Nhấn Save để lưu file với tên mới là main.c và đóng cửa sổ trên lại Bước tiếp theo là add file vừa mới lưu (main.c) và thư mục Source File của project Click chuột phải vào Source File và chọn Add Files…
Trang 23Hình 3.13 : Add file vào Source Files Chọn đường dẫn đến file main.c và nhấn Open
Hình 3.14 : Browse đường dẫn đến main.c File main.c sẽ được add vào mục Source File của project như hình bên dưới
Trang 24Hình 3.15 : Add xong main.c cho Source Files Tiếp theo ta sẽ add các thư viện cho project Đầu tiên là Header Files Cũng tương tự như khi add file vào Source File, click chuột phải và chọn Add Files Browse đường dẫn đến C:\mcc18\h
và chọn file p18f4520.h hoặc gõ tên file này vào mục File name rồi nhấn Open
Hình 3.16 : Add Header File Add file vào mục Linker Script, browse đường dẫn đến C:\mcc18\lkr và chọn file 18f4520.lkr
Trang 25Hình 3.17 : Add file Linker Script Add file lib vào mục Library Files, 18f4520.lib tại thư mục C:\mcc18\lib
Hình 3.18 : Add Library File
3.4 Cấu hình cho quá trình dịch project
Khi dịch project, compiler cần 1 số file object của nó (chẳng hạn như c018i.o), ta cần phải chỉ đường dẫn tìm kiếm các file object này cho compiler Đối với 1 số phiên bản MPLAB, nó tự động tìm đúng các file này Tuy nhiên đối với phiên bản 8.36 ta cần phải chỉ định đường dẫn tìm kiếm Từ menu Project, chọn Build Option và chọn Project
Trang 26Giao diện Build Option hiện ra, tại mục Show Directories for bạn chọn Include Search Path, chọn New và Browse đường dẫn đến C:\mcc18\h
Sau đó chỉnh sang Library Search Path và tạo mới 1 đường dẫn C:\mcc18\lib
Hình 3.19 : Tạo đường dẫn cho include file
Trang 27Hình 3.20 : Tạo đường dẫn cho Library File Nhấn OK để hoàn tất việc cấu hình của quá trình dịch
3.5 Viết code cho project
Double Click vào file main.c và bắt đầu viết code cho project Ta viết 1 đoạn code nhỏ để làm cho các led nối với PORTB của vi điều khiến sáng xen kẽ (PORTB = 0xAA)
Trang 28Hình 3.21 : Double Click và main.c và viết code
Để kiểm tra code viết có lỗi hay không bạn vào menu Project và chọn Build All hoặc nhấn tổ hợp phím nóng Ctrl F10 Nếu không có lỗi thông báo BUILD SUCCEEDED sẽ xuất hiện
Hình 3.22 : Biên dịch thành công
3.6 Kết nối với board
Sau khi biên dịch thành công, bạn kết nối máy tính với board để nạp và chạy thử chương trình Với mạch BKIT PIC bạn cắm dây USB vào chân mạch nạp, bật công tắt nguồn và gạt tất cả các switch của SW2 lên ON để kết nối mạch nạp PICKit2
Trang 29Hình 3.23 : Kết nối với PICKit2 trên BKIT PIC Gạt tất cả các switch của SW1 lên ON để enable nút Reset, Led ở PortB và chân thạch anh ngoài
Hình 3.24 : Enable Reset, Led và XTAL ngoài
3.7 Cấu hình mạch nạp
Từ menu Programmer chọn Select Programmer và chọn mạch nạp tương ứng là PICKit2 Muốn chọn mạch nạp khác hoặc kết nối với mạch nạp lỗi bạn phải chọn lại None rồi sau đó mới chọn lại mạch nạp
Hình 3.25 : Chọn mạch nạp
Để thuận tiện cho quá trình lập trình, ta nên thiết lập thêm 1 số thông số cho mạch nạp để có thể tự động nạp và chạy chương trình khi biên dịch không có lỗi Để làm được điều này ta sẽ chọn Programmer và chọn Settings
Trang 30Hình 3.26 : Setting cho mạch nạp Giao diện sau hiện ra và bạn check chọn Program after successful build (Nạp chương trình khi biên dịch thành công) và Run after a successful program (Chạy chương trình khi nạp thành công) Nhấn OK để kết thúc
Hình 3.27 : Cấu hình nạp và chạy chương trình Bây giờ bạn nhấn lại tổ hợp phím Ctrl F10 (Build All), MPLAB sẽ làm 1 loạt các thao tác nếu không có lỗi : Dịch chương trình – Nạp chương trình – Kéo chân VDD lên mức cao để thả chân Reset và chương trình bắt đầu chạy trên board
Trang 31Hình 3.28 : Dịch - Nạp - Chạy chương trình Hình ảnh chương trình chạy trên board BKIT PIC như sau :
Hình 3.29 : Chương trình chạy trên BKIT PIC
Trang 32Bài 4 : Khảo sát các chế độ dao động
1.1 Giới thiệu
Dòng PIC18F có 10 chế độ dao động khác nhau, kí hiệu và tên gọi của chúng như sau:
1 LP : Low Power Crystal , thạch anh có tần số dao động thấp (khoảng vài chục kHz)
2 XT : Crystal/ Resonator, thạch anh/resonator có tần số trung bình (dưới 4MHz)
3 HS : High Speed Crystal/Resonator, thạch anh/resonator có tần số cao (trên 4Mhz)
4 HSPLL : High Speed Crystal/Resonator with Phase Locked Loop enabled, thạch anh tần
số cao với bộ khuyết đại PLL
5 RC : External Resistor/Capacitor with Fosc/4 output on RA6, dao động RC ngoài,output với tần số chia 4 ở chân RA6
6 RCIO : External Resistor/Capacitor with I/O on RA6, chân RA6 là I/O
7 INTIO1 : Internal Oscillator with Fosc/4 output on RA6 and I/O on RA7, dao động nội, output ở chân RA6, input/output ở chân RA7 với tần số Fosc/4
8 INTIO2 : Internal Oscillator with I/O on RA6 and RA7, dao động nội với RA6, RA7 là I/O
9 EC : External Clock with Fosc/4 output, clock ngoài, RA6 là output tần số Fosc/4
10 ECIO : External Clock with I/O on RA6, clock ngoài, RA6 là chân I/O
1.2 Crystal và Resonator
Đây là loại dao động đơn giản nhất Resonator còn có tên gọi khác là Ceramic Resonator Hình ảnh của Crystal và Resonator như hình bên dưới Các loại dao động LP, XT, HS, HSPLL sẽ dùng Crystal hoặc Resonator
Ở chế độ hoạt động này, Crystal/Resonator sẽ được kết nối với 2 chân OSC1 và OSC2 của vi điều khiển như hình dưới đây
Khi dùng Crystal, giá trị của tụ điện phụ thuộc vào tần số của Crystal như bảng dưới đây
Bảng 2 1 : Giá trị Capacitor cho Crystal Giá trị của tụ điện càng cao thì dao động càng ổn định, nhưng bù lại thời giai khởi động sẽ lâu hơn
Khi dùng Resonator, giá trị của tụ điện như sau:
Trang 33Bảng 2 2 : Giá trị Capacitor cho Resonator Khi tần số resonator lớn hơn 3.5 MHz ta nên cấu hình là HS thay vì XT
1.3 External Clock
Nguồn dao động clock ngoài được nối vào chân OSC1 Đặc điểm của loại dao động này là vi điều khiển hoạt động ngay khi có nguồn cấp (hoặc thức dậy từ chế độ sleep) mà không cần tốn thời gian khởi động (start-up time) Đối với chip PIC18F thì dao động này có 2 loại :
• EC : chân RA6 output với tần số Fosc/4 (Fosc là tần số clock đưa vào chân OSC1) Chân output này có thể dùng để kiểm tra hoặc làm chân clock cho 1 số ứng dụng (như 1 tín hiệu đồng bộ) Trong cửa số Configuration Bits, tên gọi của chế độ này là EC-CLKOUT
1.5 Bộ khuếch đại tần số PLL
PLL là 1 mạch tích hợp bên trong chip, có tác dụng nâng tần số input lên nhiều lần, nâng cao tốc độ thực thi chương trình của vi điều khiển Bộ PLL có thể được dùng kết hợp với nhiều chế
độ hoạt động thạch anh của vi điều khiển PIC
• HSPLL : PLL khi dùng với chế độ HS có thể nhân gấp 4 lần tần số input Khi đó tần số input tối đa là 10Mhz, tần số khuếch đại đạt 40MHz Trong cửa sổ Configuration Bits tên
Trang 34gọi của chế độ này là HS-PLL enabled freq = 4xFosc1 Trong chế độ này bit PLLEN không có tác dụng
• PLL và INTOSC : PLL cũng có thể được dùng kết hợp với bộ dao động nội, khi đó tần số khuếch đại có thể đạt 32Mhz Chế độ này phải được thiết lập bằng phần mềm, không có option chọn lựa trong cửa số Configuration Bits PLLEN bit dùng để kích hoạt chế độ này
1.6 Bộ dao động nội
Gần tương tự với bộ dao động External Clock, bộ dao động nội (Internal Oscillator Block) cũng
có 2 chế độ, output tần số Fosc/4 ở chân RA6 và chế độ I/O ở chân này Tần số của bộ dao động nội được lập trình software Các thanh ghi ảnh hưởng đến tần số này là OSCCON và OSCTUNE
Ở bộ dao động nội có 2 nguồn clock, nguồn clock 8MHz và nguồn clock RC 31kHz Bộ nguồn clock 8MHz sẽ đi qua 1 bộ chia (Prescaller) và cấp clock cho thiết bị hoạt động Giá trị của bộ chia này được xác định bởi 3 bit IRCF2:IRCF0 trong thanh ghi OSCCON
Khi giá trị các bit đều là 0 thì việc chọn clock source dựa vào bit INTRC trong thanh ghi OSCTUN Nếu INTRC = 0 thì tần số lấy từ clock source thứ 2, 31kHz Ngược lại tần số sẽ là 8MHz/256 = 31.5kHz (bộ chia là 256 cho clock 8MHz)
Khi tần số của bộ dao động nội là 4MHz hoặc 8MHz (OSCCON<6:4> = 110 hoặc 111) thì nó có thể được sử dụng kết hợp với bộ PLL Để kích hoạt bộ PLL ta phải set bit PLLEN ở thanh ghi OSCTUNE lên 1
1.7 Demo
Kit BKIT PIC được thiết kế dùng switch gạt để kết nối với thạch anh (crystal) 20MHz, nên ta có thể sử dụng chế độ thạch anh ngoài không PLL (PLL chỉ dùng được với thạch anh nhỏ hơn 10MHz) hoặc dùng thạch anh nội kết hợp với PLL
Để demo tần số cung cấp cho chip, ta sẽ viết chương trình cứ 1s tăng giá trị của PORTB lên 1
Một câu lệnh trong PIC chiếm 4 chu kì dao động
1.7.1 Thạch anh ngoài 20MHz
Ta sẽ dùng 2 vòng lặp for để tạo hiệu ứng delay Với chu kì 20MHz ta phải đếm 5 000 000 chu
kì lệnh (do 1 chu kì lệnh chiếm 4 chu kì dao động)
Khi muốn tính toán chính xác thời gian, ta phải dùng các câu lệnh ASM Khi viết bằng ngôn ngữ C, ta chỉ có thể ước lượng gần đúng Câu lệnh (for i=0 ; I < MAX_I ; i++) tốn khoảng 4 chu kì lệnh : i++ tốn 2 chu kì lệnh, i< MAX_I tốn 2 chu kì lệnh, lệnh gán i =0 chỉ thực hiện 1 lần nên ta có thể bỏ qua
Vậy hàm tạo hiệu ứng trì hoãn 1s với tần số 20MHz ta sẽ viết như sau:
} }
}
Như đã đề cập ở trên, 1 vòng for thực hiện khoảng 4 chu kì lệnh nên tổng số chu kì lệnh của 2 vòng for ở trên là (250 * 4) * (1250 *4) = 5 000 000
Trang 35Hàm main ta có thể viết như sau:
Code:
void main()
{
TRISB = 0x00; //setup PORTB is output
PORTB = 0x00; //init value
while(1)
{
Delay1s_20MHz(); //call delay 1s }
}
Chỉnh chế độ thạch anh trong cửa sổ Configuration Bits là HS, PORTB là Digital (mặc định là analog), Disable chức năng nạp điện áp thấp (LVP), dịch và nạp chương trình ta sẽ thấy giá trị PORTB tăng dần sau 1s
Chỉnh chế độ thạch anh sang chế độ LP hoặc XT, dịch và nạp lại chương trình bạn sẽ thấy chương trình không chạy hoặc chạy sai Do với thạch anh 20MHz ta phải chọn là HS như datasheet của PIC18F4520
} }
}
Để sử dụng được thạch anh nội 8MHz, trước tiên ta phải cấu hình là dùng thạch anh nội trong cửa sổ Configuration Bits (chọn INT RC – Port on RA6, Port on RA7), sau đó viết code trong hàm main để lựa chọn bộ Prescaller cho nguồn clock 8MHz Ta sẽ set 3 bit <6:4> của thanh ghi OSCCON lên 1 Hàm main sẽ viết như sau:
Code:
void main()
{
TRISB = 0x00; //setup PORTB is output
PORTB = 0x00; //init value
OSCCON |= 0x70 //set bit <6:4> -> freq = 8MHz
while(1)
{
Delay1s_8MHz(); //call delay 1s }
Trang 36} }
TRISB = 0x00; //setup PORTB is output
PORTB = 0x00; //init value
OSCCON |= 0x70 //set bit <6:4> -> freq = 8MHz
OSCTUNE |= 0x40 //enable PLL
while(1)
{
Delay1s_8MHzPLL(); //call delay 1s }
}
Trang 37Bài 5 : Interrupt và ngắt Timer
2.1 Interrupt trong PIC
Dòng PIC18F4520 (2420, 2520, 4420) có nhiều nguồn ngắt (interrupt source) và 2 mức ưu tiên ngắt (high priority interrupt và low priority interrupt) Vector ngắt có mức ưu tiên cao có địa chỉ 0x08 còn ngắt có mức ưu tiên thấp có địa chỉ 0x18 Khi hàm phục vụ ngắt quãng cho ngắt ưu tiên thấp đang xảy ra, ngắt ưu tiên cao xảy ra sẽ tạm dừng ngắt ưu tiên thấp và phục
vụ cho ngắt ưu tiên cao
Đối với 1 ngắt, thông thường có 3 bit để điều khiển nó:
• Flag bit : Cờ báo hiệu interrupt, khi flag bit được set, ngắt sẽ xảy ra
• Enable bit : Cho phép ngắt đối với các ngắt có mặt nạ (maskabled interrupt)
• Priority bit : Thiết lập ưu tiên ngắt, khi được set ngắt sẽ có mức ưu tiên cao
Để có thể thiết lập mức độ ưu tiên cho các nguồn ngắt, ta phải enable chức năng ưu tiên ngắt bằng cách set IPEN bit (Interrupt Priority Enable bit : RCON<7>)
Khi IPEN = 1 : GIEH bit (INTCON<7>) sẽ enable các ngắt có mức ưu tiên cao, GIEL bit (INTCON<6>) sẽ enable các ngắt có mức ưu tiên thấp Khi ngắt toàn cục, Flag bit, Enable bit được set, ngắt sẽ được kích hoạt, con trỏ chương trình sẽ nhảy tới địa chỉ 0x08 hoặc 0x18 tùy theo ngắt đó được thiếp lập là ưu tiên cao (Priority bit là 1) hay ưu tiên thấp (Priority bit là 0) Khi IPEN = 0 : Đây là trường hợp mặc định, disable chức năng ưu tiên ngắt (gọi là chế độ compatibility mode) INTCON<6> lúc này là PEIE bit, enable hay disable các ngắt ngoại vi (peripheral interrupt) INTCON<7> lúc này là GIE bit, enable hay disable tất cả các nguồn ngắt Ở chế độ compatibility này, tất cả các ngắt sẽ nhảy đến địa chỉ 0x08
Khi các nguồn ngắt có cùng độ ưu tiên, chúng sẽ cùng nhảy đến 1 địa chỉ ngắt Hàm phục vụ ngắt quãng cần phải kiểm tra tất cả các cờ để xác định nguồn ngắt nào đang gây ra ngắt Cờ ngắt cần được xóa để tránh hiện tượng ngắt đệ quy (recursive interrupt), vi điều khiển sẽ lặp
vô tận trong hàm ngắt cho đến khi tràn stack
Điểm chú ý quan trọng trong thanh ghi INTCON là khi IPEN = 1 : INTCON<7> = 1 sẽ enable tất cả các ngắt có ưu tiên cao nhưng khi INTCON<7> = 0 nó lại disable tất cả các ngắt, bao gồm cả ngắt ưu tiên thấp Một ngắt ưu tiên thấp ngoài việc thiết lập GIEL (INTCON<6>) còn phải set luôn cả bit GIEH (INTCON<7>)
2.2 Giới thiệu Timer0
Timer0 có 2 chế độ 16 bit hoặc 8 bit Clock cấp cho timer 0 có thể là clock nội hoặc clock ngoại (lấy từ chân T0CKI) Ngoài ra Timer0 còn có bộ Prescaller để chia tần số clock
Hình 2.1 : Thanh ghi điều khiển T0CON Timer0 được điều khiển bởi thanh ghi T0CON Ý nghĩa các bit trong thanh ghi này như sau:
Bit 7 TMR0ON : Bật tắt Timer 0
Khi hoạt động ở chế độ 16 bit, giá trị của bộ định thời (counter)/ bộ đếm Timer 0 được ghi vào
2 thanh ghi TMR0H và TMR0L Ngược lại, ở chế độ 8 bit, giá trị đếm được lưu trong thanh ghi TMR0L
Bit 5 T0CS : Chọn nguồn clock cho Timer 0
1 : Clock ngoài từ chân T0CKI
Trang 380 : Clock nội (Fosc/4)
Bit 4 T0SE : Chọn chế độ kích Timer 0 khi dùng nguồn ngoài
1 : Timer 0 đếm lên khi có tín hiệu từ High sang Low ở chân T0CKI
0 : Timer 0 đếm lên khi có tín hiệu từ Low sang High ở chân T0CKI
Bit 3 PSA : Bật/ Tắt chế độ Prescaller cho Timer 0
Khi chọn bộ Prescaller, tần số của Timer 0 sẽ bị chia xuống Ví dụ thạch anh dùng cho mạch là
20MHz, thì tần số của clock nội là Fosc/4 = 5MHz Nếu ta chọn Prescaller là 1:2 thì tần số đếm
của timer 0 là 2.5MHz
Khi Timer 0 đếm tràn từ FF :FF (chế độ 16 bit) hoặc FF (chế độ 8 bit) lên 0, cờ TMR0IF sẽ được
bật lên 1 và gây ra ngắt nếu các bit cho phép ngắt (ngắt toàn cục, ngắt timer0) được set lên 1
2.3 Lập trình module Timer0
2.3.1 Hàm init_timer0
Trong phần này, chúng ta sẽ khởi tạo timer0 ở chế độ 16 bit, sử dụng clock nội và prescaller
1:2, ngắt timer0 sẽ được cấu hình là ngắt ưu tiên thấp và sau mỗi 1ms sẽ xảy ra ngắt 1 lần
Timer0 sẽ đếm lên sau mỗi lần tích cực của clock Trong chế độ 16 bit, khi giá trị trong 2 thanh
ghi TMR0H:TMR0L chuyển từ FFFF sang 0000 sẽ xảy ra ngắt, cờ TMR0IF sẽ được bật lên 1
Mạch BKIT PIC sử dụng thạch anh 20MHz, nên clock nội cho timer0 sẽ là 5MHz (timer0 sẽ đếm
5 000 000 đơn vị trong 1 giây) Để có được ngắt 1ms ta sẽ nạp cho thanh ghi TMR0H:TMR0L
giá trị thấp hơn FFFF 5000 đơn vị
Vì Timer0 được cấu hình sử dụng prescaller 1:2, nên con số này sẽ thấp hơn FFFF 2500 đơn vị
: 65535 – 2500 = 63035 = F63B Việc nạp giá trị này cho thanh ghi TMR0 sẽ được thực hiện
trong hàm phục vụ ngắt quãng timer0_isr
Để enable ngắt timer 0, ta cần set bit ngắt toàn cục GIE, set bit ngắt thấp GIEL, set bit enable
timer 0 TMR0IE và cờ ngắt timer 0 TMR0IF trong thanh ghi INTCON Cấu hình ưu tiên ngắt
timer 0 là ngắt thấp bằng cách clear bit TMR0IP trong thanh ghi INTCON2
Hàm ngắt timer0 sẽ được khởi tạo như sau:
Code:
void init_timer0()
{
counter0 = 0;//counter for virtual timer
timer0_flag = 0;//flag for virtual timer
T0CON = 0x00;//timer0 16bit mode, internal clock, Prescaller 1:2
RCONbits.IPEN = 1;//enable interrupt priority
INTCON2bits.TMR0IP = 0;//low interrupt priority
INTCONbits.GIE = 1;//enable global interrupt
INTCONbits.GIEL =1;//enable low priority interrupt
INTCONbits.TMR0IE = 1;//enable timer0 interrupt
INTCONbits.TMR0IF = 1;//force timer0 interrupt
}
2.3.2 Hàm timer0_isr
Hàm này được gọi khi ngắt Timer0 xảy ra Đối với tất cả các ngắt của PIC, ta cần phải xóa cờ
ngắt trước tiên vì nó không được tự động xóa bằng phần cứng Trong hàm phục vụ ngắt quãng
Timer0 này ta nên tắt nó đi bằng cách xóa bit TMR0ON, nạp lại giá trị cho 2 thanh ghi đếm
Trang 39Timer0 Ở cuối hàm phục vụ ngắt quãng ta sẽ bật cho Timer0 đếm lên (set bit TMR0ON) Giá trị trong 2 thanh ghi đếm Timer0 sẽ tăng dần theo mỗi xung nhịp của clock, và khi đạt giá trị FFFF nó sẽ xảy ra ngắt lần tiếp theo
Code:
void timer0_isr()
{
INTCONbits.TMR0IF = 0; //clear interrupt flag
T0CONbits.TMR0ON = 0; //stop timer 0
Với chỉ thị đầu tiên, hàm vecter_low sẽ được dịch tại địa chỉ 0x18, là địa chỉ vector ngắt thấp
Do 2 địa chỉ ngắt của PIC là 0x08 cho ngắt cao và 0x18 cho ngắt thấp cách gần nhau, nên ta
sẽ chỉ đặt thật ít lệnh tại 2 địa chỉ này Trên đây chỉ đặt 1 lệnh gọi hàm low_interrupt_isr tại địa chỉ 0x18 Trong hàm này ta sẽ kiểm tra ngắt đang xảy ra có phải là Timer0 hay không bằng cách xét bit thứ 2 của thanh ghi INTCON (bit TMR0IF) trước khi gọi hàm timer0_isr Hàm main() bây giờ phải thêm chỉ thị #pragma code để compiler dịch hàm này ở 1 vùng nhớ khác trong vùng code memory
Ngoài Timer0, PIC còn có thêm 3 Timer nữa Về các chức năng cơ bản như Timer0, chúng còn
có thêm 1 vài chức năng đặc biệt khác
2.4 Giới thiệu Timer 1
Khác với Timer0 là 1 interrupt, Timer1 là 1 Peripheral Interrupt Vì vậy để có thể enable cho ngắt Timer1, ta phải set bit PEIE
Trang 40Tương tự với Timer0, Timer1 cũng có chức năng counter từ clock ngoài (ở chân T13CKI) và tăng giá trị lên 1 mỗi khi có clock cạnh lên ở chân T13CKI
Khi chọn clock ngoài, T1SYNC bit dùng để chọn chế độ cho counter, là Ansynchronous Counter hoặc Synchronous Counter Hai loại counter này đều tăng giá trị đếm lên 1 sau mỗi lần tích cực của clock, điểm khác biệt của chúng nằm ở kết nối phần cứng Synchronous Counter cấp clock cho tất cả các flip flop trong khi Ansynchronous Counter chỉ cấp clock cho flip flop đầu tiên
Hình 2.2: Synchronous Counter
Hình 2.3 : Ansynchronous Counter Bên cạnh đó, Timer1 còn có thể đếm lên nhờ dao động ngoài ở 2 chân T1OSI và T1OSO Người
ta thường dùng thạch anh 32,768kHz và biến Timer1 thành 1 bộ Real Time Clock (đồng hồ thời gian thực) Sơ đồ kết nối như sau: