Tài liệu Thiết kế hệ thống nhúng: THIẾT KẾ HỆ THỐNG NHÚNG 
 1 
MỤC LỤC 
MỤC LỤC.......................................................................................................................................... 1 
DANH MỤC HÌNH VẼ ..................................................................................................................... 4 
Bài 1 ................................................................................................................................................... 5 
TỔNG QUAN VỀ VI ĐIỀU KHIỂN PIC ......................................................................................... 5 
1.1. Giới thiệu tổng quan về Pic .................................................................................................... 5 
1.2. Kiến trúc Pic ........................................................................................................................... 6 
1.2.1. Cấu trúc của PIC .................................................................................
                
              
                                            
                                
            
 
            
                 71 trang
71 trang | 
Chia sẻ: putihuynh11 | Lượt xem: 1043 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang mẫu tài liệu Thiết kế hệ thống nhúng, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
THIẾT KẾ HỆ THỐNG NHÚNG 
 1 
MỤC LỤC 
MỤC LỤC.......................................................................................................................................... 1 
DANH MỤC HÌNH VẼ ..................................................................................................................... 4 
Bài 1 ................................................................................................................................................... 5 
TỔNG QUAN VỀ VI ĐIỀU KHIỂN PIC ......................................................................................... 5 
1.1. Giới thiệu tổng quan về Pic .................................................................................................... 5 
1.2. Kiến trúc Pic ........................................................................................................................... 6 
1.2.1. Cấu trúc của PIC ............................................................................................................ 6 
1.2.2. RISC và CISC ................................................................................................................ 7 
1.3. Vi điều khiển PIC 16F877A ................................................................................................... 7 
1.3.1. Sơ đồ chân và kiểu đóng vỏ ........................................................................................... 7 
1.3.2. Sơ đồi khối ..................................................................................................................... 9 
1.3.3. Một số đặc điểm ............................................................................................................. 9 
1.3.4. So sánh với vi điều khiển họ 8051 ............................................................................... 10 
Bài 2 ................................................................................................................................................. 11 
TỔNG QUAN VỀ LẬP TRÌNH NHÚNG TRÊN PIC .................................................................... 11 
2.1. Ngôn ngữ lập trình và trình biên dịch .................................................................................. 11 
2.1.1. Trên hệ điều hành window ........................................................................................... 11 
2.1.2. Trên hệ điều hành Linux .............................................................................................. 12 
2.1.3. Các mạch nạp và mạch gỡ rối chương trình ................................................................. 12 
2.2. Lập trình PIC với CCS ......................................................................................................... 15 
2.2.1. Tổng quan về CCS ....................................................................................................... 15 
2.2.2. Tạo PROJECT đầu tiên trong CCS .............................................................................. 16 
2.3. Biến, hàm, cấu trúc lệnh và các chỉ thị tiền xử lý ................................................................ 23 
2.3.1. Biến, hằng, hàm và cấu trúc lệnh ................................................................................. 23 
2.4. Mẫu chương trình cho lập trình CCS ................................................................................... 26 
Bài 3 ................................................................................................................................................. 29 
LẬP TRÌNH VÀO RA SỐ ............................................................................................................... 29 
3.1. Các hàm xử lý bit và các phép toán ..................................................................................... 29 
3.1.1. Hàm Shift_left, Shift_right ........................................................................................... 29 
3.1.2. Hàm Bit_set, Bit_clear ................................................................................................. 29 
3.1.3. Hàm Bit_test................................................................................................................. 29 
3.1.4. Hàm Swap .................................................................................................................... 30 
3.1.5. Hàm Make8 .................................................................................................................. 30 
3.1.6. Hàm Make16 ................................................................................................................ 30 
3.1.7. Make32 ......................................................................................................................... 30 
3.2. Các hàm vào ra ..................................................................................................................... 31 
3.2.1. Output_low (pin), Output_high (pin) ........................................................................... 31 
3.2.2. Output_bit (pin, value) ................................................................................................. 31 
3.2.3. Input (pin) .................................................................................................................... 32 
3.2.4. Output_X (value) ......................................................................................................... 32 
3.2.5. Input_X () ..................................................................................................................... 32 
THIẾT KẾ HỆ THỐNG NHÚNG 
 2 
3.2.6. Port_B_pullups ............................................................................................................. 32 
3.2.7. Set_tris_X (value) ......................................................................................................... 32 
3.3. Lập trình vào ra với led đơn, led 7 thanh và bàn phím ......................................................... 33 
Bài 4 ................................................................................................................................................. 34 
THỰC HÀNH: LẬP TRÌNH VÀO RA SỐ ..................................................................................... 34 
Bài 5 ................................................................................................................................................. 34 
LẬP TRÌNH VÀO RA TƯƠNG TỰ ............................................................................................... 34 
5.1. Bộ chuyển đổi ADC và DAC ............................................................................................... 34 
5.1.1 Tổng quan ..................................................................................................................... 34 
5.1.2. Độ phân giải ................................................................................................................. 35 
5.1.3. Điện áp tham chiếu ....................................................................................................... 36 
5.2. Bộ chuyển đổi ADC trong PIC ............................................................................................. 36 
5.2.1. ADC trong PIC 16F877A ............................................................................................. 37 
5.2.2. Cấu hình bộ ADC trong CCS ....................................................................................... 39 
5.2.3. Lập trình ứng dụng ....................................................................................................... 42 
Bài 6 ................................................................................................................................................. 44 
THỰC HÀNH: LẬP TRÌNH VÀO RA TƯƠNG TỰ ...................................................................... 44 
Bài 7 ................................................................................................................................................. 44 
LẬP TRÌNH VÀ XỬ LÝ NGẮT ..................................................................................................... 44 
7.1. Tổng quan về ngắt trong PIC 16F877A ................................................................................ 44 
7.2. Khai báo và sử dụng ngắt trong CCS ................................................................................... 45 
7.3. Ngắt do sự thay đổi trạng thái của các chân trong PORTB .................................................. 48 
7.4. Chế độ Sleep ......................................................................................................................... 50 
7.5. Watch Dog Timer ................................................................................................................. 50 
7.6. “Đánh thức” vi điều khiển .................................................................................................... 51 
Bài 8 ................................................................................................................................................. 53 
THẢO LUẬN LẬP TRÌNH XỬ LÝ NGẮT .................................................................................... 53 
Bài 9 ................................................................................................................................................. 53 
THỰC HÀNH: LẬP TRÌNH NGẮT................................................................................................ 53 
Bài 10 ............................................................................................................................................... 53 
TIMER TRONG PIC 16F877A ........................................................................................................ 53 
10.1. Timer 0 ............................................................................................................................. 53 
10.2. Timer 1 ............................................................................................................................. 55 
10.3. Timer 2 ............................................................................................................................. 56 
10.4. Khai báo Timer trong CCS ............................................................................................... 57 
10.4.1. Các lệnh Timer0 ........................................................................................................... 57 
10.4.2. Các lệnh Timer1 ........................................................................................................... 59 
10.4.3. Các lệnh Timer2 ........................................................................................................... 59 
10.5. Lập trình ứng dụng ........................................................................................................... 60 
Bài 11 ............................................................................................................................................... 61 
THỰC HÀNH: LẬP TRÌNH TIMER/COUNTER .......................................................................... 61 
Bài 12 ............................................................................................................................................... 62 
THẢO LUẬN VỀ TIMER/COUNTER ........................................................................................... 62 
Bài 13 ............................................................................................................................................... 62 
THIẾT KẾ HỆ THỐNG NHÚNG 
 3 
THỰC HÀNH: LẬP TRÌNH TIMER/COUNTER (TIẾP) .............................................................. 62 
Bài 14 ............................................................................................................................................... 62 
LẬP TRÌNH TRUYỀN THÔNG ..................................................................................................... 62 
14.1. Tổng quan về lập trình truyền thông ................................................................................ 62 
14.2. Chuẩn RS232 ................................................................................................................... 62 
14.3. Lập trình ứng dụng ........................................................................................................... 66 
Bài 15 ............................................................................................................................................... 67 
THỰC HÀNH: LẬP TRÌNH TRUYỀN THÔNG ........................................................................... 67 
Bài 16 ............................................................................................................................................... 68 
LẬP TRÌNH TRUYỀN THÔNG (tiếp) ........................................................................................... 68 
16.1. Chuẩn I2C ........................................................................................................................ 68 
16.2. Lập trình ứng dụng ........................................................................................................... 69 
Bài 17: .............................................................................................................................................. 70 
THỰC HÀNH: LẬP TRÌNH TRUYỀN THÔNG (TIẾP) ............................................................... 70 
Bài 18: .............................................................................................................................................. 70 
THẢO LUẬN VỀ LẬP TRÌNH TRUYỀN THÔNG ...................................................................... 70 
Bài 19 ............................................................................................................................................... 70 
LẬP TRÌNH NÂNG CAO ............................................................................................................... 70 
19.1. GLCD ............................................................................................................................... 70 
19.2. Thẻ nhớ ............................................................................................................................ 70 
19.3. Ethernet ............................................................................................................................ 70 
Bài 20: .............................................................................................................................................. 70 
THỰC HÀNH: LẬP TRÌNH NÂNG CAO ..................................................................................... 70 
Bài 21: .............................................................................................................................................. 70 
BÀI TẬP, THẢO LUẬN TỔNG KẾT ............................................................................................ 70 
TÀI LIỆU THAM KHẢO ................................................................................................................ 71 
THIẾT KẾ HỆ THỐNG NHÚNG 
 4 
DANH MỤC HÌNH VẼ 
Hình 1: Kiến truc Harvard và Von-Neumann..................................................................................... 6 
Hình 2: Một số sơ đồ chân và kiểu đóng vỏ cho PIC 16F87XA ........................................................ 8 
Hình 3: Sơ đồ khối của vi điều khiển PIC 16F877A .......................................................................... 9 
Hình 4: Trình biên dịch MPASM trên .............................................................................................. 11 
Hình 5: Mạch nạp PIC Kit 2 và PIC Kit 3 ........................................................................................ 13 
Hình 6: MPLAB ICD3 - Công cụ nạp và gỡ rối ............................................................................... 14 
Hình 7: MPLAB REAL ICE – In Circuit Emulator ......................................................................... 15 
Hình 8: Giao diện PICC ................................................................................................................... 16 
Hình 9: Cửa sổ Save As .................................................................................................................... 17 
Hình 10: Tab General ....................................................................................................................... 18 
Hình 11: Tab Communications......................................................................................................... 18 
Hình 12: Tab SPI andLCD ............................................................................................................... 19 
Hình 13: Tab Timer .......................................................................................................................... 20 
Hình 14: Tab Analog ........................................................................................................................ 20 
Hình 15: Tab Other ........................................................................................................................... 21 
Hình 16: Tab Interrupts .................................................................................................................... 22 
Hình 17: Tab Driver ......................................................................................................................... 22 
Hình 18: Mạch flash ADC với 4 bộ so sánh ..................................................................................... 35 
Hình 19: Minh họa tín hiệu Analog và digital của hàm sin .............................................................. 36 
Hình 20: Sơ đồ khối bộ chuyển đổi ADC ......................................................................................... 38 
Hình 21: Các cách lưu kết quả chuyển đổi ADC .............................................................................. 38 
Hình 22: Sơ đồ kết nối với vi điều khiển PIC 16F877 ..................................................................... 42 
Hình 23: Sơ đồ logic của các ngắt trong PIC 16F877A ................................................................... 45 
Hình 24: Ghép nối điều khiển LED đơn ........................................................................................... 46 
Hình 25: Sơ đồ ghép nối xử lý ngoài trên PortB .............................................................................. 49 
Hình 26: Sơ đồ khối của bộ Timer0 ................................................................................................. 54 
Hình 27: Sơ đồ khối của Timer1 ...................................................................................................... 55 
Hình 28: Sơ đồ khối Timer2 ............................................................................................................. 57 
Hình 29: Sơ đồ mạch ví dụ dùng Timer0 ......................................................................................... 60 
Hình 30: Hình ảnh giao diện DB9 và DB25 ..................................................................................... 63 
Hình 31: Sơ đồ chân trên giao diện DB9 và DB25 .......................................................................... 63 
Hình 32: Sơ đồ khối các vi mạch MAX232, MAX233 .................................................................... 66 
Hình 33: Sơ đồ ghép nối thiết bị chuẩn I2C ..................................................................................... 68 
THIẾT KẾ HỆ THỐNG NHÚNG 
 5 
ĐỀ CƯƠNG BÀI GIẢNG HỌC PHẦN 
THIẾT KẾ HỆ THỐNG NHÚNG 
Bài 1 
TỔNG QUAN VỀ VI ĐIỀU KHIỂN PIC 
1.1. Giới thiệu tổng quan về Pic 
PIC bắt nguồn là chữ viết tắt của "Programmable Intelligent Computer" (Máy 
tính khả trình thông minh) là một sản phẩm của hãng General Instrument đặt cho 
dòng sản phẩm đầu tiên của họ là PIC1650. 
PIC sử dụng tập lệnh RISC (Reduced Instructions Set Computer), với 
dòng PIC low-end (độ dài mã lệnh 12 bit, ví dụ: PIC12Cxxx) và mid-range (độ dài 
mã lệnh 14 bit, ví dụ: PIC16Fxxxx), tập lệnh bao gồm khoảng 35 lệnh, và 70 lệnh 
đối với các dòng PIC high-end (độ dài mã lệnh 16 bit, ví dụ: PIC18Fxxxx). Tập 
lệnh bao gồm các lệnh tính toán trên các thanh ghi, với các hằng số, hoặc các vị trí 
bộ nhớ, cũng như có các lệnh điều kiện, lệnh nhảy/gọi hàm, và các lệnh để quay trở 
về, nó cũng có các tính năng phần cứng khác như ngắt hoặc sleep (chế độ hoạt động 
tiết kiện điện). Microchip cung cấp môi trường lập trình MPLAB, nó bao gồm phần 
mềm mô phỏng và trình dịch ASM. 
Các dòng Pic hiện nay được phân chia theo các loại: 
- Vi điều khiển 8 bit: Pic10xxxx, Pic 12xxxx, Pic 14xxxx, Pic 16xxxx, Pic 
17xxxx, Pic 18xxxx. 
- Vi điều khiển 16 bit: Điển hình ở đây là Pic 24, dsPIC30, dsPIC33F 
- Vi điều khiển 32 bit: PIC 32 
Hiện nay có khá nhiều dòng PIC và có rất nhiều khác biệt về phần cứng, nhưng 
chúng ta có thể điểm qua một vài nét như sau: 
- FLASH và ROM có thể tuỳ chọn tùy theo từng loại chip 
- Các cổng Xuất/Nhập (I/O ports) (mức logic thường từ 0V đến 5. 5V, ứng 
với logic 0 và logic 1) 
- 8/16 Bit Timer 
- Các chuẩn giao Tiếp Ngoại Vi Nối Tiếp Đồng bộ/Không đồng 
bộ USART, AUSART, EUSARTs 
- Bộ chuyển đổi ADC Analog-to-Digital Converters, 8, 10/12... bit 
- Bộ so sánh điện áp (Voltage Comparators) 
- Các module Capture/Compare/PWM 
- MSSP Peripheral dùng cho các giao tiếp I2C, SPI, và I²S 
THIẾT KẾ HỆ THỐNG NHÚNG 
 6 
