您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > AVR TWI读范例程序
AVRTWI读写范例程序(AT24C02)本程序简单的示范了如何使用ATMEGA16的TWI读写AT24C02IICEEPROM新洁家园)c#bA.h.F*@TWI协议)f9Y9`:S!O1j7z(即IIC协议,请认真参考IIC协议的内容,否则根本就不能掌握)一主多从的应用,M16作主机(M16做从机和多主多从的应用不多,请自行参考相关文档)中断模式新洁家园$e;_:B8b$T(因为AVR的速度很高,而IIC的速度相对较低,机械、电子电气、编程技术'x0z6GJ,X4M采用查询模式会长时间独占CPU,令CPU的利用率明显下降。特别是IIC速度受环境影响只能低速通讯时,对系统的实时性产生严重的影响。xjdz.5d6d.com0`;?,C4?;~!A)B;W2t查询模式可以参考其它文档和软件模拟IIC的文档)AT24C02/04/08的操作特点出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAGICE硬件仿真器#includeavr/io.hxjdz.5d6d.com!L!C'h!J1KA2{/z#includeavr/signal.h新洁家园0x&~?d,j8@!a#N6e#includeavr/interrupt.hk%L-k5?$w%X,h#includeavr/delay.h//时钟定为外部晶振7.3728MHz,F_CPU=7372800*p)J1?*V;x#t-@#includecompat/twi.hxjdz.5d6d.comA#m)O!W6Y3C//定义了各种模式下的状态码列表(TWSR已屏蔽预分频位),本文后面附上中文描述//管脚定义#definepinSCL0//PC0SCLxjdz.5d6d.com.R'h#X9J(j$h2J6h/O%_#definepinSDA1//PC1SDA//为保险起见,最好在SCL/SDA接上1~10K的外部上拉电阻到VCC。#definefSCL100000//TWI时钟为100KHzxjdz.5d6d.com6~*]8w/]+]5M9q:Y-n//预分频系数=1(TWPS=0)#ifF_CPUfSCL*36#defineTWBR_SET10;//TWBR必须大于等于10#else#defineTWBR_SET(F_CPU/fSCL-16)/2;//计算TWBR值#endif#defineTW_ACT(1TWINT)|(1TWEN)|(1TWIE)//TWCR只能IN/OUT,直接赋值比逻辑运算(|=&=)更节省空间#defineSLA_24CXX0xA0//24Cxx系列的厂商器件地址(高四位))lU$A8b3_4[t1{/E#defineADDR_24C020x00//AT24C02的地址线A2/1/0全部接地,SLAW=0xA0+0x001+0x00,SLAR=0xA0+0x001+0x015L*w3o$@*_//TWI_操作状态机械、电子电气、编程技术*y!o._;|-@3~#defineTW_BUSY0xjdz.5d6d.com5y*t-i9_9G4?;@$r.R#defineTW_OK14s#P(c(m)Z+d9a#defineTW_FAIL2!g's'h0c2K)F4s!z!e5Y;q%c//TWI_读写命令状态#defineOP_BUSY0#defineOP_RUN1:[3J9N;T(h.l//TWI读写操作公共步骤0Ns)R&n6H-G,B;b#defineST_FAIL0//出错状态'l'Z3I'Z-OgV#defineST_START1//START状态检查#defineST_SLAW2//SLAW状态检查#defineST_WADDR3//ADDR状态检查//TWI读操作步骤#defineST_RESTART4//RESTART状态检查#defineST_SLAR5//SLAR状态检查#defineST_RDATA6//读取数据状态检查,循环n字节//TWI写操作步骤#defineST_WDATA7//写数据状态检查,循环n字节6_4R:B.m!x0U7Z#defineFAIL_MAX20//重试次数最大值机械、电子电气、编程技术%Cuy0r2l$]5P1t//定义全局变量xjdz.5d6d.com5x:\*i*U*s4y$dunsignedcharORGDATA[8]=-L;E;E6B/~4A4?0L{0xAA,0xA5,0x55,0x5A,0x01,0x02,0x03,0x04};//原始数据unsignedcharCMPDATA[8];//比较数据xjdz.5d6d.com@7b)O1i.f!x4|unsignedcharBUFFER[256];//缓冲区,可以装载整个AC24C02的数据structstr_TWI//TWI数据结构新洁家园'm%I5J)}/\0N;i{volatileunsignedcharSTATUS;//TWI_操作状态unsignedcharSLA;//从设备的器件地址机械、电子电气、编程技术0D;j'a:K)a[1B4?5w;Ub*r/xunsignedintADDR;//从设备的数据地址unsignedchar*pBUF;//数据缓冲区指针机械、电子电气、编程技术P#s*C6c)yC3@unsignedintDATALEN;//数据长度unsignedcharSTATE;//TWI读写操作步骤unsignedcharFAILCNT;//失败重试次数};新洁家园&d1zc6B'B&\.K'{8K&rstructstr_TWIstrTWI;//TWI的数据结构变量//仿真时在watch窗口,监控这些全局变量。3jy$q%F'a(k//AT24C02的读写函数(包括随机读,连续读,字节写,页写)6z4C7@.y2D;d;y7M//根据sla的最低位决定(由中断程序中判断)xjdz.5d6d.com3f6A&M!W2R7p(Z7U0`//bit0=1TW_READ读//bit0=0TW_WRITE写新洁家园/?:d2B)O+p&h,R*r;X//sla器件地址(不能搞错)0e-m$u/zu1F4\//addrEEPROM地址(0~1023)8|%w7^)U+?8{//*ptr读写数据缓冲区//len读数据长度(1~1024),写数据长度(1or8or16)机械、电子电气、编程技术8g4Z/K#\)}*i9~U//返回值是否能执行当前操作unsignedcharTWI_RW(unsignedcharsla,unsignedintaddr,unsignedchar*ptr,unsignedintlen){8D/]%q*L7@)t1dunsignedchari;2`%g'A/nx1q0Yif(strTWI.STATUS==TW_BUSY){//TWI忙,不能进行操作新洁家园&?!K'm;N3\9`returnOP_BUSY;;K.Z;W4R:C)Q9K5a0b}&}#p$v,b:p1`,p&[strTWI.STATUS=TW_BUSY;机械、电子电气、编程技术.x0i&`4mW,ri=(addr8)1;i&=0x06;//考虑了24C04/08的EEPROM地址高位放在SLA里面strTWI.SLA=sla+i;strTWI.ADDR=addr;.m'm$T;d(v7B)I*@strTWI.pBUF=ptr;strTWI.DATALEN=len;strTWI.STATE=ST_START;strTWI.FAILCNT=0;机械、电子电气、编程技术8O)~4o7TP$u2L'TTWCR=(1TWSTA)|TW_ACT;//启动start信号xjdz.5d6d.com6Uo:l;?%u2A-`2OreturnOP_RUN;xjdz.5d6d.com4D*o#Q,Z(mP}%x!Y:D!yq;n/HQ&q3B9O/*;N4W%v$x%W3_TWI中断函数)T0i&`,Y+H)a8e这个函数流程只是考虑了器件地址后有一个字节数据(命令)地址的IIC器件xjdz.5d6d.com3k0m&i7?(a#p$L1A(大部分IIC接口器件都是这种类型,常见的例如AT24C01/02/04/08/16,DS1307,DS1721等)对于有两个字节数据地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),请稍作改动xjdz.5d6d.com-])_:X'Eq0s0P*^//根据strTWI.SLA的最低位决定//bit0=1TW_READ读6f%WR*Y2g#T-e*p//bit0=0TW_WRITE写虽然中断服务程序很长,但每次只执行一个case,所以耗时并不长。xjdz.5d6d.com&?:u*G;^;n8^)w;Z*/SIGNAL(SIG_2WIRE_SERIAL){//IIC中断新洁家园&Xw3U+S'w!^Yunsignedcharaction,state,status;action=strTWI.SLA&TW_READ;//取操作模式新洁家园.h:X$v5eT8g;I)Z9fstate=strTWI.STATE;status=TWSR&0xF8;//屏蔽预分频位if((status=0x60)||(status==0x00))/X2\6N4U+R2w/C{//总线错误或从机模式引发的中断,不予处理xjdz.5d6d.com1z-Z'B#R;p'j#I7jqreturn;}$c$B/d*e%j)~%S(t3I5fswitch(state)机械、电子电气、编程技术'gj7y2l,^)_1o-k.m{caseST_START://START状态检查4L/\%X9X;cif(status==TW_START)xjdz.5d6d.com%I&v6W8I2R6N-N8N{//发送start信号成功TWDR=strTWI.SLA&0xFE;//发送器件地址写SLAW新洁家园+v'n3V#C&p1H7Q2~TWCR=TW_ACT;//触发下一步动作,同时清start发送标志机械、电子电气、编程技术2y1S3`3W(A}else新洁家园'X$r/~1e)B*c{//发送start信号出错新洁家园3T.T+c-e(y:Fstate=ST_FAIL;.q*jBm&K,D,`;})a)O}break;caseST_SLAW://SLAW状态检查if(status==TW_MT_SLA_ACK)7z+b:@:w-H)?.\{//发送器件地址成功xjdz.5d6d.com,g9v:B6?9~,d,b1O&rTWDR=strTWI.ADDR;//发送eeprom地址TWCR=TW_ACT;//触发下一步动作;J#v-gR#a,M}新洁家园#f-|7Y9z*[%}:T/B7pelse{//发送器件地址出错+u%_7A3L1}3^7@state=ST_FAIL;}break;caseST_WADDR://ADDR状态检查xjdz.5d6d.com1n9O/Y#L7T;m7~if(status==TW_MT_DATA_ACK)新洁家园!c6v5mf5w.N)a+Q7K3T(U{//发送eeprom地址成功,l6u2sL2XR\3hI6n.m6Hif(action==TW_READ){//读操作模式xjdz.5d6d.com3d;HB`0E#L1l)h1~TWCR=(1TWSTA)|TW_ACT;//发送restart信号,下一步将跳到RESTART分支}else{//写操作模式TWDR=*strTWI.pBUF++;//写第一个字节strTWI.DATALEN--;state=ST_WDATA-1;//下一步将跳到WDATA分支6B2^%w3S:L3{TWCR=TW_ACT;//触发下一步动作}新洁家园)[;e:k8j1^&c/yc6V(H}else{//发送eeprom地址出错xjdz.5d6d.com&R1Vl+G+R:q,@state=ST_FAIL;2O.
本文标题:AVR TWI读范例程序
链接地址:https://www.777doc.com/doc-23810 .html