Вы находитесь на странице: 1из 10

4/30/2011 Trang web của Nguyễn Quang Nam

Các chuẩn truyền thông và giao tiếp


Trang web cá nhân của Nguyễn Quang Nam

Trang chủ
• Học vấn
• Giảng dạy
• Nghiên cứu
• Sở thích
• In

Trang này dành cho các chuẩn truyền thông và giao tiếp. Bắt đầu là chuẩn dễ tiếp xúc nhất, RS-232,
sau đó là chuẩn RS-485 khi tôi hướng dẫn các sinh viên thực hiện các đề tài liên quan đến giao tiếp
giữa các PLC với nhau hay với các thiết bị công nghiệp. Ngoài ra, các giao tiếp như 1-Wire, I²C, và
SPI cũng được hỗ trợ khá tốt trong các vi điều khiển mà tôi đang sử dụng, nên cũng nhận được sự
quan tâm đáng kể. Nhưng thách thức nhất đối với tôi hiện nay chính là chuẩn giao tiếp USB.

Nếu bạn nhận thấy trang web này có ích, mong bạn chỉ phổ biến liên kết đến trang này chứ không
sao chép nội dung của trang này đến nơi khác. Xin chân thành cám ơn bạn!

Giao tiếp RS-232 cập nhật 21/9/2006


Giao tiếp RS-485
Giao tiếp I²C cập nhật 23/9/2006
Giao tiếp SPI
Giao tiếp 1-Wire
Giao tiếp USB

Giao tiếp RS-232


Cơ bản về giao tiếp RS-232

Chuẩn RS-232 được phát triển bởi the Electronic Industry Association and the Telecommunications
Industry Association (EIA/TIA), là chuẩn truyền thông phổ biến nhất, thường được gọi tắt là RS-232
thay vì EIA/TIA-232-E. Chuẩn này chỉ đề cập đến việc truyền dữ liệu nối tiếp giữa một host (DTE-
Data Terminal Equipment) và một ngoại vi (DCE-Data Circuit-Terminating Equipment).

Phiên bản đầu tiên của RS-232 được định nghĩa vào năm 1962, do đó các mức logic được định nghĩa
khác với logic TTL. Ở ngõ ra của một mạch lái, mức cao (tương ứng với logic 0) là một điện áp từ +5
đến +15 V, còn mức thấp (tương ứng với logic 1) là một điện áp từ -5 đến -15 V. Tại ngõ vào của một
bộ thu, mức cao được định nghĩa là từ +3 đến +15 V (gọi là space), và mức thấp được định nghĩa là từ
-3 đến -15 V (gọi là mark).

Để giảm nguy cơ bị nhiễu giữa các tín hiệu kế cận, tốc độ thay đổi (slew rate) được giới hạn tối đa là
30 V/μs, và tốc độ cũng được giới hạn tối đa là 20 kbps (kilobit per second) (giới hạn này hiện đã
được nâng lên nhiều lần).

www4.hcmut.edu.vn/…/Commu.php 1/10
4/30/2011 Trang web của Nguyễn Quang Nam
Trở kháng nhìn bởi mạch lái được định nghĩa là từ 3 đến 7 kΩ. Tải dung tối đa của đường truyền
cũng được giới hạn là 2500 pF, và như vậy tùy thuộc vào loại cáp mà chiều dài tối đa có thể được xác
định từ điện dung trên đơn vị chiều dài của cáp.

Các tín hiệu RS-232 được định nghĩa tại DTE, theo bảng sau (chỉ nói đến các tín hiệu của đầu nối 9
chân)

Chân số Chức năng Chiều thông tin


1 Data Carrier Detect (DCD) Từ DCE
2 Receive Data Line (RD) Từ DCE
3 Transmit Data Line (TD) Đến DCE
4 Data Terminal Ready (DTR) Đến DCE
5 Ground
6 Data Set Ready (DSR) Từ DCE
7 Request To Send (RTS) Đến DCE
8 Clear To Send (CTS) Từ DCE
9 Ring Indicate (RI) Từ DCE

