AVRTWI读写范例程序AT24C02

AVR TWI读写范例程序(AT24C02)本程序简单的示范了如何使用ATMEGA16的TWI 读写AT24C02 IIC EEPROMTWI协议(即IIC协议,请认真参考IIC协议的内容,否则根本就不能掌握)一主多从的应用,M16作主机(M16做从机和多主多从的应用不多,请自行参考相关文档)中断模式(因为AVR的速度很高,而IIC的速度相对较低,采用查询模式会长时间独占CPU,令CPU的利用率明显下降。

特别是IIC速度受环境影响只能低速通讯时,对系统的实时性产生严重的影响。

查询模式可以参考其它文档和软件模拟IIC的文档)AT24C02/04/08的操作特点出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器*/#include ;#include ;#include ;#include ;//时钟定为外部晶振7.3728MHz,F_CPU=7372800#include ;//定义了各种模式下的状态码列表(TWSR已屏蔽预分频位),本文后面附上中文描述//管脚定义#define pinSCL//PC0 SCL#define pinSDA1//PC1 SDA//为保险起见,最好在SCL/SDA接上1~10K的外部上拉电阻到VCC。

#define fSCL100000//TWI时钟为100KHz//预分频系数=1(TWPS=0)#if F_CPU ;>;8);=0x60)||(status==0x00)){//总线错误或从机模式引发的中断,不予处理return;}switch(state){case ST_START: //START状态检查if(status==TW_START){//发送start信号成功TWDR=strTWI.SLA&0xFE;//发送器件地址写SLAWTWCR=TW_ACT;//触发下一步动作,同时清start发送标志 }else{//发送start信号出错state=ST_FAIL;}break;case ST_SLAW: //SLAW状态检查if(status==TW_MT_SLA_ACK){//发送器件地址成功TWDR=strTWI.ADDR;//发送eeprom地址TWCR=TW_ACT;//触发下一步动作}else{//发送器件地址出错state=ST_FAIL;}break;case ST_WADDR: //ADDR状态检查 if(status==TW_MT_DATA_ACK) {//发送eeprom地址成功if (action==TW_READ){//读操作模式TWCR=(1<<TWSTA)|TW_ACT;//发送restart信号,下一步将跳到RESTART分支 }else{//写操作模式TWDR=*strTWI.pBUF++;//写第一个字节strTWI.DATALEN--;state=ST_WDATA-1;//下一步将跳到WDATA分支TWCR=TW_ACT;//触发下一步动作}}else{//发送eeprom地址出错state=ST_FAIL;}break;case ST_RESTART: //RESTART状态检查,只有读操作模式才能跳到这里if(status==TW_REP_START){//发送restart信号成功TWDR=strTWI.SLA;//发器件地址读SLARTWCR=TW_ACT;//触发下一步动作,同时清start发送标志}else{//重发start信号出错state=ST_FAIL;}break;case ST_SLAR: //SLAR状态检查,只有读操作模式才能跳到这里if(status==TW_MR_SLA_ACK) {//发送器件地址成功if (strTWI.DATALEN--){//多个数据TWCR=(1<<TWEA)|TW_ACT;//设定ACK,触发下一步动作 }else{//只有一个数据TWCR=TW_ACT;//设定NAK,触发下一步动作 }}else{//发送器件地址出错state=ST_FAIL;}break;case ST_RDATA: //读取数据状态检查,只有读操作模式才能跳到这里state--;//循环,直到读完指定长度数据if(status==TW_MR_DATA_ACK){//读取数据成功,但不是最后一个数据*strTWI.pBUF++=TWDR;if (strTWI.DATALEN--){//还有多个数据TWCR=(1<<TWEA)|TW_ACT; //设定ACK,触发下一步动作}else{//准备读最后一个数据TWCR=TW_ACT;//设定NAK,触发下一步动作}}else if(status==TW_MR_DATA_NACK) {//已经读完最后一个数据*strTWI.pBUF++=TWDR;TWCR=(1<<TWSTO)|TW_ACT;//发送停止信号,不会再产生中断了 strTWI.STATUS=TW_OK;}else{//读取数据出错state=ST_FAIL;}break;case ST_WDATA: //写数据状态检查,只有写操作模式才能跳到这里state--;//循环,直到写完指定长度数据if(status==TW_MT_DATA_ACK){//写数据成功if (strTWI.DATALEN){//还要写TWDR=*strTWI.pBUF++;strTWI.DATALEN--;TWCR=TW_ACT;//触发下一步动作}else{//写够了TWCR=(1<<TWSTO)|TW_ACT;//发送停止信号,不会再产生中断了strTWI.STATUS=TW_OK;//启动写命令后需要10ms(最大)的编程时间才能真正的把数据记录下来//编程期间器件不响应任何命令}}else{//写数据失败state=ST_FAIL;}break;default://错误状态state=ST_FAIL;break;}if (state==ST_FAIL){//错误处理strTWI.FAILCNT++;if (strTWI.FAILCNT<FAIL_MAX){//重试次数未超出最大值,TWCR=(1<<TWSTA)|TW_ACT;//发生错误,启动start信号}else{//否则停止TWCR=(1<<TWSTO)|TW_ACT;//发送停止信号,不会再产生中断了 strTWI.STATUS=TW_FAIL;}}state++;strTWI.STATE=state;//保存状态int main(void){unsigned char i;//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻PORTA=0xFF;//不用的管脚使能内部上拉电阻。