- Bộ nhớ nội EEPROM - có thể ghi/xoá lên tới 1 triệu lần 
- FLASH (dùng cho bộ nhớ chương trình) có thể ghi/xóa 10. 000 lần (tiêu 
chuẩn) 
- Hỗ trợ giao tiếp USB 
- Hỗ trợ điều khiển Ethernet 
- Hỗ trợ giao tiếp CAN 
- Một số dòng có tích hợp bộ RF (PIC16F639, và rfPIC) 
- DSP những tính năng xử lý tín hiệu số (dsPIC) 
1.2. Kiến trúc Pic 
1.2.1. Cấu trúc của PIC 
Cấu trúc phần cứng của một vi điều khiển được thiết kế theo hai dạng kiến trúc: 
Kiến trúc Von Neuman và kiến trúc Harvard. 
Hình 1: Kiến truc Harvard và Von-Neumann 
Tổ chức phần cứng của Pic được thiết kế theo kiến trúc Harvard. Điểm khác biệt 
giữa kiến trúc Harvard và kiến trúc Von-Neumann là cấu trúc bộ nhớ dữ liệu và bộ 
nhớ chương trình. 
Đối với kiến trúc Von-Neumann, bộ nhớ dữ liệu và bộ nhớ chương trình nằm 
chung trong một bộ nhớ, do đó ta có thể tổ chức, cân đối một cách linh hoạt bộ nhớ 
chương trình và bộ nhớ dữ liệu. Tuy nhiên điều này chỉ có ý nghĩa khi tốc độ xử lý 
của CPU phải rất cao, vì với cấu trúc đó, trong cùng một thời điểm CPU chỉ có thể 
tương tác với bộ nhớ dữ liệu hoặc bộ nhớ chương trình. Như vậy có thể nói kiến 
trúc Von-Neumann không thích hợp với cấu trúc của một vi điều khiển. 
Đối với kiến truc Harvard, bộ nhớ dữ liệu và bộ nhớ chương trình tách ra thành 
hai bộ nhớ riêng biệt. Do đó trong cùng một thời điểm CPU có thể tương tác với cả 
hai bộ nhớ, như vậy tốc độ xử lý của vi điều khiển được cải thiện đáng kể. 
Một điểm cần lưu ý nữa là tập lệnh trong kiến trúc Harvard có thể được tối ưu 
theo yêu cầu kiến trúc của vi điều mà không phụ thuộc vào cấu trúc dữ liệu. Ví dụ, 
đối với vi điều khiển dòng 16F, độ dài lện luôn là 14 bit (trong khi dữ liệu được tổ 
Data 
memory 
CPU 
Program 
memory 
CPU 
Program 
and Data 
memory 
Harvard 
Von-Neumann 
THIẾT KẾ HỆ THỐNG NHÚNG 
 7 
chức thành từng byte), còn đối với kiến truc Von-Neumann, độ dài lệnh luôn là bội 
số của 1 byte (do dữ liệu được tổ chức thành từng byte). 
1.2.2. RISC và CISC 
Như đã trình bày, kiến truc Harvard là kiến trúc mới hơn so với kiến trục Von-
Neumann. Khái ni 
Lệnh này được hình thành nhằm cải tiến tốc độ thực thi của một vi điều khiển. 
Qua việc tách rời bộ nhớ dữ liệu và bộ nhớ chương trình, bus của chương trình và 
bus dữ liệu, CPU có thể cùng một lúc truy xuất cả bộ nhớ chương trình và bộ nhớ 
dữ liệu, giúp tăng tốc độ xử lý của vi điều khiển lên gấp đôi. Đồng thời cấu trúc 
lệnh không còn phụ thuộc vào cấu trúc dữ liệu nữa mà có thể linh động điều chỉnh 
tùy theo khả năng và tốc độ của từng vi điều khiển. Và để cải thiện tốc độ thực thi 
lệnh, tập lệnh của họ vi điều khiển PIC được thiết kế sao cho chiều dài mã lệnh luôn 
cố định (ví dụ với họ 16Fxxxx chiều dài mã lệnh luôn là 14 bit) và cho phép thực 
thi lệnh trong một chu kỳ xung clock (ngoại trừ một số trường hợp đặc biệt như 
lệnh nhảy, gọi chương trình con cần hai chu kỳ xung đồng hồ). Điều này có nghĩa 
tập lệnh của vi điều khiển thuộc cấu trúc Harvard sẽ ít lệnh hơn, đơn giản hơn và 
ngắn hơn để đáp ứng yêu cầu mà mã hóa lệnh bằng một lượng bit nhất định. 
Vi điều khiển được tổ chức theo kiến trúc Harvard còn gọi là vi điều khiển RISC 
(Reduced Instructions Set Computer) hay vi điều khiển có tập lệnh rút gọn. Vi điều 
khiển được thiết kế theo kiến trúc Von-Neumann còn được gọi là vi điều khiển 
CISC (Complex Instructions Set Computer) hay vi điều khiển có tập lệnh phức tạp 
vì mã lệnh của nó không phải là một số cố định mà luôn là bội số của 8 bit. 
1.3. Vi điều khiển PIC 16F877A 
1.3.1. Sơ đồ chân và kiểu đóng vỏ 
THIẾT KẾ HỆ THỐNG NHÚNG 
 8 
Hình 2: Một số sơ đồ chân và kiểu đóng vỏ cho PIC 16F87XA 
Hình 2 trình bày sơ đồ chân và kiểu đóng vỏ của Pic16F87XA. Trong đó: 
- Kiểu đóng vỏ 40-Pin PDIP: Pic16F87XA được đóng trong một vỏ có 44 
chân, kích thước lớn, chân cắm hàn trên mạch, thích hợp lắp đặt cho các 
mạch có kích thước linh kiện lớn. 
- Kiểu đóng vỏ 44-Pin PLCC: là kiểu đóng vỏ kích thước IC nhỏ, có 4 
hàng chân xung quanh, chân ngắn, thích hợp cho lắp mạch với linh kiện 
dán. 
- Kiểu đóng vỏ 44-Pin TQFP: gần tương tự kiểu đóng vỏ 44-Pin PLCC với 
kích thước chân dài hơn, dùng trên các mạch lắp linh kiện dán. 
Mặc dù được đóng vỏ khác nhau (kích thước lớn/nhỏ chênh lệch nhiều) 
song tính năng, khả năng hoạt động của Pic vẫn không thay đổi. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 9 
1.3.2. Sơ đồi khối 
Hình 3: Sơ đồ khối của vi điều khiển PIC 16F877A 
1.3.3. Một số đặc điểm 
Đây là vi điều khiển thuộc họ PIC16Fxxx với tập lệnh gồm 35 lệnh có độ dài 14 
bit. Mỗi lệnh đều được thực thi trong một chu kỳ xung clock. Tốc độ hoạt động tối 
đa cho phép là 20 MHz với một chu kỳ lệnh là 200ns. Bộ nhớ chương trình 8Kx14 
bit, bộ nhớ dữ liệu 368x8 (368 byte) RAM và bộ nhớ dữ liệu EEPROM với dung 
lượng 256x8 (256 byte). Số PORT I/O là 5 với 33 pin I/O. 
Các đặc tính ngoại vi bao gồm các khối chức năng sau: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 10 
- Timer0: bộ đếm 8 bit với bộ chia tần số 8 bit. 
- Timer1: bộ đếm 16 bit với bộ chia tần số, có thể thực hiện chức năng đếm 
dựa vào xung clock ngoại vi ngay khi vi điều khiển hoạt động ở chế độ 
sleep. 
- Timer2: bộ đếm 8 bit với bộ chia tần số, bộ postcaler. 
- Hai bộ Capture/so sánh/điều chế độ rông xung. 
- Các chuẩn giao tiếp nối tiếp SSP (Synchronous Serial Port), SPI và I2C. 
- Chuẩn giao tiếp nối tiếp USART với 9 bit địa chỉ. 
- Cổng giao tiếp song song PSP (Parallel Slave Port) với các chân điều 
khiển RD, WR, CS ở bên ngoài. 
- Các đặc tính Analog: 8 kênh chuyển đổi ADC 10 bit. 
- Hai bộ so sánh. 
Bên cạnh đó là một vài đặc tính khác của vi điều khiển như: 
- Bộ nhớ flash với khả năng ghi xóa được 100. 000 lần. 
- Bộ nhớ EEPROM với khả năng ghi xóa được 1. 000. 000 lần. 
- Dữ liệu bộ nhớ EEPROM có thể lưu trữ trên 40 năm. 
- Khả năng tự nạp chương trình với sự điều khiển của phần mềm. 
- Nạp được chương trình ngay trên mạch điện ICSP (In Circuit Serial 
Programming). 
- Watchdog Timer với bộ dao động trong. 
- Chức năng bảo mật mã chương trình. 
- Chế độ Sleep. 
- Có thể hoạt động với nhiều dạng Oscillator khác nhau. 
1.3.4. So sánh với vi điều khiển họ 8051 
- Về kiến trúc VXL 
- Tốc độ làm việc 
- Bộ nhớ chương trình, dữ liệu,  
- Đặc điểm bộ lệnh 
- Các hỗ trợ vào ra số, vào ra tương tự 
- Hỗ trợ về truyền thông 
- Xử lý thời gian/bộ đếm (timer/counter) 
- Các tính năng khác 
THIẾT KẾ HỆ THỐNG NHÚNG 
 11 
Bài 2 
TỔNG QUAN VỀ LẬP TRÌNH NHÚNG TRÊN PIC 
2.1. Ngôn ngữ lập trình và trình biên dịch 
2.1.1. Trên hệ điều hành window 
a) Trình biên dịch MPASM (hợp ngữ) 
Microchip cung cấp trình biên dịch MPASM miễn phí, và đi kèm trong bộ cài 
MPLAB IDE. 
Khi không sử dụng trình soạn thảo chuyên dụng trong PIC, chúng ta hoàn toàn 
có thể sử dụng Notepad hoặc Notepad Plus,... để soạn thảo chương trình và sau đó 
trực tiếp chạy MPASMWIN. exe để biên dịch. 
Hình 4: Trình biên dịch MPASM trên 
b) Hi-Tech soft 
- Trình soạn thảo: HI-TIDE (Hitech IDE) 
- Trình biên dịch: HTPIC 
- Ngôn ngữ lập trình: C 
- Đây là trình biên dịch chuyên nghiệp dành cho PIC 
c) Microchip MPLAB C 
- Trình soạn thảo: MPLAB IDE 
- Trình biên dịch: C18 (dành cho PIC 18), C30 (dành cho PIC 24, dsPIC), 
C32 (dành cho PIC 32) 
- Ngôn ngữ lập trình: C 
THIẾT KẾ HỆ THỐNG NHÚNG 
 12 
- MPLAB C không hỗ trợ cho PIC 10/12/16 do đó đây là một lựa chọn phù 
hợp cho những dòng PIC cao hơn. Tuy nhiên nếu muốn sử dụng trình hợp 
ngữ thì MPLAB cũng có thể giúp chúng ta thực hiện. 
d) CCSInfo 
- Trình soạn thảo: CCS IDE 
- Trình biên dịch: CCS C 
- Ngôn ngữ lập trình: C 
- Đây là trình biên dịch dễ dàng nhất cho người dùng, tuy nhiên các phiên 
bản CCS hỗ trợ các dòng chip mới thường rất chậm. Đây là công cụ phù 
hợp với mức độ sản xuất vừa và nhỏ và nó rất thuận tiện cho người mới 
bắt đầu hoặc chuyển từ vi điều khiển khác qua sử dụng PIC. 
e) Mikro Elektronika 
- Trình soạn thảo: MikroE IDE 
- Trình biên dịch: MikroC (ngôn ngữ C), MikroPascal (ngôn ngữ Pascal), 
MikroBasic (ngôn ngữ Basic) 
f) SourceBoost 
- Trình soạn thảo: SourceBoost IDE 
- Trình biên dịch: Boost C (ngôn ngữ C), Boost C++ (ngôn ngữ C++), 
BoostBasic (ngôn ngữ Basic), Novo RTOS (hệ điều hành), Flowcode 
(ngôn ngữ flowchart) 
- Đây là phần mềm được phát triển mạnh với nhiều ngôn ngữ lập trình 
khác nhau, đặc biệt là đây là phần mềm đầu tiên trong việc phát triển PIC 
trên nền tảng hướng đối tượng C++. 
2.1.2. Trên hệ điều hành Linux 
a) Trình biên dịch hợp ngữ 
GPUTILS là một công cụ tổng hợp, bao gồm được phát triển từ năm 2001 và 
ngày nay được phát triển và hỗ trợ rất nhiều. 
b) PIKLab 
Trình biên dịch ngôn ngữ câp cấp mã nguồn mở cho PIC là SDCC và GCC. Bên 
cạnh các phần mềm mã nguồn mở, hai công ty CCSInfo và HI-TECH Soft cũng 
cung cấp phần mềm trên Linux 
2.1.3. Các mạch nạp và mạch gỡ rối chương trình 
Nếu một vi điều khiển mà không có chương trình nằm bên trong nó (firmware) 
thì nó chưa thể thực hiện được một chức năng nào cả. Do đó, mạch nạp là một phần 
THIẾT KẾ HỆ THỐNG NHÚNG 
 13 
không thể thiếu khi chúng tra nghiên cứu và sử dụng với vi điều khiển nói chung và 
với PIC nói riêng. 
Có rất nhiều mạch nạp trên thị trường thế giới cũng như Việt Nam. Tuy nhiên 
chúng ta có thể phân loại theo đối tượng sử dụng như sau: 
Mạch nạp và gỡ rối dành cho sinh viên: Loại này giá rẻ, chức năng tương đối 
bị hạn chế, và chủ yểu chỉ đảm nhiệm chức năng nạp chương trình (firmware). 
Hiện nay mạch nạp dành cho sinh viên rất phong phú, đặc biệt với mục tiêu hạ 
giá thành sản phẩm tới mức tối đa. Điển hình là một số mạch nạp sau: 
- Mạch nạp PICKit 2, PICKit 3 của microchip 
Tính năng: Nạp hầu hết các dòng sản phẩm Microchip PIC/dsPIC, hỗ trợ 
Programmer Go (Không cần sử dụng máy tính, nạp chương trình vào PICKit, sau 
đó cấp nguồn và bấm nút để nạp vào PIC), cấp nguồn từ USB 
Giá thành: Từ 30$ đến 50$ 
Hình 5: Mạch nạp PIC Kit 2 và PIC Kit 3 
- Mạch gỡ rồi ICD2 LE (phiên bản giới hạn) 
Tính năng: nạp và debug hầu hết các dòng Microchip/dsPIC, không hỗ trợ 
nguồn từ ICDE LE. Bề ngoài nhìn giống PICKit 2 nhưng có màu xanh dương. Do 
đây là phiên bản giới hạn (limited Edition) nên sản phẩm không được phổ biến lắm. 
Giá thành: Từ 60$ đến 80$. 
- Mạch nạp PK2FUN của R&P 
Tính năng: giống với PICKit 2, nhưng bỏ đi 2 tính năng chính là tính năng 
Programmer To Go và tính năng cấp nguồn từ USB. 
Giá thành: Khoảng 10$ 
THIẾT KẾ HỆ THỐNG NHÚNG 
 14 
- Mạch nạp Gusb của PduyTech 
Tính năng: Đây là một mạch phát triển từ mạch GTP-USB, sử dụng với chương 
trình nạp WinPIC800. Tuy nhiên, sau đó Pduytech đã phát triển lại phần mềm và 
phát triển khá tốt. 
Giá thành: Khoảng 10$ 
Mạch nạp, gỡ rối dành cho nhà thiết kế: Loại này trong bị nhiều tính năng hơn, 
chủ yếu tập trung vào tính năng gỡ rối và mô phỏng. Đây là phiên bản trả phí, 
với các nhà thiết kế ở Việt Nam thường chấp nhận bỏ qua tính năng mô phỏng 
(Emulator) mà chỉ dừng ở tính năng gỡ rồi (debugger) nhằm giảm chi phí trang 
thiết bị. 
Một số sản phẩm tiểu biểu: 
- ICD3 – In Circuit Debugger 3 
Tính năng: Là một phiên bản cải tiến từ ICD2, tuy nhiên hiện nay 
ICD2 không còn sản xuất nữa, ICD3 tăng tốc độ nạp chip đáng kế. 
Giá thành: Khoảng 200$ 
Hình 6: MPLAB ICD3 - Công cụ nạp và gỡ rối 
- REAL ICE – In Circuit Emulator 
Tính năng: Mô phỏng trực tiếp trên mạch, chủ yếu sử dụng cho các mạch nạp 
phức tạp, thuật toán phức tạp 
Giá thành: Khoảng 550$ 
THIẾT KẾ HỆ THỐNG NHÚNG 
 15 
 Hình 7: MPLAB REAL ICE – In Circuit Emulator 
