IIC总线工作原理
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
起始和终止信号 :SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
数据传送格式(1)字节传送与应答
每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。
AT24C02的芯片地址如下图,1010为固定,A0,A1,A2正好与芯片的1,2,3引角对应,为当前电路中的地址选择线,三根线可选择8个芯片同时连接在电路中,当要与哪个芯片通信时传送相应的地址即可与该芯片建立连接,TX-1B实验板上三根地址线都为0。最后一位R/W为告诉从机下一字节数据是要读还是写,0为写入,1为读出。
任意地址写入数据格式 任意地址读取数据格式
1 #include2 #include 3 4 #define uint8 unsigned char 5 #define uint16 unsigned int 6 7 #define NOP() _nop_() 8 9 #define DELAY5US() do{NOP();NOP();NOP();NOP();}while(0) 10 struct Addr 11 { 12 uint8 devAddr; 13 uint8 wordAddr; 14 }; 15 16 struct Buff 17 { 18 uint8 *buff; 19 uint8 length; 20 }; 21 uint8 idata sendBuf[8] = { 1,2,3,4,5,6,7,8}; 22 uint8 idata recvBuf[8]; 23 24 sbit SDA = P2^0; 25 sbit SCL = P2^1; 26 27 void start(); 28 void stop(); 29 void ACK(); 30 void NACK(); 31 void checkACK(); 32 /**************c51通用寄存器 只有两个,a、b因此函数中参数的个数最多2个***********/ 33 void writeByte(uint8 dat); 34 void writeSlot(uint8 *addr, uint8 dat);//addr 指向一个数组,这个数组中包含设备地址,与数据地址 35 void writeSlot1(struct Addr address, struct Buff sendBuff); 36 void writeSeq(struct Addr address, struct Buff buff); 37 38 uint8 readByte(); 39 uint8 readSlot(uint8 *addr); 40 void readSeq(struct Addr address, struct Buff buff); 41 void delay() 42 { 43 uint8 i, j; 44 for(i = 0; i<100;i++) 45 for(j = 0; j<100; j++); 46 } 47 48 49 void main() 50 { 51 uint8 addr[] = { 0xa0, 2}; 52 struct Addr sendAddr; 53 struct Addr recvAddr; 54 55 struct Buff sendBuff; 56 struct Buff recvBuff; 57 58 sendAddr.devAddr = 0xa0; 59 sendAddr.wordAddr = 0x00; 60 61 recvAddr.devAddr = 0xa0; 62 recvAddr.wordAddr = 0x00; 63 64 sendBuff.buff = sendBuf; 65 sendBuff.length = 8; 66 67 recvBuff.buff = recvBuf; 68 recvBuff.length = 8; 69 70 // writeSlot1(sendAddr, sendBuff); 71 // writeSlot(addr, 0x01); 72 writeSeq(sendAddr, sendBuff); 73 74 delay(); //在读和写之间 需要一个短暂的停顿 75 76 readSeq(recvAddr, recvBuff); 77 P1 = recvBuf[3]; 78 // P1 = readSlot(addr); 79 while(1); 80 } 81 void start() 82 { 83 SDA = 1; 84 SCL = 1; 85 DELAY5US(); 86 SDA = 0; 87 DELAY5US(); 88 SCL = 0; 89 SDA = 1; 90 } 91 92 void stop() 93 { 94 SDA = 0; 95 SCL = 1; 96 DELAY5US(); 97 SDA = 1; 98 DELAY5US(); 99 SCL = 0;100 }101 102 void ACK()103 {104 SDA = 0;105 SCL = 1;106 DELAY5US();107 /****************强烈要求注意下面这两句话的顺序***************/108 /* SDA = 1*/109 /* SCL = 0*/110 /*上面的操作时序是错误的,在SCL = 1的时候将SDA拉高,这样会形成停止信号*/111 /*写时序的时候切忌啊*/ 112 SCL = 0;113 SDA = 1;//将SDA 拉高,是为了释放数据总线114 }115 116 void NACK()117 {118 SDA = 1;119 SCL = 1;120 DELAY5US();121 122 SCL = 0;123 // SDA = 0;124 }125 126 void checkACK()127 {128 SDA = 1;//释放总线129 SCL = 1;130 F0 =0;131 if(SDA == 1)132 F0 = 1;133 SCL = 0;134 }135 136 void writeByte(uint8 dat)137 {138 uint8 i = 8;139 uint8 temp;140 temp = dat;141 for(i; i>0; i--)142 { 143 SDA = ((dat & 0x80) >> 7);144 SCL = 1;145 DELAY5US();146 SCL = 0;147 DELAY5US();148 dat = dat<<1;149 }150 SCL = 0;151 SDA = 1;152 }153 void writeSlot(uint8 *addr, uint8 dat)154 {155 start();156 writeByte(addr[0]);157 checkACK();158 if(F0 == 1)159 return;160 writeByte(addr[1]);161 checkACK();162 if(F0 == 1)163 return;164 writeByte(dat);165 checkACK();166 if(F0 == 1)167 return;168 stop();169 }170 void writeSlot1(struct Addr address, struct Buff sendBuff)171 {172 start();173 writeByte(address.devAddr);174 checkACK();175 if(F0 == 1)176 return;177 writeByte(address.wordAddr);178 checkACK();179 if(F0 == 1)180 return;181 writeByte(*sendBuff.buff);182 checkACK();183 if(F0 == 1)184 return;185 stop(); 186 }187 void writeSeq(struct Addr addr, struct Buff sendBuff)188 {189 uint8 i;190 start();191 writeByte(addr.devAddr);192 checkACK();193 if(F0 == 1)194 return;195 writeByte(addr.wordAddr);196 checkACK();197 if(F0 == 1)198 return;199 for(i=sendBuff.length; i>0; i--)200 {201 writeByte(*sendBuff.buff);202 checkACK();203 if(F0 == 1)204 return;205 sendBuff.buff++;206 }207 stop();208 }209 210 uint8 readByte()211 {212 uint8 temp = 0;213 uint8 i;214 // SDA = 1;//这句话是为了释放数据总线215 for(i=0; i<8; i++)216 { 217 temp <<=1;218 SCL = 0;219 DELAY5US();220 SCL = 1;221 temp = temp | SDA; 222 DELAY5US();223 SCL = 0;224 /*SCL = 1;225 temp = temp<<1;226 temp = temp | (uint8)SDA;227 SCL = 0;*/228 }229 return temp; 230 }231 232 uint8 readSlot(uint8 *addr)233 {234 uint8 date;235 start();236 writeByte(addr[0]);237 checkACK();238 writeByte(addr[1]);239 checkACK();240 start();241 writeByte(addr[0] | 1);242 checkACK();243 date = readByte();244 stop();245 return date;246 }247 void readSeq(struct Addr address, struct Buff recvBuff)248 {249 uint8 i;250 start();251 writeByte(address.devAddr);252 checkACK();253 if(F0 == 1)254 return;255 writeByte(address.wordAddr);256 checkACK();257 if(F0 == 1)258 return;259 start();260 writeByte(address.devAddr | 1);261 checkACK();262 if(F0 == 1)263 return;264 for(i = 0; i