PORTB=0xFF;PORTC=0xFF;//SCL,SDA使能了内部的10K上拉电阻PORTD=0xFF;//TWI初始化TWSR=0x00;//预分频=0^4=1TWBR=TWBR_SET;TWAR=0x00;//主机模式,该地址无效TWCR=0x00;//关闭TWI模块sei();//使能全局中断strTWI.STATUS=TW_OK;TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_WRITE,0x10,&O RGDATA[0],8);//从0x10地址开始写入8个字节数据while(strTWI.STATUS==TW_BUSY);//等待操作完成if (strTWI.STATUS==TW_FAIL){//操作失败?}_delay_ms(10);//延时等待编程完成while(1){i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x10,& CMPDATA[0],8);//从0x10地址开始读出8个字节数据while(strTWI.STATUS==TW_BUSY);//等待操作完成//如果不加等待,则需要检测返回值i才能知道当前操作是否执行了// 0 OP_BUSY 之前的操作没完成,没执行当前操作// 1 OP_RUN 当前操作执行中if (strTWI.STATUS==TW_FAIL){//操作失败?}//读取成功,对比ORGDATA和CMPDATA的数据i=TWI_RW(SLA_24CXX+(ADDR_24C02<<1)+TW_READ,0x00,& BUFFER[0],256);//从0x00地址开始读出256个字节数据(整个ATC24C02)while(strTWI.STATUS==TW_BUSY);//等待操作完成};}/*两线串行接口总线定义两线接口TWI很适合于典型的处理器应用。

TWI协议允许系统设计者只用两根双向传输线就可以将128个不同的设备互连到一起。

这两根线一是时钟SCL,一是数据SDA。

外部硬件只需要两个上拉电阻,每根线上一个。

所有连接到总线上的设备都(必须)有自己的地址。

注意:就是说不能有两个相同地址的设备TWI协议解决了总线仲裁的问题。

所有 TWI 兼容的器件的总线驱动都是漏极开路或集电极开路的。

这样就实现了对接口操作非常关键的线与功能。

TWI器件输出为&quot;0&rdquo;时,TWI总线会产生低电平。

当所有的TWI器件输出为三态时,总线会输出高电平,允许上拉电阻将电压拉高。

注意:为保证所有的总线操作,凡是与TWI 总线连接的AVR 器件必须上电。

与总线连接的器件数目受如下条件限制:总线电容要低于400pF,而且可以用7 位从机地址进行寻址。

两个不同的规范,一种是总线速度低于100 kHz,而另外一种是总线速度高达400 kHz。

SCL和SDA引脚SCL与SDA为MCU的 TWI接口引脚。

引脚的输出驱动器包含一个波形斜率限制器以满足TWI规范。

引脚的输入部分包括尖峰抑制单元以去除小于50ns 的毛刺。

当相应的端口设置为SCL与SDA引脚时,可以使能I/O口内部的10K上拉电阻,这样可省掉外部的上拉电阻注意:如果要作高速通讯或者从机数量较多,最好还是外接合适的上拉电阻比特率发生器单元TWI工作于主机模式时,比特率发生器控制时钟信号SCL 的周期。

具体由TWI状态寄存器TWSR的预分频系数以及比特率寄存器TWBR设定。

当TWI工作在从机模式时,不需要对比特率或预分频进行设定,但从机的CPU时钟频率必须大于TWI时钟线SCL 频率的16倍。

注意,从机可能会延长SCL 低电平的时间,从而降低TWI 总线的平均时钟周期。

合集下载

24c02读写程序大全

24c02读写程序大全