Mạch nạp dành cho nhà sản xuất: Chỉ tập trung vào tính năng duy nhất là tính 
năng nạp, điều quan trong nhất là phải nạp nhanh, thao tác đơn gian, bền vữ và đảm 
bảo cho công nhân kỹ thuật có thể sử dụng. 
Vấn đề chính của các nhà sản xuất chính là số giữa tốc độ nạp chip và số lượng 
nhân công. Một bài toán rất rõ ràng như sau: nếu khi nhà sản xuất lên tới khoảng 
100000 sản phẩm mỗi năm, việc nạp chip trở thành một vấn đề lớn. Giải phải bắt 
buộc là phải nạp cùng lúc nhiều sản phẩm, vì thời gian nạp để cho chop gần như là 
khó có thể giam, tùy theo dung lượng của chip và kích thước firmware. 
Các loại mạch trên thị trường hiện nay cho phép nạp cúng lúc từ 4 đến 32 chip 
điển hình một số loại như sau: 
- SoftLog IC2GANG 
Tính năng: mỗi lần nạp 4 chip, có thể ghép nối với 16 mạch ICP2GANG với 
nhau để nạp tới 64 chip cùng lúc. 
Giá thành: Khoảng 1600$ 
- CCSInfo PRIME8 
Tính năng: Mỗi lần nạp được 8 chip, không cần sử dụng máy tính, chỉ cần nạp 
firmware vào PRIM8 sau đó chỉ cần cấp nguồn để nạp 
Giá thành: Khoảng 900$ 
2.2. Lập trình PIC với CCS 
2.2.1. Tổng quan về CCS 
CCS là trình biên dịch lập trình ngôn ngữ C cho Vi điều khiển PIC của hãng 
Microchip. Chương trình là sự tích hợp của 3 trình biên dich riêng viết cho 3 dòng 
PIC khác nhau đó là: 
‐ PCB cho dòng PIC 12‐bit opcodes 
‐ PCM cho dòng PIC 14‐bit opcodes 
THIẾT KẾ HỆ THỐNG NHÚNG 
 16 
‐ PCH cho dòng PIC 16và 18‐bit 
Tất cả 3 trình biên dich này đuợc tích hợp lại vào trong một chương trình bao 
gồm cả trình soạn thảo và biên dịch là CCS. 
Giống như nhiều trình biên dịch C khác cho PIC, CCS giúp cho người sử dụng 
nắm bắt nhanh được vi điều khiển PIC và sử dụng PIC trong các dự án. Các chương 
trình diều khiển sẽ được thực hiện nhanh chóng và đạt hiệu quả cao thông qua việc 
sử dụng ngôn ngữ lập trình cấp cao – ngôn ngữ C 
2.2.2. Tạo PROJECT đầu tiên trong CCS 
Để tạo một Project trong CCS có nhiều cách, có thể dùng ProjectWizard, 
ManualCreat, hay đơn giản là tạo một Files mới và thêm vào đó các khai báo ban 
đầu cần thiết và“bắt buộc”. 
Dưới đây sẽ trình bày cách tạo một project hợp lệ theo cả 3 phương pháp. Một 
điều ta cần chú ý khi tạo một Project đó là: khi tạo bắt cứ một Project nào mới thì ta 
nên tạo một thư mục mới với tên liên quan đến Project ta định làm, rồi lưu các files 
vào đó. Khi lập trình và biên dịch, CCS sẽ tạo ra rất nhiều files khác nhau, do đó 
nếu để chung các Project trong một thư mục sẽ rất mất thời gian trongviệc tìm kiếm 
sau này. Đây cũng là quy tắc chung khi ta làm việc với bất kỳ phần mềm nào, thiết 
kế mạch hay lập trình. 
Việc đầu tiên bạn cần làm là khởi động máy tính và bật chương trình PIC C 
Compiler. 
Tạo một PROJECT sử dụng PIC Wizard 
Trước chết bạn khởi động chương trình làm việc PICC Compiler. Từ giao diện 
chương trình bạn di chuột chọn Project ‐> New‐>PIC Wizard nhấn nút trái chuột 
để chọn. 
Hình 8: Giao diện PICC 
Sau khi nhấn chuột, một cửa sổ hiện ra yêu cầu ban nhập tên Files cần tạo. Bạn 
tạo một thư mục mới, vào thư mục đó và lưu tên files cần tạo tại đây. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 17 
Hình 9: Cửa sổ Save As 
Như vậy là xong bước đầu tiên. Sau khi nhấn nút Save, một cửa sổ NewProject 
hiện ra. Trong của sổ này bao gồm rất nhiều Tab, mỗi Tab mô tả về một vài tính 
năng của con PIC. Ta sẽ chọn tính năng sử dụng tại các Tab tương ứng. 
Dưới đây sẽ trình bày ý nghĩa từng mục chọn trong mỗi Tab. Các mục chọn này 
chính là đề cập đến các tính năng của một con PIC, tùy theo từng loại mà sẽ có các 
Tab tương ứng. Đối với từng dự án khác nhau, khi ta cần sử dụng tính năng nào của 
con PIC thì ta sẽ chọn mục đó. Tổng cộng có 13 Tab để ta lưa chọn, ta sẽ đi vào một 
số tab hay sử dụng 
a) Tab General 
Tab General cho phép ta lựa chọn loại PIC mà ta sử dụng và một số lựa chọn 
khác như chọn tần số thạch anh dao động, thiết lập các bit CONFIG nhằm thiết lập 
chế độ hoạt động cho PIC (hình dưới). 
- Device: Liệt kê danh sách các loại PIC12F, 16F, 18FTa sẽ chọn tên Vi 
điều khiển PIC mà ta sử dụng trong dự án. Lấy ví dụ chọn PIC16F877A 
- Oscilator Frequency: Tần số thạch anh ta sử dụng, chọn 20 MHz (tùy 
từng loại) 
- Fuses: Thiết lập các bit Config như: Chế độ dao động (HS, RC, Internal), 
chế độ bảovệ Code, Brownoutdetected 
- Chọn kiểu con trỏ RAM là 16bit hay 8bit 
THIẾT KẾ HỆ THỐNG NHÚNG 
 18 
Hình 10: Tab General 
b) Tab Communications 
Tab Communications liệt kê các giao tiếp nối tiếp mà một con PIC hỗ trợ, 
thường là RS232 và I2C, cùng với các lựa chọn để thiết lập chế độ hoạt động cho 
từngloại giao tiếp. 
c) Giao tiếpRS232 
Mỗi một Vi điều khiển PIC hỗ trợ một cổng truyền thông RS232 chuẩn. Tab này 
cho phép ta lựa chọn chân Rx, Tx, tốc độ Baud, Data bit, Bit Parity 
Hình 11: Tab Communications 
THIẾT KẾ HỆ THỐNG NHÚNG 
 19 
d) Giao tiếp I2C 
Để sử dụng I2C ta tích vào nút chọn Use I2C, khi đó ta có các lựa chọn: Chân 
SDA, SCL, tốc độ truyền (Fast- Slow), chế độ Master hay Slave, địa chỉ cho Salve. 
e) Tab SPI and LCD 
Tab này liệt kê cho người dùng các lựa chọn đối với giao tiếp nối tiếp SPI, 
chuẩn giao tiếp tốc độ cao mà PIC hỗ trợ về phầncứng. Chú ý khi ta dùng I2C thì 
không thể dùng SPI và ngược lại. Để có thể sử dụng cả hai giao tiếp này cùng một 
lúc thì buộc một trong 2 giao tiếp phải lập trình bằng phần mềm (giồng như khi 
dùng I2C cho các chip AT8051, không có hỗ trợ phần cứng SSP). 
Phần cấuhình choLCD dành cho các chip dòng 18F và 30F. 
Hình 12: Tab SPI andLCD 
f) Tab Timer 
Liệt kê các bộ đếm/địnhthời mà các con PIC dòng Midrangecó: Timer0, timer1, 
timer2, WDT 
Trong các lựa chọn cấu hình cho các bộ đếm /định thời có: chọn nguồn xung 
đồng hồ (trong/ngoài), khoảng thời gian xảy ra tràn 
THIẾT KẾ HỆ THỐNG NHÚNG 
 20 
Hình 13: Tab Timer 
g) Tab Analog 
Liệt kê các lựa chọn cho bộ chuyển đổi tương tự/số (ADC) của PIC. Tùy 
vàotừng IC cụthể mà cócáclựa chọn khácnhau, bao gồm: 
Lựa chọn cổng vào tương tự 
Chọn chânđiện áp lấymẫu (Vref) 
 Chọn độ phângiải:8bit = 0~ 255 hay10bit = 0~1023 
Nguồn xung đồng hồ cho bộ ADC (trong hay ngoài), từ đó mà ta có được tốc độ 
lấy mẫu, thường ta chọn là internal2-6 us. 
Khi khôngsử dụng bộ ADC ta chọn none 
Hình 14: Tab Analog 
THIẾT KẾ HỆ THỐNG NHÚNG 
 21 
h) Tab Other 
Tab này cho phép ta thiết lập các thông số cho các bộ 
Capture/Comparator/PWM. 
Capture 
- Chọn bắt giữ xung theo sườn dương (risingedge) hay sườn âm 
(fallingedge) của xung vào 
- Chọn bắt giữ au 1, 4 hay 16 xung (copy giá trị của Timer X vào thanh ghi 
lưu trữ CCCPx sau1, 4 hay 16 xung). 
Compare 
Ta có các lựa chọn thực hiện lệnh khi xayư ra bằng nhau giữa 2 đối tượng so 
sánh là giá trị của Timer1 với giá trị lưu trong thanh ghi để so sánh. Bao gồm: 
 - Thực hiệnngắt và thiết lập mức 0 
 - Thực hiệnngắt và thiết lập mức 1 
 - Thực hiệnngắt nhưng không thay đổi trạng thái của chân PIC. 
 - Đưa Timer1 về 0 nhưng không thay đổi trạng thái chân. 
PWM - Điều chế độ rộng xung 
Lựa chọn về tần số xung ra và dutycycle. Ta có thể lựa chọn sẵn hay tự chọn tần 
số, tất nhiên tần số ra phải nằm trong một khoảng nhất định. 
Comparator - So sánh 
Lựa chọn mức điện áp so sánhVref. Có rất nhiều mức điện áp để ta lựa chọn. 
Ngoài ra ta còn có thể lựa chọn cho đầu vào của các bộ so sánh. 
Hình 15: Tab Other 
THIẾT KẾ HỆ THỐNG NHÚNG 
 22 
i) Tab Interrupts và Tab Driver 
TabInterrupts cho phép ta lựa chọn nguồn ngắt mà ta muốn sử dụng. Tùy vào 
từng loại PIC mà số lượng nguồn ngắt khác nhau, bao gồm: ngắt ngoài 0 (INT0), 
ngắt RS232, ngắt Timer, ngắt I2C‐SPI, ngắt onchange PORTB. v. v 
TabDrivers được dùng để lựa chọn những ngoại vi mà trình dịch đã hỗ trợ các 
hàm giao tiếp. Đây là nhưng ngoại vi mà ta sẽ kết nối với PIC, trong các IC mà 
CCS hỗ trợ, đáng chú ý là các loại EEPROM như 2404, 2416, 2432, 9346, 
9356Ngoài ra còn có IC RAM PCF8570, IC thời gian thực DS1302, Keypad3x4, 
LCD, ADCChi tiết ta có thể xem trong thư mục Driver của chươngtrình: \... 
\PICC\Drivers 
Hình 16: Tab Interrupts 
Hình 17: Tab Driver 
THIẾT KẾ HỆ THỐNG NHÚNG 
 23 
Sau các bước chọn trên, ta nhấn OK để kết thúc quá trình tạo một Project trong 
CCS, một File ten_project. c được tạo ra, chứa những khai báo cần thiết cho PIC 
trong một Files ten_project. h. 
2.3. Biến, hàm, cấu trúc lệnh và các chỉ thị tiền xử lý 
2.3.1. Biến, hằng, hàm và cấu trúc lệnh 
Giống với ngôn ngữ lập trình C, tham khảo tài liệu lập trình c và CCS 
Chỉ thị tiền xử lý 
#ASM và #ENDASM 
Cho phép đặt một đoạn mã ASM giữa hai chỉ thị này, chỉ thị đặt trong hàm. CCS 
định nghĩa 1 biến 8 bit để giới hạn giá trị trả về cho hàm từ đoạn mã Assembly. 
Mã Assembly theo tập lệnh của vi điều khiển mà không phải theo kiểu mã của 
phần mềm hỗ trợ (MPLAB). 
#INCLUDE 
Cú pháp: #include 
Filename: tên file cho thiết bị *. h, *. c. Nếu chỉ định file ở đường dẫn khác thì 
thêm đường dẫn vào, luôn phải có khai báo chương trình viết cho VĐK nào và luôn 
đặt ở dòng đầu tiên 
Ví du: #include // Chương trình sử dụng vđk 16F877 
 #include 
#BIT, #BYTE, #LOCATE, #DEFENE 
#BIT 
Cú pháp: #BIT id = x. y 
id: tên biến, x: biến (8, 16, 32, bit) hay hằng số địa chỉ thanh ghi. 
y: vị trí bit trong x 
Tạo biến 1 bit đặt ở byte x vị trí bit y, tiện dùng kiểm tra hay gán trị cho bit 
thanh ghi. Điểm khác biệt so với dùng biến 1 bit từ khai báo int1 là: int1 tốn 1 bit bộ 
nhớ, đặt ở thanh ghi đa mục đích nào đó do CCS tự chọn, còn #BIT thì không tốn 
thêm bộ nhớ do id chỉ là danh định đại diện cho bit chỉ định ở biến x, thay đổi giá trị 
id (0 / 1) sẽ thay đổi giá trị bit tương ứng y do đó thay đổi trị x. 
VD: 
Int16 a=35; //a=00000000 00100011 
#bit b= a. 11 //b=0 
#BYTE 
Cú pháp: #BYTE id = x 
X: địa chỉ, id: tên biến 
THIẾT KẾ HỆ THỐNG NHÚNG 
 24 
Gán tên biến id cho địa chỉ (thanh ghi) x, sau đó muốn gán hay kiểm tra địa chỉ 
x chỉ cần dùng id. Không tốn thêm bộ nhớ, tên id thường dùng tên gợi nhớ chức 
năng thanh ghi ở địa chỉ đó. Lưu ý rằng giá trị thanh ghi có thể thay đổi bất kỳ lúc 
nào do hoạt động chương trình nên giá trị id cũng tự thay đổi theo giá trị thanh ghi 
đó. Không nên dùng id cho thanh ghi đa mục đích như 1 cách dùng biến int8 vì 
CCS có thể dùng các thanh ghi này bất kỳ lúc nào cho chương trình, nếu muốn dùng 
riêng, hãy dùng #LOCATE. 
VD: 
#byte port_b = 0xc6; // 16F877:0xc6 là địa chỉ portb 
Muốn port b có giá trị 120 thì: port_b=120; 
#byte status = 0xc3 
#LOCATE 
Cú pháp: #LOCATE id = x 
Làm việc như #byte nhưng có thêm chức năng bảo vệ không cho CCS sử dụng 
địa chỉ đó vào mục đích khác. 
VD: # LOCATE temp = 0xc20 // 0xc20:thanh ghi đa mục đích 
#DEFINE 
Cú pháp: #DEFINE id text 
Text: chuỗi hay số. Dùng định nghĩa giá trị. 
VD: #define a 12345 
# DEVICE 
Cú pháp: #DEVICE chip option 
chip: tên VĐK sử dụng, không dùng tham số này nếu đã khai báo tên chip ở # 
include. 
option: toán tử tiêu chuẩn theo từng chip: 
 * = 5 dùng pointer 5 bit (tất cả PIC) 
 * = 8 dùng pointer 8 bit (PIC14 và PIC18) 
 * = 16 dùng pointer 16 bit (PIC14, PIC 18) 
 ADC = x sử dụng ADC x bit (8, 10,... bit tuỳ chip), khi dùng hàm read_adc (), 
sẽ trả về giá trị x bit. 
 ICD = true: tạo mã tương thích debug phần cứng Microchip 
 HIGH_INTS = TRUE : cho phép dùng ngắt ưu tiên cao 
