IIC总线程序(芯片AT24C02 EEPROM)

  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 }
View Code

 

posted @ 2018-08-26 23:11  美梦恋黑夜  阅读(997)  评论(0编辑  收藏  举报