24c02读写程序大全2C总线的应用(24C02子程序)// 对24C02的读、写// extern void DelayMs(unsigned int);// extern void Read24c02(unsigned char *RamAddress,unsigned char Ro mAddress,unsigned char bytes);// extern void Write24c02(unsigned char *RamAddress,unsigned char Ro mAddress,unsigned char bytes);/***************************************************************************/#define WriteDeviceAddress 0xa0#define ReadDviceAddress 0xa1#include <reg52.h>#include <stdio.h>#include <absacc.h>/***************************************************************************/sbit SCL=P2^7;sbit SDA=P2^6;bit DOG;/***************************************************************************/void DelayMs(unsigned int number) {unsigned char temp;for(;number!=0;number--,DOG=!DOG) {for(temp=112;temp!=0;temp--) {}}}/***************************************************************************/void Start() {SDA=1;SCL=1;SDA=0;SCL=0;}/***************************************************************************/void Stop() {SCL=0;SDA=0;SDA=1;}/***************************************************************************/void Ack() {SDA=0;SCL=1;SCL=0;SDA=1;}/***************************************************************************/void NoAck() {SDA=1;SCL=1;SCL=0;}/***************************************************************************/bit TestAck() {bit ErrorBit;SDA=1;SCL=1;ErrorBit=SDA;SCL=0;return(ErrorBit);}/***************************************************************************/void Write8Bit(unsigned char input) {unsigned char temp;for(temp=8;temp!=0;temp--) {SDA=(bit)(input&0x80);SCL=1;SCL=0;input=input<<1;}}/***************************************************************************/void Write24c02(unsigned char *Wdata,unsigned char RomAddress,unsign ed char number) {Write8Bit(WriteDeviceAddress);TestAck();Write8Bit(RomAddress);TestAck();for(;number!=0;number--) {Write8Bit(*Wdata);TestAck();Wdata++;}Stop();DelayMs(10);}/***************************************************************************/ unsigned char Read8Bit() {unsigned char temp,rbyte=0;for(temp=8;temp!=0;temp--) {SCL=1;rbyte=rbyte<<1;rbyte=rbyte|((unsigned char)(SDA));SCL=0;}return(rbyte);}/***************************************************************************/void Read24c02(unsigned char *RamAddress,unsigned char RomAddress, unsigned char bytes) {//unsigned char temp,rbyte;Start();Write8Bit(WriteDeviceAddress);TestAck();Write8Bit(RomAddress);TestAck();Start();Write8Bit(ReadDviceAddress);TestAck();while(bytes!=1) {*RamAddress=Read8Bit();RamAddress++;bytes--;}*RamAddress=Read8Bit();NoAck();Stop();}[单片机应用]24c02的读写程序电子工匠发表于2007-1-4 22:33:07;---------------从24C02整组读数据RD_INI: LCALL DELAYRD_AREA: LCALL DELAYLCALL STARTLCALL DELAYLCALL WRITE ;24C02信息的读入LCALL DELAYLCALL ACKLCALL DELAYJC RD_AREAMOV R2, #8CLR P1.7 ;起始地址为00 ADDR_0: LCALL DELAYLCALL DELAYSETB P1.6LCALL DELAYLCALL DELAYCLR P1.6LCALL DELAYDJNZ R2, ADDR_0LCALL ACKLCALL DELAYJC RD_AREALCALL DELAYLCALL STARTMOV R0, #SAVE0MOV R3, #8 ;6个字节LCALL DELAYLCALL READLCALL DELAYLCALL ACKJC RD_AREARD_R_0: LCALL DELAYLCALL DELAYLCALL RD_INFOLCALL DELAYINC R0DJNZ R3, RD_R_1lcall ack_2lcall delayLCALL STOPRETrd_r_1: lcall ack_1sjmp rd_r_0;---------------向24C02整组写数据WR_INI: LCALL DELAYLCALL STARTLCALL DELAYLCALL WRITELCALL DELAYLCALL ACKLCALL DELAYJC WR_INICLR P1.7MOV R2, #8WR_W_0: LCALL DELAY ;写地址SETB P1.6LCALL DELAYLCALL DELAYCLR P1.6LCALL DELAYDJNZ R2, WR_W_0LCALL DELAYLCALL ACKLCALL DELAYJC WR_INIMOV R0, #SAVE0MOV R3, #8 ;6个字节WR_W_1: LCALL WR_INFOLCALL DELAYLCALL ACKLCALL DELAYJC WR_INIINC R0DJNZ R3, WR_W_1LCALL DELAYLCALL STOPRET;---------------24C02启动START: SETB P1.7SETB P1.6LCALL DELAYCLR P1.7LCALL DELAYCLR P1.6RET;---------------24C02读命令字;片选为"00";---------------------------- READ: MOV A, #10100001B MOV R2, #8RD1: RLC AMOV P1.7, CSETB P1.6LCALL DELAYCLR P1.6LCALL DELAYDJNZ R2, RD1RET;---------------24C02写命令字;片选为"00";---------------------------- WRITE: MOV A, #10100000B MOV R2, #8WR1: RLC AMOV P1.7, CSETB P1.6LCALL DELAYCLR P1.6CLR P1.7LCALL DELAYDJNZ R2, WR1RET;---------------24C02结束命令字STOP: CLR P1.7LCALL DELAYSETB P1.6LCALL DELAYSETB P1.7LCALL DELAYCLR P1.6RET;---------------24C02的应答信息ACK: SETB P1.7SETB P1.6LCALL DELAYmov a, p1MOV C, a.7LCALL DELAYCLR P1.6RETack_1: CLR P1.7 ;应答SETB P1.6lcall delayCLR P1.6lcall delaySETB P1.7lcall delayRETack_2: SETB P1.7 ;非应答SETB P1.6lcall delayCLR P1.6CLR P1.7lcall delayRET;---------------24C02的读;R0:数据的存储地址;-------------------------------- RD_INFO: SETB P1.7LCALL DELAYMOV R2, #8MOV R7, #0MOV A, #0RD_I_0: SETB P1.6LCALL DELAYMOV A, P1MOV C, A.7LCALL DELAYCLR P1.6MOV A, R7RLC AMOV R7, ALCALL DELAYDJNZ R2, RD_I_0MOV @R0, ARET;---------------24C02的写;R0:数据的写数据地址;-----------------------------------WR_INFO: MOV A, @R0MOV R2, #8WR_O_0: RLC AMOV P1.7, CLCALL DELAYSETB P1.6LCALL DELAYLCALL DELAYCLR P1.6LCALL DELAYDJNZ R2, WR_O_0RET24Cxx I2C EEPROM字节读写驱动程序,芯片A0-A1-A2要接GND(24C65接VCC,具体看DataSheet)。