Các hệ thống logic hiện nay chủ yếu sử dụng các chuẩn logic TTL hay CMOS, do đó khi cần giao
tiếp bằng chuẩn RS-232 sẽ phải dùng các mạch lái và thu (RS-232 driver và receiver, hay RS-232
transceiver) để chuyển đổi giữa TTL/CMOS và RS-232 vật lý. Các bộ transceiver hiện nay thường có
sẵn các bơm điện tích (charge pump) để tạo ra các mức áp RS-232 vật lý (phổ biến là +12 V và -12
V) từ một điện áp nguồn đơn cực giá trị nhỏ (5 V hay 3.3 V).

Vì chuẩn RS-232 chỉ dành cho giao tiếp giữa DTE và DCE, do đó khi hai máy tính (là các DTE) cần
giao tiếp với nhau thông qua chuẩn RS-232 thì cần phải có các DCE (chẳng hạn như modem) làm
trung gian. Các DCE này là các ngoại vi nên có thể giao tiếp trực tiếp với nhau thông qua một chuẩn
nào ¼ó.

Hình 1 minh họa định dạng của một ký tự (character) được truyền theo chuẩn RS-232. Ở trạng thái
nghỉ, các đường dữ liệu RS-232 ở trạng thái mark. Một ký tự luôn bắt đầu bằng một start bit (là một
space), sau đó các bit được truyền theo thứ tự bit từ thấp đến cao (bit thấp nhất được truyền trước
tiên), tiếp đến là một parity bit (nếu có), và cuối cùng là một hay nhiều stop bit (là một mark). Phổ
biến nhất là định dạng 8N1, nghĩa là 8 bit dữ liệu, không có parity, và 1 stop bit.

Hình 1. Định dạng của một ký tự truyền theo chuẩn RS-232

Việc đọc một bit được truyền đến thường được thực hiện tại giữa bit, do đó các bộ thu và phát thường
sử dụng xung clock bằng 16 lần tốc độ baud (số bit truyền được trong mỗi giây trên một đường tín
hiệu). Bộ thu sẽ dò start bit, và sẽ đọc bit đầu tiên sau 24 chu kỳ xung clock khi đã phát hiện được
start bit, các bit sau đó sẽ được đọc sau mỗi 16 chu kỳ xung clock.

Như có thể thấy, việc đồng bộ xung clock giữa phía thu và phía phát được thực hiện ở mỗi start bit
cho mỗi ký tự được truyền. Do đó, trong trường hợp xấu nhất là truyền 12 bit (1 start bit, 8 bit dữ liệu,
www4.hcmut.edu.vn/…/Commu.php 2/10
4/30/2011 Trang web của Nguyễn Quang Nam
1 parity bit, và 2 stop bit), chúng ta có thể chấp nhận việc lệch giá trị xung clock giữa phía thu và phía
phát tối đa là khoảng 3% (tại bit cuối cùng sẽ bị lệch 11x3 = 33%). Do đó, chúng ta không nhất thiết
phải sử dụng các bộ dao động thật chính xác để tạo xung clock cho các bộ thu phát RS-232. Hay nói
cách khác, chúng ta không cần độ sai lệch xung clock là 0% đối với giao tiếp RS-232.

Đa số các DTE và các DCE đều có các bộ truyền nhận bất đồng bộ đa dụng (UART-Universal
Asynchronous Receiver/Transmitter) ở dạng module phần cứng, do đó chúng ta thường không cần
quan tâm đến các thao tác cấp thấp trong việc sử dụng giao tiếp RS-232. Tuy nhiên, nếu phần cứng
của thiết bị không hỗ trợ giao tiếp RS-232, chúng ta có thể sử dụng một UART ngoài hay sử dụng
phần mềm để giả lập một UART (kỹ thuật này thường được gọi là bit-banging).

Tài liệu tham khảo: Application Note 83 của Dallas Semiconductor-Fundamentals of RS-232 Serial
Communications; Jan Axelson-Serial Port Complete

Sử dụng môđun USART trong PIC

