IIC总线程序(芯片AT24C02 EEPROM)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<reg52.h> 2 #define uint unsigned int 3 #define uchar unsigned char 4 5 sbit SCL =P2^1; 6 sbit SDA =P2^0; 7 8 sbit K1 =P3^0; 9 sbit K2 =P3^1; 10 sbit K3 =P3^0; 11 sbit K4 =P3^1; 12 13 sbit LSA =P2^2; 14 sbit LSB =P2^3; 15 sbit LSC =P2^4; 16 uchar num; 17 uchar code smgduan[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; 18 19 /******************************************************************************* 20 * 函数名 : Delay10us() 21 * 函数功能 : 延时10us 22 * 输入 : 无 23 * 输出 : 无 24 *******************************************************************************/ 25 void Delay10us()//通过计算来确定延时为10uM 26 { 27 unsigned char a,b; 28 for(b=1;b>0;b--) 29 for(a=2;a>0;a--); 30 31 } 32 /******************************************************************************* 33 * 函数名 : I2cStart() 34 * 函数功能 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿 35 * 输入 : 无 36 * 输出 : 无 37 * 备注 : 起始之后SDA和SCL都为0 38 *******************************************************************************/ 39 40 void I2cStart() 41 { 42 SDA=1; 43 Delay10us(); 44 SCL=1; 45 Delay10us();//建立时间是SDA保持时间>4.7us 46 SDA=0; 47 Delay10us();//保持时间是>4us 48 SCL=0; 49 Delay10us(); 50 } 51 /******************************************************************************* 52 * 函数名 : I2cStop() 53 * 函数功能 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿 54 * 输入 : 无 55 * 输出 : 无 56 * 备注 : 结束之后保持SDA和SCL都为1;表示总线空闲 57 *******************************************************************************/ 58 59 void I2cStop() 60 { 61 SDA=0; 62 Delay10us(); 63 SCL=1; 64 Delay10us();//建立时间大于4.7us 65 SDA=1; 66 Delay10us(); 67 } 68 //针对IIC的写字节 69 uchar IICsendByte(uchar dat) 70 { 71 uchar a=0,b; 72 SDA =dat; 73 for(a=0;a<8;a++) 74 { 75 SDA =dat>>7; //将最高位取出,然后其他的为都通过右移掉 76 dat =dat<<1; // 因为dat的值一直没有变化,故而,将其左移一位,最高位移掉,次高位变成最高位 77 SDA =1; 78 delay(1); 79 SCL=0; 80 delay(1); 81 } //此时8位数据已经全部传送完成 接下来进行应答 82 SDA=1; //SDA和SCL为1是为了下面应答做铺垫 83 delay(1); 84 SCL=1; 85 // delay(1); 86 while(SDA) //当应答成功的话,SDA=0;跳出循环 87 { 88 b++; 89 if(b>200) 90 SCL=0; 91 dealy(1); 92 return 0; //表示发送(通讯)失败 93 } 94 SCL =0; 95 delay(1); 96 return 1; //发送成功的时候,返回1 97 } 98 //针对IIC的读字节 99 uchar IICReadByte() 100 { 101 uchar a,dat =0; 102 SD1=1; //首先先让其拉高,让其处于空闲状态,不至于让下面的SDA的数据为低 103 delay(1); 104 for(a=0;a<8;a++) 105 { 106 SCL =1; //为了读数据,故而首先让SCL为高,就是为了让数据稳定后再读 107 dealy(1); 108 dat<<=1; // 0 00 10 110 要将其放在dat|=SDA前面,否则当把8位数据全部放到dat中后, 再移一位的话,就会使得最高位移走,数据出错 将其左移一位,等二次循环过来时,这是就会原来保存在dat中的数据就会继续左移一次 109 dat|=SDA; // 01 11 111 也就是只需要让其移动7次,不将最高位移走 让dat与SDA进行“按位或”将SDA的值赋给dat 110 delay(1); 111 SCL=0; //让SCL为低,就是为了让数据改变 112 delay(1); 113 } 114 return dat; 115 } 116 //芯片AT24C02通讯的读写 117 void AT24C02writeByte(uchar add,uchar dat) 118 { 119 IICstart(); 120 IICsendByte(0xa0);//这是器件地址,8位 高四位是固定的 最后一位表示0为写、1为读、其余的三位A1、A2、A3,我们接了地 121 IICsendByte(add); 122 IICsendByte(dat);//应答与否我们都在IIC的字节函数中谢了 123 IICStop(); 124 } 125 uchar AT24C02read(uchar add)//由于是要读取信号,故而需要知道读取的地址即可 126 { 127 uchar value; 128 IICstart(); 129 IICsendByte(0xa0);//这是器件地址,8位 高四位是固定的 最后一位表示0为写、1为读、其余的三位A1、A2、A3,我们接了地 130 IICsendByte(add); 131 IICstart(); //由于前面要写入它的地址,之后要读里面的数据,所以读写的方向会发生变化,所以必须要重新写入起始信号和器件地址 132 IICsendByte(0xa1); 133 value =IICReadByte();//直接读取地址中的数据,并且将读回来的值保存到value中去 134 IICstop(); 135 return value; 136 } 137 //独立按键的函数 138 void keypros() 139 { 140 if (K1==0) 141 { 142 delay(10); 143 if(K1==0) 144 { 145 AT24C02writeByte(1,num); //按键1实现将num的值,写入到 1 的地址中去,因为AT24C02这个芯片有255个内存 146 } 147 while(!K1);//判断按键是否释放 如果忘记写这个语句,这个函数的功能就会不停地进行 148 } 149 if (K2==0) 150 { 151 delay(10); 152 if(K2==0) 153 { 154 num =AT24C02read(1); //将存储到 1这个内存中的数据读取出来,再赋给变量num这个值 155 } 156 while(!K2); 157 } 158 159 if (K3==0) 160 { 161 delay(10); 162 if(K3==0) 163 { 164 num++; //对num的值进行加1运行 165 if(num>255) //因为num的变量为uchar,故而只能存储255个字符 166 num =0; 167 } 168 while(!K3); 169 } 170 if (K4==0) 171 { 172 delay(10); 173 if(K4==0) 174 { 175 num =0; //对num精心清零运算 176 } 177 while(!K4); 178 } 179 } 180 /******************************************************************************* 181 * 函数名 :DigDisplay() 182 * 函数功能 :数码管显示函数 183 * 输入 : 无 184 * 输出 : 无 185 *******************************************************************************/ 186 void DigDisplay() 187 { 188 u8 i; 189 for(i=0;i<4;i++) 190 { 191 switch(i) //位选,选择点亮的数码管, 192 { 193 case(0): 194 LSA=0;LSB=0;LSC=0; break;//显示第0位 195 case(1): 196 LSA=1;LSB=0;LSC=0; break;//显示第1位 197 case(2): 198 LSA=0;LSB=1;LSC=0; break;//显示第2位 199 case(3): 200 LSA=1;LSB=1;LSC=0; break;//显示第3位 201 } 202 P0=disp[3-i];//发送数据 203 delay(100); //间隔一段时间扫描 204 P0=0x00;//消隐 205 } 206 } 207 /******************************************************************************* 208 * 函数名 :datapros() 209 * 函数功能 :数据处理函数 210 * 输入 : 无 211 * 输出 : 无 212 *******************************************************************************/ 213 void datapros() 214 { 215 disp[0]=smgduan[num/1000];//千位 216 disp[1]=smgduan[num%1000/100];//百位 217 disp[2]=smgduan[num%1000%100/10];//个位 218 disp[3]=smgduan[num%1000%100%10]; 219 } 220 void main() 221 { 222 while(1) 223 { 224 Keypros(); //按键处理函数 225 datapros(); //数据处理函数 226 DigDisplay();//数码管显示函数 227 } 228 }