AT24C02的读写

AT24C02的读写
; R3=10100000(命令1010+器件3位地址+读/写。器件地址一个芯片,是000)
; (R4)=片内字节地址
; (R1)=欲写数据存放地址指针
; (R7)=连续写字节数n
EEPW: MOVP1,#0FFH
CLRP1.0;发开始信号
MOVA,R3;送器件地址
ACALLSUBS
MOVA,R4;送片内字节地址
RET
;读串行E2PROM子程序EEPR
;(R1)=欲读数据存放地址指针
;; R3=10100001(命令1010+器件3位地址+读/写。器件地址一个芯片,是000)
;(R4)=片内字节地址
;(R7)=连续读字节数
EEPR: MOVP1,#0FFH
CLRP1.0;发开始信号
MOVA,R3;送器件地址
MOV DPTR,#0600H;定义源数据的位置
LOOP:MOV A,#00H
MOVC A,@A+DPTR
LCALL SDATA
LCALL ACK
JC LOOP
INC DPTR
DJNZ R2,LOOP
LCALL STOP;调用停止子程序
STAR:SETB SDA
SETB SCL
NOP
NOP
NOP
NOP
应答毕sdaret程序中多处调用了delay子程序仅两条nop指令这是为了满足i2c总线上数据传送速率的要求只有当sda数据线上的数据稳定下来之后才能进行读写即scl线发出正脉冲
AT24C02的读写
作者:来源:阅读次数:372
AT24C02是美国ATMEL公司的低功耗CMOS串行EEPROM,它是内含256×8位存储空间,具有工作电压宽(2.5~5.5V)、擦写次数多(大于10000次)、写入速度快(小于10ms)等特点。

AT24C02_Read_Write_Manual

AT24C02_Read_Write_Manual

AT24C02读写测试方法I2C测试工具:武汉吉阳光电科技有限公司的I2C接口系列产品测试软件:1、串口调试助手软件支持型号:GY760X,GY75062、I2CTools V2.1支持型号:GY760X,GY7506,GY7501A,GY7512(两种测试软件任选其一即可)一、24C02信号连接:Pin 1,2,3,4,7脚接GND (该接法的SlaveAdress为0xA0)PIN 5 接SDAPIN 6接SCLPIN 8接VCC, +5V,或3.3V。

二、利用串口调试助手软件测试运行该软件后,波特率选择115200,“16进制显示”打勾,“16进制发送”打勾。

其余采用默认值,不修改。

硬件线路连接好以后,给转换器和被测设备上电。

举例1)从内部地址00开始,读256个字节键入44 A1 00 FF 点发送,若正常,则会收到256个字节,并显示出来。

2)从内部地址20开始,读2个字节键入44 A1 20 01 点发送,若正常,则会收到2个字节,并显示出来。

3)从内部地址00开始,写8个字节11 12 13 14 15 16 17 18键入44 A0 00 11 12 13 14 15 16 17 18 点发送,若正常,则会收到AA,表示通讯成功。

如果收到BB,表示I2C握手失败。

三、利用I2CTools软件。

运行I2CToolsV2.1软件,选择设备型号。

如果是GY760X, 则需选择COM端口和波特率115200点“Open”如果正常,则应将得到结果提示为打开成功和“WorkMode=0 I2C-Channel=0 ClkValue=100khz”SlaveAddr填入A0 ROM/REG ADDR 打勾,填入欲操作的内部地址举例1)从内部地址00开始,读256个字节ROM ADDR填入00WriteDataNum=0ReadRequest=256 执行Read, 如果正常则会提示OK,并返回读到的256个数据。

AT24C02串行E2PROM的工作原理与读写

AT24C02串行E2PROM的工作原理与读写

AT24C02串行E2PROM的工作原理与读写串行EEPROM中,较为典型的有ATMEL公司的AT24CXX系列和AT93CXX等系列产品。

简称I2C总线式串行器件。

串行器件不仅占用很少的资源和I/O线,而且体积大大缩小,同时具有工作电源宽、抗干扰能力强、功耗低、数据不易丢失和支持在线编程等特点。