Các thanh ghi liên quan đến môđun USART trong PIC gồm có SPBRG (thanh ghi tạo tốc độ baud),
TXSTA (thanh ghi trạng thái phát), RCSTA (thanh ghi trạng thái thu), TXREG (thanh ghi phát),
RXREG (thanh ghi thu) và các thanh ghi liên quan đến ngắt.

Với các PIC16, thanh ghi PIR1 chứa các cờ ngắt liên quan và thanh ghi PIE1 kết hợp với thanh ghi
INTCON chứa các cờ cho phép ngắt liên quan đến môđun USART. Với các PIC18, thanh ghi PIRx
chứa các cờ ngắt liên quan, thanh ghi IPRx chứa các bit thiết lập độ ưu tiên ngắt, thanh ghi PIEx kết
hợp với thanh ghi INTCON chứa các cờ cho phép ngắt liên quan đến môđun USART. Vị trí cụ thể
của từng bit tùy thuộc vào chip cụ thể, bạn cần tham khảo thêm datasheet của chip được dùng để có
các thông tin cần thiết.

Thanh ghi SPBRG được thiết lập để tạo ra tốc độ baud cần thiết Baud theo công thức sau:

SPBRG = (Fosc/(16 x Baud)) - 1, với bit BRGH = 1

SPBRG = (Fosc/(64 x Baud)) - 1, với bit BRGH = 0

Dưới đây là một ví dụ về chương trình con khởi tạo môđun USART của PIC16, viết bằng hợp ngữ:
KhoiTaoUSART:
movlw 0x33 ;Gia tri toc do baud ung voi 9600, BRGH = 1, xtal 8 MHz
banksel SPBRG ;Chon bank cho SPBRG
movwf SPBRG ;Dat toc do baud = 9600
movlw 0x24 ;Che do: high-speed, cho phep xuat, truyen bat dong bo
movwf TXSTA ;TXSTA cung bank voi SPBRG
; bsf PIE1, TXIE ;Cho phep ngat xuat, PIE1 cung bank voi TXSTA
; bsf PIE1, RCIE ;Cho phep ngat nhap
; bsf INTCON, PEIE ;Cho phep ngat ngoai vi
;INTCON truy xuat duoc tu moi bank
; bsf INTCON, GIE ;Bat co ngat global
movlw 0x90 ;Che do: nhan lien tuc, 8-bit, dung cac chan TX/RX
banksel RCSTA ;Chon bank cho RCSTA
movwf RCSTA
return

Kế tiếp là một ví dụ về chương trình con khởi tạo môđun USART của PIC18, viết bằng C18:

www4.hcmut.edu.vn/…/Commu.php 3/10
4/30/2011 Trang web của Nguyễn Quang Nam
void Init_UART(void)
{
TXSTA = 0x06; //8-bit, high speed, bat dong bo
BAUDCON = 0x40; //Chi dung SPBRG
SPBRG = (freq/16/baud) - 1;
RCSTA = 0x90; //Bat module USART và cho phep nhan lien tuc
// IPR1bits.TXIP = 1; //Ngat phat o do uu tien cao
// PIE1bits.TXIE = 0; //Ban dau khong cho phep ngat phat
PIR1bits.RCIF = 0; //Xoa co ngat thu
IPR1bits.RCIP = 1; //Ngat thu o do uu tien cao
PIE1bits.RCIE = 1; //Cho phep ngat thu
}

Để phát thông tin thì bạn ghi giá trị byte cần phát vào thanh ghi TXREG, đặt trạng thái cho bit TX9D
trong thanh ghi TXSTA nếu dùng dữ liệu 9-bit. Thông thường, chúng ta kiểm tra xem bộ đệm phát có
trống hay không rồi mới phát, nếu viết trong C18 thì có thể viết như sau:
while (PIR1bits.TXIF == 0);
TXREG = temp;

Tương tự như trên, chúng ta thường kiểm tra xem đã có dữ liệu vừa được nhận hay không, nếu có thì
đọc dữ liệu từ bộ đệm thu, nếu viết trong C18 thì có thể viết như sau:
while (PIR1bits.RCIF == 0);
temp = RCREG;

Tài liệu tham khảo: Microchip-Getting Started - USART; Microchip-PIC18FXXX DFT Hands On
Workshop

