AVR TWI读范例程序.docx
AVRTWI读写范例程序(AT24C02)本程序简单的示范了如何使用AnHgU6的NI读写AT24C02IICEEPROMUiW(即I1.C协议,谛认克参考IIC汾议的内容,否则根本就不能掌握)一主多从的应用,M1.6作主机(M16做从机和多主多从的应用不多,请自行参考相关文档)中断模式(因为IWR的速度很高,而I1.C的速度相对较低.采用查询模式会长时间独占CP1.I,令CP1.I的利用率明显下降.特别是UC速度受环境影响只能低速通讯时,时系统的实时性产生严笊的影响.杳询帙式可以参考其它文档和软件模拟IIC的文档AT24C02/04/08的操作特点出于简化程序考虑,各种数据没有对外输出.学习时建议使用JTAGICE硬件仿真零"inc1.ude<avrio.h>inc1.ude<avtsina1.h>Sinc1.ude<avrinterrupt.h>Rinc1.ude<avrde1.ay.h>时钟定为外部晶振7.3728MHz,FCPU=7372800JJinc1.udo<cmpattwi.h>定义了各种模式下的状态眄列表(TWSR已屏蔽预分频位),本文后面附上中文描述管脚定义definepinSC1.0/PCOSC1.8definepinSDA1/PC1.SDA为保险起见,见好在SCUSDA接上10K的外部上拉电皿到YCaRdefinefSC1.100OOO/TUI时仲为100KIIz预分频系数=I(TWPS=Q)#if叱CPU<fSC1.*36Sdefine1WBR_SET10;/TIBR必须大于等于10Ke1.se"defineTffBR-SET<F_CPU/fSC1.-16)/2;/计算RBR值#ondifSdefineP1.ACT(1<<TWINT>(1<<TWEN)(1<<TWIE)/TWCR只能IwoIJT,直接赋值比逻辑运算(=&=)更节省空间SdefineS1.A_24CXXOxAO2ICXX系列的厂商器件地址(高四位)defineADDR_24C020x00/AT21C02的地址线A2/1/0全部接地,S1.V*-OxAO*OxOO<<1.OxOO.S1.R-OxO*OxOO<<POx01/TIH_操作状态defineTI_B15Y0defineTI_OK1SdefineTIM1.2m_读写命令状态UdefineOPBuSY0SdefineOP_R1.N/TWI读写操作公共步骤CdfineST-FAI1.SdefineST-STARTRdefineST-S1.AWSdefineSTIADDR/TWI试操作步骤SdefineSTRESTARTRdnfineST_S1jRSdefineST-RDATA/TWI与操作步骤5defineSTWDTRdofineFAn-YAX0出错状态1 START状态检查2 /S1.AB状态检查3 /APDR状态检森4 RESTART状态检查5 /S1.AR状态检近6读取数据状态检杳,循环n字节7 写数据状态检查,循环n字节20 里试次数最大值定义全局变量unsignedchnr0RGDAT8-0xAA,0x5,0x5S,0x5At0x01,0x02,0x03,0x(M>原始数据unsignedcharCMPDATA8j;/比较数据unsignedcharB1.:FFER256;缓冲区,可以装载整个AC21C02的数据structStrJWI/TWI数据结构(vo1.ati1.eunsignedcharSTATUS;/'TW1_操作状态unsignedcharS1.A;/从设篝的器件地址unsignedi11tM)R:/从设备的数据地址unsignedchar*pM.,F:数据缓冲区指针unsignedintDATA1.EN;数据长度unsignedcharSTATE:PH读写操作步骤unsignedcharFAI1.CfJT;失败重试次数);structStJTW1.StrWI;TW1.的数据结构变瘠仿文时在watch窗口,监控这些全局变地。/AT24C02的读写照数(包括随机读,连续流,字节写,页写)/根据S1.a的最低位决定(由中断程序中判断)/ZbitO=ITW-READ读/ZbitO=OTW_WRJTE写/SIa器件地址(不能搞错)/addrEEPRoM地址(01023)/*ptr读写数据腹冲区/Ien读数据长度(厂1024),写数据长度(1or8or16)/返I可伯是否能执行当前操作unsignedcharTW1.RW(unsignedchar$1.a,unsignedintaddr,unsignedchar*>tr,unsignedint1.en)unsignedchari:if(strT,1.STAwS=II1.B1.SY)TWI忙.不能进行操作returnOP_BUSY;StrTWI.STAToS=TWBUSY:i=(addr>>8)<<1.:i=0x06:考虑了24C(M/08的EEPROM地址高位放在S1.A里面StrTWI.S1.A=s1.a+i;StrTWI.ADDR=addr;StrIW1.pB1.F=Ptr:StrTWI.DATA1.EN=Ien;StrTW1.STATE=ST-START:StrTW1.FAI1.CNT=O;TICR=(Km1STA)!TW-ACT;启动Start信号returnOP_RUN;)*TWI中断函数这个函数流程只是考虑了器件地址后有一个字节数据(命令)地址的I1.C器件(大局部IK接口器件都是这种类型,常见的例如AT2ICO"0201081.6,DS1307,DS1721等)对于有两个字节数据地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),请稍作改动根据strT,I.S1.A的最低位决定/bit=1.TW_READ读/ZbitO=OTW_WR1TE写虽然中阍效劳程序很长.但每次只执行一个case.所以耗时并不长./S1.GNA1.(SIG_2WIRE_SER1.A1.)I1.C中断unsignedcharaction,state,status;action=str1*1.S1.AtTW_RKAD;取操作模式State=StrTWI.STATE;SIa1.US=TwSR&0xF8;屏蔽预分频位if(status>=0x60)I(status0x00)(总线错误或从机模式引发的中断,不予处理return;switch(state)(caseST_START:/START状态检i5if(Siaius=TI-START)/发送Stf1.rt信号成功IWDR=StrTWI.S1.OxFE;/发送器件地址写S1.AWTwCR=111.AC;触发下一步动作,同晡清SIart发送标忐e1.se(发送Start信号出错state=ST_FAI1.:break:caseST_S1.AW:/S1.AW状态检克if(statusTB_MT_S1.A_ACK)(发送器件地址成功TWDR=StrTW1.ARDR:发送eeprom地址IWCR=TIACT:触发下一步动作e1.se(发送器件地址出错Statc=ST-FAI1.:break:caseSTJMDDR:/AM)R状态检杳if(status=!T_MT_DATA_ACK)/发送eeprom地址成功if(actiOn=TIi1.READ)(读操作模式TWCR=(KOWSTR)TW_ACT:"发送restart信号,下一步将跳到RESTART分支)e1.se(写操作模式TWDR=*str7W1.BUF+:写第一个字节StrTW1.DATA1.EN-:state=ST_UI)ATA-1.;下一步格跳到IDATA分支TWCR=D1.ACT:触发下一步动作e1.se(发送eeprom地址出错Siate=S1.FAI1.:)break;caseSTRESTART:RESTART状态检食,只有读操作模式才能跳到这里if(sia1.US=U-REP-STARn/发送restart信号成功IWDR=StrTW1.S1.A:发器件地址说S1.ARMR=TrACF;触发下一步动作,同时酒Start发送标志)e1.se(/重发Start信号出错State=ST-FAI1.:break:CaSeST_S1.AR:S1.AR状态检查,只有读操作模式才能跳到这里if(status=11_MR_S1.A_ACK)(发送器件地址成功if(strTII.RATA1.EN-)(多个数据TwCR=TWEA)!TW_ACT:设定RCK,触发下一步动作e1.se(只有一个数据三RTW,CT:设定MK.触发下一步动作e1.se(发送器件地址出爆State=ST-FAI!.:break:caseS1.RDATA:读取数据状态检查,只有该操作模式才能跳到这里state-:循环,直到读完指定长度数据ifStatus=TINR_DATA_ACK)读取数据成功,但不是最后一个数据*strTWI.PB1.iFi=TWDR;if(StrTI1.DATA1.EN-)(还有多个数据TUR=(1<<7WE)ITW_ACT:设定RCK,触发下一步动作)e1.se(/旅备读最后一个数据TWCR=7W_ACT;设定NAK.触发下一步动作1e1.seif(Status=TWJIR-DATA-NACK)已经读完Ja后一个数据"StrTW1.pBUF-TWDR;IWCK=(K<TiSTO)B,AC:发送停止信号,不会再产生中断了sir1111,Statcs=P1.OK;e1.se(读取数据出错State=ST-FAI1.:break:caseSTWDATA:写数据状态检查,只有写操作模式才能跳到这里State-;循环,宜到写完指定长度数据if(sia1.us="1.DATA_ACK)/写数据成功if(strTBI.DATAI.EN)(还要写TWI)R=*stHW1.pBUF+;StrTW1.DATA1.EN-:TwCaTW_ACr;触发下一步动作1e1.se(写装了TR=(1<<T*'STO)TWACT:发送停止信号,不会再产生中断了StrIW1.STATUS=IT1.OK;启动写命令后需要IoBS(最大)的编程时间才能真正的把数据记录下来编程期间案件不响应任何命令)e1.se(写数据失败stutc=ST_FAI1.:1break;defau1.t:播误状态state-ST_FAI1.;break:if(state=ST_FAI1.)(情误处理StrTtt1.FAI1.CNT+;if(strT»I.FAI1.CNT<FI1.J!AX)(重试次数未超出鼓大值,TWCR-(1<<7WSTA)TiJCT:发生错误,启动