I2C总线是一种用于IC器件之间连接的二线制总线。

它通过SDA(串行数据线)及SCL (串行时钟线)两根线在连到总线上的器件之间传送信息,并根据地址识别每个器件:不管是单片机、存储器、LCD驱动器还是键盘接口。

1.I2C总线的基本结构:采用I2C总线标准的单片机或IC器件,其内部不仅有I2C接口电路,而且将内部各单元电路按功能划分为若干相对独立的模块,通过软件寻址实现片选,减少了器件片选线的连接。

CPU不仅能通过指令将某个功能单元电路挂靠或摘离总线,还可对该单元的工作状况进行检测,从而实现对硬件系统的既简单又灵活的扩展与控制。

I2C总线接口电路结构如图1所示。

从图中可以看出:对于时钟及数据传送,串行数据I/O端SDA一般需要用外部上拉电阻将其电平拉高。

2.双向传输的接口特性:传统的单片机串行接口的发送和接收一般都分别用一条线,如MCS51系列的TXD和RXD,而I2C总线则根据器件的功能通过软件程序使其可工作于发送或接收方式。

当某个器件向总线上发送信息时,它就是发送器(也叫主器件),而当其从总线上接收信息时,又成为接收器(也叫从器件)。

主器件用于启动总线上传送数据并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。

I2C总线的控制完全由挂接在总线上的主器件送出的地址和数据决定。

总线上主和从(即发送和接收)的关系不是一成不变的,而是取决于此时数据传送的方向。

SDA和SCL均为双向I/O线,通过上拉电阻接正电源。

当总线空闲时,两根线都是高电平。

连接总线的器件的输出级必须是集电极或漏极开路,以具有线“与”功能。

[精品]24c02的连续读写

[精品]24c02的连续读写

24c02的连续读写/**********************************************24c02驱动程序SDA=P3^6;SCL=P3^7;可以写一个字节,写一串字符(以'\n'作为结束标志)可以读一个字节,读一串字符(以'\n'作为结束标志)**********************************************/#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define W24C02 0xA0 //存储器的写地址#define R24C02 0xA1 //存储器的读地址/********************/sbit SDA=P3^6; //AT24C02串行数据5脚sbit SCL=P3^7; //AT24C02串行时钟6脚void start_24c02(); //开始void stop_24c02(); //停止void response_24c02(bit); //应答void write_8bit(uchar); //写8位void write_byte(uchar,uchar); //写一字节void write_list(uchar, uchar *); //写*指向的数据(以'\n'作结束)uchar read_8bit(); //读8位uchar read_byte(uchar); //从某一地址读1字节void read_list(uchar,uchar *); //从某一地址开始连续读,存到*所指位置/********************开始,在读\写前调用********************/void start_24c02(){SDA=1;_nop_();_nop_();SCL=1;_nop_();_nop_();SDA=0;_nop_();_nop_();}/********************结束,在读\写完后调用********************/void stop_24c02(){SDA=0;_nop_();_nop_();SCL=1;_nop_();_nop_();SDA=1;_nop_();_nop_();}/********************应答当单片机写时,ack=1,为等待24c02的应答信号当单片机读时,ack=0,为向24c02发送应答信号********************/void respons_24c02(bit ack) //ak为1则单片机接收24c02的应答信号;ak为0则24c02接收单片机的应答信号{uchar i=0;SDA=ack;while(i<250&&SDA==1)i++;SCL=1;_nop_();_nop_();SCL=0;_nop_();SDA=1;}/********************向24c02写入一字节(8位)的数据********************/void write_8bit(uchar dat) {uchar i;SCL=0;for(i=0;i<8;i++){dat=dat<<1;SDA=CY;SCL=1;_nop_();_nop_();SCL=0;_nop_();_nop_();}}/********************从24c02读取一字节(8位)的数据********************/ uchar read_8bit(){uchar i,k;for(i=0;i<8;i++){SCL=1;_nop_();_nop_();k=(k<<1)|SDA;SCL=0;_nop_();_nop_();}return k;}/********************向地址addr写入数据dat********************/void write_byte(uchar addr,uchar dat){start_24c02();write_8bit(W24C02);respons_24c02(1);write_8bit(addr);respons_24c02(1);write_8bit(dat);respons_24c02(1);stop_24c02();}/********************从地址addr形如连续写入list中的数据,以'\n'为结束标志********************/void write_list(uchar addr, uchar *list) {uchar i=0;start_24c02();write_8bit(W24C02);respons_24c02(1);write_8bit(addr);respons_24c02(1);do{if(i==0||i%8!=0) //判断是否到了页的边缘{write_8bit(list[i]);respons_24c02(1);}else{stop_24c02(); //写完一页,则进入启动内部写周期do{start_24c02();write_8bit(W24C02);SDA=1;//delay(2);}while(SDA==1); //等待24c02完成写周期发出的应答信号,从而继续下一个读写操作SCL=1;_nop_();_nop_();SCL=0; //应答write_8bit(i);respons_24c02(1);write_8bit(list[i]);respons_24c02(1);}}while(list[i++]!='\n');stop_24c02();}/********************从addr中读取一字节数据返回dat********************/uchar read_byte(uchar addr){uchar dat;start_24c02();write_8bit(W24C02);respons_24c02(1);write_8bit(addr);respons_24c02(1);start_24c02();write_8bit(R24C02);respons_24c02(1);dat=read_8bit(); //读取一字节后若发送停止指令,则结束并返回datstop_24c02();return dat;}/********************从地址addr开始连续读取数据,并存入list中以'\n'为结束********************/void read_list(uchar addr,uchar *list){uchar i=0;start_24c02();write_8bit(W24C02);respons_24c02(1);write_8bit(addr);respons_24c02(1);start_24c02();write_8bit(R24C02);respons_24c02(1);do{list[i]=read_8bit(); //读取1字节后,若其不为结束标志,则发送应答信号,继续读下一个if(list[i]!='\n')respons_24c02(0);}while(list[i++]!='\n');stop_24c02();}。