Sử dụng môđun UART trong dsPIC

Các thanh ghi liên quan đến môđun UART trong dsPIC gồm có UxBRG (thanh ghi tạo tốc độ baud),
UxMODE (thanh ghi chế độ), UxSTA (thanh ghi trạng thái), UxTXREG (thanh ghi phát), UxRXREG
(thanh ghi thu) và các thanh ghi liên quan đến ngắt, với x (= 1 hay 2) là số hiệu của môđun.

Về các thanh ghi liên quan đến ngắt, các thanh ghi IFSx chứa các cờ ngắt, các thanh ghi IECx chứa
các cờ cho phép ngắt, và các thanh ghi IPCx chứa các giá trị độ ưu tiên ngắt (dài 3-bit). Tham khảo
datasheet của chip để biết giá trị cụ thể của x.

Tốc độ baud của môđun UART được thiết lập thông qua thanh ghi UxBRG, theo công thức:

UxBRG = (Fcy/(16 x Baud)) - 1

với Fcy là tần số thực thi lệnh, Baud là tốc độ baud cần thiết.

dsPIC hỗ trợ các vectơ ngắt độc lập cho việc thu hay phát, và cho từng môđun. Lấy ví dụ một chip
dsPIC có 2 môđun UART1 và UART2, chip sẽ có 4 vectơ ngắt riêng biệt cho việc thu hay phát của
môđun UART1 cũng như thu hay phát của môđun UART2. Tất nhiên mỗi (vectơ) ngắt đều có cờ
ngắt, cờ cho phép ngắt, cũng như các bit thiết lập độ ưu tiên ngắt riêng biệt.

Dưới đây là một ví dụ về chương trình con khởi tạo môđun UART1 của dsPIC, viết bằng C30:
void Init_UART1_Module(void) {

www4.hcmut.edu.vn/…/Commu.php 4/10
4/30/2011 Trang web của Nguyễn Quang Nam
U1MODE = 0x8000; //Main I/O, 8-bit, khong co parity, 1 stop bit
U1STA = 0x0400; //bit10=UTXEN
U1BRG = (((8000000/38400)/16)-1); //38400 bps @ Fcy = 8 MHz
}

Để phát thông tin ra bằng môđun UART, bạn chỉ cần ghi vào thanh ghi U1TXREG (hay U2TXREG),
với điều kiện tất nhiên là chúng ta đã khởi tạo cho chế độ phát. Chú ý là module UART của dsPIC có
bộ đệm phát 4 mức, do đó bạn có thể ghi liên tiếp 5 ký tự mà vẫn không làm tràn bộ đệm phát ở lần
phát ký tự đầu tiên (vì ngoài bộ đệm phát còn có thanh ghi dịch khi phát, đang còn trống).

Chú ý: Khi dùng chế độ phát, bit UTXEN (trong thanh ghi UxSTA) chỉ nên được bật khi đã bật bit
UARTEN (trong thanh ghi UxMODE).

Chúng ta thường kiểm tra trạng thái của bộ đệm trước khi xuất dữ liệu tiếp theo, như trong ví dụ dưới
đây (viết bằng C30):
while (!U1STAbits.TRMT); //Cho den khi bo dem phat trong
U1TXREG = Chuoi1[idx++]; //Phat du lieu ke tiep

Tương tự như vậy, bạn đọc từ thanh ghi U1RXREG (hay U2RXREG) để lấy thông tin đã được môđun
UART nhận từ bên ngoài, tất nhiên là chúng ta đã khởi tạo đầy đủ cho chế độ thu. Bộ đệm thu cũng
có 4 mức, và bạn có thể thiết lập để môđun UART chỉ tạo ra ngắt khi có đủ 4 word ở bộ đệm (điều
này giúp làm giảm số lần vào ngắt thu).

Để thực hiện công việc một cách hiệu quả, chúng ta thường hỏi vòng qua tất cả các phần của chương
trình để thực hiện các thao tác cần thiết. Đoạn mã dưới đây (viết bằng C30) có thể được dùng như
một phần của quá trình hỏi vòng đó.
if (U1STAbits.URXDA) { //Co du lieu moi hay khong?
temp = U1RXREG; //Co, doc du lieu da nhan duoc vao temp
};

