linux下iic(i2c)读写AT24C02
- 格式:doc
- 大小:40.00 KB
- 文档页数:6
IIC总线协议及EEPROMAT24C02IIC总线协议及EEPROMAT24C02IIC总线协议是一种串行通信协议,用于在电子设备之间进行数据传输。
它也被称为I2C(Inter-Integrated Circuit)协议。
IIC总线协议由Philips(现在的NXP Semiconductors)在1982年开发,用于同一电路板上的集成电路芯片之间的通信。
IIC总线是一种主从式结构,其中一个设备作为主设备,其他设备作为从设备。
主设备负责控制数据传输和通信的时序。
每个从设备都有一个唯一的地址,主设备根据地址选择要与之通信的从设备。
从设备根据主设备发出的命令来执行特定的操作,例如读取数据或写入数据。
EEPROM是一种可擦写可编程只读存储器(Electrically Erasable Programmable Read-Only Memory),用于存储非易失性数据。
AT24C02是Microchip Technology公司制造的一种EEPROM芯片,具有容量为2Kbit的存储能力。
AT24C02采用了IIC总线协议,因此可以通过IIC总线与其他设备进行通信。
它有一个7位地址寄存器,可以设置其作为IIC总线上的从设备的地址。
在与主设备通信时,主设备发送一个启动条件,然后发送从设备地址,接下来是读写位和数据。
AT24C02根据主设备的指令来执行读取或写入操作。
AT24C02有一个内部的写保护电路,可以保护存储的数据被误写。
它还支持分页写入,即可以一次写入多个字节的数据,从而提高写入效率。
总结:IIC总线协议是一种用于串行通信的协议,适用于设备之间的数据传输。
AT24C02是一种采用IIC总线协议的EEPROM芯片,具有2Kbit的存储容量。
它通过主设备的控制来进行读写操作,同时具有写保护和分页写入等特性。
I2C总线协议(AT24c02)程序主:STC89C54从:AT24C02电路图时序图下面是代码#include ;#define uchar unsigned char#define addr_x 0xae//写#define addr_d 0xaf//读sbit sda = P2^1;//数据管脚sbit scl = P2^0;//时钟管脚bit ack;void DelayUs2x(unsigned char t)//延时1{while(--t);}void DelayMs(unsigned char t)//延时2{ while(t--){ //大致延时1mS DelayUs2x(245); DelayUs2x(245);}}void delay() //延时大于4μs{;;}void i2_qs()//起始信号{sda = 1;//拉高数据scl = 1;//拉高时钟delay();//延时大于 4μssda =0;//拉低数据产生起始信号(下降沿)delay();//延时大于 4μsscl = 0;//拉低时钟delay();//延时大于4μs}void i2_tz()//停止信号{sda = 0;//拉低数据scl = 1;//拉高时钟delay();//延时大于 4μssda = 1;//拉高时钟产生结束信号(上升沿)delay();//延时大于4μs}void i2_ack(bit _ack)//入口产生 0 ack 1nak{sda = _ack;//ack或者nakscl = 1;//拉高时钟delay();//延时大于 4μsscl = 0;//拉低时钟delay();//延时大于 4μs}void i2_fs(uchar Data) //发送8位数据{uchar i;for(i=0;i<8;i++)//8位计数{Data <<= 1;//把最高位移送到进制标志位中(CY)sda = CY;//把进制位中的数据赋值给数据线scl = 1;//拉高时钟delay();//延时大于 4μsscl = 0;//拉低时钟//这里}//下面代码是接收ACK的代码delay();//延时大于4μssda = 1;//拉高数据准备接收ACKscl = 1;//拉高时钟产生稳定的有效的数据(相对的)if(sda==1)//确认接收的是ACK还是NAKack = 0;//ackelseack = 1;//nakscl = 0;//拉低时钟delay();//延时大于 4us}uchari2_js()//接收8位数据{uchar i,Data = 0;sda = 1;//使能内部上拉,准备读取数据for(i=0;i<8;i++)//8位计数器{Data <<= 1;//移出数据的最高位scl = 1;//拉高时钟delay();//延时大于 4usData |= sda;//接收数据scl = 0;//拉低时钟delay();//延时大于 4us}return Data;}void i2_sj_x(uchar addr,uchar Data)//往设备内写入数据(参数 1、寄存器地址 2、写入的数据){i2_qs();//起始信号i2_fs(addr_x);//设备地址+写信号i2_fs(addr);//寄存器内部地址i2_fs(Data);//写入设备的数据i2_tz();//停止信号}uchar i2_sj_d(uchar addr)//读取数据(参数寄存器地址){ucharData;i2_qs();//起始信号i2_fs(addr_x);//设备地址+写信号i2_fs(addr);//寄存器内部地址i2_qs();//起始信号i2_fs(addr_d);//设备地址+读信号Data =i2_js();//读取数据i2_ack(0);//ACK应答i2_tz();//停止信号return Data;//返回读取的数据}voidmain(void){uchar dat;i2_sj_x(3,0x0f); //数据写入24c02DelayMs(50);dat = i2_sj_d(3); //从24c02中读取数据P1 = dat;//使用8个LED显示读出的数据while(1){;}}以上代码只是简单的实现I2C总线的读写。
I2C总线编程实例(k1-k4:写⼊、读取、加+、清零)【EEPROM-AT24C02】(1)AT24C02是⼀种EEPROM元器件,是⼀种只读寄存器,断电保持,可保存数据100年, 是⼀种可擦除读写的芯⽚,相当于ROM硬盘,在下⾯实验中充当从机⾓⾊;(2)51在下⾯实验中充当主机⾓⾊;(3)在IIC总线标准协议上,进⾏51单⽚机(主机)和AT24C02(从机)的相互读写数据的操作。
⼩结:51单⽚机和各种EEPROM芯⽚之间可以通过IIC总线标准协议进⾏数据交互(通信)的。
实验:四个独⽴按键对应四个不同的功能,k1:将数据写⼊单⽚机,断电保存k2:读取上次保存的数据,断电后仍可读取上次保存的数据k3:当前数据+1k4:当前数据清零------------------------------------------------------------- 采⽤多⽂件的框架模式 -------------------------------------------------------------i2c.h:/*这个⽂件进⾏宏定义:定义I2C串⾏总线的相关数据端⼝、⽅法函数,以及定义⼀些使⽤频率较⾼的元素*/#ifndef _I2C_H_ // 如果没有定义宏#define _I2C_H_ // 定义⼀个宏// 需要⽤到51单⽚机的管脚,所以需要引⼊库⽂件#include <reg52.h>// 查单⽚机原理图可知(其中,SCL是时钟线,SDA是数据线)sbit SCL=P2^1;sbit SDA=P2^0;/* 相关函数 */// I2C的起始信号函数void I2cStart();// I2C的终⽌信号函数void I2cStop();// I2C发送(写⼊)字节函数,成功返回1,失败返回0unsigned char I2cSendByte(unsigned char dat);// I2C接收(读取)字节函数,返回读取的数据unsigned char I2cReadByte();// AT24C02芯⽚的写⼊数据函数void At24c02Write(unsigned char addr, unsigned dat);// AT24C02芯⽚的读取数据函数,返回读取的数据unsigned char At24c02Read(unsigned char addr);#endif // 结束i2c.c:/* 这个⽂件专门针对I2C模块的编程,其他模块可以新建另外⼀个⽂件 */#include <i2c.h> // 引⼊I2C的库⽂件/******************************************************************************** 函数名 : Delay10us()* 函数功能 : 延时10us* 输⼊ : ⽆* 输出 : ⽆*******************************************************************************/void Delay10us() //误差 0usunsigned char a,b;for(b=1;b>0;b--)for(a=2;a>0;a--);}/******************************************************************************** 函数名 : I2cStart()* 函数功能 : 起始信号:在SCL时钟信号在⾼电平期间SDA信号产⽣⼀个下降沿* 输⼊ : ⽆* 输出 : ⽆* 备注 : 起始之后SDA和SCL都为0,表⽰总线被主机占⽤*******************************************************************************/void I2cStart(){// 根据各个单⽚机的时序图来写SDA=1;Delay10us();SCL=1;Delay10us(); // 建⽴时间是SDA保持时间>4.7usSDA=0;Delay10us(); // 保持时间是>4usSCL=0;Delay10us();}/******************************************************************************** 函数名 : I2cStop()* 函数功能 : 终⽌信号:在SCL时钟信号⾼电平期间SDA信号产⽣⼀个上升沿* 输⼊ : ⽆* 输出 : ⽆* 备注 : 结束之后保持SDA和SCL都为1;表⽰总线处于空闲状态*******************************************************************************/void I2cStop(){// 根据各个单⽚机的时序图来写SDA=0;Delay10us();SCL=1;Delay10us(); // 建⽴时间是SDA保持时间>4.7usSDA=1;Delay10us(); // 保持时间是>4us}/******************************************************************************** 函数名 : I2cSendByte(unsigned char dat)* 函数功能 : 通过I2C发送⼀个字节。
325密码储存电路密码储存电路采用l2C总线at24c02存储芯片存放密码,可实现断电密码不消失,at24c02存储芯片可长期存储信息,可上百万次以上重新擦写。
2.4.3 I 2C总线密码存储芯片at24c02介绍S-I&ad TSSOP图2-3 at24c02 引脚图(1)引脚功能介绍及相关知识WP写保护引脚,将该引脚接VCC U PROM就实现写保护(只读)。
引脚接地或悬空,可以对器件进行读写操作。
SCL串行时钟引脚,串行输入输出时该引脚用于输入时钟。
SDA串行数据输入输出引脚,用来输入输出数据,该引脚为射极开路输出,需接上拉电阻。
(2) |2C总线协议只有总线非忙时才被允许进行数据传送,在传送时,当时钟线为高电平,数据线必须为固定状态,不允许有跳变。
时钟线为高电平时数据线的任何电平变化将被当作总线的启动或停止条件。
(3)起始条件起始调教必须在所有操作命令之前发送。
时钟线保持高电平期间,数据线电平从高到低跳变作为I2C总线的启动信号。
CAT24Cxx>一直监视SDA和SCL电平信号,直到条件满足时才响应。
(4) 停止条件时钟线保持高电平期间,数据线电平从低到高跳变作为l 2C 总线的停止信号。
(5) 器件地址的约定主器件在发送启动命令后开始传送数据,主器件发送相应的从器件地址, 8位从器件地址的高四位固定为1010,接下来的3位用来定义存储器的地址,对 于CAT24C021/022这三位无意义,对于 CAT24C41/042接下来的2位无意义, 第三位是地址高位,CAT24C081/082中,第一位无意义,后两位表示地址高位。
最后一位为读写控制位,“ 1”表示对从器件进行读写操作,“ 0 ”表示写操 作。
在主器件发送启动命令和一字节从器件地址后,如果与从器件地址吻合, CAT24C02各发送一个应答信号,然后再根据读/写控制为进行读或写操作。
(6) 应答信号每次数据传送成功后,接收器件将发送一个应答信号。
实验说明:T24C01A/AT24C02为I2C总线型EEPROM存储器,容量为1K/2K位(128/256*8),前读/写时序遵循I2C总线协议标准。
A T24C01A/A T24C02内部设有一个控制寄存器,其每一位的含义如下:Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit01 0 1 0 A2 A1 A0 R/W其中A2/A1/A0用于选择总线上待访问的I2C器件,R/W=1读操作,R/W=0写操作;从上述时序可以看出,I2C总线上最多可以扩展23=8片同样的1K/2K容量EEPROM存储器或者可以扩展1片容量为16K Bits的EEPROM存储器。
如果扩展8片2K以内容量的EEPROM 存储器,每片存储器将对应一个地址,这个由于实验仪上的A T24C01A/AT24C02的A2/A1/A0引脚全部接地,等效为实验仪上的AT24C01A/AT24C02的地址为0,所以在实验中读写控制字分别为:0xa1/0xa0实验要求利用实验仪上的I2C总线器件AT24C01A/AT24C02,编写I2C总线读写程序并自行验证程序的正确性。
c语言:/* 实验四十二IIC总线24C02读写*//* C51 */#include <reg51.h>#include <intrins.h>/* **********************************************************24C01/02 为IIC总线EEPROM存储器, 容量为1k位(128 * 8)************************************************************//* **********************************************************EEPROM控制字节格式:[1, 0, 1, 0, A2, A1, A0, (R/W)], 其中R/W=1读,R/W=0写;由于实验仪上的AT24C01A(AT24C02) 的A2/A1/A0全部接地,所以读/写控制字分别为:0xa1/0xa0************************************************************/#define WriteDeviceAddress 0xa0#define ReadDeviceAddress 0xa1/******************IIC器件驱动引脚定义**********************/sbit SCL = P1^0;sbit SDA = P1^1;/***********************简单延时****************************/void DelayMs(unsigned int number){unsigned char temp = 112;while(number--!=0){while(temp--!=0){}}}/*********************启动IIC总线***************************/void Start() {SDA = 1;SCL = 1;SDA = 0;SCL = 0;}/*********************停止IIC总线***************************/void Stop() {SCL = 0;SDA = 0;SCL = 1;SDA = 1;}/***********************请求相应****************************/void Ack() {SDA = 0; /*从器件响应信号将SDA线拉到低电平*/SCL = 1;SCL = 0;SDA = 1; /*响应结束,SDA回到高电平继续下一个传送周期*/ }/*******************不对IIC总线产生应答*********************/void NoAck() {SDA = 1; /*从机不响应时,数据线保持高电平*/SCL = 1;SCL = 0;}/**********************检查应答位***************************/bit TestAck() {SDA = 1;SCL = 1;CY = SDA;SCL = 0;return(CY); /*CY=0表应答*/}【关于I2C的检查应答信号的程序】unsigned char I2C_CheckAck(void){unsigned char i;unsigned char Ack=1;I2C_SDA=1;DelayUs(I2C_DELAY);I2C_SCL=1;DelayUs(I2C_DELAY);for(i=0;i<10;i++){Ack=I2C_SDA;if(!Ack){I2C_SCL=0;return 1;}}I2C_Stop();return 0;}/********************向IIC总线写数据************************/ bit Write8Bit(unsigned char input){unsigned char temp;for(temp = 8; temp != 0; temp--){SDA = (bit)(input&0x80); /*取Input最高位*/SCL = 1;SCL = 0;input = input<<1; /*input左移输入下一位*/ }return(0);}/****************从IIC总线上读数据子程序********************/unsigned char Read8Bit(){unsigned char temp, rbyte=0;for(temp=8;temp!=0;temp--){SCL=1;rbyte=rbyte<<1;rbyte=rbyte|((unsigned char)(SDA)); /*循环结束把8位的SDA(串行的)读成了一个8位的数放到rbyte中*/SCL=0;}return(rbyte);}/*******************向EEPROM中写入数据块********************/void AT24C02WriteBlock(unsigned char *Wdata, unsigned char RomAddress, unsigned char number){if(number > 8)number %= 8; /*对于24C02, 一个页为8字节,所以最大的块写操作字节数为8*/ Start();Write8Bit(WriteDeviceAddress); //总线上器件地址TestAck();Write8Bit(RomAddress); //器件内部要写入地址,有时将此处省略默认从00开始TestAck();for(;number!=0;number--){Write8Bit(*Wdata);TestAck();Wdata++;}Stop();DelayMs(10);}/**************从EEPROM中读出数据块到指定RAM中**************/void AT24C02ReadBlock(unsigned char *RamAddress, unsigned char RomAddress, unsigned char bytes){EA = 0; //单片机读操作限制在外部ROMStart();Write8Bit(WriteDeviceAddress);TestAck();Write8Bit(RomAddress);TestAck();Start(); //重新启动总线Write8Bit(ReadDeviceAddress);TestAck();while(bytes!=1){*RamAddress = Read8Bit();Ack();RamAddress++;bytes--;}*RamAddress = Read8Bit();NoAck();Stop();}/*****************向EEPROM中写入单字节数据******************/ void AT24c02WriteByte(unsigned char WriteData, unsigned char RomAddress) { Start();Write8Bit(WriteDeviceAddress);TestAck();Write8Bit(RomAddress);TestAck();Write8Bit(WriteData);TestAck();Stop();DelayMs(10);}/************从EEPROM中读出单字节数据到指定RAM中************/ unsigned char AT24c02ReadByte(unsigned char RomAddress) {unsigned char ReadData;Start();Write8Bit(WriteDeviceAddress);TestAck();Write8Bit(RomAddress);TestAck();Start();Write8Bit(ReadDeviceAddress);TestAck();ReadData = Read8Bit();NoAck();Stop();return(ReadData);}void main(void){unsigned char i;unsigned char WriteBuff[8], ReadBuff[8];/* 读写缓冲初始化*/for(i = 0; i < 8; i++){WriteBuff[i] = 0x55 + i;ReadBuff[i] = 0xff;}/* 从地址0开始按字节方式写入8个数据'0' */for(i = 0; i < 8; i++){A T24c02WriteByte(0, i);}/* 按字节方式读出数据*/for(i = 0; i < 8; i++) {ReadBuff[i] = AT24c02ReadByte(i);}/* 按写Page方式从地址0开始写入WriteBuff指向的8个数据*/ A T24C02WriteBlock(WriteBuff, 0x00, 8);/* 按连续读取方式读出从地址0开始的8个数据*/A T24C02ReadBlock(ReadBuff, 0x00, 8);while(1);}汇编语言:; 实验四十二IIC总线24C02读写; ASM51; ********************************************************** ; 24C01/02 为IIC总线EEPROM存储器, 容量为1k位(128 * 8); **********************************************************; ********************************************************** ; EEPROM控制字节格式:; [1, 0, 1, 0, A2, A1, A0, (R/W)], 其中R/W=1读,R/W=0写;; 由于实验仪上的AT24C01A(AT24C02) 的A2/A1/A0全部接地, ; 所以读/写控制字分别为:0xa1/0xa0; ********************************************************** WriteDeviceAddress equ 0a0hReadDeviceAddress equ 0a1h; ******************IIC器件驱动引脚定义********************* SCL equ P1.0SDA equ P1.1; *******************读写数据缓冲定义*********************** ReadBuff equ 40hWriteBuff equ 48hRWLength equ 30hRomAddress equ 31horg 0000hljmp Mainorg 0100h; ***********************简单延时*************************** DelayMs:push 06nopDelayMsLoop2:mov r6, #0ffhDelayMsLoop1:djnz r6, DelayMsLoop1djnz acc, DelayMsLoop2pop 06ret; ********************启动IIC总线*************************** Start:setb SDAsetb SCLclr SDAclr SCLret; ********************停止IIC总线*************************** Stop:clr SCLclr SDAsetb SCLsetb SDAret; **********************请求相应**************************** Ack:clr SDAsetb SCLclr SCLsetb SDAret; ******************不对IIC总线产生应答********************* NoAck:setb SDAsetb SCLclr SCLret; *********************检查应答位*************************** TestAck:setb SDAsetb SCLmov C, SDAclr SCLnopnopnopret; *******************向IIC总线写数据************************Write8Bit:push 07mov r7, #8Write8BitLoop:rlc amov SDA, Csetb SCLclr SCLnop ; 此处建议加入几个NOP指令降低MCU对器件操作的速度nopnopdjnz r7, Write8BitLooppop 07ret; ***************从IIC总线上读数据子程序********************Read8Bit:push 07clr amov r7, #8Read8BitLoop:clr Csetb SCLmov C, SDArlc aclr SCLnop ; 此处建议加入几个NOP指令降低MCU对器件操作的速度nopnopdjnz r7, Read8BitLooppop 07ret; ******************向EEPROM中写入数据块********************AT24C02WriteBlock:clr eamov r0, #WriteBuffinc RWLengthanl RWLength, #0f0h ;对于24C02, 一个页为8字节,所以最大的块写操作字节数为8*/mov r7, RWLengthcall Startmov a, #WriteDeviceAddresscall Write8Bitcall TestAckmov a, RomAddresscall Write8Bitcall TestAckAT24C02WriteBlockLoop:mov a, @r0call Write8Bitcall TestAckinc r0djnz r7, AT24C02WriteBlockcall Stopmov a, #10call DelayMsret; *************从EEPROM中读出数据块到指定RAM中************** AT24C02ReadBlock:clr eamov r0, #ReadBuffmov r7, RWLengthcall Startmov a, #WriteDeviceAddresscall Write8Bitcall TestAckmov a, RomAddresscall Write8Bitcall TestAckcall Startmov a, #ReadDeviceAddresscall Write8Bitcall TestAckAT24C02ReadBlockLoop:call Read8Bitmov @r0, acall Ackinc r0djnz r7, AT24C02ReadBlockcall NoAckcall Stopret; ****************向EEPROM中写入单字节数据****************** AT24c02WriteByte:clr eacall Startmov a, #WriteDeviceAddresscall Write8Bitcall TestAckmov a, RomAddresscall Write8Bitcall TestAckmov a, @r0call Write8Bitcall TestAckcall Stopmov a, #10call DelayMsret; ***********从EEPROM中读出单字节数据到指定RAM中************ AT24c02ReadByte:clr eacall Startmov a, #WriteDeviceAddresscall Write8Bitcall TestAckmov a, RomAddresscall Write8Bitcall TestAckcall Startmov a, #ReadDeviceAddresscall Write8Bitcall TestAckcall Read8Bitmov @r0 ,acall NoAckcall StopretSetReadBuff:mov r0, #ReadBuffmov r7, RWLengthSetReadBuffLoop:mov @r0, ainc r0djnz r7, SetReadBuffLoopretSetWriteBuff:mov r0, #WriteBuffmov r7, RWLengthSetWriteBuffLoop:mov @r0, ainc r0djnz r7, SetWriteBuffLoopretMain:mov SP, #60h; 读写缓冲初始化mov a, #00mov RWLength, #8call SetReadBuffmov a, #00mov RWLength, #8call SetWriteBuff; 写缓冲初始化mov r0, #WriteBuffmov r7, #8mov a, #55hInitWriteBuffLoop:mov @r0, ainc ainc r0djnz r7, InitWriteBuffLoop; 从地址0开始按字节方式写入8个数据'0' mov RomAddress, #0mov r7, #8mov r0, #WriteBuffWriteLoop:call AT24c02WriteByteinc RomAddressinc r0djnz r7, WriteLoop; 按字节方式读出数据mov RomAddress, #0mov r7, #8mov r0, #ReadBuffReadLoop:call AT24c02ReadByteinc RomAddressinc r0djnz r7, ReadLoop; 按写Page方式从地址0开始写入WriteBuff指向的8个数据mov RomAddress, #0mov RWLength, #8mov r0, #WriteBuffcall AT24C02WriteBlock; 按连续读取方式读出从地址0开始的8个数据mov RomAddress, #0mov RWLength, #8mov r0, #ReadBuffcall AT24C02ReadBlockjmp $end。
51单片机IIC总线操作及24c02指定地址的读写(单片机用STC89C58RD+)//24c02数据读写操作。
程序实现每一秒钟往24c02的指定地址内写入数据(既每一秒钟保存一次当前值)。
//共计时100秒,计时同步显示到数码管上,同时由8个led灯指示十位数的编码值。
//两个按键:单片机上电后按key6按键读取上次关机时存储到24c02内的数据,接着此数据继续计时显示。
//按key5按键计时停止。
#include <STC89C5xRC.H>#include<intrins.h>#define uchar unsigned char#define sda P20 //24c02数据接到P2.0口#define scl P21 //24c02时钟接到P2.1口//sbit sda=P2^0;//sbit scl=P2^1;sbit key6=P3^7;sbit key5=P3^6;uchar cont=0;uchar write=0; //标志位uchar code table[]={0x28,0xeb,0x32,0xa2,0xe1,0xa4,0x24,0xea,0x20,0xa0};void delay(){_nop_();_nop_();_nop_();}void delay1(uchar x){uchar a,b;for(a=x;a>0;a--)for(b=100;b>0;b--);}/***以下为24c02的IIC总线操作及读写数据的通用程序,IIC总线部分的程序可以用在其他IIC器件中参考郭天祥新概念51c语言***/void start() //开始{sda=1;delay();scl=1;delay();sda=0;delay();}void stop() //停止{sda=0;delay();scl=1;delay();sda=1;delay();}void respons() //应答{uchar i;scl=1;delay();while((sda==1)&&(i<250))i++;scl=0;delay();}void init(){sda=1;delay();scl=1;delay();}void write_byte(uchar date){uchar i,temp;temp=date;for(i=0;i<8;i++){temp=temp<<1;scl=0;delay();sda=CY;delay();scl=1;delay();// scl=0;// delay();}scl=0;delay();sda=1;delay();}uchar read_byte(){uchar i,k;scl=0;delay();sda=1;delay();for(i=0;i<8;i++){scl=1;delay();k=(k<<1)|sda;scl=0;delay();}return k;}void write_add(uchar address,uchar date) //24c02任一地址写入数据{start();write_byte(0xa0);respons();write_byte(address);respons();write_byte(date);respons();stop();}uchar read_add(uchar address) //24c02任一地址读取数据{uchar date;start();write_byte(0xa0);respons();write_byte(address);respons();start();write_byte(0xa1);respons();date=read_byte();stop();return date;}/***以上为24c02的IIC总线操作及读写数据的通用程序,IIC总线部分的程序可以用在其他IIC器件中参考郭天祥新概念51c语言***/void display(uchar shi,uchar ge) //显示子程序,P0口为数码管段{P0=table[shi];P27=0;delay1(5);P27=1;P0=table[ge];P26=0;delay1(5);P26=1;P1=table[shi]; //led指示灯按十位数变化相应亮灭}void main(){uchar keyscan;init();cont=read_add(36);if(cont==100)cont=0;TMOD=0X01; //ding shi qi gong zuo zai fang shi 1.EA=1;ET0=1;TH0=(65536-50000)/256;TL0=(65536-50000)%256;TR0=1; //启动定时器0P3=P3|0xfc; //11111100 置位按键位,p3口除p3.0和p3.1外接有6个按键keyscan=P3;switch(keyscan|0x03){case 0x7f: //如果key6被按下{while(key5!=0){display(cont/10,cont%10); //分解为十位数和个位数if(write==1){write=0;write_add(36,cont); //每1s写入数据cont到36地址处(地址0~255可任选)}}break;}case 0xbf: //如果key5被按下{while(key6!=0){TR0=0; //停止定时器read_add(36); //读取36号地址处数据静态显示display(cont/10,cont%10);}break;}}}void timer0() interrupt 1{uchar temp;TH0=(65536-50000)/256; //50ms中断初值,晶振12MHzTL0=(65536-50000)%256;temp++;if(temp==20) //temp每中断20次为1s(50ms*20=1000ms=1s){temp=0;cont++; //每1s时间到cont加一write=1; //到1s时标志位置一,开始往24c02里写入数据if(cont==100)cont=0; //100s时间到从00重新开始计时}}。
1. AT24C02写操作首先我们来看一下写AT24C02。
一般步骤是:1) 发送起始信号2) 发送写器件地址3) 等待应答4) 发送要写入的24C02 的地址5) 等待应答6) 发送要写入的数据7) 等待应答8) 发送数据结束发送结束信号具体程序如下:/****************************************************************************** ** 函数名: AT24Cxx_WriteOneByte* 函数功能: 24c02写一个字节地址数据* 输入: addr dt* 输出: 无********************************************/void AT24Cxx_WriteOneByte(u16 addr,u8 dt){I2C_Start();if(EE_TYPE>AT24C16){I2C_Send_Byte(0xA0);I2C_Wait_Ack();I2C_Send_Byte(addr>>8); //发送数据地址高位}else{I2C_Send_Byte(0xA0+((addr/256)<<1));//器件地址+数据地址}I2C_Wait_Ack();I2C_Send_Byte(addr%256);//双字节是数据地址低位//单字节是数据地址低位I2C_Wait_Ack();I2C_Send_Byte(dt);I2C_Wait_Ack();I2C_Stop();delay_ms(10);}2. AT24C02读操作那么读取AT24C02 的步骤是:1)发送起始信号2) 发送写器件地址3) 等待应答4) 发送要读取的AT24C02 的地址5) 等待应答6) 再发送其实信号7) 发送读器件地址8) 等待应答9) 接收数据10) 如果没有接收完数据,发送应答11) 接收数据12) 直到接收完数据,发送非应答13) 发送结束信号/****************************************************************************** ** 函数名: AT24Cxx_ReadOneByte* 函数功能: 24c02读一个字节地址数据* 输入: addr* 输出: 返回值temp*****************************************************************************/ u8 AT24Cxx_ReadOneByte(u16 addr){u8 temp=0;I2C_Start();if(EE_TYPE>AT24C16){I2C_Send_Byte(0xA0);I2C_Wait_Ack();I2C_Send_Byte(addr>>8); //发送数据地址高位}else{I2C_Send_Byte(0xA0+((addr/256)<<1));//器件地址+数据地址}I2C_Wait_Ack();I2C_Send_Byte(addr%256);//双字节是数据地址低位//单字节是数据地址低位I2C_Wait_Ack();I2C_Start();I2C_Send_Byte(0xA1);I2C_Wait_Ack();temp=I2C_Read_Byte(0); // 0 代表NAC I2C_NAck();I2C_Stop();return temp;}。
1. AT24C02写操作首先我们来看一下写AT24C02。
一般步骤是:1) 发送起始信号2) 发送写器件地址3) 等待应答4) 发送要写入的24C02 的地址5) 等待应答6) 发送要写入的数据7) 等待应答8) 发送数据结束发送结束信号具体程序如下:/****************************************************************************** ** 函数名: AT24Cxx_WriteOneByte* 函数功能: 24c02写一个字节地址数据* 输入: addr dt* 输出: 无********************************************/void AT24Cxx_WriteOneByte(u16 addr,u8 dt){I2C_Start();if(EE_TYPE>AT24C16){I2C_Send_Byte(0xA0);I2C_Wait_Ack();I2C_Send_Byte(addr>>8); //发送数据地址高位}else{I2C_Send_Byte(0xA0+((addr/256)<<1));//器件地址+数据地址}I2C_Wait_Ack();I2C_Send_Byte(addr%256);//双字节是数据地址低位//单字节是数据地址低位I2C_Wait_Ack();I2C_Send_Byte(dt);I2C_Wait_Ack();I2C_Stop();delay_ms(10);}2. AT24C02读操作那么读取AT24C02 的步骤是:1)发送起始信号2) 发送写器件地址3) 等待应答4) 发送要读取的AT24C02 的地址5) 等待应答6) 再发送其实信号7) 发送读器件地址8) 等待应答9) 接收数据10) 如果没有接收完数据,发送应答11) 接收数据12) 直到接收完数据,发送非应答13) 发送结束信号/****************************************************************************** ** 函数名: AT24Cxx_ReadOneByte* 函数功能: 24c02读一个字节地址数据* 输入: addr* 输出: 返回值temp*****************************************************************************/ u8 AT24Cxx_ReadOneByte(u16 addr){u8 temp=0;I2C_Start();if(EE_TYPE>AT24C16){I2C_Send_Byte(0xA0);I2C_Wait_Ack();I2C_Send_Byte(addr>>8); //发送数据地址高位}else{I2C_Send_Byte(0xA0+((addr/256)<<1));//器件地址+数据地址}I2C_Wait_Ack();I2C_Send_Byte(addr%256);//双字节是数据地址低位//单字节是数据地址低位I2C_Wait_Ack();I2C_Start();I2C_Send_Byte(0xA1);I2C_Wait_Ack();temp=I2C_Read_Byte(0); // 0 代表NAC I2C_NAck();I2C_Stop();return temp;}。
STM32F0单片机快速入门九: 用I2C HAL 库读写24C02发表评论1.24C02介绍24C02 现在基本是开发板的标配,对于需要掉电存储的应用来说确是不二选择。
现在单片机因为内部集成了Flash存储器,一般也都支持数据的掉电保存,但相对于24C02 这种EEPROM 来说,使用单片机内部的Flash 有一些需要注意的问题:1.Flash 写入数据之前需要先执行擦除操作,而且擦除以扇区为单位。
2.Flash读写次数比EEPROM 少很多。
3.容易误操作,把Flash 内部的代码擦除掉。
4.影响中断的响应时间。
24C02 有256 字节的数据,一般说来也够用了。
它的地址是可以通过引脚配置的,这样一条I2C 总线上就可以挂多个24C02。
如下:我们把A2,A1,A0 都接地,这样地址为A0。
然后SCL,SDA 脚接MCU 的PB8 和PB9。
需要注意SCL,和SDA 需要加上拉电阻。
1.代码下面我们在一个I2C 例程上面修改代码来实现24C02 的读写。
大家可以看到使用库函数的好处,基本上不用看STM32F030 的手册,很快就能实现我们想要实现的功能。
我们用Keil 打开下面这个工程:STM32Cube_FW_F0_V1.11.0\Projects\STM32F030R8-Nucleo\Examples\I2C\I2C_TwoBoards_ComPolling\MDK-AR M\Project.uvprojxStep 1, 把I2C 地址改为跟我们硬件一致:Step 2, 根据实际使用的I2C 模块和引脚进行配置:Step 3, 把地址模式改为7BIT:Step 4, 操作EEPROM,我们不使用例子中的HAL_I2C_Master_Transmit 和HAL_I2C_Master_Receive,这两个函数适用于两个I2C 器件之间进行数据传输。
我们这里要用的是下面这两个函数:HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, // 使用的I2C 模块的Handle 的指针uint16_t DevAddress, // I2C 器件的地址,这里是24C02 的地址0xA0uint16_t MemAddress, // 存储器内部地址uint16_t MemAddSize, // 存储器内部地址位数8BIT or 16BIT ?uint8_t *pData, // 发送数据缓冲区指针uint16_t Size, // 数据长度uint32_t Timeout // 超时设置);HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, // 使用的I2C 模块的Handle 的指针uint16_t DevAddress, // I2C 器件的地址,这里是24C02 的地址0xA0uint16_t MemAddress, // 存储器内部地址uint16_t MemAddSize, // 存储器内部地址位数8BIT or 16BIT ?uint8_t *pData, // 接收数据缓冲区指针uint16_t Size, // 接收数据长度uint32_t Timeout // 超时设置);在此我们写入数据用的24C02 的Page Write 命令,每次写入8个字节的数据,然后存储器写入地址加8。
I2C总线上接两个AT24C02读写实例、本例对I2C总线上关节两个AT24C02进行读写操作,想将数据0xaa写入第一个at24c02的指定地址,再将该数据读出后存入第二个AT24C02的指定地址,最后读出该数据并送P1口用8位LED显示验证2、实现方法:1)两个器件地址的确定由于第一个AT24C02的3位地址位(A0A1A2)均接地(低电平),第二个AT24C02的三个地址位(A0A1A2)均接电源(高电平),因此第一个AT24C02的地址为000,第二个AT24C02的地址为111.在写命令时,指名要操作的器件地址,即可对不同的AT24C02进行操作3、在keil c51中新建工程ex54,编写如下程序代码,编译并生成ex54.hex文件//对I2C总线上挂接多个AT24C02的读写操作#include <reg51.h> // 包含51单片机寄存器定义的头文件#include <intrins.h> //包含_nop_()函数定义的头文件#define OP_READ1 0xa1 // 器件1地址以及读取操作,0xa1即为1010 0001B#define OP_WRITE1 0xa0 // 器件1地址以及写入操作,0xa1即为1010 0000B#define OP_READ2 0xaf // 器件2地址以及读取操作,0xa1即为1010 1111B#define OP_WRITE2 0xae // 器件2地址以及写入操作,0xa1即为1010 1110Bsbit SDA=P3^4; //将串行数据总线SDA位定义在为P3.4引脚sbit SCL=P3^3; //将串行时钟总线SDA位定义在为P3.3引脚/*****************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/***************************************************** 函数功能:延时若干毫秒入口参数:n***************************************************/ void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/***************************************************函数功能:开始数据传送***************************************************/ void start()// 开始位{SDA = 1; //SDA初始化为高电平“1”SCL = 1; //开始数据传送时,要求SCL为高电平“1”_nop_(); //等待一个机器周期SDA = 0; //SDA的下降沿被认为是开始信号_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)_nop_(); //等待一个机器周期}/***************************************************函数功能:结束数据传送***************************************************/void stop()// 停止位{SDA = 0; //SDA初始化为低电平“0”_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SCL = 1; //结束数据传送时,要求SCL为高电平“1”_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SDA = 1; //SDA的上升沿被认为是结束信号}/***************************************************函数功能:从AT24Cxx读取数据出口参数:x***************************************************/unsigned char ReadData()// 从AT24Cxx移入数据到MCU{unsigned char i;unsigned char x; //储存从AT24Cxx中读出的数据for(i = 0; i < 8; i++){SCL = 1; //SCL置为高电平x<<=1; //将x中的各二进位向左移一位x|=(unsigned char)SDA; //将SDA上的数据通过按位“或“运算存入x中SCL = 0; //在SCL的下降沿读出数据}return(x); //将读取的数据返回}/***************************************************函数功能:向AT24Cxx的当前地址写入数据入口参数:y (储存待写入的数据)***************************************************///在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0bit WriteCurrent(unsigned char y){unsigned char i;bit ack_bit; //储存应答位for(i = 0; i < 8; i++) // 循环移入8个位{SDA = (bit)(y&0x80); //通过按位“与”运算将最高位数据送到S//因为传送时高位在前,低位在后_nop_(); //等待一个机器周期SCL = 1; //在SCL的上升沿将数据写入AT24Cxx_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SCL = 0; //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲y <<= 1; //将y中的各二进位向左移一位}SDA = 1; // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,//以让SDA线转由接收设备(AT24Cxx)控制_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SCL = 1; //根据上述规定,SCL应为高电平_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期ack_bit = SDA; //接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节//若送高电平,表示没有接收到,传送异常SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)return ack_bit;// 返回AT24Cxx应答位}/***************************************************函数功能:向第一个AT24Cxx中的指定地址写入数据入口参数:add (储存指定的地址);dat(储存待写入的数据)***************************************************/void WriteSet1(unsigned char add, unsigned char dat)// 在指定地址addr处写入数据WriteCurrent{start(); //开始数据传递WriteCurrent(OP_WRITE1); //选择要操作的第一个AT24Cxx芯片,并告知要对其写入数据WriteCurrent(add); //写入指定地址WriteCurrent(dat); //向当前地址(上面指定的地址)写入数据stop(); //停止数据传递delaynms(4); //1个字节的写入周期为1ms, 最好延时1ms以上}/***************************************************函数功能:向第二个AT24Cxx中的指定地址写入数据入口参数:add (储存指定的地址);dat(储存待写入的数据)***************************************************/void WriteSet2(unsigned char add, unsigned char dat)// 在指定地址addr处写入数据WriteCurrent{start(); //开始数据传递WriteCurrent(OP_WRITE2); //选择要操作的AT24Cxx芯片,并告知要对其写入数据WriteCurrent(add); //写入指定地址WriteCurrent(dat); //向当前地址(上面指定的地址)写入数据stop(); //停止数据传递delaynms(4); //1个字节的写入周期为1ms, 最好延时1ms以上}/***************************************************函数功能:从第一个AT24Cxx中的当前地址读取数据出口参数:x (储存读出的数据)***************************************************/unsigned char ReadCurrent1(){unsigned char x;start(); //开始数据传递WriteCurrent(OP_READ1); //选择要操作的第一个AT24Cxx芯片,并告知要读其数据x=ReadData(); //将读取的数据存入xstop(); //停止数据传递return x; //返回读取的数据}/***************************************************函数功能:从第二个AT24Cxx中的当前地址读取数据出口参数:x (储存读出的数据)***************************************************/unsigned char ReadCurrent2(){unsigned char x;start(); //开始数据传递WriteCurrent(OP_READ2); //选择要操作的第二个AT24Cxx芯片,并告知要读其数据x=ReadData(); //将读取的数据存入xstop(); //停止数据传递return x; //返回读取的数据}/***************************************************函数功能:从第一个AT24Cxx中的指定地址读取数据入口参数:set_addr出口参数:x***************************************************/unsigned char ReadSet1(unsigned char set_addr)// 在指定地址读取{start(); //开始数据传递WriteCurrent(OP_WRITE1); //选择要操作的第一个AT24Cxx芯片,并告知要对其写入数据WriteCurrent(set_addr); //写入指定地址return(ReadCurrent1()); //从第一个AT24Cxx芯片指定地址读出数据并返回}/***************************************************函数功能:从第二个AT24Cxx中的指定地址读取数据入口参数:set_addr出口参数:x***************************************************/unsigned char ReadSet2(unsigned char set_addr)// 在指定地址读取{start(); //开始数据传递WriteCurrent(OP_WRITE2); //选择要操作的第二个AT24Cxx芯片,并告知要对其写入数据WriteCurrent(set_addr); //写入指定地址return(ReadCurrent2()); //从第二个AT24Cxx芯片指定地址读出数据并返回}/***************************************************函数功能:主函数***************************************************/main(void){unsigned char x;SDA = 1; // SDA=1,SCL=1,使主从设备处于空闲状态SCL = 1;WriteSet1(0x36,0xaa); //将数据"0xaa"写入第一个AT24C02的指定地址"0x36" x=ReadSet1(0x36); //从第二个AT24C02中的指定地址"0x36"读出数据 WriteSet2(0x48,x); //将读出的数据写入第二个AT24C02的指定地址"0x48"?P1=ReadSet2(0x48); //将从第二个AT24C02的指定地址读出的数据送P1口显示验证}4、在proteus中新建仿真文件ex54.dsn,电路原理图如下所示5、将ex54.hex文件载入at89c51中,启动仿真,观察运行结果。
如何对AT24C02编写驱动程序——IIC总线协议AT24C02是一种2Kbit(256字节)的串行EEPROM芯片,采用I2C总线协议进行通信。
编写AT24C02的驱动程序需要了解I2C总线协议的工作原理以及AT24C02的读写操作。
以下是编写AT24C02驱动程序的步骤:1. 硬件配置:首先,需要在单片机上配置I2C总线的硬件连接。
I2C 总线需要两根信号线,即SDA(Serial Data Line)和SCL(Serial Clock Line)。
将SDA和SCL引脚连接到AT24C02的对应引脚,并通过上拉电阻将其拉高。
2.初始化I2C总线:在驱动程序中,需要初始化I2C总线的相关寄存器和配置参数。
这包括设置I2C总线的通信速率、使能I2C模块、使能中断等。
3.开始信号和设备地址:发送开始信号START,然后发送AT24C02的设备地址,设备地址由3位固定的值和一个读/写位组成。
读写位为0代表写操作,为1代表读操作。
4.发送数据:如果是写操作,发送要写入的数据到AT24C02的指定地址。
数据写入时,需要注意AT24C02的内存地址范围,以及页写操作的限制。
如果是读操作,发送读取的目标地址。
5.停止信号:传输完成后,发送停止信号STOP,结束通信。
6.延时和轮询:在I2C总线通信中,需要一定的延时等待数据传输完成。
在写入大量数据或读取数据时,还需要轮询等待操作完成。
7.错误处理:在驱动程序中,需要考虑到可能发生的错误和异常情况。
例如,设备地址未响应、通信超时、数据传输错误等,都需要进行相应的错误处理。
8.封装函数接口:为了方便上层应用调用,可以将上述操作封装成函数接口。
例如,提供读写函数、擦除函数和查询设备ID的函数等。
除了以上的驱动程序,还可以根据实际需求进行功能扩展。
例如,可以实现批量写入数据、随机读取数据、擦除操作等。
总之,编写AT24C02的驱动程序主要包括硬件配置、初始化I2C总线、发送开始信号和设备地址、发送数据、发送停止信号、延时和轮询、错误处理等步骤。
ATMEL 24c02使用详解(汇编及C程序都有)1000字ATMEL 24c02是一种串行EEPROM存储器,具有2KB的存储容量,可通过I2C总线进行读写操作。
使用ATMEL 24c02时,需先设置I2C总线的通信速率和设备地址。
然后,可以使用汇编语言或C语言编写程序进行读写数据操作。
汇编语言程序示例:1. 设置I2C总线通信速率及设备地址```LDAA #$0 ;设置I2C总线通信速率为100kHzSTAA SCLDIVLDAA #$A0 ;设置EEPROM的设备地址为0xA0STAA SLA```2. 写入数据到EEPROM```BYTE_WRITE PROCLDAA #$00 ;设置数据的存储地址为0x00STAA DADDRLDAA #$A5 ;设置需要写入的数据为0xA5STAA DATAJSR I2C_WRITE ;调用I2C总线写入函数RTSBYTE_WRITE ENDP```3. 从EEPROM读取数据```BYTE_READ PROCLDAA #$00 ;设置数据的读取地址为0x00STAA DADDRJSR I2C_START ;发送起始信号LDAA #$A1 ;设置EEPROM的设备地址为0xA1,读操作时需要在地址末位添加1JSR I2C_SEND ;发送EEPROM设备地址LDAA #$00 ;设置要读取的数据长度为1JSR I2C_READ ;调用I2C总线读取函数LDA DATA ;将读取到的数据保存到DATA寄存器中RTSBYTE_READ ENDP```C语言程序示例:1. 在main函数中,调用I2C_Init()函数,设置I2C总线速率和设备地址。
```void main(){I2C_Init(); //设置I2C总线速率和设备地址}```2. 写入数据到EEPROM```void Write_Byte(unsigned char addr, unsigned char dat) {I2C_Start(); //发送起始信号I2C_SendByte(0xa0); //写入EEPROM的设备地址I2C_SendByte(addr); //设置存储地址I2C_SendByte(dat); //写入数据I2C_Stop(); //发送停止信号}```3. 从EEPROM读取数据```unsigned char Read_Byte(unsigned char addr){unsigned char res;I2C_Start(); //发送起始信号I2C_SendByte(0xa0); //写入EEPROM的设备地址I2C_SendByte(addr); //设置读取地址I2C_Start(); //发送起始信号I2C_SendByte(0xa1); //设置EEPROM的设备地址为读取模式 res = I2C_ReadByte(); //读取数据I2C_Stop(); //发送停止信号return res; //返回读取的数据}```即可进行EEPROM的读写操作。
/jammy_lee/
linux下iic(i2c)读写AT24C02
linux驱动2010-02-09 16:02:03 阅读955 评论3 字号:大中小订阅
linux内核上已有iic的驱动,因此只需要对该iic设备文件进行读写则能够控制外围的iic器件。
这里以AT24C02为对象,编写一个简单的读写应用程序。
iic设备文件在我的开发板上/dev/i2c/0 ,打开文件为可读写。
AT24C02的器件地址为0x50 ,既是iic总线上从器件的地址,每次只读写一字节数据。
/************************************************************/
//文件名:app_at24c02.c
//功能:测试linux下iic读写at24c02程序
//使用说明: (1)
// (2)
// (3)
// (4)
//作者:jammy-lee
//日期:2010-02-08
/************************************************************/
//包含头文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
//宏定义
#define Address 0x50 //at24c02地址
#define I2C_RETRIES 0x0701
#define I2C_TIMEOUT 0x0702
#define I2C_SLAVE 0x0703 //IIC从器件的地址设置
#define I2C_BUS_MODE 0x0780
typedef unsigned char uint8;
uint8 rbuf[8] = {0x00}; //读出缓存
uint8 wbuf[8] = {0x01,0x05,0x06,0x04,0x01,0x01,0x03,0x0d}; //写入缓存int fd = -1;
//函数声明
static uint8 AT24C02_Init(void);
static uint8 i2c_write(int fd, uint8 reg, uint8 val);
static uint8 i2c_read(int fd, uint8 reg, uint8 *val);
static uint8 printarray(uint8 Array[], uint8 Num);
//at24c02初始化
static uint8 AT24C02_Init(void)
{
fd = open("/dev/i2c/0", O_RDWR); //允许读写
if(fd < 0)
{
perror("Can't open /dev/nrf24l01 \n"); //打开iic设备文件失败
exit(1);
}
printf("open /dev/i2c/0 success !\n"); //打开iic设备文件成功
if(ioctl(fd, I2C_SLAVE, Address)<0) { //设置iic从器件地址printf("fail to set i2c device slave address!\n");
close(fd);
return -1;
}
printf("set slave address to 0x%x success!\n", Address);
if(ioctl(fd, I2C_BUS_MODE, 1)<0) //设置iic总线模式printf("set bus mode fail!\n");
else
printf("set bus mode ok!\n");
return(1);
}
/*
uint8 AT24C02_Write(uint8 *nData, uint8 Reg, uint8 Num)
{
write(fd, &Reg, 1); //
usleep(100); //延时100us
write(fd, nData, Num);
usleep(1000*4); //延时4ms
return(1);
}
uint8 AT24C02_Read(uint8 nData[], uint8 Reg, uint8 Num) {
write(fd, &Reg, 1);
usleep(100); //延时100us
read(fd, nData, Num);
usleep(1000*4); //延时4ms
return(1);
}
*/
//at24c02写入一字节
static uint8 i2c_write(int fd, uint8 reg, uint8 val)
{
int retries;
uint8 data[2];
data[0] = reg;
data[1] = val;
for(retries=5; retries; retries--) {
if(write(fd, data, 2)==2)
return 0;
usleep(1000*10);
}
return -1;
}
//at24c02读取一字节
static uint8 i2c_read(int fd, uint8 reg, uint8 *val)
{
int retries;
for(retries=5; retries; retries--)
if(write(fd, ®, 1)==1)
if(read(fd, val, 1)==1)
return 0;
return -1;
}
//输出数组
static uint8 printarray(uint8 Array[], uint8 Num) {
uint8 i;
for(i=0;i<Num;i++)
{
printf("Data [%d] is %d \n", i ,Array[i]);
}
return(1);
}
//主函数
int main(int argc, char *argv[])
{
int i;
AT24C02_Init();
usleep(1000*100);
for(i=0; i<sizeof(rbuf); i++)
if(i2c_read(fd, i, &rbuf[i]))
break;
printarray(rbuf ,8);
printf("Before Write Data \n"); sleep(1);
for(i=0; i<sizeof(rbuf); i++)
if(i2c_write(fd, i, wbuf[i]))
break;
printarray(wbuf ,8);
printf("Writing Data \n");
sleep(1);
for(i=0; i<sizeof(rbuf); i++)
if(i2c_read(fd, i, &rbuf[i]))
break;
printarray(rbuf ,8);
printf("After Write Data \n");
close(fd);
}。