24C02读写实验

24C02读写实验
1. 熟悉单片机与 24C02 的接口电路; 2. 根据程序设计分析,画出流程图,编写源程序; 3. 调试程序,可以分两步进行:
(1)分段运行程序,对 24C02 进行字节的读/写操作后,观察存储器 RAM 30H-37H 单 元的数据,比较写入与读出的数据是否一致;
(2)连续运行程序,观察数码管的显示的数据,是否是写入的数据。
实验四 E2PROM 读写实验
一、 实验内容与要求:
1.向 24C02 的 00H-07H 存储单元写入 8 个字节的数据,再读出数据存入单片机 RAM 的 30H-37H,比较是否一致。
2.将读出的数据在数码管上显示出来。
二、 实验设计
1.24C02 与单片机的接口电路如图 4.1 所示。
图 4.1 24C02 与单片机的接口电路
返回
返回
(a) 写操作流程图
(b) 读操作流程图
图4.2 24C02数据传输流程图
开始 系统初始化 确定要写入的数据 写入 24C02
N 数据写完?
Y 读 24C02
存入 RAM
显示数据
结束
图 4.3 主程序流程图
四、实验报告要求:
1.实验名称 2.实验内容 3.实验设计
画出实验电路原理图,程序流程图,源程序; 4.实验操作:程序调试过程和运行结果; 5.实验总结。
发启始信号
发启始信号
器件地址写
器件地址写
写入读单元地址
写入存储单元地址
发起始信号
写入数据
器件地址读
发停止信号
读出数据
延时 10ms 等待写
发停止信号
单片机的 P1.0 口接 24C02 的 SDA,作为串行数据的输入输出端口;P1.1 口为 24C02 提供 串行时钟信号。

ATMEGA16读写iic(TWI)(24c02) C语言程序