Tài liệu tham khảo: Microchip-dsPIC30F Family Reference Manual; Nguyễn Quang Nam-dsPIC
Tutorial 4: Sử dụng các module UART và I2C của dsPIC

Giao tiếp RS-485

Giao tiếp I²C


Cơ bản về giao tiếp I²C

I²C-bus là một bus với 2 đường tín hiệu, dùng để kết nối nhiều vi mạch với nhau. Đây là một bus
dùng quan hệ master/slave, với master khởi đầu mọi thao tác truyền dữ liệu, và tạo xung clock cho
bus. I²C hỗ trợ nhiều master cùng tồn tại trên bus, có phát hiện xung đột và phân xử bus để tránh
trường hợp có từ 2 master trở lên cùng khởi đầu việc truyền dữ liệu (vì ở mỗi thời điểm chỉ có thể có
một master điều khiển việc truyền dữ liệu trên bus).
www4.hcmut.edu.vn/…/Commu.php 5/10
4/30/2011 Trang web của Nguyễn Quang Nam
I²C-bus hỗ trợ truyền dữ liệu theo hai chiều, bán song công (nghĩa là master đang phát thì không thu
và ngược lại), với các tốc độ khác nhau như đến 100 kbps ở Standard-mode, đến 400 kbps ở Fast-
mode, và đến 3.4 Mbps (megabit/s) ở High-speed mode.

Số lượng vi mạch được nối vào bus chỉ bị giới hạn bởi điện dung bus tối đa là 400 pF. Do đó, tùy vào
chiều dài vật lý của cáp, điện dung của cáp, và điện dung ngõ vào của các vi mạch nối vào bus mà
chúng ta có thể xác định được có thể nối bao nhiêu vi mạch vào một bus cụ thể.

Các vi mạch nối vào I²C-bus có các chân SDA và SCL ở dạng cực thu/cực máng hở. Do đó các
đường SDA và SCL cần có các điện trở kéo lên, giá trị của các điện trở phụ thuộc vào điện áp nguồn,
tốc độ truyền và điện dung của bus (vì nó liên quan đến thời gian lên của các đường tín hiệu). Với
điện áp nguồn, tốc độ truyền, và điện dung bus đã biết, tồn tại một phạm vi cho phép đối với các
điện trở kéo lên: Rpmin < Rp < Rpmax. Các nhà sản xuất vi mạch thường có các khuyến cáo đối với
giá trị điện trở kéo lên dành cho vi mạch cụ thể.

Các điều kiện START, và STOP được định nghĩa như sau. Điều kiện START: một sự chuyển mức từ
CAO xuống THẤP ở đường SDA khi đường SCL ở trạng thái CAO. Điều kiện STOP: một sự chuyển
mức từ THẤP lên CAO ở đường SDA khi đường SCL ở trạng thái CAO. Các điều kiện này luôn luôn
do master tạo ra.

Khi master ghi dữ liệu, trình tự sau được tiến hành: START, địa chỉ của slave cùng với bit trạng thái
ghi, nhận ACK từ slave, ghi các byte dữ liệu vào slave, nhận ACK/NACK từ slave cho mỗi byte được
ghi, STOP. Trong trình tự này, chiều truyền dữ liệu là không đổi.

Để tạo ACK, chân SDA sẽ được kéo xuống mức THẤP bởi vi mạch chịu trách nhiệm tạo tín hiệu
ACK/NACK. Trạng thái NACK do đó tương ứng với việc chân SDA được thả ở mức CAO.

Khi master đọc dữ liệu, trình tự sau được tiến hành: START, địa chỉ của slave cùng với bit trạng thái
đọc, đọc các byte dữ liệu từ slave, tạo ACK nếu tiếp tục đọc và NACK cho byte dữ liệu sau cùng,
STOP. Trong trình tự này, chiều truyền dữ liệu là không đổi.

