| I2C是由Philips公司發(fā)明的一種串行數(shù)據(jù)通信協(xié)議,僅使用兩根信號線:SerialClock(簡稱SCL)和SerialData(簡稱SDA)。I2C是總線結(jié)構(gòu),1個Master,1個或多個Slave,各Slave設(shè)備以7位地址區(qū)分,地址后面再跟1位讀寫位,表示讀(=1)或者寫(=0),所以我們有時也可看到8位形式的設(shè)備地址,此時每個設(shè)備有讀、寫兩個地址,高7位地址其實(shí)是相同的。 I2C數(shù)據(jù)格式如下: 無數(shù)據(jù):SCL=1,SDA=1; 開始位(Start):當(dāng)SCL=1時,SDA由1向0跳變; 停止位(Stop):當(dāng)SCL=1時,SDA由0向1跳變; 數(shù)據(jù)位:當(dāng)SCL由0向1跳變時,由發(fā)送方控制SDA,此時SDA為有效數(shù)據(jù),不可隨意改變SDA; 當(dāng)SCL保持為0時,SDA上的數(shù)據(jù)可隨意改變; 地址位:定義同數(shù)據(jù)位,但只由Master發(fā)給Slave; 應(yīng)答位(ACK):當(dāng)發(fā)送方傳送完8位時,發(fā)送方釋放SDA,由接收方控制SDA,且SDA=0; 否應(yīng)答位(NACK):當(dāng)發(fā)送方傳送完8位時,發(fā)送方釋放SDA,由接收方控制SDA,且SDA=1。 當(dāng)數(shù)據(jù)為單字節(jié)傳送時,格式為: 開始位,8位地址位(含1位讀寫位),應(yīng)答,8位數(shù)據(jù),應(yīng)答,停止位。 當(dāng)數(shù)據(jù)為一串字節(jié)傳送時,格式為: 開始位,8位地址位(含1位讀寫位),應(yīng)答,8位數(shù)據(jù),應(yīng)答,8位數(shù)據(jù),應(yīng)答,……,8位數(shù)據(jù),應(yīng)答,停止位。 需要注意的是: 1,SCL一直由Master控制,SDA依照數(shù)據(jù)傳送的方向,讀數(shù)據(jù)時由Slave控制SDA,寫數(shù)據(jù)時由Master控制SDA。當(dāng)8位數(shù)據(jù)傳送完畢之后,應(yīng)答位或者否應(yīng)答位的SDA控制權(quán)與數(shù)據(jù)位傳送時相反。 2,開始位“Start”和停止位“Stop”,只能由Master來發(fā)出。 3,地址的8位傳送完畢后,成功配置地址的Slave設(shè)備必須發(fā)送“ACK”。否則否則一定時間之后Master視為超時,將放棄數(shù)據(jù)傳送,發(fā)送“Stop”。 4,當(dāng)寫數(shù)據(jù)的時候,Master每發(fā)送完8個數(shù)據(jù)位,Slave設(shè)備如果還有空間接受下一個字節(jié)應(yīng)該回答“ACK”,Slave設(shè)備如果沒有空間接受更多的字節(jié)應(yīng)該回答“NACK”,Master當(dāng)收到“NACK”或者一定時間之后沒收到任何數(shù)據(jù)將視為超時,此時Master放棄數(shù)據(jù)傳送,發(fā)送“Stop”。 5,當(dāng)讀數(shù)據(jù)的時候,Slave設(shè)備每發(fā)送完8個數(shù)據(jù)位,如果Master希望繼續(xù)讀下一個字節(jié),Master應(yīng)該回答“ACK”以提示Slave準(zhǔn)備下一個數(shù)據(jù),如果Master不希望讀取更多字節(jié),Master應(yīng)該回答“NACK”以提示Slave設(shè)備準(zhǔn)備接收Stop信號。 6,當(dāng)Master速度過快Slave端來不及處理時,Slave設(shè)備可以拉低SCL不放(SCL=0將發(fā)生“線與”)以阻止Master發(fā)送更多的數(shù)據(jù)。此時Master將視情況減慢或結(jié)束數(shù)據(jù)傳送。 7,I2C規(guī)程運(yùn)用主/從雙向通訊。器件發(fā)送數(shù)據(jù)到總線上,則定義為發(fā)送器,器件接收據(jù) 定義為接收器。主器件和從器件都可以工作于接收和發(fā)送狀態(tài)。 總線必須由主器件(通常 為微控制器)控制,主器件產(chǎn)生串行時鐘(SCL)控制總線的傳輸方向,并產(chǎn)生起始和停止 條件。SDA線上的數(shù)據(jù)狀態(tài)僅在SCL為低電平的期間才能改變,SCL為高電平的期間,SDA 狀態(tài)的改變被用來表示起始和停止條件。 ? 在實(shí)際應(yīng)用中,并沒有強(qiáng)制規(guī)定數(shù)據(jù)接收方必須對于發(fā)送的8位數(shù)據(jù)做出回應(yīng),尤其是在Master和Slave端都是用GPIO軟件模擬的方法來實(shí)現(xiàn)的情況下,編程者可以事先約定數(shù)據(jù)傳送的長度,不發(fā)送ACK,有時可以起到減少系統(tǒng)開銷的效果。 源碼: /********************************************************************/ void i2c_init(void) { PACNT_init; PADDR_init; PADAT_init; SCL_high; SDA_high; } /********************************************************************/ uint8 i2c_write(uint8 slave_address, uint8 *buffer, int byte_count, int freq) { ????uint8 out_mask = 0x80; ????uint8 value = 0x00; ??uint8 send_byte = 0x00; ??uint8 status = 0x81; ??int count = 8; ??int clk_count = 0; int i = 0; /* Set delay value based on frequency. */ int D = (int) ((4000/freq) - 14); slave_address = (slave_address & 0xFE); ????????? ??i2c_start(); ??delay(500); ?? ?? send_byte = slave_address; ???????? ?? for(i = 0; i <= byte_count; i++) ?? {???? ????count = 8;?? ????out_mask = 0x80; ????????? ????/* Send data bytes one bit at a time. */??? ????while(count > 0) ????{???????????? ???? value = ((send_byte & out_mask) ? 1 : 0); ??????if (value == 1) ??????{ ?????? PADAT_init; ????????SDA_high;} ??????else ??????{ ?????? PADAT_init; ?????? SDA_low;} ??????? ??????delay(D);????? ??????????????????? ????????PADAT_init; ??????SCL_high; ?????? ??????/* Clock stretching wait statement.??Wait until clock is released ??????by slave.??Only effects program on first iteration.??*/ ?? while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;} ??????delay(2*D);?? ??????? ??????PADAT_init; ??????SCL_low; ??????delay(D);? ??????? ??????out_mask >>= 1;? ??????count--;??? ???? } ????? ???? PADAT_init; ???? SDA_high;??/* Let go of data pin. */ ???? delay(D);? ?????? ???? if (((GPIO_PADAT & 0x0400) ? 1 : 0) == 1) ???? {? ??????status = 0xA1; /* Transfer complete, bus busy, acknowledge not received. */ ??????break; } /* If not acknowledged, exit loop. */ ????? ????PADAT_init; ???? SCL_high; ???? delay(2*D);?? ???? ???? PADAT_init; ???? SCL_low; ???? status = 0xA0;??/* Transfer complete, bus busy, acknowledge received. */ ???? delay(D);? ????? ???? send_byte = buffer[i];?????? ????} ???? ????PADAT_init; ????SDA_high; ????SCL_low;??? delay(100); return(status); } /********************************************************************/ uint8 i2c_read(uint8 slave_address, uint8 *buffer, int byte_count, int freq) { uint8 input_byte = 0x00; uint8 value = 0x00; uint8 out_mask = 0x80; uint8 status = 0x81; int count = 8; int clk_count = 0; int i = 0; /* Set delay value based on frequency. */ int D = (int) ((4000/freq) - 14); slave_address = (slave_address | 0x01); ??? i2c_start(); delay(500); ??????????????? /**********??Write Address Procedure **********/ ?? ?? while(count > 0) ?? { ????value = ((slave_address & out_mask) ? 1 : 0); ???? if (value == 1) ???? { ??????PADAT_init; ?????? SDA_high;} ???? else ???? { ??????PADAT_init; ??????SDA_low;} ??????delay(D);?????? ??????????????????? ??????PADAT_init; ???? SCL_high; ?????? ???? /* Clock stretching wait.??Wait until clock is released ???? by slave.??*/ ???? while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;} ???? delay(2*D);? ??????? ???? PADAT_init; ???? SCL_low; ???? delay(D);?? ??????? ???? out_mask >>= 1;? ???? count--;????????? ??} ????? ????PADAT_init; ??SDA_high;??/* Let go of data pin. */ ????delay(D); ????SCL_high; ????delay(2*D);?? ???? ????/* If not acknowleged, set status accordingly and exit read process. */ ????if (((GPIO_PADAT & 0x0400) ? 1 : 0) == 1) ????{ ???? status = 0xA1; ???? return(status);} ???? ????PADAT_init; ????SCL_low; ????delay(D); /**********??Begin Read Procedure **********/ /* Release SDA and SCL to initiate transfer. */ PADAT_init;???? SDA_high; SCL_high; for(i = 0; i < byte_count; i++) { ??count = 8; ??input_byte = 0x00; ??? ??PADAT_init; ??SCL_high; ??? ??/* Clock stretching wait.??Wait until clock is released ???? by slave.??*/ ??while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;} ??????????? ??/* Loop for bit-by-bit read of data. */ ??while(count > 0)? ??{ ????PADAT_init; ????SCL_high; ????delay(D);?? ????delay(4); /* Required to make read and write clocks the same freq. */ ???? ?? if ((GPIO_PADAT & 0x0600) == 0x0600) ????input_byte++; ?? ?? delay(D);?? ??? ?? PADAT_init; ?? SCL_low; ?? delay(2*D);? ?????? ?? if (count == 1) ????break; ?? else?? ????input_byte <<= 1; ?? ?? count--; ??} ??/* Write input byte to "read_buffer". */ ??buffer[i] = input_byte; ???? ??if(i == (byte_count - 1)) ?? break; ????? ???? /* Below is the acknowledge procedure. */????? ???? PADAT_init; ???? SDA_low; ???? delay(D);?? ???? SCL_high;????? ??delay(2*D);?? ???? ???? PADAT_init; ???? SCL_low; ???? delay(D);?? ???? SDA_high;? ???? status = 0xA0;? }????? /* Standard protocol calls for the last read byte to ????not receive an acknowledge from the master. */????? PADAT_init; ????SDA_high; ????SCL_high;????? delay(2*D);? ????? ?? PADAT_init; ?? SCL_low; ?? delay(D);?? ?? SDA_high; ?? status = 0xA1; ?? return(status); } /********************************************************************/ void i2c_start(void) { int clk_count = 0; uint8 compare = 0x00; PADAT_init;?? SDA_high; delay(100); PADAT_init;?? SCL_high; delay(100); /* Clock stretching wait.??Wait until clock is released ????by slave.??*/ while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;}???? ?? PADAT_init; SDA_low; delay(100); ????? ????PADAT_init;?? SCL_low; delay(100); } /********************************************************************/ uint8 i2c_stop(void) { uint8 status = 0x00; int clk_count = 0; ?? PADAT_init; SCL_low; delay(100); PADAT_init; SDA_low; delay(100); ???? ????PADAT_init;? SCL_high; /* Clock stretching wait statement.??Wait until clock is released ????by slave.??*/ while (((GPIO_PADAT & 0x0200) ? 1 : 0) == 0){;} ?????? delay(100); ???? ????PADAT_init;? SDA_high; status = 0x81; /* Set bus idle. */ return(status); } /********************************************************************/ void delay(int value) { int clk_count = 0; while (clk_count < value) {clk_count++;} } /********************************************************************/ ? 第二個例子 函數(shù)定義: gpio_iic.h: #ifndef __IIC_GPIO__ #define __IIC_GPIO__ void delay(); /* 設(shè)置scl引腳電平,0低電平,1高電平,其他值無效,返回值一直為0,留著它用。 */ int set_scl( int value ); /* 得到scl引腳電平,0低電平,1高電平,必須是這兩個值,其他函數(shù)需要調(diào)用。 */ int get_scl(); /* 設(shè)置sda引腳電平,0低電平,1高電平,其他值無效,返回值一直為0,留著它用。 */ int set_sda( int value ); /* 得到sda引腳電平,0低電平,1高電平,必須是這兩個值,其他函數(shù)需要調(diào)用。 */ int get_sda(); /* 重新發(fā)送iic start位,這個是在傳送數(shù)據(jù)過程中使用。 */ void iic_restart(); /* 發(fā)送iic start位,這里假設(shè)總線空閑,此時SDL與SCL都為高電平。 */ void iic_start(); /* 發(fā)送stop位,這里假設(shè)scl此時為低電平。 */ void iic_stop(); /* 發(fā)送一個bit0,這里假設(shè)scl此時為低電平,sda電平不定。 */ void send_bit0(); /* 發(fā)送一個bit 1,這里假設(shè)scl此時為低電平,sda電平不定。 ?*/ void send_bit1(); /* 接收一個bit位,返回值只能是0或1。 ?*/ int receive_bit(); /* 發(fā)送ACK,實(shí)際上是發(fā)送一個bit0. */ void send_ack(); /* 接收ACK。 */ int receive_ack(); /* 接收一個字節(jié)。 */ char receive_byte(); /* 接收一個buf,返回值總是為0,它不能保證從器件一定能收到ACK,也不能保證從器件正在工作。 */ int receive_buf( char *buf, int buf_size ); /* 發(fā)送一個字節(jié),返回ACK的值,發(fā)送時,沒有收到ACK會重試n次,這是常。 ?*/ int send_byte( char data_byte ); /* 發(fā)送一個buf,返回值是成功發(fā)送,收到ACK的字節(jié)數(shù)量。 */ int send_buf( char *buf, int buf_size ); #endif gpio_iic.c: #include "gpio_iic.h" //#define __80C52__ #define __MINI2440__ #ifdef __MINI2440__ #include <linux/gpio.h> #include <linux/delay.h> #include <mach/regs-gpio.h> #endif #ifdef __80C52__ #include <reg52.h> sbit SCL? = P1^0; sbit SDA??? = P1^1; #endif void delay() { #ifdef __MINI2440__ ???? udelay(1); #endif #ifdef __80C52__ ???? int i = 0; ???? for( i = 0; i < 10000; i ++ ); #endif } /* 設(shè)置scl引腳電平,0低電平,1高電平,其他值無效,返回值一直為0,留著它用。 */ int set_scl( int value ) { #ifdef __MINI2440__ //??? s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA); //???? s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL); ???? s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT); ???? switch( value ) ???? { ???? case 0: ????? s3c2410_gpio_setpin(S3C2410_GPE(14), 0); // IICSCL ????? break; ???? case 1: ????? s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL ????? break; ???? default: ????? break; ???? } #endif #ifdef __80C52__ ???? if ( 0 == value ) ????? SCL = 0; ???? else if ( 1 == value ) ????? SCL = 1; #endif ???? return 0;?????????????????? } /* 得到scl引腳電平,0低電平,1高電平,必須是這兩個值,其他函數(shù)需要調(diào)用。 */ int get_scl() { #ifdef __MINI2440__ ???? s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_INPUT); ???? return s3c2410_gpio_getpin(S3C2410_GPE(14)) > 0 ? 1: 0; #endif #ifdef __80C52__ ???? return SCL; #endif } ? /* 設(shè)置sda引腳電平,0低電平,1高電平,其他值無效,返回值一直為0,留著它用。 */ int set_sda( int value ) { #ifdef __MINI2440__ ???? s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT); ???? switch( value ) ???? { ???? case 0: ????? s3c2410_gpio_setpin(S3C2410_GPE(15), 0); // IICSDA ????? break; ???? case 1: ????? s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA ????? break; ???? default: ????? break; ???? } #endif #ifdef __80C52__ ???? if ( 0 == value ) ????? SDA = 0; ???? else if ( 1 == value ) ????? SDA = 1;???? #endif???????? ???? return 0; } ? /* 得到sda引腳電平,0低電平,1高電平,必須是這兩個值,其他函數(shù)需要調(diào)用。 */ int get_sda() { #ifdef __MINI2440__ ???? int sda_pin = 0; ???? s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_INPUT); ???? sda_pin = s3c2410_gpio_getpin(S3C2410_GPE(15)) > 0 ? 1:0; ???? return sda_pin; #endif #ifdef __80C52__ ???? return SDA; #endif } /* 重新發(fā)送iic start位,這個是在傳送數(shù)據(jù)過程中使用。 */ void iic_restart() { ???? set_scl( 0 ); ???? delay(); ???? set_sda( 1 ); ???? delay(); ???? set_scl( 1 ); ???? delay(); ???? set_sda( 0 ); ???? delay(); ???? set_scl( 0 ); ???? delay(); } /* 發(fā)送iic start位,這里假設(shè)總線空閑,此時SDL與SCL都為高電平。 */ void iic_start() { ???? set_sda( 0 ); ???? delay(); ???? set_scl( 0 ); ???? delay(); } /* 發(fā)送stop位,這里假設(shè)scl此時為低電平。 */ void iic_stop() { ???? set_sda( 0 ); ???? delay(); ???? set_scl( 1 ); ???? delay(); ???? set_sda( 1 );???????? ???? delay(); } /* 發(fā)送一個bit0,這里假設(shè)scl此時為低電平,sda電平不定。 */ void send_bit0() { ???? set_sda( 0 ); ???? delay(); ???? set_scl( 1 ); ???? delay(); ???? set_scl( 0 ); ???? delay(); } /* 發(fā)送一個bit 1,這里假設(shè)scl此時為低電平,sda電平不定。 ?*/ void send_bit1() { ???? set_sda( 1 ); ???? delay(); ???? set_scl( 1 ); ???? delay(); ???? set_scl( 0 ); ???? delay(); } /* 接收一個bit位,返回值只能是0或1。 ?*/ int receive_bit() { ???? int value = -1; ???? set_sda( 1 ); ???? delay(); ???? set_scl( 0 ); ???? delay(); ???? set_scl( 1 ); ???? delay(); ???? value = get_sda(); ???? set_scl( 0 ); ???? return value;???? } /* 發(fā)送ACK,實(shí)際上是發(fā)送一個bit0. */ void send_ack( ) { ???? send_bit0(); } /* 接收ACK。 */ int receive_ack() { ???? int ack = 1; ???? set_sda( 1 ); ???? delay(); ???? set_scl( 1 ); ???? delay(); ???? ack = get_sda();???????? ???? delay(); ???? set_scl( 0 ); ???? return ack; } /* 接收一個字節(jié)。 */ char receive_byte( ) { ???? int i = 0; ???? int recv_data = 0; ???? for ( i = 0; i < 8; i++ ) ???? { ????? recv_data = recv_data | receive_bit(); ????? if ( 7 == i ) ?????????? break; ????? recv_data <<= 1; ???? } ???? send_ack(); ???? return recv_data;???? } /* 接收一個buf,返回值總是為0,它不能保證從器件一定能收到ACK,也不能保證從器件正在工作。 */ int receive_buf( char *buf, int buf_size ) { ???? int i = 0; ???? for( i = 0; i < buf_size; i ++ ) ???? { ????? buf[i] = receive_byte(); ???? } ???? return buf_size; } /* 發(fā)送一個字節(jié),返回ACK的值,發(fā)送時,沒有收到ACK會重試n次,這是常。 ?*/ int send_byte( char data_byte ) { ???? int retry_count = 8;//重試次數(shù)。 ???? int i = 0; ???? int ack = 1;???????? ???? char send_data = 0; ???? send_data = data_byte; ???? do{ ????? for ( i = 0; i < 8; i ++ ) ????? { ?????????? if ( 0x80 & send_data ) ??????????? send_bit1(); ?????????? else ??????????? send_bit0(); ?????????? send_data <<= 1; ????? } ????? ack = receive_ack(); ????? if ( 0 == ack ) ?????????? break; ????? send_data = data_byte; ????? retry_count --; ???? } ???? while( retry_count >= 0 ); ???? return ack; } /* 發(fā)送一個buf,返回值是成功發(fā)送,收到ACK的字節(jié)數(shù)量。 */ int send_buf( char *buf, int buf_size ) { ???? int i = 0; ???? int count = 0; ???? for ( i = 0; i < buf_size; i ++ ) ???? { ????? if (0 != send_byte( buf[i] ) ) ?????????? break; ????? count ++; ???? } ???? return count;???????? } ? 下面是可以用來讀寫at24c02的測試代碼,在mini2440板測試通過, static void m24c02_send( int addr, char *buf,? int buf_size) { ???? int count = 0; ???? int rev = -1; ??? iic_start(); ??? rev = send_byte( 0xa0 ); ??? rev = send_byte( (addr >> 0) & 0xff ); ??? count = send_buf( buf, buf_size ); ??? iic_stop(); ? } static void m24c02_recv( int addr , char *buf, int buf_size ) { ????? iic_start(); ??? send_byte( 0xa0 ); ??? send_byte( (addr >> 0) & 0xff ); ????? iic_restart(); ??? send_byte( 0xa1 ); ??? receive_buf( buf, buf_size ); ??? iic_stop(); }? ? ? (1)基礎(chǔ)宏定義 #define GPIO_SCL???????????? S3C2410_GPF3 #define GPIO_SDA???????????? S3C2410_GPF0 #define GPIO_SDA_OUTP?? S3C2410_GPF0_OUTP? //設(shè)定SDA輸出 #define GPIO_SDA_INP????? S3C2410_GPF0_INP???? //設(shè)定SDA輸入 #define GPIO_SCL_OUTP?? S3C2410_GPF3_OUTP? //設(shè)定SCL輸出 void I2C_SCL_OUTP( void ) { s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP); } void I2C_SCL_Output(u8 value) { if(value) {??????????????????????????????????????????????? s3c2410_gpio_setpin(GPIO_SCL,value);? } else { s3c2410_gpio_setpin(GPIO_SCL,value );? } } void I2C_SDA_Mode(u8 v_mode)?? //SDA輸出方向 { if(v_mode) {??????????????????????????????????????????????? s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP);?? } else { s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP);?? } } void I2C_SDA_Output(u8 value) { if(value) {??????????????????????????????????????????????? s3c2410_gpio_setpin(GPIO_SDA,value);? } else { s3c2410_gpio_setpin(GPIO_SDA,value );? } } u8 I2C_SDA_Read(void)??? //SDA讀數(shù)據(jù) { return s3c2410_gpio_getpin(GPIO_SDA);? } (2)基礎(chǔ)段 void I2C_Init(void) { I2C_SDA_Output(1); I2C_SCL_Output(1);????? //默認(rèn)拉高 } void I2C_Wait(void) { u16 i; for(i=0;i<200;i++); } void I2C_Start(void) { I2C_SDA_Output(1); I2C_SCL_Output(1); I2C_Wait(); I2C_SDA_Output(0); I2C_Wait(); I2C_SCL_Output(0); } void I2C_Stop(void) { I2C_SDA_Output(0); I2C_Wait(); I2C_SCL_Output(1); I2C_Wait(); I2C_SDA_Output(1); } ? (3)讀寫單個字節(jié)的段 u8 I2C_Send_Byte(u8 bytedata) { u8 i,ack; I2C_SDA_Mode(1);? //SDA輸出 I2C_SCL_OUTP(); for (i = 0; i < 8; i++)? { if (bytedata & 0x80) { I2C_SDA_Output(1); } else { I2C_SDA_Output(0); } bytedata <<= 1; I2C_SCL_Output(1); udelay(3); I2C_SCL_Output(0); udelay(1); }???? I2C_SDA_Output(1);? //release udelay(3); I2C_SDA_Mode(0);? //設(shè)定SDA輸入 I2C_SCL_Output(1);?? udelay(3); ack = I2C_SDA_Read();?? //讀應(yīng)答 I2C_SDA_Mode(1); I2C_SCL_Output(0); udelay(3); return ack;?? } u8 I2C_Receive_Byte(void)? { u8 i; u8 bytedata = 0x00; u8 temp; I2C_SDA_Mode(0); for ( i = 0; i < 8; i++) { I2C_SCL_Output(1); udelay(3); bytedata <<= 1; temp = I2C_SDA_Read(); printk("reda SDA'value is:%d\n",temp); if (temp) bytedata |= 0x01; printk("? bytedata is:%x\n",bytedata); I2C_SCL_Output(0); udelay(1); } I2C_SDA_Mode(1); return bytedata; } (4)讀寫單個字節(jié)的I2C應(yīng)用函數(shù) u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata) {?? u8 ack; printk("device_ID is:%x\n",device_ID); printk("address is:%x\n",address); printk("date is:%x\n",bytedata); I2C_Start();? ack=I2C_Send_Byte(device_ID); printk("ack is:%d\n",ack); if(ack) I2C_Stop(); I2C_Send_Byte(address); I2C_Send_Byte(bytedata); I2C_Stop(); I2C_Wait(); return 0; } u8 I2C_Byte_Read(u8 device_ID,u8 address) {?? u8 bytedata; I2C_Start(); I2C_Send_Byte(device_ID); I2C_Send_Byte(address); I2C_Start(); I2C_Send_Byte(device_ID+1); bytedata = I2C_Receive_Byte();? //讀單個字節(jié),不需要再發(fā)應(yīng)答 I2C_Stop();??? return bytedata; } |