ATMEGA16读写iic(24c02) C语言程序测试通过#include <iom16v.h>#include "I2C.h"#include "1602.h"#include "delay.h"/*通过AVR往I IC写数据,并通过串口把数据读出显示出来*///===============================================================void UART_init(void) //UART初始化{ DDRD = 0x02;PORTD = 0x00;UCSRA = 0x02; /*无倍速*/UCSRB = 0x18; /*允许接收和发送*/UC SRC = 0x06; /*8位数据,1位停止位,无校验*/UBRRH = 0x00;UBRRL = 12; /*9600*/}//===============================================================void USART_TXD(float data) //发送采用查询方式{while( !(UCSRA & BIT(UDRE)) );UDR=data;while( !(UCSRA & BIT(TXC )) );UCSRA|=BIT(TXC);}void main(void){unsigned char i;//LCD_init();uart_init();//TART初始化SEI(); //全局中断使能while(1){/*I2C_Write('n',0x00);I2C_Write('c',0x01);I2C_Write('e',0x02);I2C_Write('p',0x03);I2C_Write('u',0x04);*/i=I2C_Read(0x00);//LCD_write_char(0,0,i); USART_TXD(i);i=I2C_Read(0x01);//LCD_write_data(i);USART_TXD(i);i=I2C_Read(0x02);//LCD_write_data(i);USART_TXD(i);i=I2C_Read(0x03);//LCD_write_data(i);USART_TXD(i);i=I2C_Read(0x04);//LCD_write_data(i);USART_TXD(i);}}/*上面上主函数部分*/#include <macros.h>#include "delay.h"//I2C 状态定义//MT 主方式传输 MR 主方式接受#define START 0x08#define RE_START 0x10#define MT_SLA_ACK 0x18#define MT_SLA_NOACK 0x20#define MT_DATA_ACK 0x28#define MT_DATA_NOACK 0x30 #define MR_SLA_ACK 0x40#define MR_SLA_NOACK 0x48#define MR_DATA_ACK 0x50#define MR_DATA_NOACK 0x58#define RD_DEVICE_ADDR 0xA1 //前4位器件固定,后三位看连线,最后1位是读写指令位#define WD_DEVICE_ADDR 0xA0//常用TWI操作(主模式写和读)#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) //启动I2C#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) //停止I2C#define Wait() {while(!(TWCR&(1<<TWINT)));} //等待中断发生#define TestAck() (TWSR&0xf8) //观察返回状态#define SetAck (TWCR|=(1<<TWEA)) //做出ACK应答#define SetNoAck (TWCR&=~(1<<TWEA)) //做出Not Ack应答#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN)) //启动I2C#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} //写数据到TWDRunsigned char I2C_Write(unsigned char Wdata,unsigned char RegAddress); unsigned char I2C_Read(unsigned RegAddress);/*********************************************I2C总线写一个字节返回0:写成功返回1:写失败**********************************************/unsigned char I2C_Write(unsigned char Wdata,unsigned char RegAddress){Start(); //I2C启动Wait();if(TestAck()!=START)return 1; //ACKWrite8Bit(WD_DEVICE_ADDR); //写I2C从器件地址和写方式Wait();if(TestAck()!=MT_SLA_ACK)return 1; //ACKWrite8Bit(RegAddress); //写器件相应寄存器地址Wait();if(TestAck()!=MT_DATA_ACK)return 1; //ACKWrite8Bit(Wdata); //写数据到器件相应寄存器Wait();if(TestAck()!=MT_DATA_ACK)return 1; //ACKStop(); //I2C停止delay_nms(10); //延时return 0;}/*********************************************I2C总线读一个字节返回0:读成功返回1:读失败**********************************************/ unsigned char I2C_Read(unsigned RegAddress){unsigned char temp;Start();//I2C启动Wait();if (TestAck()!=START)return 1; //ACKWrite8Bit(WD_DEVICE_ADDR); //写I2C从器件地址和写方式Wait();if (TestAck()!=MT_SLA_ACK)return 1; //ACKWrite8Bit(RegAddress); //写器件相应寄存器地址Wait();if (TestAck()!=MT_DATA_ACK)return 1;Start(); //I2C重新启动Wait();if (TestAck()!=RE_START)return 1;Write8Bit(RD_DEVICE_ADDR); //写I2C从器件地址和读方式Wait();if(TestAck()!=MR_SLA_ACK)return 1; //ACKTwi(); //启动主I2C读方式Wait();if(TestAck()!=MR_DATA_NOACK)return 1; //ACKtemp=TWDR;//读取I2C接收数据Stop();//I2C停止return temp;}/*以上是IIC.h头文件部分,需要对照技术文档好好研究*/*----------------------------------------------------------------------- 延时函数编译器:I CC-AVR v6.31A 日期: 2005-11-24 20:29:57目标芯片 : M16时钟: 8.0000M Hz作者:archeng504-----------------------------------------------------------------------*/ #ifndef __delay_h#define __delay_hvoid delay_nus(unsigned int n);void delay_nms(unsigned int n);void delay_1us(void);void delay_1ms(void) ;void delay_1us(void) //1us延时函数{asm("nop");}void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1us();}void delay_1ms(void) //1ms延时函数{unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}#endif/*以上是delay.h部分,再加上IIC中自带的iom16v.h 和macros.h就可以编译通过*//*注意点:本程序在实验板ATMEGA16上测试通过,在示波器把SCL,SDA信号线有数据,移值到自己电路上可以放心使用,在ATMEGA32上一样使用,本人24C02的A2,A1,A0都是接地,若地址不一样,在程序相应位置改一下就可以,串口上调试单片机的基础,所以它一定要会用*//*本程序调试软件环境是ICC6.31*/。

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。

51单片机读写AT24C02源代码详细注释

51单片机读写AT24C02源代码(详细注释)在P1口上接八个led灯,结果就显示在这八个灯上面。

AT24C02的接线方式见程序的顶部的定义。