Nếu master cần thực hiện ghi/đọc dữ liệu kết hợp trong một thông điệp (bắt đầu bằng START và kết
thúc bằng STOP), các RESTART có thể được dùng để đổi chiều dữ liệu. Ở những phần mà dữ liệu
chỉ truyền theo một chiều nhất định, các trình tự đã được mô tả ở trên có thể được áp dụng.

Tài liệu tham khảo: Philips Semiconductors-The I²C-bus Specification; Microchip-dsPIC30F Family
Reference Manual

Sử dụng môđun MSSP trong chế độ I²C của PIC

Các thanh ghi liên quan đến môđun MSSP trong chế độ I²C của PIC gồm có SSPCON1 (thanh ghi
điều khiển 1), SSPCON2 (thanh ghi điều khiển 2), SSPSTAT (thanh ghi trạng thái), SSPADD (thanh
ghi địa chỉ, cũng dùng để tạo tốc độ baud), và SSPBUF (thanh ghi đệm dữ liệu), và các thanh ghi liên
quan đến ngắt.

Môđun MSSP hỗ trợ một số chế độ làm việc cho cả master và slave, nhưng chỉ có chế độ master với
sự hỗ trợ trực tiếp từ phần cứng được đề cập ở đây (vì đây là chế độ tận dụng phần cứng tốt nhất).
Chú ý: một số chip chỉ có môđun SSP sẽ không hỗ trợ làm việc ở chế độ master theo giao tiếp I²C.

www4.hcmut.edu.vn/…/Commu.php 6/10
4/30/2011 Trang web của Nguyễn Quang Nam
Thanh ghi PIR1 chứa cờ ngắt SSPIF và thanh ghi PIE1 kết hợp với thanh ghi INTCON chứa các cờ
cho phép ngắt liên quan đến môđun MSSP. Riêng với các PIC18, còn có thêm thanh ghi IPR1 chứa
bit thiết lập độ ưu tiên ngắt. Vị trí cụ thể của từng bit tùy thuộc vào chip được dùng, bạn cần tham
khảo thêm datasheet của chip được dùng để có các thông tin cần thiết.

Cờ ngắt SSPIF được bật khi xảy ra một trong các sự kiện: điều kiện START, điều kiện STOP, đã
phát/thu dữ liệu, truyền bit ACK/NACK, điều kiện RESTART (hay Start lặp lại). Tuy nhiên, mô tả
của Microchip về trình tự phát dữ liệu không khẳng định được việc có thể dùng bit này để xác định
môđun MSSP có rỗi hay không. Đồng thời Microchip lại đưa ra chú ý về bit R/W trong thanh ghi
SSPSTAT trong việc xác định khi nào môđun MSSP rỗi, do đó chương trình con chờ môđun MSSP
sẽ được viết theo cách thứ hai.

Để sử dụng môđun MSSP ở chế độ I²C, cần thiết lập các thanh ghi: SSPCON1 (thường chỉ quan tâm
đến bit SSPEN và đặt các bit SSPM<3:0> = 1000), SSPCON2 (đảm bảo 5 bit thấp nhất là 0),
SSPSTAT (đảm bảo là tắt slew rate control đối với tốc độ baud 100 kHz), và SPPADD (thiết lập tốc
độ baud). Giá trị của thanh ghi SSPADD được xác định theo công thức sau:

SPPADD = (Fosc/(4 x Baud)) - 1

với Fosc là tần số xung clock, Baud là tốc độ baud cần thiết.

Sau đây là một ví dụ về chương trình con khởi tạo chế độ master I²C cho môđun MSSP, viết bằng
C18:
void Init_I2C(void) {
SSPCON1 = 0x28; //Bat che do I2C cua MSSP, che do master
SSPCON2 = 0x00; //Tat cac co trang thai va cho phep
SSPSTAT |= 0xC0; //Tat slew rate control
SSPADD = (Fcy/Baud) - 1; //Dat toc do baud can thiet
}

Trước khi thực hiện một thao tác nào đó, cần đảm bảo là môđun MSSP đang ở trạng thái rỗi. Chúng
ta có thể thực hiện chương trình con kiểm tra trạng thái rỗi (viết bằng C18) của môđun MSSP (chế độ
I²C) như sau:
void Wait_I2C(void) {
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)) continue;
}

