Lời cảm ơn 3
Mục lục 4
Lời mở đầu 5
Chương 1: Tổng quan
1.1 Giới thiệu 6
1.2 Nhiệm vụ 6
1.3 Nội dung luận văn 6
Chương 2: Giới thiệu họ vi điều khiển PIC
2.1 Các thông số chính của PIC 16F877A 7
2.2 Cấu trúc các cổng vào/ra 9
2.3 Bản đồ địa chỉ thanh ghi và bộ nhớ RAM 14
2.4 Bản đồ bộ nhớ chương trình 16
2.5 Tập lệnh PIC 17
Chương 3: Thiết kế và thi công
3.1 Sơ đồ khối 25
3.2 Chức năng từng khối 26
3.3 Tính toán thiết kế từng khối 27
3.4 L ưu đồ giải thuật 38
22 trang |
Chia sẻ: NguyễnHương | Lượt xem: 1159 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Thiết kế và thi công hệ thống đo đồ thị phụ tải công suất 3kva, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
able Logic Device).
-Cho phép nối mạng.
-Có thể tháo lắp thiết bị trong lúc máy tính đang làm việc.
-Có thể cung cấp nguồn cho các mạch điện đơn giản
Các thiết bị ghép nối chia thành 2 loại: DTE (Data Terminal Equipment) và DCE (Data Communication Equipment). DCE là các thiết bị trung gian như MODEM còn DTE là các thiết bị tiếp nhận hay truyền dữ liệu như máy tính, PLC, vi điều khiển, Việc trao đổi tín hiệu thông thường qua 2 chân RxD (nhận) và TxD (truyền). Các tín hiệu còn lại có chức năng hỗ trợđể thiết lập và điều khiển quá trình truyền, được gọi là các tín hiệu bắt tay (handshake). Ưu điểm của quá trình truyền dùng tín hiệu bắt tay là có thể kiểm soát đường truyền.
Tín hiệu truyền theo chuẩn RS-232 của EIA (Electronics Industry Associations). Chuẩn RS-232 quy định mức logic 1 ứng với điện áp từ -3V đến -25V (mark), mức logic 0 ứng với điện áp từ 3V đến 25V (space) và có khả năng cung cấp dòng từ 10 mA đến 20 mA. Ngoài ra, tất cả các ngõ ra đều có đặc tính chống chập mạch.
Chuẩn RS-232 cho phép truyền tín hiệu với tốc độđến 20.000 bps nhưng nếu cáp truyền đủ ngắn có thể lên đến 115.200 bps.
Các phương thức nối giữa DTE và DCE:
-Đơn công (simplex connection): dữ liệu chỉđược truyền theo 1 hướng.
- Bán song công ( half-duplex): dữ liệu truyền theo 2 hướng, nhưng mỗi thời điểm chỉđược truyền theo 1 hướng.
- Song công (full-duplex): số liệu được truyền đồng thời theo 2 hướng. Định dạng của khung truyền dữ liệu theo chuẩn RS-232 như sau:
01
Khi không truyền dữ liệu, đường truyền sẽở trạng thái mark (điện áp -10V). Khi bắt đầu truyền, DTE sẽđưa ra xung Start (space: 10V) và sau đó lần lượt truyền từ D0 đến D7 và Parity, cuối cùng là xung Stop (mark: -10V) để khôi phục trạng thái đường truyền.
Dạng tín hiệu truyền mô tả như sau (truyền ký tự A):
Các đặc tính kỹ thuật của chuẩn RS-232 nhưsau:
Chiều dài cable cực đại
15m
Tốc độ dữ liệu cực đại
20 Kbps
Điện áp ngõ ra cực đại
± 25V
Điện áp ngõ ra có tải
± 5V đến ± 15V
Trở kháng tải
3K đến 7K
Điện áp ngõ vào
± 15V
Độ nhạy ngõ vào
± 3V
Trở kháng ngõ vào
3K đến 7K
Các tốc độ truyền dữ liệu thông dụng trong cổng nối tiếp là: 1200 bps, 4800 bps, 9600 bps và 19200 bps.
Cổng COM có hai dạng: đầu nối DB25 (25 chân) và đầu nối DB9 (9 chân) mô tả như hình 3.10. Ý nghĩa của các chân mô tả như sau:
D25
D9
Tín hiệu
Hướng truyền
Mô tả
1
-
-
-
Protected ground: nối đất bảo vệ
2
3
TxD
DTEÆDCE
Transmitted data: dữ liệu truyền
3
2
RxD
DCEÆDTE
Received data: dữ liệu nhận
4
7
RTS
DTEÆDCE
Request to send: DTE yêu cầu truyền dữ liệu
5
8
CTS
DCEÆDTE
Clear to send: DCE sẵn sàng nhận dữ liệu
6
6
DSR
DCEÆDTE
Data set ready: DCE sẵn sàng làm việc
7
5
GND
-
Ground: nối đất (0V)
8
1
DCD
DCEÆDTE
Data carier detect: DCE phát hiện sóng mang
20
4
DTR
DTEÆDCE
Data terminal ready: DTE sẵn sàng làm việc
22
9
RI
DCEÆDTE
Ring indicator: báo chuông
23
-
DSRD
DCEÆDTE
Data signal rate detector: dò tốc độ truyền
24
-
TSET
DTEÆDCE
Transmit Signal Element Timing: tín hiệu định thời truyền đi từ DTE
15
-
TSET
DCEÆDTE
Transmitter Signal Element Timing: tín hiệu định thời truyền từ DCE để truyền dữ liệu
17
-
RSET
DCEÆDTE
Receiver Signal Element Timing: tín hiệu định thời truyền từ DCE để truyền dữ liệu
18
-
LL
Local Loopback: kiểm tra cổng
21
-
RL
DCEÆDTE
Remote Loopback: Tạo ra bởi DCE khi tín hiệu nhận từ DCE lỗi
14
-
STxD
DTEÆDCE
Secondary Transmitted Data
16
-
SRxD
DCEÆDTE
Secondary Received Data
19
-
SRTS
DTEÆDCE
Secondary Request To Send
13
-
SCTS
DCEÆDTE
Secondary Clear To Send
12
-
SDSRD
DCEÆDTE
Secondary Received Line Signal Detector
25
-
TM
Test Mode
9
-
Dành riêng cho chế độ test
10
-
Dành riêng cho chế độ test
11
Không dùng
Truyền thông giữa hai nút
Các sơ đồ khi kết nối dùng cổng nối tiếp:
DTE1 DTE2 DTE DCE
Hình 3.3 – Kết nối đơn giản trong truyền thông nối tiếp
Khi thực hiện kết nối như trên, quá trình truyền phải bảo đảm tốc độ ở đầu phát và thu giống nhau. Khi có dữ liệu đến DTE, dữ liệu này sẽ được đưa vào bộ đệm và tạo ngắt. Ngoài ra, khi thực hiện kết nối giữa hai DTE, ta còn dùng sơđồ sau:
DTE1 DTE2
Hình 3.4 – Kết nối trong truyền thông nối tiếp dùng tín hiệu bắt tay
Khi DTE1 cần truyền dữ liệu thì cho DTR tích cực tác động lên DSR của DTE2 cho biết sẵn sàng nhận dữ liệu và cho biết đã nhận được sóng mang của MODEM (ảo). Sau đó, DTE1 tích cực chân RTS để tác động đến chân CTS của DTE2 cho biết DTE1 có thểnhận dữ liệu. Khi thực hiện kết nối giữa DTE và DCE, do tốc độ truyền khác nhau nên phải thực hiện điều khiển lưu lượng. Quá trinh điều khiển này có thể thực hiện bằng phần mềm hay phần cứng. Quá trình điều khiển bằng phần mềm thực hiện bằng hai ký tự Xon và Xoff. Ký tự Xon được DCE gởi đi khi rảnh (có thể nhận dữ liệu). Nếu DCE bận thì sẽ gởi ký tựXoff. Quá trình điều khiển bằng phần cứng dùng hai chân RTS và CTS. Nếu DTE muốn truyền dữ liệu thì sẽ gởi RTS để yêu cầu truyền, DCE nếu có khả năng nhận dữ liệu (đang rảnh) thì gởi lại CTS.
Giới thiệu CCS:
CCS là trình biên dịch dùng ngôn ngữ C lập trình cho vi điều khiển. Đây llà ngôn ngữ lập trình đầy sức mạnh, giúp bạn nhanh chóng trong việc viết chương trình hơn so với ngôn ngữ Assembly.
Mã lệnh được tối ưu khi biên dịch.
Tuy nhiên C không phải là vạn năng, có thể thực hiện mọi thứ như ý muốn. Trong 1 số trường hợp, nó có thể sinh mã chạy sai (tham khảo các cải tiến ở các version CCS trên web: info.CCS.com hoăc trang web đi kèm).
CCS chứa rất nhiều hàm phục vụ cho mọi mục đích và có rất nhiều cách lập trình mã cho cùng một vấn đề dẫn đến khác nhau tốc độ thực thi mã, độ dài chương trình.Sự tối ưu là do khả năng lập trình C của bạn.
CCS C có đủ khả năng để bạn không cần phải chèn thêm bất kì dòng lệnh ASSEMBLY nào, và mặc dù vẫ cho phép bạn phối hợp ASSEMBLY cùng với C, tuy nhiên CCS sẽ không đảm bảo chương trình chạy chính xác.
CCS cung cấp các công cụ tiện ích giám sát hoạt động chương trình như: C/ASM list: cho phép xem mã ASM của file bạn phiên dịch, giúp bạn quản lí mã và nắm được cách thức mã sinh ra và nó chạy như thế nào, là công cụ rất quan trọng, ban cố thể gỡ rối cgương trình và nắm được hoạt động của nó; SYMBOL hiển thị bộ nhớ cấp phát cho từng biến, giúp quản lý bộ nhớ các biến chương trình, Calltree hiển thị phân bổ bộ nhớ.
Có nhiều tiện ích trong mục Tools, nhưng do bản crack nên nhiều cí không ài được.
Chương rình CCS dùng cho đề tài này là PCW COMPILER bản version 3.7, bao gồm: PCB, PCM, và PCH, lập trình cho các họ PIC10 bit, 12 bit và PIC 18, chưa có DSPIC.
ADC trong PIC16F877:
Bộ ADC trong PIC và ứng dụng
Bộ chuyển đổi từ tương tự sang số là một khối mạch điện tử quan trọng, có mặt trong rất nhiều thiết kế điện tử. Các bộ ADC thực tế được đóng gói trong những IC chuyên dụng, do nhiều hãng sản xuất. Điểm quan trọng cần lưu ý ở các bộ ADC này là độ phân giải và tốc độ lấy mẫu tín hiệu. Độ phân giải của ADC có thể là 8-bít, 10-bít, 12-bít, 16-bít, 24-bít, Tốc độ lấy mẫu của ADC có thể nhanh hay chậm, tuỳ từng ứng dụng mà ta chọn tốc độ thích hơp.
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 đã được tích hợp sẵn một bộ ADC có độ phân giải tối đalà 10-bít (tuỳ chọn là 8-bít hay 10-bít).
Xử lý ADC:
PIC có nhiều chân phục vụ xử lý ADC với nhiều cách thức khác nhau. Đẻ dùng ADC, bạn phải có khai báo #DEVICE cho biết dùng ADC mấy bít (tuỳ chíp hỗ trợ, thường là 8 hay 10 bít hoặc hơn). Bạn cần lưu ý là: 1 vi điều khiển hỗ trợ ADC 10 bít thì giá trị vào luôn là 10 bít, nhưng chia cho 4 thì là 8 bít.
Do đó một biến trở chiết áp cấp cho ngõ vào ADC mà bạn chọn chế độ 10 bít thì sẽ rất nhạy so với chế độ 8 bít ( vì 2 bít cuối có thay đổi cũng không ản hưởng giá trị 8 bít cao và do đó kết quả 8 bít ADC ít thay đổi), nếu chương trình có chế độ kiểm tra ADC để cập nhật tính toán, hay dùng ngắt ADC, thì nó sẽ chạy hoài thôi. Dùng ADC 8 bít sẽ hạn chế điều này. Do đó mà CCS cung cấp chọn lựa 8 hay 10 bít tuỳ mục đích sử dụng.
Cấu hình bộ ADC:
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 chaan biến đổi ADC, kết quả cho 1 giá trị số ADC 8 bít (0-255) hay ADC 10 bít (0-1023). Thường thì áp Vref lấy bằng Vdd (5V).
Trên các PIC có ngõ AVdd và AVss (PIC18) , thường thì bạn luôn nối AVdd tới Vdd, AVss tới Vss để đảm bảo cho lập trình qua ICD2.
Các hàm sau phục vụ ADC:
Setup_ADC (mode):
Không trả về trị. Dùng xác định cách thức hoạt động bộ biến đổi ADC.Tham so mode týu thuộc file thiết bị *.h có tên tương ứng tên chíp 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 đó, bạn 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 đay 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 một số thứ là ADC_CLOCK_DIV_2/4/8/1/32/64):
ADC_OFF: tắt hoạt dộng ADC (tiết kiệm điện, dành chân cho hoạt đông khác).
ADC_CLOCK_INTERNAL: tthời gian lâý 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.4us 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).
Seup_ADC_ports (value)
Xác định chân lấy tín hiệu analog và điện thế chuẩn sử dụng. Tuỳ thuộc bố tríi chân trên chip, số chân và chân nào dùng cho ADC và số chức năng ADC mỗi chip mà value có thể có những gía trị khác nhau. Xem file tương ứng trong thư mục DEVICES đẻ biết số chứ 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 ten khác nhau ( nhưng cùng chức năng do định nghĩa cùng địa chỉ ), ở đây dùng phiên bản 3.227. Lưu ý: Vref: áp chuẩn; Vdd: áp nguồn.
Sau đây là các giá trị cho value (chỉ dùng 1trong các giá trị ) của 16F877:
ALL_ANALOGS: dùng tất cả chân sau làm analog: A0 A1 A2 A5 E0 E1 E2 (Vref=Vdd)
NO_ANALOG: không dùng analog, các chân đó sẽ là 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 cr 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_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 A1VRefh=A3, VRefl=A2
AN0:A0
AN0_VREF_VREF: A0 VRefh=A3, VRefl=A2
Set_ADC_channel(channel):
Chọn chân đẻ đọc vào giá trị amalog bằng lệnh Read_ADC( ). Gias 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 1 2-chân A2 3-chân A3 4-chân A5
5-chân E0 6-chân E1 7-chân E2
Hàm này 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( ) để đảm bảo 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ế đổi. Lưu ý hàm này sẽ hỏi vòng cờ cho tới khi cờ này báo đã hàn thành biến đổi AD (sẽ mất vài us)thì xong hà.
Nếu giá trị ADC là 8 bít như khai báo trong chỉ thị #DEVICE, gía trị trả về của hàm 8 bít, ngược lại là 16 bít nếu khai báo #DEVICEsử dụng ADC 10bít trở lên .
Khi dùng hàm naỳ, 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, gồm có:
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
#DEVICE 8bít 10bít 11bít 16bít
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
16F877 chỉ hỗ trợ ADC 8 và 10 bít .
Lưu ý: 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 sẽ đề cập sau.
Vấn đề ngắt trong CCS:
Ngắt 1cấp :
Trên PIC 14, 12, 10, tất cả các ngắt đều có 1 cấp ưu tiên. Nghĩa là ngắt nào đang được phục vụ thì không thể bị ngắt bởi ngắt khác xảy ra Cơ chế sinh ngắt của CCS như sau: nhảy đến địa chỉ ngắt, thường là 004h, sao lưu thanh lưu W, STATUS, CPLATCH, FSR, và nhiều thứ vớ vẩn khác, sau đó nó mới hỏi vòng xem cờ ngắt nào xảy ra thì đến hàm phục vụ ngắt đó. Thực hiện xong thì phục hồi tất cả các thanh ghi trên, rồi mới “RETFLE” – thoát ngắt. Số chu kỳ thực thi từ chỗ ngắt đến khi nhảy vào hàm ngắt cỡ 20 chu kỳ lệnh, nhảy ra cũng cỡ đó.
Điều gì xảy ra nếu chương trình dùng nhiều ngắt và khi có ngắt thì có 2 ngắt trở lên xảy ra đồng thời ? Nghĩa là : 2 ngắt xảy ra cùng lúc, hay khi ngắt A kích hoạt và CCS đang lưu các thanh ghi ( chưa hỏi đến vòng cờ ngắt) thì ngắt B xảy ra,dĩ nhiên ngắt B không thể kích vector ngắt nhảy tới 004h vì bit cho phép ngắt toàn cục ( GIE )bị khoá tự động khi có ngắt, chỉ có cờ ngắt B bật mà thôi. Sau khi ghi các thanh ghi, trương trình kiểm tra cờ ngắt, rõ ràng là bit nào kiểm tra trước thì phục vụ trước, dù nó xảy ra sau. Để tránh phục vụ không đúng chỗ, bạn dùng #priority để xác định ưu tiên ngắt ( xem phần chỉ thị tiền xử lý) . Ngắt ưu tiên nhất sẽ luôn được hỏi vòng trước. Sauk hi xác định cờ ngắt cần phục vụ, nó sẽ thực thi hàm ngắt tương ứng. Xong thì xoá cờ ngắt đó và thoát ngắt. Phục vụ cờ ngắt nào xong thì chỉ xoá cờ ngắt đó. Nếu A ưu tiên hơn B thì sau khi làm A, chương trình xoá cờ ngắt A, nhưng cờ B không xoá ( vì đâu có phục vụ) nên khi thoát ra ngắt A, nó sẽ lại ngắt tiếp (vi cờ B đã bật), lại hỏi vòng cờ ngắt từ đầu nếu cờ A chưa bật thì xét B, lúc này B bật nên phục vụ B, xong thì xoá cờ B và thoát ngắt.
Một chương trình nhiều ngắt phải lưu ý điều này, tránh trường hợp ngắt xảy ra lien tục (tràn ngắt), 1 ngắt bị đáp ứng trễ, ngắt không đúng,
Ngắt 2 cấp:
Chỉ có trên PIC 18 ( và dsPIC), có 2 khái niệm: ngắt ưu tiên thấp(low priority) và ngắt ưu tiên cao (high priority), 2 vector thực thi ngắt tương ứng thường là 0008h (high) và 0018h(low) một ngắt thấp đang được phục vụ sẽ bị ngưng và phục vụ ngắt cao ở 0008h nếu ngắt cao xảy ra. Ngược lại, ngắt cao đang xảy ra thì không bao giờ bị ngắt bởi ngắt thấp.
Nếu viết hàm ngắt bình thường, không đòi hỏi ưu tiên gì thì CCS sẽ sinh mã đẻ tất cả hàm ngắt đều là hàm ngắt ưu tiên cao. Quy trình thự hiện ngắt sẽ như ngắt cấp 1 trên. #priority vẫn được dùng. Số chu kì thực thi từ 0008h đến khi nhảy vào thực thi hàm ngắt khoảng 30chu kì, xong hàm ngắt tới khi kết thúc ngắt cũng mất khoảng 30 chu kì lệnh.
Để sử dụng ngắt 2 cấp, khai báo #device phải có high ints=true. Và hàm ngắt nào muốn ưu tiên cao thì thêm FAST hay HIGH theo sau chỉ thị tiền xử lí hàm đó.
Lưu ý: khi dùng FAST thì không nên dùng HIGH cho các ngắt khác thì mới có nghĩa và chỉ có duy nhất một ngắt được ưu tiên FAST, nhưng có thể có nhiều ngắt đặt ở mức HIGH.
VD: #int_timer1 FAST
Void xu ly ( )
{ . . .
}
#int_temer2 HIGH
Void dinh_thi ()
{ . . .
}
#int_timer5 HIGH
Void vong_lap ()
{ . . .
}
Cơ chế sinh mã như sau : có ngắt thấp thì nhảy tới 0018h , sao lưu W, STATUS, FSR0/1/2, rồi mới hỏi vòng cờ ngắt thấp, chạy xong vòng ngắt thì phục hồi tất cả và “RETFIE 0”.
Riêng ngắt cao đánh dấu FAST không sinh mã sao lưu gì cả mà nhảy thẳng vào hàm ngắt chạy luôn, PIC 18 và dsPIC có cơ chế lưu siêu tốc là FAST TACK REGISTER ( xem data sheet) . Khi xảy ra ngắt bất kỳ, W, S, BSR tự động lưu vào thanh ghi trên , PC lưu vào stack, xong ngắt thì pop ra. Vấn đề ở chỗ :khi ngắt thấp xảy ra, FAST STACK REGISTER tự động lưu W,S, BSR, PC -> stack. Trong khi thực hiện hàm phục vụ ngắt thì trường hợp Ư, S, BSR, thay đổi là có thể (vì vậy mới sao lưu chứ) ,nhưng nếu xảy ra ngắt cao vào thời điểm đó? FAST STACK REGISTER tự động lưu W, S, BRS, PC ->stack. Trong khi thực hiện hàm phục vụ ngắt thì trường hợp W, S, BSR thay đổi là có có thể (vì vậy mới sao lưu chứ), nhưng nếu xảy ra ngắt caovào thời điểm đó? FAST STACK REGISTER sẻ bị ghi đè, mất data. Do đó, cơ chế sinh mã của CCS cần phải luôn đúng, có nghĩa là luôn tự sao lưu riêng W, S, BSR, và các thanh ghi FSR nữa, khi thực hiện ngắt thấp.Còn ngắt cao FAST khi chạy xong sẽ “RETFIE 1” -tự động phục hồi W, S, BSR từ FAST STACK REGISTER. Có 2 trường hợp : 1 là chỉ có ngắt cao thì không có vấn đề gì, 2 là ngắt cao ngắt 1 ngắt thấp đang chạy. Phân tích sẽ thấy rằng cho dù bị ngắt trong khi đang sao lưu, hay chưa kịp sao lưu, hay đã sao lưu vào các biến riêng rồi, cuối cùng chương trình cũng quay ra đúng địa chỉ ban đầu với các thanh ghi W, S, BSR như cũ.
Tuân thủ nguyên tắc ngắt cao thực thi tức thời nên CCS chỉ cho 1 ngắt cao FASTduy nhất bất kỳ hoạt động, nên không sinh mã hỏi vòng, sao lưu thêm gì cả.
Nếu bạn muốn có nhiều ngắt ưu tiên cao, thì dùng HIGH, chương trình sao lưu bình thường như với ngắt thấp, nhưng khi đó ngắt đánh dấu FAST cũng mất tác dụng, CCS xem như là HIGH và xử lý bình thường.
Như vậy dùng FAST hay HIGH đều có ý nghĩa riêng của nhà lập trình.
Khai báo ngắt:
Mỗi dòng VDK có số lượng nguồn ngắt ngắt khác nhau : PIC 14 có 14 ngắt, PIC 18 có 35 ngắt.
Muốn biết CCS hỗ trợ những ngắt nào cho VDK của bạn mở file *.h tương ứng, ở cuối file là danh sách các ngắt mà CCS hỗ trợ nó. Cách khác là vào CCS -> View -> Valid interrupts , chọn VDK muốn xem, nó sẽ hiển thị danh sách sẽ cho VDK đó.
Sau đây là danh sách một số ngắt với chức năng tương ứng:
#INT_GLOBAL : ngắt chung, nghĩa là khi có ngắt xảy ra, hàm theo sau chỉ thị này được thực thi, bạn sẽ không được khai báo thêm chỉ thị ngắt nào khác khi sử dụng chỉ thị này. CCS không sinh bất kì mã lưu nào, hàm ngắt bắt đầu quay tại vector ngắt. Nếu bật nhiều cờ cho phép ngắt, có thể bạn sẽ phải hỏi vòng để xác định ngắt nào. Dùng chỉ thị này tương đương viết hàm ngắt 1 cách thủ công mà thôi, như là viết hàm ngắt với ASM vậy.
#INT_AD: chuyển đổi A/D đã hoàn tất, thường thì không nên dùng
#INT_ADOF: I don’t know
#INT_BUSCOL: xung đột bus
#INT_BUTTON: nút nhấn
#INT_CCP1: có capture hay compare trên CCP1
#INT_CCP2: có capture hay compare trên CCP2
#INT_COMP: kiểm tra bằng nhau trên Comparater
#INT_EEPROM: hoàn toàn ghi EEPROM
#INT_EXT: ngắt ngoài
#INT_EXT1: ngắt ngoài 1
#INT_EXT2: ngắt ngoài 2
#INT_I2C: có hoạt động I2C
#INT_LCD:có hoạt động LCD
#INT_LOWVOLT: phát hiện áp thấp
#INT_PSP:có data vào cổng parallel slave
#INT_RB: bất kì thay đổi nào trên chân B4 dến B7
#INT_RC:bất kì thay đổi nào trên chân C4 dến C7
#INT_RDA: data nhận từ RS 232 sẵn sàng
#INT_RTCC: tràn timer 0
#INT_SSP:có hoạt động SPI hay I2C
#INT_TBE: bộ đệm chuyển RS 232 trống
#INT_TIMER0: một tên khác của #INT_RTCC
#INT_TIMER1: tràn Timer 1
#INT_TIMER2: tràn Timer 2
#INT_TIMER3: tràn Timer 3
#INT_TIMER5: tràn Timer 5
#INT_OSCF: lỗi OSC
#INT_PWMTB: ngắt của PWM time base
#INT_IC3DR: ngắt đổi hướng (direct) của IC3
#INT_IC2QEI: ngắt của QEI
#INT_IC1: ngắt IC1
Hàm đi kèm phục vụ ngắt không cần tham số vì không có tác dụng.
Sử dụng NOCLEAR sau #int_xxx để CCS không xoá cờ ngắt của hàm đó.
Để cho phép ngăt đó hoạt động phải dùng lệnh enable_interrupts ( int_xxx) và inable_interrupts ( global ).
Khoá FAST theo sau #int_xxx để cho ngắt đó là ưu tiên cao, chỉ được ngắt 1 ngắt thôi, chỉ có ở PIC 18 và dsPIC.
VD : #int_timer0 FAST NOCLEAR
Các hàm thiết lập hoạt động ngắt:
Enable_interrupts (level):
Level là tên các ngắt đã cho ở trên hay là GLOBAL để cho phép ngắt ở cấp toàn cục.
Mọi ngắt của VDK đều có 1 bit cờ ngắt, 1 bit cho phép ngắt. Khi có ngắt thì bit cờ ngắt bị set = 1, nhưng ngắt có hoạt động đựơc hay không tuỳ thuộc vào bit cho phép ngắt.enable_inerrupts (int_xxx) sẽ bật bit cho phép ngắt. Nhưng tất cả các ngắt đều không thể thực thi nếu bit cho phép ngắt toàn cục = 0 , enable_interrupts (global) sẽ bật bit này.
VD: để cho phép ngắt timer0 và timer1 hoạt động:
enable_interrupts (int_timer0);
enable_interrupts (int_timer1;
enable_interrupts ( global ); // chỉ cần dùng 1 lần trừ phi muốn có thay đổi đặc biệt
Disable_interrupts (level)
level giống như trên.
Hàm này vô hiệu 1 ngắt bằng cách set bit cho phép ngắt = 0.
Disable_interrupts (global) set bit cho phép ngắt toàn cục = 0, cấm tất cả các ngắt.
Không dùng hàm này trong hàm phục vụ ngắt vì không có tác dụng, cờ ngắt luôn bị xoá tự động.
Clear_interrupt (level)
Level không có GLOBAL.
Hàm này xoá cờ ngắt của ngắt được chỉ định bởi level.
Ext-int-edge ( source , edge ):
Hàm này thiết lập nguồn ngắt ngoài EXTx là cạnh lên hay cạnh xuống.
Source: nguồn ngắt . Trên PIC 18 có 3 nguồn ngắt trên 3 chân EXT0, EXT1, EXT2 ứng với source = 0, 1, 2 . Các PIC khác chỉ có 1 nguồn EXT nên source = 0.
Edge: chọn cạnh kích ngắt , edge = L_TO_H nếu chọn cạnh lên ( từ mức thấp chuyển lên mức cao ) hay H_TO_L nếu chọn cạnh xuống.
Các lệnh khác của PIC trong C:
DELAY_MS(time)
Cú pháp : delay_ms(time)
Tham số : time - 0~255 nếu time là một biến số, 0~65535 nếu time là hằng số
Trị trả về : không
Chức năng:Tạo code để thực hiện delay một thời gian định trước. Thời gian tính bằng milisecond. Hàm này sẽ thực hiện một số lệnh nhằm delay 1 thời gian yêu cầu. Hàm này không sử dụng bất kỳ timer nào. Nếu sử dụng ngắt (interupt), thời gian thực hiện các lệnh trong khi ngắt không được tính vào thời gian delay.
Yêu cầu : #uses delay.
DELAY_US(time)
Cú pháp : delay_us(time)
Tham số : time - 0~255 nếu time là một biến số, 0~65535 nếu time là hằng số
Trị trả về : không
Chức năng : Tạo code để thực hiện delay một thời gian định trước. Thời gian tính bằng microsecond. Hàm này sẽ thực hiện một số lệnh nhằm delay 1 thời gian yêu cầu. Hàm này không sử dụng bất kỳ timer nào. Nếu sử dụng ngắt (interupt), thời gian thực hiện các lệnh trong khi ngắt không được tính vào thời gian delay.
Yêu cầu : #uses delay
SET_TIMER0()
Cú pháp : set_rtcc()
set_timer0()
Tham số : 8 bit, value = 0~255
Trị trả về : không
Chức năng : Đặt giá trị ban đầu cho real time clock/counter. Tất cả các biến đều đếm tăng. Khi giá trị timer vượt quá 255, value được đặt trở lại 0 và đếm tiếp tục (, 254, 255, 0, 1, 2, )
Yêu cầu : không.
SETUP_TIMER1()
Cú pháp : setup_timer_1(mode)
Tham số : mode - tham số như sau
T1_DISABLED : tắt timer1
T1_INTERNAL : xung clock của timer1 bằng 1/4 xung clock nội của IC (OSC/4)
T1_EXTERNAL
T1_EXTERNAL_SYNC
T1_CLK_OUT : enable xung clock ra
T1_DIV_BY_1 : 65535-(samplingtime(s)/(4/20000000)) timemax = 13.1ms
T1_DIV_BY_2 : 65535-(samplingtime (s)/(8/20000000)) timemax =26.2ms
T1_DIV_BY_4 :65535-(samplingtime(s)/(16/20000000)) timemax = 52.4ms
T1_DIV_BY_8 :65535-(samplingtime(s)/(32/20000000)) timemax = 104.8ms
Trị trả về : không
Chức năng : Khởi động timer 1. Sau đó timer 1 có thể được ghi hay đọc dùng lệnh set_timer1() hay get_timer1(). Timer 1 là 16 bit timer. Với xung clock là 20MHz, timer 1 tăng 1 đơn vị sau mỗi 1,6us và tràn sau 104,8576ms.
Yêu cầu : các hằng số phải được định nghĩa trong device file PIC18F452.h
SET_TIMER1()
Cú pháp : set_timer1()
Tham số : 16 bit, value = 0~65535
Trị trả về : không
Chức năng : Đặt giá trị ban đầu cho real time clock/counter. Tất cả các biến đều đếm tăng. Khi giá trị timer vượt quá 65535, value được đặt trở lại 0 và đếm tiếp tục (, 65534, 65535, 0, 1, 2, )
Yêu cầu : không.
SETUP_TIMER2()
Cú pháp : setup_timer_2(mode,period,postscale)
Tham số : mode - tham số như sau
T2_DISABLED : tắt timer2
T2_DIV_BY_1
T2_DIV_BY_4
T2_DIV_BY_16
Period – 0~255 qui định khi giá trị clock được reset
Postscale – 1~16 qui định số lần reset timer trước khi ngắt (interupt)
Trị trả về : không
Chức năng : Khởi động timer 2. mode qui định số chia xung clock. Sau đó timer 2 có thể được ghi hay đọc dùng lệnh set_timer2() hay get_timer2(). Timer 1 là 8 bit counter/timer.
Yêu cầu: các hằng số phải được định nghĩa trong device file PIC18F452.h
SET_TIMER2()
Cú pháp : set_timer2(value)
Tham số : 8 bit, value = 0~255
Trị trả về : không
Chức năng : Đặt giá trị ban đầu cho real time clock/counter. Tất cả các biến đều đếm tăng. Khi giá trị timer vượt quá 255, value được đặt trở lại 0 và đếm tiếp tục (, 254, 255, 0, 1, 2, )
Yêu cầu: không.
SET_PWM1_DUTY(value); SET_PWM2_DUTY(value)
Cú pháp : set_pwm1_duty(value)
Tham số : value có thể là biến hay hằng số với 8 hay 16 bit
Trị trả về : không
Chức năng : xác định % thời gian trong 1 chu kỳ, PWM ở mức cao
Yêu cầu : không
Ví dụ: set_pwm1_duty(512): đặt 50% mức cao (50% duty)
SETUP_CCP1(); SETUP_CCP2()
Cú pháp : setup_ccp1(mode)
setup_ccp2(mode)
Tham số : mode là hằng số như sau
long CCP_1;
#byte CCP_1 = 0x15
#byte CCP_1_LOW = 0x15
#byte CCP_1_HIGH = 0x1