以下是源代码:#include ;//包含头文件typedef unsigned char uchar;typedef unsigned int uint;#define write_c02 0xa0#define read_c02 0xa1sbit sda = P2^0;sbit scl = P2^1;void delay(){ //delay:5us;;}//i2c:initvoid i2c_init(){sda = 1;delay();scl = 1;delay();}//delayms:void delayms(uint xms){uchar x, y;for(x = xms; x >; 0; x--)for(y = 110; y >; 0; y--);}//start:void start() //启动i2c{sda = 1;scl = 1;delay();//延时必须大于4.7us,此约为五微秒sda = 0; //在scl为高电平时,sda一个下降沿为启动信号delay();}//stop:void stop() //停止i2c{sda = 0;scl = 1;delay();sda = 1; //在scl为高电平时,sdasda一个上升沿为停止信号delay();}//ack:void ack() //应答信号0{uchar i = 0; //等待变量scl = 1;//在scl为高电平期间等待应答delay();while((sda == 1) && i < 250)//若为应答0即退出,从机向主机发送应答信号i++;//等待一段时间scl = 0; //应答之后将scl拉低delay();}//nack:void nack() //非应答{scl = 1;//在scl为高电平期间,由主机向从机发送一个1,非应答信号delay();sda = 1;scl = 0; //应答之后将scl拉低delay();}//send byte:void send_byte(uchar date)//写一个字节{uchar i, temp;temp = date; //存入要写入的数据,即要发送到sda上的数据for(i = 0; i < 8; i++){ //发送8位temp <<= 1; //to CY 将数据的最高位移入到PSW中的CY位中scl = 0;//只有在scl为低电平时,才允许sda上的数据变化delay();sda = CY; //将CY里的数据发送到sda数据线上delay(); //可以延时scl = 1; //在scl为高电平时,不允许sda上的数据变化,使数据稳定delay();scl = 0;//允许sda数据线的数据变化,等待下一个数据的传输delay();}//wait ack:发送完一个字节数据后要主机要等待从机的应答,第九位scl = 0;//允许sda变化delay();sda = 1;//wait:ack,sda拉高等待应答,当sda=0时,表示从机的应答delay();}//read: byteuchar read_byte() //读一个字节数据{uchar i, j, k;scl = 0; //读之前先允许sda变化delay(); //等待数据for(i = 0; i < 8; i++){scl = 1; //不允许sda变化delay(); //使sda数据稳定后开始读数据j = sda; //读出sda上的数据k = (k << 1)| j; //将数据通过|运算存入k中scl = 0;//允许sda变化等待下一位数据的到来delay();}//delay();//可不用延时return k;//返回读出的数据}//write:at24c02 在at24c02中的指定地址写入数据void write_at24c02(uchar address, uchar date) {start(); //启动i2csend_byte(write_c02);//写入期间地址和写操作ack(); //从机应答0send_byte(address); //写入写数据的单元地址ack(); //ack0send_byte(date); //在指定地址中写入数据ack(); //从机应答0stop();//停止i2c}//read: at24c02在at24c02的指定地址中读出写入的数据uchar read_at24c02(address){uchar dat;//用来存储读出的数据start(); //启动i2csend_byte(write_c02); //写入at24c02器件地址和写操作ack(); //从机应答0send_byte(address); //写入要读取AT24C02的数据的单元地址ack(); //从机应答0start(); //再次启动i2csend_byte(read_c02); //写入AT24C02器件地址和读操作ack();//从机应答&lsquo;0&rsquo;dat = read_byte();//读出指定地址中的数据nack(); //主机发出非应答&lsquo;1&rsquo;stop(); //停止i2creturn dat;//返回读出的数据}//main:void main(){uchar i;i2c_init();start();while(1){for(i = 0x00; i < 0xff; i++){write_at24c02(10, i);delayms(10);//需等待十毫秒P1 = read_at24c02(10);//1010 1010 delayms(2000);}}}。

24c02读写--相关资料

24c02读写—相关资料AT24C02是美国Atmel公司的低功耗CMOS型E2PROM,内含256×8位存储空间,具有工作电压宽(2.5~5.5 V)、擦写次数多(大于10 000次)、写入速度快(小于10 ms)、抗干扰能力强、数据不易丢失、体积小等特点。

而且他是采用了I2C总线式进行数据读写的串行器件,占用很少的资源和I/O线,并且支持在线编程,进行数据实时的存取十分方便。

1 AT24C02的引脚功能AT24C02引脚如图1所示。

他的的1、2、3脚是3根地址线,用于确定芯片的硬件地址。

第8脚和第4脚分别为正、负电源。

第5脚SDA为串行数据输入/输出,数据通过这根双向I2C总线串行传送。

第6脚SCL为串行时钟,SDA和SCL为漏极开路端,在实际的应用当中都需要和正电源间各接一个5.1 kΩ的电阻上拉。

第7脚为WP写保护端,接地时允许芯片执行一般的读写操作;接正电源时只允许对器件进行读操作。

2 AT24C02的内部结构图2为AT24C02的内部结构图。

启动、停止逻辑单元 接收数据引脚SDA上的电平信号,判断是否进行启动和停止操作串行控制逻辑单元 根据SCL,SDA电平信号以及“启动、停止逻辑”部件发出的各种信号进行区分,并排列出有关的“寻址”、“读数据”和“写数据”等逻辑,将他们传送到相应的操作单元。

例如:当操作命令为“寻址”时候,他将通知地址计数器加1,并启动“地址比较”器进行工作。

在“读数据”时,他控制“Dout/确认逻辑”单元;在“写数据”时候,他控制“高压泵/定时”电路,以便向E2PROM电路提供编程所需要的高电压。

地址/计数器单元 产生访问E2PROM所需要的存储单元的地址,并将其分别送到X译码器进行字选,送到Y译码器进行位选。

高压泵/定时单元 由于E2PROM数据写入时候需要向电路施加编程高电压,为了解决单一电源电压的供电问题,芯片生产厂家采用了电压的片内提升电路。

电压的提升范围一般可以达12~21.5 V。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档