I2C总线AT24C02存储器读写程序
I2C总线芯片AT24C02程序设计
I2C总线芯片AT24C02程序设计I2C总线芯片AT24C02是一种常用的存储器芯片,在嵌入式系统中广泛应用。
本文将介绍如何使用AT24C02进行程序设计,包括芯片初始化、读取数据和写入数据等操作。
为了简化整个流程,本文将只介绍关键的代码部分。
首先,我们需要了解AT24C02芯片的连接方式和寄存器地址。
AT24C02通过I2C总线连接到控制器,其中使用两根信号线SCL和SDA进行通信。
芯片的I2C地址为0xA0,并且有256个存储器单元,每个单元8位,总共可以存储2KB的数据。
接下来,我们需要进行芯片的初始化。
初始化过程包括初始化I2C总线、设置AT24C02的I2C地址和其他必要的配置。
以下是AT24C02初始化的代码示例:```c#include <Wire.h>#define AT24C02_ADDRESS 0xA0 // AT24C02芯片的I2C地址void setupWire.begin(; // 初始化I2C总线void loop//主程序代码```在进行读取数据之前,我们需要指定要读取的存储器单元的地址,并将其发送给AT24C02芯片。
以下是读取数据的代码示例:```c#include <Wire.h>#define AT24C02_ADDRESS 0xA0 // AT24C02芯片的I2C地址#define MEMORY_ADDRESS 0x00 // 要读取的存储器单元的地址void setupWire.begin(; // 初始化I2C总线Wire.beginTransmission(AT24C02_ADDRESS); // 开始I2C通信Wire.write(MEMORY_ADDRESS); // 发送存储器单元的地址Wire.endTransmission(; // 结束I2C通信void loop//主程序代码```在进行写入数据之前,我们需要指定要写入的存储器单元的地址,并将数据发送给AT24C02芯片。
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为读出。
AT24C02的芯片地址(0xa0为写,0xa1为读)
任一地址写入数据格式
任一地址读取数据格式。
STM32----6----I2C读写AT24C02
STM32----6----I2C读写AT24C02文章发表于:2011-05-09 13:51STM32作为主机I2C,读写24C02 EEPROM1、时钟和数据的传输:开始和停止条件,数据在SCL的高电平期间有效,在SCL的低电平期间改变。
2、开始条件:在SCL高电平期间,SDA产生一个下降沿3、停止条件:在SCL高电平期间,SDA产生一个上升沿4、应答:成功接收到数据(地址和数据),产生一个应答位(在第9个时钟周期,将SDA拉低)下面是源程序:原理上说,下面程序再移植时,只要将数据类型变化,可以应用到任何处理器AT24c02.h#ifndef __24CXX_H#define __24CXX_H#include "i2c.h"/***************************************************************- 说明:以下参数是AT24Cxx的寻址空间,C0x ,X 表示XK 如C01表示1K- 127表示2^7 1Kbit/8=128Byte 128字节- 255表示2^8 2Kbit/8=256Byte 256字节- 512表示2^9 4Kbit/8=512Byte 512字节-***************************************************************/#define AT24C01 127#define AT24C02 255#define AT24C04 511#define AT24C08 1023#define AT24C16 2047#define AT24C32 4095#define AT24C64 8191#define AT24C128 16383#define AT24C256 32767/**************************************************************--板子使用的是24c02,所以定义EE_TYPE为AT24C02**************************************************************/#define EE_TYPE AT24C02/**************************************************************--EEPROM的操作函数--24CXX驱动函数**************************************************************/u8 AT24CXX_ReadOneByte(u16 ReadAddr); //指定地址读取一个字节void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite); //指定地址写入一个字节void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len);//指定地址开始写入指定长度的数据u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len); //指定地址开始读取指定长度数据void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite); //从指定地址开始写入指定长度的数据void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead); //从指定地址开始读出指定长度的数据u8 AT24CXX_Check(void); //检查器件void AT24CXX_Init(void); //初始化IIC#endif----------------------------------------------------------------------------------------------------------------------------------------- AT24c02.c#include "at24cxx.h"#include "delay.h"/*************************************************************************** - 功能描述:STM32f103 EEPORM初始化函数- 隶属模块:STM32 EEPROM操作- 函数属性:外部,使用户使用- 参数说明:无- 返回说明:无- 函数功能:实现I2C的初始化。
I2C24LC02C读写例程(PIC单片机)
I2C24LC02C读写例程(PIC单片机)I2C 24LC02 C读写例程(PIC单片机)[单片机]发布时间:2008-04-22 10:11:001 I2C总线特点I2C总线最主要的优点是其简单性和有效性。
由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。
总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。
I2C总线的另一个优点是,它支持多主控(multimastering),其中任何能够进行发送和接收的设备都可以成为主总线。
一个主控能够控制信号的传输和时钟频率。
当然,在任何时间点上只能有一个主控。
2 I2C总线工作原理I2C总线上的数据稳定规则,SCL为高电平时SDA上的数据保持稳定,SCL为低电平时允许SDA变化。
如果SCL处于高电平时,SDA 上产生下降沿,则认为是起始位,SDA上的上升沿认为是停止位。
通信速率分为常规模式(时钟频率100kHz)和快速模式(时钟频率400kHz)。
同一总线上可以连接多个带有I2C接口的器件,每个器件都有一个唯一的地址,既可以是单接收的器件,也可以是能够接收发送的器件。
每次数据传输都是以一个起始位开始,而以停止位结束。
传输的字节数没有限制。
最高有效位将首先被传输,接收方收到第8位数据后会发出应答位。
数据传输通常分为两种:主设备发送从设备接收和从设备发送主设备接收。
这两种模式都需要主机发送起始位和停止位,应答位由接收方产生。
从设备地址一般是1或2个字节,用于区分连接在同一I2C上的不同器件。
I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。
开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC 发出特定的低电平脉冲,表示已收到数据。
linux下iic(i2c)读写AT24C02
/jammy_lee/linux下iic(i2c)读写AT24C02linux驱动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 0x0780typedef 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");elseprintf("set bus mode ok!\n");return(1);}/*uint8 AT24C02_Write(uint8 *nData, uint8 Reg, uint8 Num){write(fd, &Reg, 1); //usleep(100); //延时100uswrite(fd, nData, Num);usleep(1000*4); //延时4msreturn(1);}uint8 AT24C02_Read(uint8 nData[], uint8 Reg, uint8 Num) {write(fd, &Reg, 1);usleep(100); //延时100usread(fd, nData, Num);usleep(1000*4); //延时4msreturn(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);}。
I2C总线协议AT24c02程序
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总线芯片AT24C02程序设计
I2C总线芯片AT24C02程序设计AT24C02是一种常见的I2C总线芯片,具有2K字节的存储空间。
在程序设计方面,主要需要考虑以下几个方面:初始化、读取数据、写入数据。
首先,需要考虑的是初始化芯片。
在初始化过程中,主要有两个关键的步骤,一个是设置I2C总线的速率,另一个则是设置芯片地址。
以下是AT24C02初始化的伪代码:```void init_AT24C0//设置I2C总线速率i2c_set_speed(I2C_SPEED);//设置AT24C02芯片地址i2c_write_byte(AT24C02_ADDR);if (!i2c_check_ack()//错误处理机制}```在初始化完成后,就可以进行数据的读取和写入。
以下是读取数据的伪代码:```uint8_t read_AT24C02(uint16_t addr)//发送开始信号i2c_start(;//发送芯片地址和写入模式i2c_write_byte(AT24C02_ADDR , I2C_WRITE); if (!i2c_check_ack()//错误处理机制}//发送要读取的地址高位和低位i2c_write_byte(addr >> 8);if (!i2c_check_ack()//错误处理机制}i2c_write_byte(addr & 0xFF);if (!i2c_check_ack()//错误处理机制}//发送重新开始信号i2c_restart(;//发送芯片地址和读取模式i2c_write_byte(AT24C02_ADDR , I2C_READ);if (!i2c_check_ack()//错误处理机制}//读取数据uint8_t data = i2c_read_byte(;//发送停止信号i2c_stop(;//返回读取到的数据return data;```以上是读取数据的伪代码,对应地,写入数据的伪代码如下:```void write_AT24C02(uint16_t addr, uint8_t data)//发送开始信号i2c_start(;//发送芯片地址和写入模式i2c_write_byte(AT24C02_ADDR , I2C_WRITE);if (!i2c_check_ack()//错误处理机制}//发送要写入的地址高位和低位i2c_write_byte(addr >> 8);if (!i2c_check_ack()//错误处理机制}i2c_write_byte(addr & 0xFF); if (!i2c_check_ack()//错误处理机制}//写入数据i2c_write_byte(data);if (!i2c_check_ack()//错误处理机制}//发送停止信号i2c_stop(;```需要注意的是,在读取或写入数据之前,必须实现I2C总线的相关函数,如设置速率、发送信号、写入数据等。
最好的24C02储存开机次数实验 读写程序
24C02储存开机次数实验24C02是2K字节的串行EEPROM, 内部含有256个8位字节,该器件通过总线操作,并有专门的写保护功能。
串行EEPROM简称I2C总线式串行器件。
串行器件不仅占用很少的资源和I/O 线,而且体积大大缩小,同时具有工作电源宽、抗干扰能力强、功耗低、数据不易丢失和支持在线编程等特点。
I2C总线是一种用于IC器件之间连接的二线制总线。
它通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件:不管是单片机、存储器、LCD驱动器还是键盘接口。
我们通过一个实验来了解24C02的读写操作过程:该实验功能是单片机复位一次,自动从24C02中读取数据,然后加1,最终数码管中的数据就是开机的次数,具有一定的实用意义。
相关原理:程序运行的照片:接线方法:1、接8位数码管的数据线。
将数码管部份的数据口 JP5接到CPU部份的P0口JP51.2、接8位数码管的显示位线。
将数码管部份的显示位口 JP8接到CPU部份的P2口JP52.3、用一根2PIN数据线一端插入CPU部份JP53(P3口)的P3.6,P3.7另外一端插入24C02部份的控制端JP38。
烧写后用手按复位键可以看到数码管每按一下加一。
程序流程图:汇编语言参考程序: SDA24 EQU P3.7 SCLK24 EQU P3.6 ORG 0000HAJMP MAINORG 0080HMAIN:CLR P3.7 ;打开写保护MOV DPTR,#TABMOV A,#00H ;读地址LCALL RD24CJNE A,#10,TTTT: JNC TT1AJMP TT2TT1: MOV A,#00TT2: MOV 30H,AMOVC A,@A+DPTRCLR P2.6 ;开数码管MOV P0,A ;送显示MOV A,30HINC AMOV B,AMOV A,#00HLCALL WT24AJMP $TAB: DB 28H,7EH,0A2H,62H,74H,61H,21H,7AH,20H,60HRD24: PUSH ACC ;读24C02子程序。
I2C总线上接两个AT24C02读写实例
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 1110B页脚内容1sbit 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***************************************************/页脚内容2void 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_(); //等待一个机器周期_nop_(); //等待一个机器周期SDA = 0; //SDA的下降沿被认为是开始信号页脚内容3_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递) _nop_(); //等待一个机器周期}/***************************************************函数功能:结束数据传送***************************************************/void stop()// 停止位{SDA = 0; //SDA初始化为低电平“0”_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SCL = 1; //结束数据传送时,要求SCL为高电平“1”页脚内容4_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期SDA = 1; //SDA的上升沿被认为是结束信号}/*************************************************** 函数功能:从AT24Cxx读取数据出口参数:x***************************************************/ unsigned char ReadData()// 从AT24Cxx移入数据到MCU{unsigned char i;unsigned char x; //储存从AT24Cxx中读出的数据页脚内容5for(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=0 bit WriteCurrent(unsigned char y){unsigned char i;页脚内容6bit 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_(); //等待一个机器周期页脚内容7SCL = 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{页脚内容8start(); //开始数据传递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); //写入指定地址页脚内容9WriteCurrent(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; //返回读取的数据}页脚内容10/***************************************************函数功能:从第二个AT24Cxx中的当前地址读取数据出口参数:x (储存读出的数据)***************************************************/unsigned char ReadCurrent2(){unsigned char x;start(); //开始数据传递WriteCurrent(OP_READ2); //选择要操作的第二个AT24Cxx芯片,并告知要读其数据 x=ReadData(); //将读取的数据存入xstop(); //停止数据传递return x; //返回读取的数据}/***************************************************函数功能:从第一个AT24Cxx中的指定地址读取数据入口参数:set_addr出口参数:x页脚内容11***************************************************/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)// 在指定地址读取{页脚内容12start(); //开始数据传递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口显示验证页脚内容13}4、在proteus中新建仿真文件ex54.dsn,电路原理图如下所示5、将ex54.hex文件载入at89c51中,启动仿真,观察运行结果。
IIC总线24C02读写
实验说明: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。
24C02(IIC)读写操作
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;}。
单片机对存储器AT24C02页读,写程序
/****************************************************************************** 定义控制存储器操作的程序******************************************************************************/ 这是自己写的程序,已经经过验证,细节要求的地方,参考一下AT24CXX数据手册即可#include <intrins.h>#include "AT89S52_reg.h"#include "Delay.h"sbit SDA = P3^6;sbit SCL = P3^7;/*********************************初始化存储器子程序*********************************/void InitMemory(void){SCL = 1;flash();SDA = 1;flash();}/*********************************I2C总线短延时子程序*********************************/static void flash(){_nop_();_nop_();_nop_();_nop_();_nop_(); /时序图要求开始建立时间tSU.STA大于4.7us,开始保持时间tHD.STA大于4us。
51中每个_nop_ ();延时1个CPU cycle,即1us}/*********************************启动I2C总线子程序*********************************/static void Start(void){SDA = 1;flash();SCL = 1;SDA = 0;flash();SCL = 0;flash();}/*********************************停止I2C总线子程序*********************************/static void Stop(void){SDA = 0;flash();SCL = 1;flash();SDA = 1;flash();}/******************************************** 写一字节子程序********************************************/ static void Mmr_SendByte(unsigned char byte){unsigned char i, temp;temp = byte;for (i=0; i<8; i++){temp <<= 1;SCL = 0;flash();SDA = CY;flash();SCL = 1;flash();}SCL = 0;flash();SDA = 1;flash();i = 0;flash();while ((SDA==1) && (i<255)){i++;}SCL = 0;flash();}/**************************************读一字节子程序**************************************/static unsigned char Mmr_GetByte(void){unsigned char i;unsigned char byte;SCL = 0;flash();SDA = 1;for (i=0; i<8; i++){byte <<= 1;flash();SCL = 1;flash();if (SDA == 1){byte |= 0x01;}SCL = 0;}flash();SDA = 0;SCL = 1;flash();SCL = 0;flash();SDA = 1;flash();return(byte);}/*********************************************************************从存储器指定地址中读取n个字节数据子程序(页读)*********************************************************************/void ReadMemory(unsigned char addr, unsigned char *p, unsigned char n) reentrant//addr 为数据开始地址*p为指向所需写入数据数组的指针n为个数,因不同存储器而不同这个可以参见数据手册{Start();Mmr_SendByte(0xA0); // 写入数据指令Mmr_SendByte(addr); // 写入读取数据的地址Start();Mmr_SendByte(0xA1); // 读取数据指令while(n--){*p = Mmr_GetByte();p++;}Stop();Delayms(2);}/**********************************************************************写存储器指定地址中写入n个字节数据子程序(页写)**********************************************************************/void WriteMemory(unsigned char addr, unsigned char *p, unsigned char n) reentrant{EA = 0;Start();Mmr_SendByte(0xA0);Mmr_SendByte(addr);while(n--){Mmr_SendByte(*p);p++;}Stop();EA = 1;Delayms(10);}。
最好的24C02储存开机次数实验 读写程序
24C02储存开机次数实验24C02是2K字节的串行EEPROM, 内部含有256个8位字节,该器件通过总线操作,并有专门的写保护功能。
串行EEPROM简称I2C总线式串行器件。
串行器件不仅占用很少的资源和I/O线,而且体积大大缩小,同时具有工作电源宽、抗干扰能力强、功耗低、数据不易丢失和支持在线编程等特点。
I2C总线是一种用于IC器件之间连接的二线制总线。
它通过SDA(串行数据线)及SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件:不管是单片机、存储器、LCD驱动器还是键盘接口。
我们通过一个实验来了解24C02的读写操作过程:该实验功能是单片机复位一次,自动从24C02中读取数据,然后加1,最终数码管中的数据就是开机的次数,具有一定的实用意义。
相关原理:程序运行的照片:接线方法:1、接8位数码管的数据线。
将数码管部份的数据口 JP5接到CPU部份的P0口JP51.2、接8位数码管的显示位线。
将数码管部份的显示位口 JP8接到CPU部份的P2口JP52.3、用一根2PIN数据线一端插入CPU部份JP53(P3口)的P3.6,P3.7另外一端插入24C02部份的控制端JP38。
烧写后用手按复位键可以看到数码管每按一下加一。
程序流程图:汇编语言参考程序:SDA24 EQU P3.7 SCLK24 EQU P3.6 ORG 0000HAJMP MAINORG 0080HMAIN:CLR P3.7 ;打开写保护MOV DPTR,#TABMOV A,#00H ;读地址LCALL RD24CJNE A,#10,TTTT: JNC TT1AJMP TT2TT1: MOV A,#00TT2: MOV 30H,AMOVC A,@A+DPTRCLR P2.6 ;开数码管MOV P0,A ;送显示MOV A,30HINC AMOV B,AMOV A,#00HLCALL WT24AJMP $TAB: DB 28H,7EH,0A2H,62H,74H,61H,21H,7AH,20H,60HRD24: PUSH ACC ;读24C02子程序。
I2C存储器AT24C02读写实验(一)
开发板原理图仿真连线
实训报告
实训名称、地点、时间 实训内容: AT24C02读写实训 请画出AT24C02与单片机的引脚连线图 源程序 写个人体会以及实训过程中碰到的问题
参考程序
请参考书上P187例8.3.1。 注意:例题的寻址地址如右图, 跟开发板的连接有所不同。 因此需要注意。
at24c02读写实训?请画出at24c02与单片机的引脚连线图?源程序?写个人体会以及实训过程中碰到的问题参考程序?请参考书上p187例831
I2C存储器AT24C02读写实训
实训内容
第一步:通示; 第二步:在第一步成功的基础上,在实验板 上验证;
I2C总线上接两个AT24C02读写实例
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中,启动仿真,观察运行结果。
单片机模拟I2C总线及24C02(I2C EEPROM)读写实例
/*发送1,在SCL为高电平时使SDA信号为高*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
bit Check_Acknowledge(void)
/* Language: C51单片机编程语言 */
/* Platform: Win98,Intel Celeron 433 Processor,伟福仿真器,仿真8751 */
/* Author: StephenZhu javasdk@ */
for(i=0;i<7;i++)
{
WriteI2CByte(buffer[i]);
if(!Check_Acknowledge())
{
I2C_Stop();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
WriteI2CByte(thedata);/*thedata*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
for(i=0;i<n;i++)
如何对AT24C02编写驱动程序——IIC总线协议
如何对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总线、发送开始信号和设备地址、发送数据、发送停止信号、延时和轮询、错误处理等步骤。
24c02读写程序
E2PROM芯片24C02的读写程序一、实验目的:给24C02的内部RAM写入一组数据,数据从24C02内部RAM的01h开始存放。
然后再把这组数据读出来,检验写入与读出就是否正确。
在这里我们给24C02中写入0、1、2的段码,然后把它读出来,送到数码管显示。
二、理论知识准备:上面两个实验主要学习的就是利用单片机的串口进行通讯,本实验要介绍的就是基于I2C 总线的串行通讯方法,下面我们先介绍一下I2C总线的相关理论知识。
(一)、I2C总线概念I2C总线就是一种双向二线制总线,它的结构简单,可靠性与抗干扰性能好。
目前很多公司都推出了基于I2C总线的外围器件,例如我们学习板上的24C02芯片,就就是一个带有I2C总线接口的E2PROM存储器,具有掉电记忆的功能,方便进行数据的长期保存。
(二)、I2C总线结构I2C总线结构很简单,只有两条线,包括一条数据线(SDA)与一条串行时钟线(SCL)。
具有I2C 接口的器件可以通过这两根线接到总线上,进行相互之间的信息传递。
连接到总线的器件具有不同的地址,CPU根据不同的地址进行识别,从而实现对硬件系统简单灵活的控制。
一个典型的I2C总线应用系统的组成结构如下图所示(假设图中的微控制器、LCD驱动、E2PROM、ADC各器件都就是具有I2C总线接口的器件):我们知道单片机串行通讯的发送与接收一般都各用一条线TXD与RXD,而I2C总线的数据线既可以发送也可以接受,工作方式可以通过软件设置。
所以,I2C总线结构的硬件结构非常简洁。
当某器件向总线上发送信息时,它就就是发送器,而当其从总线上接收信息时,又成为接收器。
(三)、I2C总线上的数据传送下面我们瞧瞧I2C总线就是如何进行数据传送的。
我们知道,在一根数据线上传送数据时必须一位一位的进行,所以我们首先研究位传送。
1、位传输I2C总线每传送一位数据必须有一个时钟脉冲。
被传送的数据在时钟SCL的高电平期间保持稳定,只有在SCL低电平期间才能够改变,示意图如下图所示,在标准模式下,高低电平宽度必须不小于4、7us。
实验15 I2C 总线串行扩展——AT24C02存储器读写[共2页]
312 式。
液晶显示屏模块1602内置控制器44780,可显示2行,每行16个字符,要求单片机控制1602液晶显示模块分两行显示“Hello Welcome To Heilongjiang”,第一行显示“Hello Welcome”,第二行显示“To HeiLongJiang”。
2.实验目的(1)了解单片机控制字符型的工作原理和方法。
(2)掌握单片机如何来控制液晶显示屏模块1602。
(3)接口电路设计完毕后,编写程序控制字符型液晶显示屏模块1602的字符显示。
实验13 DAC0832的D/A转换实验 1.实验要求单片机输出的数字量D0~D7加到DAC0832的输入端,用虚拟直流电压表测量DAC0832的输出电流经运放LM358N的I/V转换后的电压值,并使用虚拟直流电压表查看输出电压的变化。
仿真运行,可看到虚拟直流电压表测量的电压在-2.5~0V范围内变化。
如果由于电压表图标太小,显示的电压值不清楚,可用鼠标滚轮放大整个电路原理图。
2.实验目的掌握单片机与DAC0832的接口设计和软件编程。
实验14 ADC0809的A/D转换实验 1.实验要求利用A/D转换器ADC0809 (Proteus元件库中没有ADC0809,可用库中与其兼容的ADC0808替代),由输入模拟电压通过调整电位器阻值的大小提供给ADC0809模拟量输入,编写程序控制ADC0809将模拟量转换成二进制数字量,并送P1口输出来控制发光二极管亮或灭来表示转换结果的二进制代码显示转换完毕的数字量。
2.实验目的(1)掌握ADC0809的工作原理及基本性能。
(2)掌握单片机与ADC0809的接口设计。
(3)掌握软件编程控制单片机进行数据采集。
实验15 I2C总线串行扩展——AT24C02存储器读写1. 实验要求利用AT24C02、Proteus的I2C调试器,实现单片机读写存储器AT24C02的实验。
KEY1充当外部中断0中断源,当按下KEY1时,单片机通过I2C总线发送数据AAH给AT24C02,等发送数据完毕后,将数据AAH送P2口通过LED显示出来。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
write_byte(date);//在芯片第address位置写date.
respons();//写完后调用应答函数
stop();//I2C结束时钟函数
}
uchar read_add(uchar address)
{
uchar date;
{ start();//I2C开始时钟函数
write_byte(0xa0);//at24c02的固定地址A,1010,AO-A3都接地都为0。
respons();//写完后调用应答函数
write_byte(address);//确定从at24c02的第address位置写数据。
aa=k;
ee=aa*2200;
if(D4==0)
{
delay (100);
if(D4==1)
{
aa++;
delay (1);
init();//写直址,最后低位应为0。
write_add(2,aa);//23为at24c02内部储存地址,0xaa为写到23地址的数据。
#include <reg52.h>
#define uint unsigned int //定义unsigned int 为uint
#define uchar unsigned char //定义unsigned char 为uchar
#define uchar unsigned char //定义unsigned char 为uchar
delay (1);
k=read_add(2);//送到P1口显示。//从23地址读数据
aa=k;
stop();
if(aa==8)
{
aa=7;
}
}
}
if(aa>1)
{
sda=1;//总线释放。
delay2();
}
uchar read_byte()//读一字节函数。带返回值的函数
{
uchar i,j,k;
scl=0;
delay2();
sda=1;//总线释放。
delay2();
for(i=0;i<8;i++)
delay (1);
k=read_add(2);//送到P1口显示。//从23地址读数据
aa=k;
stop();
//ee=aa*2200;
if(aa==1)
{
aa=2;
}
}
}
}
if(dd==0)
{
if(D1==0)
{
delay (5000);
if(D1==0)
{
D2=0;
D3=1;
dd=1;
delay (ee);
D2=0;
D3=0;
}
{
sda=1;
delay2();//延迟6us是时序要求。
scl=1;
delay2();
sda=0;
delay2();
}
void stop()//I2C结束时钟函数
{
sda=0;
delay2();//延迟6us是时序要求。
scl=1;
start();//I2C开始时钟函数
write_byte(0xa1);//读数据
respons();//读完后调用应答函数
date=read_byte();//送到P1口显示。
stop();//I2C结束时钟函数
return date;
}
uint intnum,aa,ee,dd,cc;
start();//I2C开始时钟函数
write_byte(0xa0);//开始读。
respons();//读完后调用应答函数
write_byte(address);//确定从at24c02的第address位置读数据。
respons();//读完后调用应答函数
{
scl=1;
delay2();
j=sda;
k=(k<<1)|j;//k左移一位最低位变成了0,再与J相或,J就送到K最低位。
scl=0;//置低以便下次读数据。
delay2();
}
return k;
}
void write_add(uchar address,uchar date)
sbit D1=P3^4;//位定义
sbit D2=P3^5;//位定义
sbit D3=P3^7;//位定义
sbit D4=P1^6;//位定义
sbit D5=P1^7;//位定义
void delay (uint z);
void main ()
{
P1=0xff;
dd=0;
D2=0;
D3=0;
}
}
}
}
}
void delay(uint z)//代参数无返回值
{ uint x,y;
for (x=300;x>0;x--)
for (y=z;y>0;y--);//100*2000次
}
delay2();
sda=1;
delay2();
}
void respons()//应答函数
{
uchar i;/Βιβλιοθήκη 定义变量I scl=1;
delay2();
while((sda==1)&&(i<250))i++;//没有收到应答信号在等
//过一段时间后还是没收到自动跳出该语句.相与。
if(D5==0)
{
delay (100);
if(D5==1)
{
aa--;
delay (1);
init();//写直址,最后低位应为0。
write_add(2,aa);//23为at24c02内部储存地址,0xaa为写到23地址的数据。
D3=0;
delay (2200);
//aa=5;
//ee=11000;
while(1)
{
uchar f,k;
f=2;
init();//写直址,最后低位应为0。
delay (1);
k=read_add(f);//送到P1口显示。//从23地址读数据
temp=temp<<1;//TEMP左移一位!
scl=0;
delay2();
sda=CY;//送走最高位,依次把八位送完。
scl=1;//保持数据稳定。
delay2();
}
scl=0;
delay2();
}
}
if(dd==1)
{
if(D1==1)
{
delay (5000);
if(D1==1)
{
D2=1;
D3=0;
dd=0;
delay (ee);
D2=0;
#define uint unsigned int //定义unsigned int 为uint
sbit sda=P3^3;//定义I2C数据线
sbit scl=P3^2;//定义I2C时钟线
void delay2()//延迟6us函数
{;;;}
void start()//I2C开始时钟函数
scl=0;
delay2();
}
void init()//初始化函数。
{
scl=1;
sda=1;
}
void write_byte(uchar date)//写一字节函数。
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{