- Khai báo pointer 8 bit, bạn sử dụng được tối đa 256 byte RAM cho tất cả biến 
chương trình. 
- Khai báo pointer 16 bit, bạn sử dụng được hết số RAM có của VDK 
- Chỉ nên dùng duy nhất 1 khai báo #device cho cả pointer và ADC. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 25 
VD: #device * = 16 ADC = 10 
# ORG 
Cú pháp: 
#org start, end 
#org segment 
#org start, end { } 
Start, end: bắt đầu và kết thúc vùng ROM dành riêng cho hàm theo sau, hoặc để 
riêng không dùng 
VD: 
Org 0x30, 0x1F 
Void xu_ly () 
{ 
} // hàm này bắt đầu ở địa chỉ 0x30 
org 0x1E00 
anotherfunc () 
{ 
} //hàm này bắt đầu tuỳ ý ở 0x1E00 đến 0x1F00 
Org 0x30, 0x1F { } 
// không có gì cả đặt trong vùng ROM này, thường thì không dùng ORG. 
#USE 
#USE delay (clock = speed) 
Speed: giá trị OSC mà bạn dùng. VD: dùng thạch anh dao động 40Mhz thì: #use 
delay (clock = 40000000) 
Chỉ khi có chỉ thị này thì trong chương trình bạn mới được dùng hàm delay_us 
() và delay_ms (). 
#USE fast_io (port) 
Port: là tên port:từ A-G (tuỳ chip) 
Dùng cái này thì trong chương trình khi dùng các lệnh io như output_low (),  
nó sẽ set chỉ với 1 lệnh, nhanh hơn so với khi không dùng chỉ thị này. 
Trong hàm main () bạn phải dùng hàm set_tris_x () để chỉ rõ chân vào ra thì chỉ 
thị trên mới có hiệu lực, không thì chương trình sẽ chạy sai. 
Không cần dùng nếu không có yêu cầu gì đặc biệt. 
VD: # use fast_io (A) 
#USE I2C (options) - thiết lập giao tiếp I2C. 
Option bao gồm các thông số sau, cách nhau bởi dấu phẩy: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 26 
Master : chip ở chế độ master 
Slave : chip ở chế độ slave 
SCL = pin : chỉ định chân SCL 
SDA = pin : chỉ định chân SDA 
ADDRESS = x : chỉ định địa chỉ chế độ slave 
FAST : chỉ định FAST I2C 
SLOW : chỉ định SLOW I2C 
RESTART_WDT: restart WDT trong khi chờ I2C_READ () 
FORCE_HW : sử dụng chúc năng phần cứng I2C (nếu chip hỗ trợ) 
VD: 
#use I2C (master, sda=pin_B0, scl = pin_B1) 
#use I2C (slave, sda= pin_C4, scl= pin_C3, address = 0xa00, FORCE_HW) 
#USE RS232 (options) 
Thiết lập giao tiếp RS232 cho chip (có hiệu lực sau khi nạp chương trình cho 
chip, không phải giao tiếp RS232 đang sử dụng để nạp chip). 
Option bao gồm: 
BAUD = x : thiết lập tốc độ baud rate: 19200, 38400, 9600,... 
PARITY = x : x= N, E hay O, với N: không dùng bit chẵn lẻ. 
XMIT = pin : set chân transmit (chuyển data) 
RCV = pin : set chân receive (nhận data) 
- Các thông số trên là những thông hay dùng nhất, các tham số khác sẽ bổ sung 
sau. 
VD: 
#use rs232 (baud=19200, parity=n, xmit=pin_C6, rcv=pin_C7) 
2.4. Mẫu chương trình cho lập trình CCS 
a) Mô tả một số nội dung tiền xử lý 
#include16f877a. h:Đikèmchươngtrìnhdịch, chứakhaibáovềcácthanhghitrong 
mỗi con PIC, dùng cho việc cấuhình cho PIC. 
#include def_877a. h: Files do người lập trình tạo ra, chứa khai báo về 
cácthanhghitrongPICgiúpchoviêclậptrìnhđượcdễdanghơnvídụtacothểgánPORTB=0
xAA (chi tiết files này sẽ trình bày trong phần dưới đây) 
#device *=16 ADC = 10: Khai báo dùng con trỏ 8 hay 16 bit, bộ ADC là 8 hay 
10 bit 
#FUSES NOWDT, HS: Khai báovề cấu hình cho PIC 
THIẾT KẾ HỆ THỐNG NHÚNG 
 27 
#use delay (clock=20000000) : Tần số thạch anh sử dụng 
#use rs232 (baud=9600, ) : Khai báo cho giao tiếp nốitiếp RS232 
#use i2c (master, SDA=PIN_C4, ) : Khai báo dùng I2C, chế độ hoạt động 
#include :Khai báo các files thư việnđược sử dụng vídụ 
LCD_lib_4bit. c 
#INT_xxx: Khai báo địa chỉ chương trình phục vụ ngắt 
Void tên_chương_trình (tên_biến) {}: Chương trình chínhhay chươngtrình con 
b) Viết chương trình trong CCS 
Đầu tiên là chỉ thị tiền xử lý #... có nhiệm vụ báo cáo cho CCS cần sử dụng 
những gì trong chương trình: Dùng loại chip nào, dùng ADC hay không? Sử dụng 
thạch anh.... 
Khai báo các biến 
Chương trình con: Có hoặc không 
Các hàm phục vụ ngắt theo sau bởi một tiền xử lý cho biết dùng ngắt nào: Nếu 
sử dụng ngắt 
Chương trình chính 
Chương trình được thể hiện qua đoạn code sau: 
#include 
#device PIC6f877*=16 ADC = 10 
#use delay (clock = 20000000) 
.............. 
Int 16 a, b; 
Void CTC_ADC () 
{ 
............. 
} 
# INT_TIMER1 
Void ngat_timer () 
{ 
.......... 
} 
Main () 
{ 
............ 
} 
THIẾT KẾ HỆ THỐNG NHÚNG 
 28 
Vi dụ 
//#include"E:\TES PIC_HIEU\NGAT\ngat timer0\ctrinh. h" 
#include 
#include 
#device *=16 adc=8 
#use delay (clock=4000000) // su dung thach anh 20mhz 
#use fast_io (b) // dung voi cac lenh nhu output_low... nhanh hon binh thuong 
#byte portb=0x06 
#byte portd=0x08 
 int16 count; 
 int8 a; 
 // chuong trinh ngat ngat timer0 
 #int_timer0 // cho phep vao ngat timer0 
 void interrupt_timer0 () 
 { 
 //set_timer0 (6) ;//T_dinhthi = 2* (256 - 6) *1us = 500us 
 ++count; 
 if (count==2000) //2000*500=1s 
 {count=0; 
 rotate_left (&a, 1) ; //xuay bien a 1 lan 1 bit 
 } 
 } 
 // chuong trinh chinh 
 void main () 
 { 
 set_tris_d (0) ; //cong B la cong xuat 
 enable_interrupts (int_timer0) ; //cho phep ngat timer0 hoat dong 
 setup_timer_0 (rtcc_internal|rtcc_div_2) ; //chon xung clock noi va chia tan 
 enable_interrupts (global) ; //cho phep tat ca ngat hoat dong 
 set_timer0 (6) ; 
 a=0x01; 
 while (true) 
 { portd=a; } 
 } 
THIẾT KẾ HỆ THỐNG NHÚNG 
 29 
Bài 3 
LẬP TRÌNH VÀO RA SỐ 
3.1. Các hàm xử lý bit và các phép toán 
3.1.1. Hàm Shift_left, Shift_right 
Cú pháp: Shift_right (address, byte, value) 
 Shift_left (address, byte, value) 
Chức năng Dịch phải (trái) 1 bit vào 1 mảng hay 1 cấu trúc. Địa chỉ có thể là địa 
chỉ mảng hay địa chỉ trỏ tới cấu trúc (kiểu như &data). Bit 0 byte thấp nhất là LSB. 
3.1.2. Hàm Bit_set, Bit_clear 
Cú pháp: Bit_set (var, bit) 
Dùng set=1 bit được chỉ định bởi vị trí bit trong biến var 
 Bit_clear (var, bit) 
dùng xóa (set = 0) bit được chỉ định bởi vị trí bit trong biến var. 
var: biến 8, 16, 32 bit bất kỳ. 
bit: vị trí clear (set) : từ 0-7 (biến 8 bit), 0-15 (biến 16 bit), 0-31 (biến 32 bit). 
Hàm không trả về trị. 
VD: 
Int x; 
x=11; //x=1011 
Bit_clear (x, 1) ; // x= 1001b = 9 
3.1.3. Hàm Bit_test 
- Cú pháp: Bit_test (var, bit) 
- Tác dụng: Dùng kiểm tra vị trí bit trong biến var. 
- Hàm trả về 0 hay 1 là giá trị bit đó trong var. 
- var: biến 8, 16, 32 bit. 
- bit: vị trí bit trong var. 
Ví dụ: 
Giả sử có biến x 32 bit đếm từ 0 lên và muốn kiểm tra xem nó có lớn hơn 4096 
không (4096= 2^12 =1000000000000b) : 
If (x >= 4096)... // phép kiểm tra này mất ~5 us 
Trong 1 vòng lặp, việc kiểm tra thường xuyên như vậy sẽ làm mất 1 thời gian 
đáng kể. Để tối ưu, chỉ cần dùng: 
if (bit_test (x, 12) ) : chỉ mất ~ 0. 4 us. (20 Mhz thạch anh). 
Do đó việc kiểm tra đếm lên tới những giá trị đặc biệt (2^ i) thì dùng hàm này 
rất tiện lợi. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 30 
3.1.4. Hàm Swap 
- Cú pháp: Swap (var) 
- var: biến 1 byte 
- Hàm này đảo vị trí 4 bit trên với 4 bit dưới của var, tương đương var = 
(var>>4) | (var << 4) 
- Hàm không trả về trị. 
VD: 
X= 5; //x=00000101b 
Swap (x) ; //x = 01010000b = 80 
3.1.5. Hàm Make8 
- Cú pháp: Make8 (var, offset) 
- Hàm này trích 1 byte từ biến var. 
- var: biến 8, 16, 32 bit. 
- offset: là vị trí của byte cần trích (0, 1, 2, 3). 
- Hàm trả về giá trị byte cần trích. 
VD: 
Int16 x = 1453; // x=0x5AD 
Y = Make (x, 1) ; //Y= 5 = 0x05 
3.1.6. Hàm Make16 
- Cú pháp: Make16 (varhigh, varlow) 
- Tác dung: Hàm trả về giá trị 16 bit kết hợp từ 2 biến 8 bit varhigh và varlow 
Byte cao là varhigh, thấp là varlow 
3.1.7. Make32 
- Cú pháp: Make32 (var1, var2, var3, var4) 
- Trả về giá trị 32 bit kết hợp từ các giá trị 8 bit hay 16 bit từ var1 tới var4. 
Trong đó var2 đến var4 có thể có hoặc không. Giá trị var1 sẽ là MSB, kế tiếp là 
var2,... Nếu tổng số bit kết hợp ít hơn 32 bit thì 0 được thêm vào MSB cho đủ 32 
bit. 
VD: 
Int a=0x01, b=0x02, c=0x03, d=0x04; // các giá trị hex 
Int32 e; 
e = make32 (a, b, c, d) ; // e = 0x01020304 
e = make32 (a, b, c, 5) ; // e = 0x01020305 
e = make32 (a, b, 8) ; // e = 0x00010208 
THIẾT KẾ HỆ THỐNG NHÚNG 
 31 
e = make32 (a, 0x1237) ; // e = 0x00011237 
3.2. Các hàm vào ra 
3.2.1. Output_low (pin), Output_high (pin) 
- Tác dụng: 
+ Dùng thiết lập mức 0 (low, 0V) hay mứ c 1 (high, 5V) cho chân IC, pin chỉ vị 
trí chân, 
+ Hàm sẽ đặt pin làm ngõ ra. 
+ Hàm này dài 2-4 chu kỳ máy. Cũng có thể xuất xung dùng set_tris_X () và 
#use fast_io. 
Ví dụ: 
Chương trình sau xuất xung vuông chu kỳ 500ms, duty =50% ra chân B0, nối 
B0 với 1 led sẽ làm nhấp nháy led. 
#include 
#use delay (clock=20000000) 
Main () 
{ while (1) 
 { output_high (pin_B0) ; 
 Delay_ms (250) ; // delay 250ms 
 Output_low (pin_B0) ; 
Delay_ms (250) ; 
 } 
} 
3.2.2. Output_bit (pin, value) 
- Pin: tên chân của vi điều khiển 
- value: có giá trị 0 hoặc 1 
- Hàm này cũng xuất giá trị 0 / 1 trên pin, tương tự 2 hàm trên. Thường dùng nó 
khi giá trị ra tuỳ thuộc giá trị biến 1 bit nào đó, hay muốn xuất đảo của giá trị ngõ ra 
trước đó. 
Ví dụ: 
Khai báo int1 x; // x mặc định = 0 
Trong hàm main: 
Main () 
{ while (1) 
{ output_bit (pin_B0, !x) ; 
 Delay_ms (250) ; 
THIẾT KẾ HỆ THỐNG NHÚNG 
 32 
 } 
} 
Chương trình trên cũng xuất xung vuông chu kỳ 500ms, duty =50% 
3.2.3. Input (pin) 
Hàm này trả về giá trị 0 hay 1 là trạng thái của chân IC và có giá trị là 1 bit 
3.2.4. Output_X (value) 
- X là tên port có trên chip. 
- Value là giá trị 1 byte. 
- Hàm này xuất giá trị 1 byte ra port. Tất cả chân của port đó đếu là ngõ ra. 
Ví dụ: 
Output_B (212) ; // xuất giá trị 11010100 ra port B 
3.2.5. Input_X () 
- X: là tên port (a, b, c, d e) của PIC 
- Hàm này trả về giá trị 8 bit là giá trị đang hiện hữu của port đó. 
Ví dụ: m=input_E () ; 
3.2.6. Port_B_pullups 
- Hàm này thiết lập ngõ vào port B pullup. Value =1 sẽ kích hoạt tính năng này 
và value =0 sẽ ngừng. 
- Chỉ các chip có port B có tính năng này mới dùng hàm này. 
3.2.7. Set_tris_X (value) 
- Hàm này định nghĩa chân IO cho 1 port là ngõ vào hay ngõ ra. Chỉ được dùng 
với #use fast_IO. Sử dụng #byte để tạo biến chỉ đến port và thao tác trên biến này 
chính là thao tác trên port. 
- Value là giá trị 8 bit. Mỗi bit đại diện 1 chân và bit=0 sẽ set chân đó là ngõ 
vào, bit= 1 set chân đó là ngõ ra. 
Ví dụ: 
Chương trình sau cho phép thao tác trên portB: 
#include 
#use delay (clock=20000000) 
#use Fast_IO (B) 
#byte portB = 0x6 // 16F877 có port b ở địa chỉ 6h 
#bit B0 = portB. 0 // biến B0 chỉ đến chân B0 
#bit B1=portB. 1 // biến B1 chỉ đến chân B1 
#bit B2=portB. 2 // biến B2 chỉ đến chân B2 
THIẾT KẾ HỆ THỐNG NHÚNG 
 33 
