GIAO TIẾP I2C

Giao tiếp I2C cho vi điều khiển 8051

Cũng như giao tiếp UART, I2C là chuẩn giao tiếp nối tiếp sử dụng 2 dây phát triển bởi Philips… cái này có thể tra google để biết thêm, mình sẽ ko giới thiệu về lịch sử phát triển mà hương dẫn bạn code luôn :)

I2C được ứng dụng rất nhiều trong tất cả các thiết bị do lường, cảm biến, module, VDK, IC thời gian thực, EEPROM 24Cxx …… nên khi học VDK bạn sẽ ko thể bỏ qua nó vì các ứng dụng sau này sẽ phải cần đến nó.

Để giao tiếp được với các thiết bị trên ta phải kết nối chúng với nhau qua 2 dây là SDA (dữ liệu 2 chiều) và SCL (xung nhịp). I2C cho phép tất cả các thiết bị có I2C nối chung đường giao tiếp tức là VD có 3 thiết bị có I2C thì có thể dùng chung 2 dây giao tiếp SDA và SCL, tại sao có thể chung như vậy dc là vì tất cả các thiết bị I2C đều phải có 1 địa chỉ riêng(như là mỗi ng có 1 tên vậy – gọi tới ai thì ng đó mới dc giao tiếp) đây là mối quan hệ Chủ-Tớ (Master-Slave)

Giao tiếp I2C cho vi điều khiển 8051 - SangTaoClub.Net

Khác với PIC và AVR dc tích hợp sẵn 1 cổng I2C thì 8051 hơi thiệt thòi một chút nhưng ko sao ta vẫn có thể giao tiếp bình thường khi xây dựng Hàm thư viện viết sẵn.

Giao tiếp I2C cho vi điều khiển 8051 - SangTaoClub.Net

Dưới đây là các hàm giao tiếp I2C cho 8051:

/****************Khai báo chân giao tiep I2C***************************/

#define SCL    P0_3
#define SDA    P0_2

/****************Cac ham giao tiep I2C***************************/
void I2C_time_start(){
SCL = 1;
SDA = 1;
SDA = 0;
SCL = 0;
}
void I2C_time_stop(){
SCL = 1;
SDA = 0;
SDA=1;
SCL=1;
}
unsigned char I2C_write(unsigned char dat){
unsigned char i;
for (i=0;i<8;i++){
SDA = (dat & 0x80); ///? 1:0;
SCL=1;
SCL=0;
dat<<=1;
}
SCL = 1;
SCL = 0;
return dat;
}
unsigned char I2C_read(void){
bit rd_bit;
unsigned char i, dat;
dat = 0x00;
for(i=0;i<8;i++){ /* For loop read data 1 byte */
SCL = 1;
rd_bit = SDA; /* Keep for check acknowledge */
dat = dat<<1;
dat = dat | rd_bit; /* Keep bit data in dat */
SCL = 0; /* Clear SCL */
}
return dat;
}

Như code trên ta chỉ cần viết I2C_write(dữ liệu); để gửi dữ liệu đi và I2C_read(); để lấy dữ liệu về

Code I2C giao tiếp IC thời gian thực DS1307:

/***************Dia chi giao tiep DS1307*********************/
#define DS1307_SEC      0x00 //Giay
#define DS1307_MIN       0x01 //Phut
#define DS1307_HOUR     0x02 //Gio
#define DS1307_DAY        0x03 //Thu
#define DS1307_DATE      0x04 //Ngay
#define DS1307_MONTH    0x05 //Thang
#define DS1307_YEAR       0x06 //Nam

void DS1307_Write(unsigned char addr,unsigned char dat){
unsigned int temp;
temp = dat ; /*HEX to BCD*/
dat = (((dat/10)*16)|(temp %10)); /*for Led 7seg*/
I2C_time_start(); /* time_start i2c bus */
I2C_write(0XD0); /* Connect to DS1307 */
I2C_write(addr); /* Requetime_5 RAM address on DS1307 */
I2C_write(dat);
I2C_time_stop();
}
unsigned char DS1307_Read(unsigned char addr){
unsigned int tm,ret;
I2C_time_start(); /* time_start i2c bus */
I2C_write(0xD0); /* Connect to DS1307 */
I2C_write(addr); /* Requetime_5 RAM address on DS1307 */
I2C_time_start(); /* time_start i2c bus */
I2C_write(0XD1); /* Connect to DS1307 for Read */
ret = I2C_read(); /* Receive data */
I2C_time_stop();
tm = ret; /*BCD to HEX*/
ret = (((ret/16)*10)+ (tm & 0x0f)); /*for Led 7seg*/
return ret;
}
void DS1307_Set(){
//Ghi du lieu ngay gio vao DS1307
DS1307_Write(DS1307_SEC,sec);
DS1307_Write(DS1307_MIN,min);
DS1307_Write(DS1307_HOUR,hour);
DS1307_Write(DS1307_DATE,day);
DS1307_Write(DS1307_MONTH,month);
DS1307_Write(DS1307_YEAR,year);
}
void DS1307_GetTime(){
//Doc du lieu gio tu DS1307
hour=DS1307_Read(DS1307_HOUR);
min=DS1307_Read(DS1307_MIN);
sec=DS1307_Read(DS1307_SEC);
}
void DS1307_GetDate(){
//Doc du lieu ngay tu DS1307
day=DS1307_Read(DS1307_DATE);
month=DS1307_Read(DS1307_MONTH);
year=DS1307_Read(DS1307_YEAR);
}//End code DS1307

Nguồn: http://sangtaoclub.net/

Comments