Các điều kiện START, STOP, và RESTART (hay START lặp lại) được tạo ra bằng cách bật các bit
SEN, PEN, và RSEN của thanh ghi SSPCON2 một cách tương ứng. Phần cứng sẽ tự động tắt các bit
này khi đã hoàn tất điều kiện.

Để ghi thông tin ra bus I²C, bạn chỉ cần ghi vào thanh ghi SSPBUF, sau đó chờ cho đến khi môđun
MSSP rỗi, và đọc trạng thái ACK/NACK được slave trả về. Dưới đây là một ví dụ về chương trình
con ghi thông tin ra bus I²C, viết bằng C18:
void Write_I2C(unsigned char d) {
SSPBUF = d;
Wait_I2C();
if (SSPCON2bits.ACKSTAT) flag1 |= 0x01;
}

Để đọc thông tin từ bus I²C, bạn chỉ cần bật cờ cho phép nhận RCEN (trong thanh ghi SSPCON2),
chờ cho môđun MSSP hoàn tất công việc, sau đó đọc từ thanh ghi SSPBUF, và tạo trạng thái
ACK/NACK như mong muốn. Sau đây là một ví dụ về chương trình con đọc thông tin từ bus I²C,

www4.hcmut.edu.vn/…/Commu.php 7/10
4/30/2011 Trang web của Nguyễn Quang Nam
viết bằng C18:
unsigned char Read_I2C(void) {
unsigned char d;
SSPCON2bits.RCEN = 1;
Wait_I2C();
d = SSPBUF;
if (flag2 & 0x0001) SSPCON2bits.ACKDT = 1;
else SSPCON2bits.ACKDT = 0;
SSPCON2bits.ACKEN = 1;
Wait_I2C();
return d;
}

Chú ý: Hoàn toàn có thể dùng một trình biên dịch C nào đó để viết các chương trình con tương tự
cho các PIC16. Về mặt cú pháp thì các trình biên dịch C chuẩn đều tương thích nhau, nhưng có khả
năng cách đặt tên bit và thanh ghi chức năng của mỗi trình biên dịch C là khác nhau đôi chút.

Tài liệu tham khảo: Microchip-PICmicro Mid-range MCU Family Reference Manual;
Microchip-PICmicro 18C Family Reference Manual

Sử dụng môđun I²C của dsPIC

Các thanh ghi liên quan đến môđun I²C trong dsPIC gồm có I2CBRG (thanh ghi tạo tốc độ baud),
I2CCON (thanh ghi điều khiển), I2CSTAT (thanh ghi trạng thái), I2CTRN (thanh ghi phát), I2CRCV
(thanh ghi thu), I2CADD (thanh ghi địa chỉ ở chế độ slave), và các thanh ghi liên quan đến ngắt.

Tương tự như với môđun UART, các thanh ghi IFSx chứa các cờ ngắt, các thanh ghi IECx chứa các
cờ cho phép ngắt, và các thanh ghi IPCx chứa các giá trị độ ưu tiên ngắt (dài 3-bit). Tham khảo
datasheet của chip để biết giá trị cụ thể của x.

Môđun I²C chỉ tạo ra ngắt MI2CIF khi hoàn tất một sự kiện nào đó ở chế độ master, và ngắt SI2CIF
khác khi phát hiện có sự kiện dành cho nó ở chế độ slave. Ở chế độ master, các sự kiện sau sẽ tạo ra
ngắt MI2CIF: điều kiện START, điều kiện STOP, đã phát/thu dữ liệu, truyền bit ACK/NACK, điều
kiện RESTART (hay Start lặp lại), phát hiện xung đột bus. Ở chế độ slave, các sự kiện sau tạo ra ngắt
SI2CIF: phát hiện địa chỉ hợp lệ (kể cả general call), yêu cầu phát dữ liệu, thu được dữ liệu.