#bit B3=portB. 3 // biến B3 chỉ đến chân B3 
#bit B4=portB. 4 // biến B4 chỉ đến chân B4 
#bit B5=portB. 5 // biến B5 chỉ đến chân B5 
#bit B6=portB. 6 // biến B6 chỉ đến chân B6 
#bit B7=portB. 7 // biến B7 chỉ đến chân B7 
Main () 
{ set_tris_B (126) ; //portB=01111110 b 
// B0 là ngõ vào, thường làm ngắt ngoài 
//B1... B6 là ngõ ra, ví dụ làm 6 ngõ ra điều chế PWM 
//B7 là ngõ vào, Vd là nhận tín hiệu cho phép chẳng hạn 
 if (B7) //nếu ngõ vào chân B7 là 1 thì xuất 3 cặp xung đối nghịch 
 { B1 = 1; 
 B2 = 0; 
 B3 = 1; 
 B4 = 0; 
 B5 = 1; 
 B6 = 0; 
 } 
 Else B1=B2=B3=B4=B5=B6= 0; 
} 
Chú ý: 
- Set_tris_B (0) : port B =00000000: tất cả chân portB là ngõ ra 
- Set_tris_B (1) : portB = 00000001: chỉ B0 là ngõ vào, còn lại là ngõ ra 
- Set_tris_B (255) : portB=11111111: tất cả chân portB là ngõ vào 
3.3. Lập trình vào ra với led đơn, led 7 thanh và bàn phím 
- Sử dụng hàm set_tris_X () để thiết lập trạng thái cho cổng ứng dụng cho 
việc nhập hay xuất. Nếu đường tín hiệu vào phải thiết lập “1”, đường ra 
phải thiết lập “0”. 
- Với LED đơn thực hiện bật tắt theo 2 phương pháp: active “1” và active 
“0” tùy theo cách ghép nối LED. 
- LED 7 thanh có thể điều khiển theo 2 phương pháp là quét từng thanh 
hoặc sử dụng IC chuyên dụng để chốt tín hiệu cho từng thanh. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 34 
Bài 4 
THỰC HÀNH: LẬP TRÌNH VÀO RA SỐ 
Chi tiết theo cuốn bài tập thực hành 
Bài 5 
LẬP TRÌNH VÀO RA TƯƠNG TỰ 
5.1. Bộ chuyển đổi ADC và DAC 
5.1.1 Tổng quan 
Trong các ứng dụng đo lường và điều khiển bằng vi điều khiển bộ chuyển đổi 
tương tự-số là một thành phần rất quan trọng. Dữ liệu trong thực tế là các dữ liệu 
tương tự (analog). Ví dụ nhiệt độ không khí buổi sáng là 250C và buổi trưa là 320C, 
giữa hai mức giá trị này có vô số các giá trị liên tục mà nhiệt độ phải “đi qua” để có 
thể đạt mức 320 C từ 250C, đại lượng nhiệt độ như thế gọi là một đại lượng analog. 
Trong khi đó, rõ ràng vi điều khiển là một thiết bị số (digital), các giá trị mà một vi 
điều khiển có thể thao tác là các con số rời rạc vì thực chất chúng được tạo thành từ 
sự kết hợp của hai mức 0 và 1. Ví dụ chúng ta muốn dùng một thanh ghi 8 bit trong 
vi điều khiển để lưu lại các giá trị nhiệt độ từ 00 C đến 2550C, như chúng ta đã biết, 
một thanh ghi 8 bit có thể chứa tối đa 256 (28) giá trị nguyên từ 0 đến 255, như thế 
các mức nhiệt độ không nguyên như 28. 123 0C sẽ không được ghi lại. Nói cách 
khác, chúng ta đã “số hóa” (digitalize) một dữ liệu analog thành một dữ liệu số 
(digital signal). Quá trình “số hóa” này thường được thực hiện bởi một thiết bị gọi 
là “bộ chuyển đổi tương tự - số” hay gọi tắt là ADC (Analog to Digital Converter). 
Có rất nhiều phương pháp chuyển đổi ADC trong đó phương pháp chuyển đổi 
trực tiếp (direct converting) hoặc flash ADC là phương pháp cơ bản nhất. Các bộ 
chuyển đổi ADC theo phương pháp này được cấu thành từ một dãy các bộ so sánh, 
các bộ so sánh được mắc song song và được kết nối trực tiếp với tín hiệu analog cần 
chuyển đổi. Một điện áp tham chiếu (reference) và một mạch chia áp được sử dụng 
để tạo ra các mức điện áp so sánh khác nhau cho mỗi bộ so sánh. Hình dưới mô tả 
một bộ chuyển đổi flash ADC có 4 bộ so sánh, Vin là tín hiệu analog cần chuyển 
đổi và giá trị sau chuyển đổi là các con số tạo thành từ sự kết hợp các mức nhị phân 
trên các chân Vo. Trong hình dưới, ta thấy rằng do ảnh hưởng của mạch chia áp 
(các điện trở mắc nối tiếp từ điện áp +15V đến ground), điện áp trên chân âm của 
các bộ so sánh sẽ khác nhau. Trong lúc chuyển đổi, giả sử điện áp Vin lớn hơn điện 
áp “V-“ của bộ so sánh 1 (opamp ở phía thấp nhất trong mạch) nhưng lại nhỏ hơn 
điện áp V- của các bộ so sánh khác, khi đó ngõ Vo1 ở mức 1 và các ngõ Vo khác ở 
THIẾT KẾ HỆ THỐNG NHÚNG 
 35 
mức 0, chúng ta thu được một kết quả số. Một cách tương tự, nếu tăng điện áp Vin 
ta thu được các tổ hợp số khác nhau. Với mạch điện có 4 bộ so sánh như trong hình 
1, sẽ có tất cả 5 trường hợp có thể xảy ra, hay nói theo cách khác điện áp analog Vin 
được chia thành 5 mức số khác nhau. Tuy nhiên, chú ý là các ngõ Vo không phải là 
các bit của tín hiệu số ngõ ra, chúng chỉ là đại diện để tổ hợp thành tín hiệu số ngõ 
ra, dễ hiểu hơn chúng ta không sử dụng được các bit Vo trực tiếp mà cần một bộ 
giải mã (decoder). 
Hình 18: Mạch flash ADC với 4 bộ so sánh 
Bảng 1: Giá trị số ngõ ra sau khi giải mã 
5.1.2. Độ phân giải 
Như trong ví dụ trên, nếu mạch điện có 4 bộ so sánh, ngõ ra digital sẽ có 5 mức 
giá trị. Tương tự nếu mạch điện có 7 bộ so sánh thì sẽ có 8 mức giá trị có thể ở ngõ 
ra digital, khoảng cách giữa các mức tín hiệu trong trường hợp 8 mức sẽ nhỏ hơn 
trường hợp 4 mức. Nói cách khác, mạch chuyển đổi với 7 bộ so sánh có giá trị 
THIẾT KẾ HỆ THỐNG NHÚNG 
 36 
digital ngõ ra “mịn” hơn khi chỉ có 4 bộ, độ “mịn” càng cao tức độ phân giải 
(resolution) càng lớn. Khái niệm độ phân giải được dùng để chỉ số bit cần thiết để 
chứa hết các mức giá trị digital ngõ ra. Trong trường hợp có 8 mức giá trị ngõ ra, 
chúng ta cần 3 bit nhị phân để mã hóa hết các giá trị này, vì thế mạch chuyển đổi 
ADC với 7 bộ so sánh sẽ có độ phân giải là 3 bit. Một cách tổng quát, nếu một 
mạch chuyển đổi ADC có độ phân giải n bit thì sẽ có 2n mức giá trị có thể có ở ngõ 
ra digital. Để tạo ra một mạch chuyển đổi flash ADC có độ phân giải n bit, chúng ta 
cần đến 2n-1 bộ so sánh, giá trị này rất lớn khi thiết kế bộ chuyển đổi ADC có độ 
phân giải cao, vì thế các bộ chuyển đổi flash ADC thường có độ phân giải ít hơn 8 
bit. Độ phân giải liên quan mật thiết đến chất lượng chuyển đổi ADC, việc lựa chọn 
độ phân giải phải phù hợp với độ chính xác yêu cầu và khả năng xử lý của bộ điều 
khiển. Trong hình phía dưới mô tả một ví dụ “số hóa” một hàm sin analog thành 
dạng digital. 
Hình 19: Minh họa tín hiệu Analog và digital của hàm sin 
5.1.3. Điện áp tham chiếu 
Cùng một bộ chuyển đổi ADC nhưng có người muốn dùng cho các mức điện áp 
khác nhau, ví dụ người A muốn chuyển đổi điện áp trong khoảng 0-1V trong khi 
người B muốn dùng cho điện áp từ 0V đến 5V. Rõ ràng nếu hai người này dùng 2 
bộ chuyển đổi ADC đều có khả năng chuyển đổi đến điện áp 5V thì người A đang 
“phí phạm” tính chính xác của thiết bị. Vấn đề sẽ được giải quyết bằng một đại 
lượng gọi là điện áp tham chiếu - Vref (reference voltage). 
Điện áp tham chiếu thường là giá trị điện áp lớn nhất mà bộ ADC có thể chuyển 
đổi. Trong các bộ ADC, Vref thường là thông số được đặt bởi người dùng, nó là 
điện áp lớn nhất mà thiết bị có thể chuyển đổi. Ví dụ, một bộ ADC 10 bit (độ phân 
giải) có Vref=3V, nếu điện áp ở ngõ vào là 1V thì giá trị số thu được sau khi chuyển 
đổi sẽ là: 1023x (1/3) =314. Trong đó 1023 là giá trị lớn nhất mà một bộ ADC 10 
bit có thể tạo ra (1023=210-1). Vì điện áp tham chiếu ảnh hưởng đến độ chính xác 
của quá trình chuyển đổi, chúng ta cần tính toán để chọn 1 điện áp tham chiếu phù 
hợp, không được nhỏ hơn giá trị lớn nhất của input nhưng cũng đừng quá lớn. 
5.2. Bộ chuyển đổi ADC trong PIC 
THIẾT KẾ HỆ THỐNG NHÚNG 
 37 
Các bộ ADC trong vi điều khiển nói chung và trong PIC nói riêng có độ phân 
giải khác nhau, có thể là 10bit, 12bit, 16bit, 24bit... Tốc độ lấy mẫu trong ADC 
nhanh hay chậm, tùy từng ứng dụng mà ta chọn tốc độ cho thích hợp. 
Với vi điều khiển PIC là một trong những dòng vi điều khiển có phần giao tiếp 
ngoại vi mạnh và đa dạng. Bên trong PIC đã tích hợp sẵn một bộ ADC thường có 
độ phân giải là 8bit hay 10bit (có thể cao hơn tùy dòng PIC). 
5.2.1. ADC trong PIC 16F877A 
PIC16F877A có 8 ngõ vào analog (RA4:RA0 và RE2:RE0). Hiệu điện thế chuẩn 
VREF có thể được lựa chọn là VDD, VSS hay hiệu điện thể chuẩn được xác lập 
trên hai chân RA2 và RA3. Kết quả chuyển đổi từ tín tiệu tương tự sang tín hiệu số 
là 10 bit số tương ứng và được lưu trong hai thanh ghi ADRESH:ADRESL. Khi 
không sử dụng bộ chuyển đổi ADC, các thanh ghi này có thể được sử dụng như các 
thanh ghi thông thường khác. Khi quá trình chuyển đổi hoàn tất, kết quả sẽ được lưu 
vào hai thanh ghi ADRESH:ADRESL, bit (ADCON0) được xóa về 0 và cờ ngắt 
ADIF được set. 
Quy trình chuyển đổi từ tương tự sang số bao gồm các bước sau: 
1. Thiết lập các thông số cho bộ chuyển đổi ADC: 
- Chọn ngõ vào analog, chọn điện áp mẫu (dựa trên các thông số của 
thanh ghi ADCON1) 
- Chọnh kênh chuyển đổi AD (thanh ghi ADCON0) 
- Chọn xung clock cho kênh chuyển đổi AD (thanh ghi ADCON0) 
- Cho phép bộ chuyển đổi AD hoạt động (thanh ghi ADCON0) 
2. Thiết lập các cờ ngắt cho bộ AD 
- Clear bit ADIF 
- Set bit ADIE 
- Set bit PEIE 
- Set bit GIE 
3. Đợi cho tới khi quá trình lấy mẫu hoàn tất 
4. Bắt đầu quá trình chuyển đổi (set bit) 
5. Đợi cho tới khi quá trình chuyển đổi hoàn tất bằng cách: 
- Kiểm tra bit. Nếu =0, quá trình chuyển đổi đã hoàn tất 
- Kiểm tra cờ ngắt 
6. Đọc kết quả chuyển đổi và xóa cờ ngắt, set bit (nếu cần tiếp tục chuyển 
đổi) 
7. Tiếp tục thực hiện các bước 1 và 2 cho quá trình chuyển đổi tiếp theo 
THIẾT KẾ HỆ THỐNG NHÚNG 
 38 
Hình 20: Sơ đồ khối bộ chuyển đổi ADC 
Cần chú ý là có hai cách lưu kết quả chuyển đổi AD, việc lựa chọn cách lưu 
được điều khiển bởi bit ADFM và được minh họa cụ thể trong hình sau: 
Hình 21: Các cách lưu kết quả chuyển đổi ADC 
Các thanh ghi liên quan đến bộ chuyển đổi ADC bao gồm: 
- INTCON (địa chỉ 0Bh, 8Bh, 10Bh, 18Bh) : cho phép các ngắt (các bit 
GIE, PEIE). 
THIẾT KẾ HỆ THỐNG NHÚNG 
 39 
- PIR1 (địa chỉ 0Ch) : chứa cờ ngắt AD (bit ADIF). 
- PIE1 (địa chỉ 8Ch) : chứa bit điều khiển AD (ADIE). 
- ADRESH (địa chỉ 1Eh) và ADRESL (địa chỉ 9Eh) : các thanh ghi 
chứa kết quả chuyển đổi AD. 
- ADCON0 (địa chỉ 1Fh) và ADCON1 (địa chỉ 9Fh) : xác lập các thông 
số cho bộ chuyển đổi AD. 
- PORTA (địa chỉ 05h) và TRISA (địa chỉ 85h) : liên quan đến các ngõ 
vào analog ở PORTA. 
- PORTE (địa chỉ 09h) và TRISE (địa chỉ 89h) : liên quan đến các ngõ 
vào analog ở PORTE. 
5.2.2. Cấu hình bộ ADC trong CCS 
Thông dụng nhất khi dùng ADC là sử dụng 1 biến trở, điều chỉnh bởi 1 nút vặn, 
qua đó thu được 1 điện áp nhỏ hơn điện áp tham chiếu (Vref – áp max), đưa vào 
chân biến đổi ADC, kết quả cho 1 giá trị số ADC 8 bit (0-255) hay ADC 10 bit (0-
1023). Thường thì áp Vref lấy bằng Vdd (5V). Trên các PIC có ngõ AVdd và AVss 
(PIC 18), thường thì bạn luôn nối AVdd tới Vdd, AVss tới Vss để đảm bảo họat 
động cho lập trình qua ICD 2. 
Các hàm phục vụ ADC 
Setup_ADC (mode) : Không trả về giá trị. Dùng xác định cách thức hoạt động 
bộ biến đổi ADC. Tham số mode tuỳ thuộc file thiết bị *. h có tên tương ứng tên 
chip bạn đang dùng, nằm trong thư mục DEVICES của CCS. Muốn biết có bao 
nhiêu tham số có thể dùng cho chip đó, ta có thể mở file tương ứng đọc, tìm tới chỗ 
các định nghĩa cho chức năng ADC dùng cho chip đó tương ứng với hàm này. Sau 
đây là các giá trị mode của 16F877, (1 số khác có thể không có hoặc có thêm như 
16F877A có thêm 1 số thứ là ADC_CLOCK_DIV_2/4/8/16/32/64... ) : 
- ADC_OFF: Tắt hoạt động ADC (tiết kiệm điện, dành chân cho hoạt 
động khác). 
- ADC_CLOCK_INTERNAL: thời gian lấy mẫu bằng xung clock IC 
(mất 2-6 us) thường là chung cho các chip. 
- ADC_CLOCK_DIV_2: thời gian lấy mẫu bằng xung clock / 2 (mất 0. 
4 us trên thạch anh 20MHz) 
- ADC_CLOCK_DIV_8: thời gian lấy mẫu bằng xung clock / 8 
(1. 6 us) 
- ADC_CLOCK_DIV_32 : thời gian lấy mẫu bằng xung clock / 32 
(6. 4 us) 
Setup_ADC_ports (value) : Xác định chân lấy tín hiệu analog và điện thế 
chuẩn sử dụng. Tùy thuộc bố trí chân trên chip, số chân và chân nào dùng cho ADC 
THIẾT KẾ HỆ THỐNG NHÚNG 
 40 
