Truyền 1 byte dữ liệu

Một phần của tài liệu Lập trình 8051 siêu chi tiết (Trang 107)

Khi truyền 1 byte dữ liệu, bit có trọng số cao nhất (bit 7) sẽ được truyền trước. Khi bit cuối cùng (bit 0) được truyền, sẽ có thêm bit ACK báo hiệu kết thúc 1 byte dữ liệu.

Truyền từ master xuống slave:

Ở chế độ này, master sẽ gửi 8 bit dữ liệu, sau khi nhận xong 8 bit này, slave sẽ tự động gửi lại 1 bit ACK và master phải tạo ra thêm 1 clock để nhận bit ACK này.

//write I2C

void write_I2C(unsigned char data2send) {

int i;

for (i=0;i<8;i++) {

SDA = (data2send & 0x80) ? 1:0; SCL=1; nop(); SCL=0; data2send<<=1; nop(); }

//clock to receive ACK from slave SCL = 1;

nop();nop(); SCL = 0; }

Truyền từ slave lên master

Ở chế độ này, master sẽ nhận vào 8 bit dữ liệu, và sau khi nhận xong, master phải gửi 1 bit ACK xuống slave. Trong quá trình đọc 1 chuỗi byte từ slave, master gửi bit ACK. Đối với byte cuối cùng, master sẽ gửi bit NO ACK và sau đó gửi tín hiệu stop. Hàm đọc 1 byte sau đây có tham số là ACK_Bit, dùng để phân biệt ACK và NACK.

unsigned char read_I2C(bit ACK_Bit) {

unsigned char Data=0; int i; SDA = 1; for (i=0;i<8;i++) { SCL = 1; Data<<= 1;

Data = (Data | SDA); SCL = 0;

nop(); }

if (ACK_Bit == 1)

SDA = 0; // Send ACK else

SDA = 1; // Send NO ACK nop();nop();

//clock to send (N)ACK SCL = 1; nop();nop(); SCL = 0; return Data; } 16.8.4 Giao tiếp với DS1307

Ghi dữ liệu vào DS1307

Đây là quá trình truyền dữ liệu từ master xuống slave. Khi master gửi xong 1 byte, slave sẽ gửi lại bit ACK. Quá trình giao tiếp như sau:

vMaster gửi tín hiệu Start.

vMaster gửi địa chỉ của DS1307 (1101 000) và bit R/W, trong trường hợp này là 0. Byte đầu tiên mà master gửi xuống sau khi start là D0.

vMaster gửi địa chỉ pointer dữ liệu cần ghi, chẳng hạn là 0x00 (register pointer, word address)

vMaster gửi các byte data cần ghi.

vMaster gửi tín hiện stop.

Code hiện thực cho quá trình này như sau

void write_RTC(unsigned char *buff) {

start_I2C(); write_I2C(0xD0); write_I2C(0x00); write_I2C(*(buff+0)); (adsbygoogle = window.adsbygoogle || []).push({});

BKIT HARDWARE CLUB www.bkit4u.com 109 write_I2C(*(buff+3)); write_I2C(*(buff+4)); write_I2C(*(buff+5)); write_I2C(*(buff+6)); stop_I2C(); }

buff là 1 mảng có 7 phần tử, tương ứng với các giá trị giây, phút, giờ, thứ, ngày, tháng và năm.

Đọc dữ liệu từ DS1307

Đây là quá trình truyền dữ liệu từ slave lên master. Như đã trình bày ở phần trước, khi gửi nhận từng byte, sẽ có bit ACK đi kèm ngoại trừ byte cuối cùng trước khi stop.

Để có thể đọc chính xác giá trị mong muốn, thông thường ta phải ghi vào thanh ghi địa con trỏ dữ liệu (register pointer). Quá trình này chính là trình truyền dữ liệu từ master xuống slave nên R/W bit sẽ là 0. Sau khi ghi dữ liệu và register pointer xong, quá trình đọc dữ liệu mới bắt đầu, và bit R/W sẽ là 1.

Từng bước đọc dữ liệu từ DS1307 như sau:

vMaster gửi tín hiệu start.

vMaster gửi địa chỉ DS1307 + R/W = 0 : 0xD0.

vMaster gửi byte ghi vào register pointer : 0x00.

vMaster gửi tín hiệu start

vMaster gửi địa chỉ DS1307 + R/W = 1 : 0xD1.

vMaster đọc các byte dữ liệu và gửi bit ACK. Byte cuối cùng trước khi stop, master gửi bit NACK.

vMaster gửi tín hiện stop.

Code hiện thực cho quá trình này như sau

void read_RTC(unsigned char * buff) {

//send address to slave and reset pointer start_I2C();

write_I2C(0xD0); //address + direction write_I2C(0x00); //pointer data

//start read operation start_I2C(); write_I2C(0xD1); *(buff+0)=read_I2C(ACK); // Second *(buff+1)=read_I2C(ACK); // Minute *(buff+2)=read_I2C(ACK); // hour *(buff+3)=read_I2C(ACK); // Day

*(buff+4)=read_I2C(ACK); // date *(buff+5)=read_I2C(ACK); // month *(buff+6)=read_I2C(NO_ACK); // year stop_I2C();

}

Hàm main() dưới đây minh hoạ cho việc sử dụng các hàm trong module RTC DS1307: void main() { P1 = P3 = 0x00; RTC_ARR[0] = 0x12; //second = 12 RTC_ARR[1] = 0x55; // minute = 55

RTC_ARR[2] = 0x05; // hour = 05 ,24-hour mode(bit 6=0) RTC_ARR[3] = 0x01; // Day = 1 or sunday

RTC_ARR[4] = 0x01; // Date = 01 RTC_ARR[5] = 0x08; // month = August RTC_ARR[6] = 0x05; // year = 05 or 2005 write_RTC(&RTC_ARR[0]); // Set RTC

while(1) {

read_RTC(&RTC_ARR[0]); //read 7 bytes RTC P3=RTC_ARR[0]; //out second to P3

delay();; // delay about 1 second }

Một phần của tài liệu Lập trình 8051 siêu chi tiết (Trang 107)