Để sử dụng môđun I²C của dsPIC ở chế độ master, cần thiết lập các thanh ghi: I2CCON (thường chỉ
quan tâm đến các bit I2CEN và DISSLW), và I2CBRG. Giá trị của thanh ghi I2CBRG được xác định
theo công thức sau:

I2CBRG = ((Fcy/Baud) - (Fcy/1111111)) - 1

với Fcy là là tần số thực thi lệnh, Baud là tốc độ baud cần thiết.

Sau đây là một ví dụ về chương trình con khởi tạo chế độ master cho môđun I²C, viết bằng C30:
void Init_I2C(void) {
I2CCON = 0x8200; //bit15=I2CEN, bit9=DISSLW (tat Slew Rate
//Control cho cac toc do baud khac 400 kbps)
I2CBRG = (((Fcy/I2Cbaud) - (Fcy/1111111))-1);
}

www4.hcmut.edu.vn/…/Commu.php 8/10
4/30/2011 Trang web của Nguyễn Quang Nam
Theo thông tin về cách tạo ngắt của môđun I²C ở chế độ master, sau mỗi thao tác như tạo điều kiện
START, STOP, RESTART, xuất/nhập dữ liệu, đọc/tạo trạng thái ACK/NACK đều có thể kiểm tra cờ
MI2CIF để đảm bảo thao tác đã hoàn tất trước khi thực hiện thao tác tiếp theo, và đây cũng là cách
được khuyên dùng.

Có thể thực hiện điều này bằng một chương trình con Wait_I2C() như ví dụ dưới đây (viết bằng C30),
được gọi sau mỗi thao tác cần kiểm tra trạng thái cờ MI2CIF như đã nêu trên.
void Wait_I2C(void) {
while (!_MI2CIF);
_MI2CIF = 0;
}

Các điều kiện START, STOP, và RESTART (hay START lặp lại) được tạo ra bằng cách bật các bit
SEN, PEN, và RSEN của thanh ghi I2CCON một cách tương ứng. Phần cứng sẽ tự động tắt các bit
này khi đã hoàn tất điều kiện.

Để ghi thông tin ra bus I²C, bạn chỉ cần ghi vào thanh ghi I2CTRN, sau đó chờ cho cờ MI2CIF bật,
và đọc trạng thái ACK/NACK được slave trả về. Dưới đây là một ví dụ về chương trình con ghi thông
tin ra bus I²C, viết bằng C30:
void Write_I2C(unsigned char d) {
I2CTRN = d;
Wait_I2C();
if (_ACKSTAT) flag1 |= 0x0001; //Bat co flag1 neu nhan duoc NACK
}

Để đọc thông tin từ bus I²C, bạn chỉ cần bật cờ cho phép nhận RCEN, sau đó đọc từ thanh ghi
I2CRCV, và tạo trạng thái ACK/NACK như mong muốn. Sau đây là một ví dụ về chương trình con
đọc thông tin từ bus I²C, viết bằng C30:
unsigned char Read_I2C(void) {
unsigned char d;
_RCEN = 1; //Cho phep nhan byte
Wait_I2C(); //Cho hoat dong I2C hoan tat
d = I2CRCV; //Lay byte da nhan dat vao d
if (flag2 & 0x0001) _ACKDT = 1; //Neu NACK thi bat ACKDT
else _ACKDT = 0; //Nguoc lai thi tat ACKDT
_ACKEN = 1; //Ghi bit ACK/NACK ra I2C bus
Wait_I2C(); //Cho hoat dong I2C hoan tat
return d; //Tra byte da doc ve chuong trinh goi
}

Tài liệu tham khảo: Microchip-dsPIC30F Family Reference Manual; Nguyễn Quang Nam-dsPIC
Tutorial 4: Sử dụng các module UART và I2C của dsPIC

Giao tiếp SPI

www4.hcmut.edu.vn/…/Commu.php 9/10
4/30/2011 Trang web của Nguyễn Quang Nam
Giao tiếp 1-Wire

Giao tiếp USB

Trang này đã được viếng thăm 4330 lần, kể từ ngày 14/5/2006

Cập nhật ngày: 23/9/2006

www4.hcmut.edu.vn/…/Commu.php 10/10

Вам также может понравиться