và số chức năng ADC mỗi chip mà value có thể có những giá trị khác nhau. Xem 
file tương ứng trong thư mục DEVICES để biết số chức năng tương ứng chip đó. 
Để tương thích chương trình viết cho phiên bản cũ, 1 số tham số có 2 tên khác nhau 
(nhưng cùng 15 chức năng do định nghĩa cùng địa chỉ). 
Lưu ý: 
- Vref: áp chuẩn, 
- Vdd: áp nguồn. 
Sau đây là các giá trị cho value (chỉ dùng 1 trong các giá trị) của 16F877: 
- ALL_ANALOGS: dùng tất cả chân sau làm analog: A0 A1 A2 A3 A5 
E0 E1 E2 (Vref=Vdd) 
- NO_ANALOG: không dùng analog, các chân đó sẽ là chân I /O. 
- AN0_AN1_AN2_AN4_AN5_AN6_AN7_VSS_VREF : A0 A1 A2 
A5 E0 E1 E2 VRefh=A3 
- AN0_AN1_AN2_AN3_AN4: A0 A1 A2 A3 A5 (tên thì giống nhau 
cho tất cả thiết bị nhưng 16F877 chỉ có portA có 5 chân nên A0, A1, 
A2, A5 được dùng, A6, A7 không có) 
- AN0_AN1_AN3: A0 A1 A3, Vref = Vdd 
- AN0_AN1_VSS_VREF: A0 A1 VRefh = A3 
- AN0_AN1_AN4_AN5_AN6_AN7_VREF_VREF : A0 A1 A5 E0 E1 
E2 VRefh=A3, VRefl=A2. 
- AN0_AN1_AN2_AN3_AN4_AN5: A0 A1 A2 A3 A5 E0 
- AN0_AN1_AN2_AN4_AN5_VSS_VREF : A0 A1 A2 A5 E0 
VRefh=A3 
- AN0_AN1_AN4_AN5_VREF_VREF: A0 A1 A5 E0 VRefh=A3 
VRefl=A2 
- AN0_AN1_AN4_VREF_VREF: A0 A1 A5 VRefh=A3 VRefl=A2 
- AN0_AN1_VREF_VREF: A0 A1 VRefh=A3 VRefl=A2 
- AN0: A0 
- AN0_VREF_VREF: A0 VRefh=A3 VRefl=A2 
Ví Dụ: 
setup_adc_ports (AN0_AN1_AN3) ; // A0, A1, A3 nhận analog, áp nguồn +5V 
cấp cho IC sẽ là điện áp chuẩn. 
Set_ADC_channel (channel) 
Chọn chân để đọc vào giá trị analog bằng lệnh Read_ADC (). Giá trị channel tuỳ 
số chân chức năng ADC mỗi chip. Với 16F877, channel có giá trị từ 0 -7: 0-chân 
A0, 1-chân A1, 2-chân A2, 3-chân A3 4-chân A5, 5-chân E0, 6-chân E1, 7-chân E2. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 41 
Hàm không trả về trị. Nên delay 10 us sau hàm này rồi mới dùng hàm 
read_ADC () để bảo đảm kết quả đúng. Hàm chỉ hoạt động với A /D phần cứng trên 
chip. 
Read_ADC (mode) 
Dùng đọc giá trị ADC từ thanh ghi (cặp thanh ghi) chứa kết quả biến đổi ADC. 
Lưu ý hàm này sẽ hỏi vòng cờ cho tới khi cờ này báo đã hoàn thành biến đổi ADC 
(sẽ mất vài us) thì xong hàm. Nếu giá trị ADC là 8 bit như khai báo trong chỉ thị 
#DEVICE, giá trị trả về của hàm là 8 bit, ngược lại là 16 bit nếu khai báo #DEVICE 
sử dụng ADC 10 bit trở lên. 
Khi dùng hàm này, nó sẽ lấy ADC từ chân bạn chọn trong hàm 
Set_ADC_channel () trước đó. Nghĩa là mỗi lần chỉ đọc 1 kênh Muốn đổi sang đọc 
chân nào, dùng hàm set_ADC_channel () lấy chân đó. Nếu không có đổi chân, dùng 
read_ADC () bao nhiêu lần cũng được. Mode có thể có hoặc không, bao gồm: 
- ADC_START_AND_READ: giá trị mặc định 
- ADC_START_ONLY: bắt đầu chuyển đổi và trả về 
- ADC_READ_ONLY: đọc kết quả chuyển đổi lần cuối 
#DEVCE 8 bit 10 bit 11 bit 16 bit 
- ADC=8 0-255 0-255 00-255 00-255 
- ADC=10 x 0-1023 x x 
- ADC=11 x x 0-2047 x 
- ADC=16 0-65280 0-65472 0-65504 0-65535 
Ví dụ: 
setup_adc (ADC_CLOCK_INTERNAL) ; 
setup_adc_ports (ALL_ANALOG) ; 
set_adc_channel (1) ; 
while (input (PIN_B0) ) 
{ 
 delay_ms (5000) ; 
 value = read_adc () ; 
 printf ("A/D value = %2x\n\r", value) ; 
} 
read_adc (ADC_START_ONLY) ; 
sleep () ; 
value=read_adc (ADC_READ_ONLY) ; 
THIẾT KẾ HỆ THỐNG NHÚNG 
 42 
Chú ý: trên PIC 18, cấu trúc ADC tương đối phức tạp, đa năng hơn như là cho 
phép lấy 2 mẫu cùng lúc,... cũng sử dụng với các hàm trên, có nhiều thông số trong 
file *. h. 
5.2.3. Lập trình ứng dụng 
Viết chương trình lấy ADC 8 bit, đọc và xuất ra dãy led được kết nối ở Port B và 
xuất ra màn hình máy tính. 
 Hình 22: Sơ đồ kết nối với vi điều khiển PIC 16F877 
Code chương trình: 
#include 
#use delay (clock=20000000) 
#device *= 16 ADC = 8 // sử dụng ADC 8 bit, giá trị ADC vào từ 0-255 
#use rs232 (baud=19200, parity=n, xmit=pin_C6, rcv=pin_C7) 
Int8 adc; 
Main () 
{ 
Setup_ADC (ADC_internal) ; 
Setup_ADC_ports (AN0) ; 
Set_ADC_channel (0) ; 
Delay_us (10) ; // delay 10 us 
While (true) 
{ adc = read_adc () ; 
THIẾT KẾ HỆ THỐNG NHÚNG 
 43 
 Output_B (adc) ; // xuat ra port B gia tri bien adc 
 Printf (“ gia tri adc la: %u “, adc) ; // in ra man hinh 
} 
Chú ý: Giá trị biến adc từ 0-255, khi thiết lập thông số truyền với máy tính phải 
trùng với thông số được khởi tạo ở đầu chương trình (ở ví dụ trên ta sẽ thiết lập tốc 
độ là 19200 như khai báo bên trên đầu chương trình). 
THIẾT KẾ HỆ THỐNG NHÚNG 
 44 
Bài 6 
THỰC HÀNH: LẬP TRÌNH VÀO RA TƯƠNG TỰ 
Chi tiết theo cuốn bài tập thực hành 
Bài 7 
LẬP TRÌNH VÀ XỬ LÝ NGẮT 
7.1. Tổng quan về ngắt trong PIC 16F877A 
PIC16F877A có đến 15 nguồn tạo ra hoạt động ngắt được điều khiển bởi thanh 
ghi INTCON (bit GIE). Bên cạnh đó mỗi ngắt còn có một bit điều khiển và cờ ngắt 
riêng. Các cờ ngắt vẫn được set bình thường khi thỏa mãn điều kiện ngắt xảy ra bất 
chấp trạng thái của bit GIE, tuy nhiên hoạt động ngắt vẫn phụ thuôc vào bit GIE và 
các bit điều khiển khác. Bit điều khiển ngắt RB0/INT và TMR0 nằm trong thanh 
ghi INTCON, thanh ghi này còn chứa bit cho phép các ngắt ngoại vi PEIE. Bit điều 
khiển các ngắt nằm trong thanh ghi PIE1 và PIE2. Cờ ngắt của các ngắt nằm trong 
thanh ghi PIR1 và PIR2. 
Trong một thời điểm chỉ có một chương trình ngắt được thực thi, chương trình 
ngắt được kết thúc bằng lệnh RETFIE. Khi chương trình ngắt được thực thi, bit GIE 
tự động được xóa, địa chỉ lệnh tiếp theo của chương trình chính được cất vào trong 
bộ nhớ Stack và bộ đếm chương trình sẽ chỉ đến địa chỉ 0004h. Lệnh RETFIE được 
dùng để thoát khỏi chương trình ngắt và quay trở về chương trình chính, đồng thời 
bit GIE cũng sẽ được set để cho phép các ngắt hoạt động trở lại. Các cờ hiệu được 
dùng để kiểm tra ngắt nào đang xảy ra và phải được xóa bằng chương trình trước 
khi cho phép ngắt tiếp tục hoạt động trở lại để ta có thể phát hiện được thời điểm 
tiếp theo mà ngắt xảy ra. 
Đối với các ngắt ngoại vi như ngắt từ chân INT hay ngắt từ sự thay đổi trạng 
thái các chân của PORTB (PORTB Interrupt on change), việc xác định ngắt nào xảy 
ra cần 3 hoặc 4 chu kỳ lệnh tùy thuộc vào thời điểm xảy ra ngắt. 
Cần chú ý là trong quá trình thực thi ngắt, chỉ có giá trị của bộ đếm chương trình 
được cất vào trong Stack, trong khi một số thanh ghi quan trọng sẽ không được cất 
và có thể bị thay đổi giá trị trong quá trình thực thi chương trình ngắt. Điều này nên 
được xử lí bằng chương trình để tránh hiện tượng trên xảy ra. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 45 
Hình 23: Sơ đồ logic của các ngắt trong PIC 16F877A 
7.2. Khai báo và sử dụng ngắt trong CCS 
Trong CCS ngắt được khai báo với các dòng lệnh sau: 
- enable_interrupts (level) ; //cho phép ngắt kiểu level 
- disable_interrupts (level) ; //cấm ngắt kiểu level 
- ext_int_edge (edge) ; // chọn cách lấy xung loại edge 
Level bao gồm: 
- GLOBAL: ngắt toàn cục 
- INT_RTCC: tràn TMR0 
- INT_RB: có thay đổi trạng thái một trong các chân RB4 đến RB7 
- INT_EXT: ngắt ngoài 
- INT_AD: chuyển đổi AD đã hoàn tất 
- INT_TBE: bộ đệm chuyển RS232 trống 
- INT_RDA: data nhận từ RS232 sẵn sàng 
- INT_TIMER1: tràn TMR1 
- INT_TIMER2: tràn TMR2 
- INT_CCP1: có capture hay compare trên CCP1 
- INT_CCP2: có capture hay compare trên CCP2 
- INT_SSP: có hoạt động SPI hay I2C 
- INT_PSP: có data vào cổng parallel slave 
- INT_BUSCOL: xung đột bus 
THIẾT KẾ HỆ THỐNG NHÚNG 
 46 
- INT_EEPROM: ghi vào eeprom hoàn tất 
- INT_TIMER0: tràn TMR0 
- INT_COMP: kiểm tra bằng nhau comparator 
Edge bao gồm: 
- L_TO_H: cạnh lên 
- H_TO_L: cạnh xuống 
Sau khai báo trên để vào đoạn chương trình ngắt, khai báo: 
 #INT_......... 
Ví dụ: 
Ví dụ 1: Viết chương trình sử dụng ngắt INT trong PIC hiển thị led đơn theo các 
trạng thái khác 
Hình 24: Ghép nối điều khiển LED đơn 
Code: 
 // CTRINH su dung ngat ngoai tren chan RB0 
 // Nhan 1 lan ctrinh 1 se chay, nhan lan 2 ctrinh 2 se chay, nhan lan 3 ctrinh 3 
chay 
 // nhan lien luc ba lan se chay lan luot ctrinh1, ctrinh2, ctrinh3 
#include 
#include 
 #device *=16 adc=8 
 #use delay (clock=20000000) // su dung thach anh 20mhz 
 #use fast_io (d) // dung voi cac lenh nhu output_low... nhanh hon binh thuong 
 #byte portb=0x06 
THIẾT KẾ HỆ THỐNG NHÚNG 
 47 
 #byte portd=0x08 
 int8 mode, i; 
 byte a; 
 //chuong trinh ngat 
 #int_ext // giup vao ngat 
 ngat_int () 
 { 
 mode++; 
 if (mode==4) 
 mode=0; 
 } 
 //khai bao ham nguyen mau cho chuong trinh con 
 void ctrinh1 () ; 
 void ctrinh2 () ; 
 void ctrinh3 () ; 
 // chuong trinh chinh 
void main () 
{ 
 set_tris_d (0) ; //cong D la cong xuat 
 trisb= (0XFF) ; 
 portd=0xff; // cong d o muc cao 
 enable_interrupts (int_ext) ; // cho phep ngat ngoai 
 ext_int_edge (h_to_l) ; //chon canh kich ngat la tu cao xuong thap 
 enable_interrupts (global) ; 
 mode=0; 
 while (1) 
 { 
 switch (mode) 
 { 
 case 1: 
 ctrinh1 () ; break; 
 case 2: 
 ctrinh2 () ; break; 
 case 3: 
 ctrinh3 () ; break; 
THIẾT KẾ HỆ THỐNG NHÚNG 
 48 
 } 
 } 
} 
// cac chuong trinh con 
 void ctrinh1 () 
 { 
 a=0xff; 
 for (i=0;i<=8;i++) 
 { 
 portd =a; 
 delay_ms (50) ; 
 a>>=1; //dich trai a; 
 } 
 } 
 void ctrinh2 () 
 { 
 a=0xff; 
 for (i=0;i<=8;i++) 
 { 
 portd =a; 
 delay_ms (50) ; 
 a<<=1; //dich trai a; 
 } 
 } 
void Ctrinh3 () 
 { 
 portd=0x00; 
 delay_ms (50) ; 
 portd=0xff; 
 } 
7.3. Ngắt do sự thay đổi trạng thái của các chân trong PORTB 
Các chân của PortB được dùng cho ngắt này và được điều khiển bởi bit 
RBIE (trong thanh ghi INTCON). Cờ ngắt này là bit RBIF (INTCON). 
Lưu ý: Phải dùng lệnh đọc cổng B để xóa cờ ngắt khi lập trình ngắt này. 
Ví dụ 1: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 49 
Sử dụng ngắt RB để điều khiển bật tắc các led được nối vào các chân tương ứng 
trên PortD 
Hình 25: Sơ đồ ghép nối xử lý ngoài trên PortB 
Code: 
 #include 
 #include 
 #device *=16 adc=8 
 #use delay (clock=20000000) // su dung thach anh 20mhz 
 #use fast_io (b) // dung voi cac lenh nhu output_low... nhanh hon bthuong 
 #byte portb=0x06 
 #byte portd=0x08 
 // Chương trình ngắt RB 
 #int_rb 
 void rb_led () 
 { 
 portd=portb;//Xóa ngắt, đưa trạng thái ra cổng D 
 } 
 void main () 
 { 
 set_tris_b (0xf0) ; //portb=11110000: B4:B7 la ngo vao, B0:B3 la ngo ra 
THIẾT KẾ HỆ THỐNG NHÚNG 
 50 
 set_tris_d (0x00) ; //pordD la ngo ra 
 enable_interrupts (int_rb) ; //cho phep ngat RB: bat ki thay doi nao tren B4:B7 
 enable_interrupts (global) ; //cho phep ngat tat ca ngat 
 while (true) 
 { 
 } 
 } 
Ví dụ 2: 
Cho sơ đồ kết nối như hình trên, hãy viết chương trình điều khiển các nút nhấn 
thay đổi tốc độ nhấp nháy của các led được nối ở Port B (Sử dụng ngắt RB). 
Code: sinh viên tự lập trình 
Gợi ý: Sử dụng một biến để lưu khoảng thời gian tắt mở của led và cho thay đổi 
trong ngắt RB khi kiểm tra từng chân (RB7:RB4). 
7.4. Chế độ Sleep 
Đây là chế độ hoạt động của vi điều khiển khi lệnh SLEEP được thực thi. Khi đó 
nếu được cho phép hoạt động, bộ đếm của WDT sẽ bị xóa nhưng WDT vẫn tiếp tục 
hoạt động, bit PD (STATUS) được reset về 0, bit TO được set, oscillator ngưng 
tác động và các PORT giữ nguyên trạng thái như trước khi lệnh SLEEP được thực 
thi. Do khi ở chế độ SLEEP, dòng cung cấp cho vi điều khiển là rất nhỏ nên ta cần 
thực hiện các bước sau trước khi vi điều khiển thực thi lệnh SLEEP: 
- Đưa tất cả các pin về trạng thái VDD hoặc VSS 
- Cần bảo đảm rằng không còn mạch ngoại vi nào được điều khiển bởi 
dòng điện của vi điều khiển vì dòng điện nhỏ không đủ khả năng cung 
cấp cho các mạch ngoại vi hoạt động 
- Tạm ngưng hoạt động của khối A/D và không cho phép các xung 
clock từ bên ngoài tác động vào vi điều khiển 
- Để ý đến chức năng kéo lên điện trở ở PORTB 
- Chân Reset phải ở mức cao 
7.5. Watch Dog Timer 
Watchdog timer (WDT) là bộ đếm độc lập dùng nguồn xung đếm từ bộ tạo xung 
được tích hợp sẵn trong vi điều khiển và không phụ thuộc vào bất kỳ nguồn xung 
clock ngoại vi nào. Điều đó có nghĩa là WDT vẫn hoạt động ngay cả khi xung clock 
được lấy từ pin OSC1/CLKI và pin OSC2/CLKO của vi điều khiển ngưng hoạt 
THIẾT KẾ HỆ THỐNG NHÚNG 
 51 
động (chẳng hạn như do tác động của lệnh sleep). Bit điều khiển của WDT là bit 
WDTE nằm trong bộ nhớ chương trình ở địa chỉ 2007h (Configuration bit). 
WDT sẽ tự động reset vi điều khiển (Watchdog Timer Reset) khi bộ đếm của 
WDT bị tràn (nếu WDT được cho phép hoạt động), đồng thời bit tự động được xóa. 
Nếu vi điều khiển đang ở chế độ sleep thì WDT sẽ đánh thức vi điều khiển 
(Watchdog Timer Wake-up) khi bộ đếm bị tràn. Như vậy WDT có tác dụng reset vi 
điều khiển ở thời điểm cần thiết mà không cần đến sự tác động từ bên ngoài, chẳng 
hạn như trong quá trình thực thi lệnh, vi điều khiển bị “kẹt” ở một chổ nào đó mà 
không thoát ra được, khi đó vi điều khiển sẽ tự động được reset khi WDT bị tràn để 
chương trình hoạt động đúng trở lại. 
WDT cũng có sự phiền toái vì vi điều khiển sẽ thường xuyên được reset sau một 
thời gian nhất định, do đó cần tính toán thời gian thích hợp để xóa WDT (dùng lệnh 
CLRWDT). Và để việc ấn định thời gian reset được linh động, WDT còn được hỗ 
trợ một bộ chia tần số prescaler được điều khiển bởi thanh ghi OPTION_REG 
(prescaler này được chia sẻ với Timer0). Một điểm cần chú ý nữa là lệnh sleep sẽ 
xóa bộ đếm WDT và prescaler. Ngoài ra lệnh xóa CLRWDT chỉ xóa bộ đếm chứ 
không làm thay đổi đối tượng tác động của prescaler (WDT hay Timer0). 
7.6. “Đánh thức” vi điều khiển 
Vi điều khiển có thể được “đánh thức” dưới tác động của một trong số các hiện 
tượng sau: 
- Tác động của reset ngoại vi. 
- Tác động của Watchdog timer (WDT) khi bị tràn. 
- Tác động từ các ngắt ngoại vi từ PORTB (PORTB Interrupt on 
change hoặc pin INT). 
Các bit PD và TO được dùng để thể hiện trạng thái của vi điều khiển và để phát 
hiện nguồn tác động làm reset vi điều khiển. Bit PD được set khi vi điều khiển được 
cấp nguồn và được reset về 0 khi vi điều khiển ở chế độ sleep. Bit TO được reset về 
0 khi WDT tác động do bộ đếm bị tràn. 
Ngoài ra còn có một số nguồn tác động khác từ các chức năng ngoại vi bao gồm: 
- Đọc hay ghi dữ liệu thông qua PSP (Parallel Slave Port). 
- Ngắt Timer1 khi hoạt động ở chế độ đếm bất đồng bộ. 
- Ngắt CCP khi hoạt động ở chế độ Capture. 
- Các hiện tượng đặc biệt làm reset Timer1 khi hoạt động ở chế độ đếm 
bất đồng bộ dùng nguồn xung clock ở bên ngoài). 
- Ngắt SSP khi bit Start/Stop được phát hiện. 
- SSP hoạt động ở chế độ Slave mode khi truyền hoặc nhận dữ liệu. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 52 
- Tác động của USART từ các pin RX hay TX khi hoạt động ở chế độ 
Slave mode đồng bộ. 
- Khối chuyển đổi A/D khi nguồn xung clock hoạt động ở dạng RC. 
- Hoàn tất quá trình ghi vào EEPROM. 
- Ngõ ra bộ so sánh thay đổi trạng thái. 
Các tác động ngoại vi khác không có tác dụng đánh thức vi điều khiển vì khi ở 
chế độ sleep các xung clock cung cấp cho vi điều khiển ngưng hoạt động. Bên cạnh 
đó cần cho phép các ngắt hoạt động trước khi lệnh SLEEP được thực thi để bảo 
đảm tác động của các ngắt. Việc đánh thức vi điều khiển từ các ngắt vẫn được thực 
thi bất chấp trạng thái của bit GIE. Nếu bit GIE mang giá trị 0, vi điều khiển sẽ thực 
thi lệnh tiếp theo sau lệnh SLEEP của chương trình (vì chương trình ngắt không 
được cho phép thực thi). Nếu bit GIE được set trước khi lệnh SLEEP được thực thi, 
vi điều khiển sẽ thực thi lệnh tiếp theo của chương trình và sau đó nhảy tới địa chỉ 
chứa chương trình ngắt (0004h). Trong trường hợp lệnh tiếp theo không đóng vai 
trò quan trọng trong chương trình, ta cần đặt thêm lệnh NOP sau lệnh SLEEP để bỏ 
qua tác động của lệnh này, đồng thời giúp ta dễ dàng hơn trong việc kiểm soát hoạt 
động của chương trình ngắt. Tuy nhiên cũng có một số điểm cần lưu ý như sau: 
- Nếu ngắt xảy ra trước khi lệnh SLEEP được thực thi, lệnh SLEEP sẽ 
không được thực thi và thay vào đó là lệnh NOP, đồng thời các tác 
động của lệnh SLEEP cũng sẽ được bỏ qua. 
- Nếu ngắt xảy ra trong khi hay sau khi lệnh SLEEP được thực thi, vi 
điều khiển lập tức được đánh thức từ chế độ sleep, và lệnh SLEEP sẽ 
được thực thi ngay sau khi vi điều khiển được đánh thức. 
- Để kiểm tra xem lệnh SLEEP đã được thực thi hay chưa, ta kiểm tra 
bit. Nếu bit vẫn mang giá trị 1 tức là lệnh SLEEP đã không được thực 
thi và thay vào đó là lệnh NOP. Bên cạnh đó ta cần xóa WDT để chắc 
chắn rằng WDT đã được xóa trước khi thực thi lệnh SLEEP, qua đó 
cho phép ta xác định được thời điểm vi điều khiển được đánh thức do 
tác động của WDT. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 53 
Bài 8 
THẢO LUẬN LẬP TRÌNH XỬ LÝ NGẮT 
- Quy trình xử lý ngắt 
- Phương pháp triển khai trong Pic 
Bài 9 
THỰC HÀNH: LẬP TRÌNH NGẮT 
Chi tiết theo cuốn bài tập thực hành 
Bài 10 
TIMER TRONG PIC 16F877A 
Trong vi điều khiển PIC 16F877A được tích hợp 2 bộ timer 8 bit là Timer0, 
Timer 2 và một bộ Timer 16 bit là Timer 1. 
Timer được sử dụng vào nhiều ứng dụng khác nhau: Interrupts, capture, pwm... 
10.1. Timer 0 
Đây là một trong ba bộ đếm hoặc bộ định thời của vi điều khiển PIC16F877A. 
Timer0 là bộ đếm 8 bit được kết nối với bộ chia tần số (prescaler) 8 bit. Cấu trúc 
của Timer0 cho phép ta lựa chọn xung clock tác động và cạnh tích cực của xung 
clock. Ngắt Timer0 sẽ xuất hiện khi Timer0 bị tràn. Bit TMR0IE (INTCON) là 
bit điều khiển của Timer0. TMR0IE=1 cho phép ngắt Timer0 tác động, TMR0IF= 0 
không cho phép ngắt Timer0 tác động. Sơ đồ khối của Timer0 như sau: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 54 
Hình 26: Sơ đồ khối của bộ Timer0 
Muốn Timer0 hoạt động ở chế độ Timer ta clear bit TOSC (OPTION_REG), 
khi đó giá trị thanh ghi TMR0 sẽ tăng theo từng chu kỳ xung đồng hồ (tần số vào 
Timer0 bằng ¼ tần số oscillator). Khi giá trị thanh ghi TMR0 từ FFh trở về 00h, 
ngắt Timer0 sẽ xuất hiện. Thanh ghi TMR0 cho phép ghi và xóa được giúp ta ấn 
định thời điểm ngắt Timer0 xuất hiện một cách linh động. 
Muốn Timer0 hoạt động ở chế độ counter ta set bit TOSC (OPTION_REG). 
Khi đó xung tác động lên bộ đếm được lấy từ chân RA4/TOCK1. Bit TOSE 
(OPTION_REG) cho phép lựa chọn cạnh tác động vào bột đếm. Cạnh tác động 
sẽ là cạnh lên nếu TOSE=0 và cạnh tác động sẽ là cạnh xuống nếu TOSE=1. 
Khi thanh ghi TMR0 bị tràn, bit TMR0IF (INTCON) sẽ được set. Đây chính 
là cờ ngắt của Timer0. Cờ ngắt này phải được xóa bằng chương trình trước khi bộ 
đếm bắt đầu thực hiện lại quá trình đếm. Ngắt Timer0 không thể “đánh thức” vi 
điều khiển từ chế độ sleep. 
Bộ chia tần số (prescaler) được chia sẻ giữa Timer0 và WDT (Watchdog Timer). 
Điều đó có nghĩa là nếu prescaler được sử dụng cho Timer0 thì WDT sẽ không có 
được hỗ trợ của prescaler và ngược lại. Prescaler được điều khiển bởi thanh ghi 
OPTION_REG. Bit PSA (OPTION_REG) xác định đối tượng tác động của 
prescaler. Các bit PS2:PS0 (OPTION_REG) xác định tỉ số chia tần số của 
THIẾT KẾ HỆ THỐNG NHÚNG 
 55 
