在单片机应用中,I2C(I方C)总线一种简单,双向的二线制同步串行总线,它只需要两根串行线,脉冲线,就可以在总线与连接的器件之间传送信息, 它不外乎有以下几个特点: a.每个连接到总线上的器件都可以进行唯一的寻址,还可建立起简单的主从关系,主器件既可作为发送器,也可作为接收器. b.它带竞争电路和仲裁电路,可以接收多个主器件发送的数据,而这些数据不会产混乱. c.同步脉冲可以允许器件可以通过总线以不同的波特率进行通信. d.因为只有两根线,连接简单,方便. 对于MCS51系列来讲,内部并没I2C总线接口,在这种情况下,可以采用软件模拟的方法来写出I2C总线的操作,下面我的程序就在开始处定义哪个引脚作为数据线SDA,哪个引脚作为脉冲线,请看我的程序(C51写的,总共有8个函数来模拟I2C总线): Common.h File #pragma LA DB SB OE CD OT(SPEED,6) //LA indicate LARGE Compling Mode-All local and global variables are located in external-ram. //DB indicate DEBUG //SB indicate SYMBOL //OE indicate OBJECTEXTEND //CD indicate CODE //Generate ASM Code //OT indicate OPTIMIZATION #include <stdio.h> #include <reg51.h> #include <intrins.h> #include <stdlib.h> #pragma REGPARMS #pragma SAVE #define BOOL bit #define BYTE unsigned char #define UINT unsigned int #define ULONG unsigned long #define HIGH 1 #define LOW 0 #define TRUE 1 #define FALSE 0 #define MAXLONGS 2147483647 #define MINLONGS -2147483648 #define MAXINTS 32767 #define MININTS -32768 #define MAXLONGU 4294967295 #define MAXINTU 65535 #define BLOCKLOW 0x0000 //The start-address in AT24C64 is 0x0000 #define BLOCKSIZE 0x20 //Each block is 32 bytes #define BLOCKNUM 0xC8 //At best 200,Only Save the newest 200 records. #define BLOCKHIGH 0x18FF//The end-address in AT24C64 is 0x18FF #define OSC 24000000 //Osillcator Frequency #define BAUDRATE 9600 #define OTV 256-OSC/12/BAUDRATE/32 //character O represents Obtain,character T represents Timer,character V represents Value //IMPORTANT ANNOUNCEMENT:I use a word 0x1FFC,0x1FFD to save the next block's address and 0x1FFE,0x1FFF to save the block's no. sbit GUN=0x85;//PIN P05 sbit SCL=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C sbit SDA=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C sbit SHKL=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C sbit SHKH=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C sbit KH0=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C sbit KH1=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C sbit KH2=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C extern void DEFI2C(char *name) //To define which pin is SDA and which pin is SCL extern void I2CInit() //Initialization For I2C Bus extern void I2CStart() //Start I2C Bus extern void I2CStop(); //Stop I2C Bus extern bit I2CClock(); //return SDA while SCL is HIGH extern void I2CDelay(); //Delay extern void I2CAck(); //Answer extern bit I2CSend(BYTE I2CData);//Send data with I2C Bus extern BYTE I2CReceive(); //Receive data
Common.c void DEFI2C(char *name) { //Todo:add your codes here.... //Announcement:If you question me why use the function DEFI2C? //Well,the function will be used to define which PIN is SCL and which PIN is SDA,especially there are more than 1 I2C //equipment in your circuit.In this sitiuation,we write a function for defining I2C Bus named DEFI2C.... } void I2CStart() { SCL=HIGH; I2CDelay(); SDA=LOW; I2CDelay(); SCL=LOW; I2CDelay(); } void I2CStop() { SDA=LOW; I2CDelay(); SCL=HIGH; I2CDelay(); SDA=HIGH; I2CDelay(); SCL=LOW; I2CDelay(); } void I2CInit() { SCL=LOW; I2CStop(); } bit I2CClock() //return SDA while SCL is HIGH { bit sample; SCL=HIGH; I2CDelay(); sample=SDA; SCL=LOW; I2CDelay(); return sample; } bit I2CSend(BYTE I2CData) { BYTE i; for(i=0;i<8;i++) { SDA=(bit)(((I2CData) & 0x80) / 0x80) ; I2CData=I2CData << 1; I2CClock(); } SDA=HIGH; return (~I2CClock()); } void I2CAck() { SDA=LOW; I2CClock(); SDA=HIGH; } void I2CDelay() { BYTE ll; for(ll=0;ll<100;ll++) { ; } } BYTE I2CReceive() { BYTE I2CData=0; BYTE kk; for(kk=0;kk<8;kk++) { I2CData*=2; if(I2CClock()) { I2CData++; } } return I2CData; }
上面的代码是用软件来模拟I2C总线,在对特定I2C器件进行操作时,一定要和该器件的时序对应起来才可以,本人从事单片机开发不久,上述程序是去年在北京时写的,如有错误还请各位硬件大侠,前辈给予指教.

|