| 1 基本原理1.1 IIC总线 
 
 
 
 
 
 
 
 
 
 
 
 需要注意的是,高四位对于同种芯片而言,都是一样的。例如AT24C02芯片的高四位固定为1010。 1.2 AT24C02芯片
 
 
 
 2 源代码
 
 
 /*---------------------函数功能:
 IIC总线 AT24C02
 
 -----------------------------------------*/
 
 
 #include<pic.h>// 调用PIC16f87XA单片机的头文件
 #include"delay.h"//调用延时子函数的头文件
 
 
 
 __CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关
 //__CONFIG(HS&WDTDIS&LVPDIS);
 
 
 
 /*-----------宏定义--------------*/
 #define  uint  unsigned int
 #define  uchar unsigned char
 #define  SDA     RC4                        // IIC的数据线
 #define  SCL     RC3                        // IIC的时钟线
 
 
 
 /*-----------子函数声明--------------*/
 void IIC_start(void);                // IIC启动信号函数
 void IIC_end(void);                        // IIC终止信号函数
 
 void write_1Byte(uchar buf);//向IIC总线写一个字节的函数
 char read_1Byte();                        //从IIC总线读一个字节的函数
 
 void write_AT24C02(char address,char databuf);        //向AT24C02芯片的指定地址写一个字节的数据
 char read_AT24C02(char address);                                //从AT24C02芯片的指定地址读一个字节的数据
 
 
 
 /*-----------主函数--------------*/
 void main()
 {
 char bufdata;
 
 // data direction register is TRISA.
 // Setting  a TRISA bit (= 1) will make the corresponding PORTA pi an input.
 // Clearing a TRISA bit (= 0) will make the corresponding PORTA pin an output.
 TRISD=0x00;                        //RD作为输出口,作为LED灯的显示
 PORTD=0x00;                        //LED的初值为0
 delay(1000);
 
 while(1)
 {
 bufdata=read_AT24C02(0x18);// 从AT24C02中地址0x18读出数据
 PORTD=bufdata;
 delay(1000);
 
 
 bufdata=bufdata+1;
 PORTD=bufdata;
 delay(1000);
 
 
 write_AT24C02(0x18,bufdata);//将+1的数据保存在0x18中
 }
 
 }
 
 
 
 
 
 
 
 
 /*************IIC启动信号函数***************/
 void IIC_start(void)
 {
 //为什么这样写,见IIC的时序图
 SDA=1;
 SCL=1;
 asm("NOP");
 asm("NOP");
 
 SDA=0;
 asm("NOP");
 asm("NOP");
 
 SCL=0;
 asm("NOP");
 asm("NOP");
 
 }
 
 
 
 
 /*************IIC终止信号函数***************/
 void IIC_end(void)
 {
 SDA=0;
 SCL=0;
 asm("NOP");
 asm("NOP");
 
 SCL=1;
 asm("NOP");
 asm("NOP");
 
 SDA=1;
 asm("NOP");
 asm("NOP");
 
 SCL=0;//拉低
 asm("NOP");
 asm("NOP");
 
 }
 
 
 
 
 /*************向IIC总线写一个字节(8 bit)的函数***************/
 void write_1Byte(uchar buf)
 {
 int k=0;
 for(k=0;k<8;k++)
 {
 //将最高位写到SDA总线上去
 //SDA=buf&0x80;                // 等价于下面的if语句
 if(buf&0x80)                // 提取buf的最高位数据
 SDA=1;                        //如果buf的最高位为1,就写1
 else
 SDA=0;                        //如果buf的最高位为0,就写0
 asm("NOP");
 asm("NOP");
 
 SCL=1;
 asm("NOP");
 
 SCL=0;                                //时钟信号归零
 asm("NOP");
 
 buf=buf<<1;                        //左移一位,准备提取下一个待写的数据
 }
 
 
 // 每接收到一个字节的数据后,从机必须产生一个应答信号给主机。
 // 应答器件在第9个时钟周期将SDA线拉低,表示已经接收了一个八位数据
 TRISC4=1;                                //RC4作为输入,SDA引脚接的是RC4口   开始读数据,读SDA的值
 asm("NOP");
 
 SCL=1;
 asm("NOP");
 asm("NOP");
 //if(RC4=0)                         //说明SDA=0,即成功接收
 SCL=0;
 TRISC4=0;
 }
 
 
 
 
 /*************向IIC总线读一个字节(8 bit)的函数***************/
 char read_1Byte()
 {
 int k=0;
 char t_byte=0x00;
 
 TRISC4=1;                                        //RC4作为输入,SDA引脚接的是RC4口     开始读数据,读SDA的值
 
 for(k=0;k<8;k++)
 {
 t_byte=t_byte<<1;                //左移一位
 SCL=1;
 asm("NOP");
 asm("NOP");
 
 //读 SDA的值
 if(SDA=1)
 t_byte=t_byte|0x01;//写1 只对最低位有影响
 else
 t_byte=t_byte&0xfe;//写0
 
 SCL=0;
 asm("NOP");
 asm("NOP");
 }
 
 TRISC4=0;
 
 return t_byte;                // 返回的是一个字节 eg:0x3f
 }
 
 
 
 
 
 /*************向AT24C02芯片的指定地址写一个字节的数据***************/
 void write_AT24C02(char address,char databuf)
 {
 IIC_start();                        //发送起始信号
 
 //AT24C02芯片寄存器: 1010 A2 A1 A0 R/W_n  AT24C02芯片的高四位固定为1010
 // A2A1A0:从机选择,一共可以接八个AT24C02芯片。  A2A1A0=000,选择第一个芯片。  R/W_n:读/写
 
 //选择某一个从器件(确定用哪一个芯片)
 write_1Byte(0xa0);                //发送从器件地址000,选择第一个芯片。R/W_n=0,表示写
 //指定该器件内部的某一个地址(确定芯片内部地址)
 write_1Byte(address);        //指定该芯片内部的某一个地址(一共有256个地址)
 //向该芯片的指定地址里面写数据
 write_1Byte(databuf);        //向指定地址发送数据
 
 IIC_end();                                //发送结束信号
 }
 
 
 
 
 /*************从AT24C02芯片的指定地址读一个字节的数据***************/
 char read_AT24C02(char address)
 {
 char buf;
 
 //AT24C02芯片寄存器: 1010 A2 A1 A0 R/W_n  AT24C02芯片的高四位固定为1010
 // A2A1A0:从机选择,一共可以接八个AT24C02芯片。  A2A1A0=000,选择第一个芯片。  R/W_n:读/写
 
 
 IIC_start();                        //发送起始信号
 //选择某一个从器件(确定用哪一个芯片)
 write_1Byte(0xa0);                //发送从器件地址000,选择第一个芯片。R/W_n=0,表示写
 //指定该器件内部的某一个地址(确定芯片内部地址)
 write_1Byte(address);        //指定该芯片内部的某一个地址(一共有256个地址)
 
 
 
 
 //在传输过程中,当需要改变传送方向时(写<->读),起始信号IIC_start()和从机地址write_1Byte(0xa1)都被重复产生一次
 //由于写变成读,所以需要下面两条指令
 IIC_start();                        //再次启动
 //选择某一个从器件(确定用哪一个芯片)  此时要准备读数据
 write_1Byte(0xa1);                //发送从器件地址,选择第一个芯片。R/W_n=1,表示读
 //读出该芯片指定地址的数据
 buf=read_1Byte();
 
 
 IIC_end();                                //发送结束信号
 
 
 
 return buf;                                // 返回的是一个字节 eg:0x3f
 }
 
 
 
 
 |