prescaler. Xem lại thanh ghi OPTION_REG để xác định lại một cách chi tiết về các 
bit điều khiển trên. 
Các lệnh tác động lên giá trị thanh ghi TMR0 sẽ xóa chế độ hoạt động của 
prescaler. Khi đối tượng tác động là Timer0, tác động lên giá trị thanh ghi TMR0 sẽ 
xóa prescaler nhưng không làm thay đổi đối tượng tác động của prescaler. Khi đối 
tượng tác động là WDT, lệnh CLRWDT sẽ xóa prescaler, đồng thời prescaler sẽ 
ngưng tác vụ hỗ trợ cho WDT. 
Các thanh ghi điều khiển liên quan đến Timer0 bao gồm: 
- TMR0 (địa chỉ 01h, 101h) : chứa giá trị đếm của Timer0. 
- INTCON (địa chỉ 0Bh, 8Bh, 10Bh, 18Bh) : cho phép ngắt hoạt động 
(GIE và PEIE). 
- OPTION_REG (địa chỉ 81h, 181h) : điều khiển prescaler. 
10.2. Timer 1 
Timer1 là bộ định thời 16 bit, giá trị của Timer1 sẽ được lưu trong hai thanh ghi 
(TMR1H:TMR1L). Cờ ngắt của Timer1 là bit TMR1IF (PIR1). Bit điều khiển 
của Timer1 sẽ là TMR1IE (PIE). Tương tự như Timer0, Timer1 cũng có hai chế 
độ hoạt động: chế độ định thời (timer) với xung kích là xung clock của oscillator 
(tần số của timer bằng ¼ tần số của oscillator) và chế độ đếm (counter) với xung 
kích là xung phản ánh các sự kiện cần đếm lấy từ bên ngoài thông qua chân 
RC0/T1OSO/T1CKI (cạnh tác động là cạnh lên). Việc lựa chọn xung tác động 
(tương ứng với việc lựa chọn chế độ hoạt động là timer hay counter) được điều 
khiển bởi bit TMR1CS (T1CON). Sau đây là sơ đồ khối của Timer1: 
Hình 27: Sơ đồ khối của Timer1 
Ngoài ra Timer1 còn có chức năng reset input bên trong được điều khiển bởi 
một trong hai khối CCP (Capture/Compare/PWM). 
THIẾT KẾ HỆ THỐNG NHÚNG 
 56 
Khi bit T1OSCEN (T1CON) được set, Timer1 sẽ lấy xung clock từ hai chân 
RC1/T1OSI/CCP2 và RC0/T1OSO/T1CKI làm xung đếm. Timer1 sẽ bắt đầu đếm 
sau cạnh xuống đầu tiên của xung ngõ vào. Khi đó PORTC sẽ bỏ qua sự tác động 
của hai bit TRISC và PORTC được gán giá trị 0. Khi clear bit 
T1OSCEN Timer1 sẽ lấy xung đếm từ oscillator hoặc từ chân RC0/T1OSO/T1CKI. 
Timer1 có hai chế độ đếm là đồng bộ (Synchronous) và bất đồng bộ 
(Asynchronous). Chế độ đếm được quyết định bởi bit điều khiển T1SYNC 
(T1CON). 
Khi =1 xung đếm lấy từ bên ngoài sẽ không được đồng bộ hóa với xung clock 
bên trong, Timer1 sẽ tiếp tục quá trình đếm khi vi điều khiển đang ở chế độ sleep và 
ngắt do Timer1 tạo ra khi bị tràn có khả năng “đánh thức” vi điều khiển. Ở chế độ 
đếm bất đồng bộ, Timer1 không thể được sử dụng để làm nguồn xung clock cho 
khối CCP (Capture/Compare/Pulse width modulation). 
Khi =0 xung đếm vào Timer1 sẽ được đồng bộ hóa với xung clock bên trong. Ở 
chế độ này Timer1 sẽ không hoạt động khi vi điều khiển đang ở chế độ sleep. 
Các thanh ghi liên quan đến Timer1 bao gồm: 
- INTCON (địa chỉ 0Bh, 8Bh, 10Bh, 18Bh) : cho phép ngắt hoạt động 
(GIE và PEIE). 
- PIR1 (địa chỉ 0Ch) : chứa cờ ngắt Timer1 (TMR1IF). 
- PIE1 (địa chỉ 8Ch) : cho phép ngắt Timer1 (TMR1IE). 
- TMR1L (địa chỉ 0Eh) : chứa giá trị 8 bit thấp của bộ đếm Timer1. 
- TMR1H (địa chỉ 0Eh) : chứa giá trị 8 bit cao của bộ đếm Timer1. 
- T1CON (địa chỉ 10h) : xác lập các thông số cho Timer1. 
10.3. Timer 2 
Timer2 là bộ định thời 8 bit và được hỗ trợ bởi hai bộ chia tần số prescaler và 
postscaler. Thanh ghi chứa giá trị đếm của Timer2 là TMR2. Bit cho phép ngắt 
Timer2 tác động là TMR2ON (T2CON). Cờ ngắt của Timer2 là bit TMR2IF 
(PIR1). Xung ngõ vào (tần số bằng ¼ tần số oscillator) được đưa qua bộ chia 
tần số prescaler 4 bit (với các tỉ số chia tần số là 1:1, 1:4 hoặc 1:16 và được điều 
khiển bởi các bit T2CKPS1:T2CKPS0 (T2CON)). 
THIẾT KẾ HỆ THỐNG NHÚNG 
 57 
