IIC,AT24C02
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 #include <reg52.h> 2 #include <intrins.h> 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<recvBuff.length; i++) 265 { 266 recvBuff.buff[i] =readByte(); //readByte(); 267 ACK(); 268 NOP(); 269 } 270 NACK(); 271 stop(); 272 }