Hình 28: Sơ đồ khối Timer2 
Timer2 còn được hỗ trợ bởi thanh ghi PR2. Giá trị đếm trong thanh ghi TMR2 
sẽ tăng từ 00h đến giá trị chứa trong thanh ghi PR2, sau đó được reset về 00h. Khi 
reset thanh ghi PR2 được nhận giá trị mặc định FFh. 
Ngõ ra của Timer2 được đưa qua bộ chia tần số postscaler với các mức chia từ 
1:1 đến 1:16. Postscaler được điều khiển bởi 4 bit T2OUTPS3:T2OUTPS0. Ngõ ra 
của postscaler đóng vai trò quyết định trong việc điều khiển cờ ngắt. 
Ngoài ra ngõ ra của Timer2 còn được kết nối với khối SSP, do đó Timer2 còn 
đóng vai trò tạo ra xung clock đồng bộ cho khối giao tiếp SSP. 
 Các thanh ghi liên quan đến Timer2 bao gồm: 
- INTCON (địa chỉ 0Bh, 8Bh, 10Bh, 18Bh) : cho phép toàn bộ các ngắt 
(GIE và PEIE). 
- PIR1 (địa chỉ 0Ch) : chứa cờ ngắt Timer2 (TMR2IF). 
- PIE1 (địa chị 8Ch) : chứa bit điều khiển Timer2 (TMR2IE). 
- TMR2 (địa chỉ 11h) : chứa giá trị đếm của Timer2. 
- T2CON (địa chỉ 12h) : xác lập các thông số cho Timer2. 
10.4. Khai báo Timer trong CCS 
10.4.1. Các lệnh Timer0 
Setup_TIMER_0 (mode) ; Chọn chế độ làm việc cho 
Timer0 
Set_TIMER0 (value) // hay set_RTCC 
(value) 
Khởi tạo giá trị ban đầu 
cho Timer 
THIẾT KẾ HỆ THỐNG NHÚNG 
 58 
Get_TIMER0 () ; // hay get_RTCC () Trả lại giá trị cho timer0 
là giá trị xung hoặc giá trị 
đếm 
Setup_COUNTERS (rtcc_state, ps_state) ; 
Trong đó mode là một hoặc hai constant (nếu dùng hai thì chèn dấu "|"ở giữa) 
được định nghĩa trong file 16F877A. h gồm: 
- RTCC_INTERNAL : chọn xung clock nội 
- RTCC_EXT_L_TO_H: chọn bit cạnh lên trên chân RA4 
- RTCC_EXT_H_TO_L: chọn bit cạnh xuống trên chân RA4 
- RTCC_DIV_2:chia prescaler 1:2 
- RTCC_DIV_4 1:4 
- RTCC_DIV_8 1:8 
- RTCC_DIV_16 1:16 
- RTCC_DIV_32 1:32 
- RTCC_DIV_64 1:64 
- RTCC_DIV_128 1:128 
- RTCC_DIV_256 1:256 
rtcc_state là một trong những constant sau: 
- RTCC_INTERNAL 
- RTCC_EXT_L_TO_H 
- RTCC_EXT_H_TO_L 
ps_state là một trong những constant sau: 
- RTCC_DIV_2 
- RTCC_DIV_4 
- RTCC_DIV_8 
- RTCC_DIV_16 
- RTCC_DIV_32 
- RTCC_DIV_64 
- RTCC_DIV_128 
- RTCC_DIV_256 
- WDT_18MS 
- WDT_36MS 
- WDT_72MS 
- WDT_144MS 
THIẾT KẾ HỆ THỐNG NHÚNG 
 59 
- WDT_288MS 
- WDT_576MS 
- WDT_1152MS 
- WDT_2304MS 
10.4.2. Các lệnh Timer1 
Setup_TIMER_1 (mode) ; Chọn chế độ làm việc cho 
Timer0 
Set_TIMER1 (value) ; Khởi tạo giá trị ban đầu cho 
Timer 1 (16 bit) 
Get_TIMER1 () ; // hay get_RTCC () Trả lại giá trị của bộ 
Timer1 là giá trị xung hoặc 
giá trị đếm 
mode gồm (có thể kết hợp bằng dấu "|") : 
- T1_DISABLED: tắt Timer1 
- T1_INTERNAL: xung clock nội (Fosc/4) 
- T1_EXTERNAL: xung clock ngoài trên chân RC0 
- T1_EXTERNAL_SYNC: xung clock ngoài đồng bộ 
- T1_CLK_OUT 
- T1_DIV_BY_1 
- T1_DIV_BY_2 
- T1_DIV_BY_4 
- T1_DIV_BY_8 
10.4.3. Các lệnh Timer2 
setup_TIMER_2 (mode, period, 
postscale) 
Chọn chế độ làm việc cho 
Timer0 
Set_TIMER2 (value) ; Khởi tạo giá trị ban đầu cho 
Timer 2 
Get_TIMER2 () ; // hay get_RTCC () Trả lại giá trị của bộ Timer 
THIẾT KẾ HỆ THỐNG NHÚNG 
 60 
là giá trị xung hoặc giá trị 
đếm 
Với mode gồm (có thể kết hợp bằng dấu "|") : 
- T2_DISABLED 
- T2_DIV_BY_1 
- T2_DIV_BY_4 
- T2_DIV_BY_16 
period là số nguyên từ 0-255, xác định giá trị xung reset 
postscale là số nguyên 1-16, xác định reset bao nhiêu lần trước khi ngắt. 
10.5. Lập trình ứng dụng 
Ví dụ 1: 
Cho sơ đồ kết nối như hình vẽ: 
Hình 29: Sơ đồ mạch ví dụ dùng Timer0 
Lập trình cho các led sáng lần lượt từ trái sang phải sau khoảng thời gian nhất 
định (sử dụng timer0) 
Code: 
#include 
 #include 
 #device *=16 adc=8 
 #use delay (clock=4000000) // 
 #use fast_io (b) // dung voi cac lenh nhu output_low... nhanh hon binh thuong 
THIẾT KẾ HỆ THỐNG NHÚNG 
 61 
 #byte portb=0x06 
 #byte portd=0x08 
 int16 count; 
 int8 a; 
 // chuong trinh ngat ngat timer0 
 #int_timer0 // cho phep vao ngat timer0 
 void interrupt_timer0 () 
{ 
 ++count; 
 if (count==2000) //2000*500=1s 
 {count=0; 
 rotate_left (&a, 1) ; //xuay bien a 1 lan 1 bit 
 } 
 } 
 // chuong trinh chinh 
 void main () 
 { 
 set_tris_d (0) ; //cong B la cong xuat 
 enable_interrupts (int_timer0) ; //cho phep ngat timer0 hoat dong 
 setup_timer_0 (rtcc_internal|rtcc_div_2) ; //chon xung clock noi va chia tan trc 
1:2 
 enable_interrupts (global) ; //cho phep tat ca ngat hoat dong 
 set_timer0 (6) ; //T_dinhthoi = 2* (256 - 6) *1us = 500us 
 a=0x01; 
 while (true) 
 { 
 portd=a; 
 } 
 } 
Bài 11 
THỰC HÀNH: LẬP TRÌNH TIMER/COUNTER 
Chi tiết theo cuốn bài tập thực hành 
THIẾT KẾ HỆ THỐNG NHÚNG 
 62 
Bài 12 
THẢO LUẬN VỀ TIMER/COUNTER 
- Timer 
- Counter 
- Phương pháp lập trình Timer/Counter trong Pic 
Bài 13 
THỰC HÀNH: LẬP TRÌNH TIMER/COUNTER (TIẾP) 
Chi tiết theo cuốn bài tập thực hành 
Bài 14 
LẬP TRÌNH TRUYỀN THÔNG 
14.1. Tổng quan về lập trình truyền thông 
Vi điều khiển PIC 16F877A hỗ trợ nhiều chuẩn truyền thông khác nhau như 
chuẩn nối tiếp USART giao tiếp với máy tính theo chuẩn RS232, PSP (chuẩn song 
song), SPI, I2C. 
- USART: chuẩn truyền thông nối tiếp không đồng bộ hoàn toàn tương 
thích với giao tiếp máy tính qua RS232. Do chuẩn điện áp sử dụng tại 
PIC 16F877A là TTL nên để ghép nối với máy tính hoặc thiết bị khác 
sử dụng chuẩn RS232 cần có bộ chuyển đổi điện áp, ví dụ như IC 
MAX232. USART mặc định sử dụng 2 chân C6 và C7 để truyền 
thông. 
- PSP: với giao tiếp này, Pic sử dụng cổng D với vai trò là cổng truyền 
nhận song song 8 bit. Với PSP cho phép PIC có thể giao tiếp trực tiếp 
với các VĐK khác bằng bus dữ liệu 8 bit. Các chân RD, CS, WR sẽ 
giúp điều khiển đường truyền, chế độ hoạt động. PSP không hỗ trợ 
trên PIC16F873A, PIC16F876A. 
- Truyền thông nối tiếp đồng bộ: hỗ trợ 2 chế độ là SPI và I2C. 
14.2. Chuẩn RS232 
Với USART cho phép PIC 16F877A giao tiếp với máy tính theo chuẩn RS232. 
Đặc điểm RS232: 
Giao diện: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 63 
Hình 30: Hình ảnh giao diện DB9 và DB25 
Giao diện COM sử dụng cổng nối 9 chân và 25 chân. Cổng nối 25 
chân chỉ có một số chân được sử dụng. Thông dụng nhất là cổng nối 9 chân. 
Hình 31: Sơ đồ chân trên giao diện DB9 và DB25 
Giao diện và công dụng các chân được thể hiện ở bảng sau: 
Sơ đồ chuyển đổi, ghép nối giữa giao diện 9 chân và giao diện 25 
chân: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 64 
Các kiểu ghép nối truyền thông trên cổng RS232: 
Điện áp sử dụng truyền thông trong RS232 bao gồm cả mức điện áp 
âm và dương (không tương thích với các mức logic TTL và CMOS). 
Số "0" được biểu diện bằng mức điện áp +5V còn số "1" biểu diễn 
bằng mức đienẹ áp -5V. 
Giải điện áp sử dụng trong RS232 thể hiện trong bảng sau: 
THIẾT KẾ HỆ THỐNG NHÚNG 
 65 
Các chip giao tiếp, hỗ trợ chuyển đổi mức logic TTL sang mức điện 
áp thích hợp trên cổng RS232, sử dụng giao tiếp được với VĐK Pic: 
MAX232, MAX233,... 
THIẾT KẾ HỆ THỐNG NHÚNG 
 66 
Hình 32: Sơ đồ khối các vi mạch MAX232, MAX233 
Ghép nối pic với máy tính qua RS232: 
- Sử dụng phương pháp truyền thông không điều khiển luồng: chỉ dùng 3 chân: 
TX (truyền), RX (nhận), Ground (chung-nối đất). 
- Ghép nối thông qua IC chuyển điện áp MAX232. 
14.3. Lập trình ứng dụng 
Để lập trình truyền thông nối tiếp trên Pic ta cần thực hiện một số thiết lập sau: 
- Sử dụng chỉ thị: 
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) 
Trong đó: tham số thứ nhất là tốc độ truyền, thứ 2 là sử dụng kiểu kiểm tra chẵn 
lẻ gì, thứ 3 chân truyền đi, thứ 4 là chân nhận về, thứ 5 là số bit dữ liệu truyền 
- Gửi dữ liệu: trong CCS có thể sử dụng các hàm PutC(), Putchar(), Printf() 
- Nhận dữ liệu: trong CCS có thể dùng các hàm GetC(), Getchar() 
- Thiết lập cấu hình bằng: setup_uart(baud, stream) 
Ví dụ: 
printf("Continue (Y,N)?"); 
do { 
 answer=getch(); 
THIẾT KẾ HỆ THỐNG NHÚNG 
 67 
}while(answer!='Y' && answer!='N'); 
#use rs232(baud=9600,xmit=pin_c6, 
 rcv=pin_c7,stream=HOSTPC) 
#use rs232(baud=1200,xmit=pin_b1, 
 rcv=pin_b0,stream=GPS) 
#use rs232(baud=9600,xmit=pin_b3, 
 stream=DEBUG) 
... 
while(TRUE) { 
 c=fgetc(GPS); 
 fputc(c,HOSTPC); 
 if(c==13) 
 fprintf(DEBUG,"Got a CR\r\n"); 
} 
Bài 15 
THỰC HÀNH: LẬP TRÌNH TRUYỀN THÔNG 
Chi tiết theo cuốn bài tập thực hành 
THIẾT KẾ HỆ THỐNG NHÚNG 
 68 
Bài 16 
LẬP TRÌNH TRUYỀN THÔNG (tiếp) 
16.1. Chuẩn I2C 
Vi điều khiển PIC 16F877A hỗ trợ nhiều chuẩn truyền thông nối tiếp đồng bộ 
theo 2 chế độ: SPI, I2C. 
Một giao tiếp I2C gồm có 2 dây: Serial Data (SDA) và Serial Clock (SCL). SDA
là đường truyền dữ liệu 2 hướng, còn SCL là đường truyền xung đồng hồ và chỉ the
o một hướng. 
Như hình vẽ , khi một thiết bị ngoại vi kết nối vào đường I2C thì chân SDA của 
nó sẽ nối với dây SDA của bus, chân SCL sẽ nối với dây SCL. 
Hình 33: Sơ đồ ghép nối thiết bị chuẩn I2C 
Mỗi dây SDA hay SCL đều được nối với điện áp dương của nguồn cấp thông 
qua một điện trở kéo lên (pull‐up resistor). Sự cần thiết của các điện trở kéo này là 
vì chân giao tiếp I2C của các thiết bị ngoại vi thường là dạng cực máng hở 
(open‐drain or open‐collector). Giá trị của các điện trở này khác nhau tùy vào từng 
thiết bị và chuẩn giao tiếp, thường dao động trong khoảng 1KΩ đến 4.7KΩ. 
Trở lại với hình trên, ta thấy có rất nhiều thiết bị (ICs) cùng được kết nối vào 
một bus I2C, tuy nhiên sẽ không xảy ra chuyện nhầm lẫn giữa các thiết bị, bởi mỗi 
thiết bị sẽ được nhận ra bởi một địa chỉ duy nhất với một quan hệ chủ/tớ tồn tại 
trong suốt thời gian kết nối. Mỗi thiết bị có thể hoạt đông như là thiết bị nhận dữ 
liệu hay có thể vừa truyền vừa nhận. Hoạt động truyền hay nhận còn tùy thuộc vào 
việc thiết bị đó là chủ (master) hay tớ (slave). 
Một thiết bị hay một IC khi kết nối với bus I2C, ngoài một địa chỉ (duy nhất) để 
phân biệt, nó còn được cấu hình là thiết bị chủ (master) hay tớ (slave). Tại sao lại có 
sự phân biệt này ? Đó là vì trên một bus I2C thì quyền điều khiển thuộc về thiết bị 
chủ (master). Thiết bị chủ nắm vai trò tạo xung đồng hồ cho toàn hệ thống, khi giữa 
hai thiết bị chủ/tớ giao tiếp thì thiết bị chủ có nhiệm vụ tạo xung đồng hồ và quản lý 
địa chỉ của thiết bị tớ trong suốt quá trình giao tiếp. Thiết bị chủ giữ vai trò chủ 
động, còn thiết bị tớ giữ vai trò bị động trong viêc giao tiếp. 
THIẾT KẾ HỆ THỐNG NHÚNG 
 69 
Về dữ liệu truyền trên bus I2C, một bus I2C chuẩn truyền 8‐bit dữ liệu có hướng 
trên đường truyền với tốc độ là 100Kbits/s – Chế độ chuẩn (Standard mode). Tốc độ 
truyền có thể lên tới 400Kbits/s – Chế độ nhanh (Fast mode) và cao nhất là 
3,4Mbits/s – Chế độ cao tốc (High‐speed mode). 
Một bus I2C có thể hoạt động ở nhiều chế độ khác nhau: 
- Một chủ một tớ (one master – one slave) 
- Một chủ nhiều tớ (one master – multi slave) 
- Nhiều chủ nhiều tớ (Multi master – multi slave) 
Dù ở chế độ nào, một giao tiếp I2C đều dựa vào quan hệ chủ/tớ. Giả thiết một 
thiết bị A muốn gửi dữ liệu đến thiết bị B, quá trình được thực hiện như sau: 
‐ Thiết bị A (Chủ) xác định đúng địa chỉ của thiết bị B (tớ), cừng với việc xác 
định địa chỉ, thiết bị A sẽ quyết định việc đọc hay ghi vào thiết bị tớ
            Các file đính kèm theo tài liệu này:
 01200050_0051_1983579.pdf 01200050_0051_1983579.pdf