⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 twi.lst

📁 一个基于MEGA16的GUI
💻 LST
📖 第 1 页 / 共 2 页
字号:
   1               		.file	"twi.c"
   2               		.arch atmega16
   3               	__SREG__ = 0x3f
   4               	__SP_H__ = 0x3e
   5               	__SP_L__ = 0x3d
   6               	__tmp_reg__ = 0
   7               	__zero_reg__ = 1
   8               		.global __do_copy_data
   9               		.global __do_clear_bss
  11               		.text
  12               	.Ltext0:
 130               	.global	TWI_RW
 132               	TWI_RW:
   1:twi.c         **** /***********************************************
   2:twi.c         **** ****      AVR TWI读写读写范例                 ***
   3:twi.c         **** ****  	                                     ***
   4:twi.c         **** **** 作者:  HJJourAVR                        ***
   5:twi.c         **** **** 编译器:WINAVR20050214                   ***
   6:twi.c         **** ****                                         ***
   7:twi.c         **** ****  	www.OurAVR.com	 2005.10.18          ***
   8:twi.c         **** ***********************************************/
   9:twi.c         **** /*
  10:twi.c         **** 本程序简单的示范了如何使用ATMEGA16的TWI 读写AT24C02 IIC EEPROM
  11:twi.c         ****     TWI协议
  12:twi.c         ****      	(即IIC协议,请认真参考IIC协议的内容,否则根本就不能掌握)
  13:twi.c         ****     一主多从的应用,M16作主机
  14:twi.c         ****      	(M16做从机和多主多从的应用不多,请自行参考相关文档)
  15:twi.c         **** 	中断模式
  16:twi.c         ****     	(因为AVR的速度很高,而IIC的速度相对较低,
  17:twi.c         ****      	采用查询模式会长时间独占CPU,令CPU的利用率明显下降。
  18:twi.c         ****      	特别是IIC速度受环境影响只能低速通讯时,对系统的实时性产生严重的影响。
  19:twi.c         ****      	查询模式可以参考其它文档和软件模拟IIC的文档)
  20:twi.c         ****      AT24C02/04/08的操作特点
  21:twi.c         ****  
  22:twi.c         **** 出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器
  23:twi.c         **** */
  24:twi.c         **** 
  25:twi.c         **** #include    "config.h"
  26:twi.c         **** 
  27:twi.c         **** 
  28:twi.c         **** //定义全局变量
  29:twi.c         **** uint8 BUFFER[10];						//缓冲区,可以装载整个AC24C02的数据
  30:twi.c         **** 
  31:twi.c         **** struct str_TWI									//TWI数据结构
  32:twi.c         **** {
  33:twi.c         ****     volatile uint8	STATUS;				//TWI_操作状态
  34:twi.c         ****     uint8	SLA;						//从设备的器件地址
  35:twi.c         ****     uint16	ADDR;						//从设备的数据地址
  36:twi.c         ****     uint8	*pBUF;						//数据缓冲区指针
  37:twi.c         ****     uint16	DATALEN;					//数据长度
  38:twi.c         ****     uint8	STATE;						//TWI读写操作步骤
  39:twi.c         ****     uint8	FAILCNT;					//失败重试次数
  40:twi.c         **** };
  41:twi.c         **** 
  42:twi.c         **** struct str_TWI strTWI;							//TWI的数据结构变量
  43:twi.c         **** 
  44:twi.c         **** //仿真时在watch窗口,监控这些全局变量。
  45:twi.c         **** 
  46:twi.c         **** 
  47:twi.c         **** //AT24C02的读写函数(包括随机读,连续读,字节写,页写)
  48:twi.c         **** //根据sla的最低位决定(由中断程序中判断)
  49:twi.c         **** //bit0=1 TW_READ  读
  50:twi.c         **** //bit0=0 TW_WRITE 写
  51:twi.c         **** //  sla			器件地址(不能搞错)
  52:twi.c         **** //	addr		EEPROM地址(0~1023)
  53:twi.c         **** //	*ptr		读写数据缓冲区
  54:twi.c         **** //	len			读数据长度(1~1024),写数据长度(1 or 8 or 16)
  55:twi.c         **** //  返回值		是否能执行当前操作
  56:twi.c         **** uint8 TWI_RW(uint8 sla,uint16 addr,uint8 *ptr,uint16 len)
  57:twi.c         **** {
 134               	.LM1:
 135               	/* prologue: frame size=0 */
 136               	/* prologue end (size=0) */
 137 0000 982F      		mov r25,r24
  58:twi.c         **** //    uint8 i;
  59:twi.c         ****     if (strTWI.STATUS==TW_BUSY)
 139               	.LM2:
 140 0002 8091 0000 		lds r24,strTWI
 141 0006 8823      		tst r24
 142 0008 19F4      		brne .L2
  60:twi.c         ****     {//TWI忙,不能进行操作
  61:twi.c         ****         return OP_BUSY;
 144               	.LM3:
 145 000a 80E0      		ldi r24,lo8(0)
 146 000c 90E0      		ldi r25,hi8(0)
 147 000e 0895      		ret
 148               	.L2:
  62:twi.c         ****     }
  63:twi.c         ****     strTWI.STATUS=TW_BUSY;
 150               	.LM4:
 151 0010 1092 0000 		sts strTWI,__zero_reg__
  64:twi.c         ****  //   i=(addr>>8)<<1;
  65:twi.c         ****  //   i&=0x06;   strTWI.SLA=sla+i;									//考虑了24C04/08的EEPROM地址高位放在SLA里面
  66:twi.c         ****     strTWI.SLA=sla;
 153               	.LM5:
 154 0014 9093 0000 		sts strTWI+1,r25
  67:twi.c         ****     strTWI.ADDR=addr;
 156               	.LM6:
 157 0018 7093 0000 		sts (strTWI+2)+1,r23
 158 001c 6093 0000 		sts strTWI+2,r22
  68:twi.c         ****     strTWI.pBUF=ptr;
 160               	.LM7:
 161 0020 5093 0000 		sts (strTWI+4)+1,r21
 162 0024 4093 0000 		sts strTWI+4,r20
  69:twi.c         ****     strTWI.DATALEN=len;
 164               	.LM8:
 165 0028 3093 0000 		sts (strTWI+6)+1,r19
 166 002c 2093 0000 		sts strTWI+6,r18
  70:twi.c         ****     strTWI.STATE=ST_START;
 168               	.LM9:
 169 0030 81E0      		ldi r24,lo8(1)
 170 0032 8093 0000 		sts strTWI+8,r24
  71:twi.c         ****     strTWI.FAILCNT=0;
 172               	.LM10:
 173 0036 1092 0000 		sts strTWI+9,__zero_reg__
  72:twi.c         ****     TWCR=(1<<TWSTA)|TW_ACT;						//启动start信号
 175               	.LM11:
 176 003a 85EA      		ldi r24,lo8(-91)
 177 003c 86BF      		out 86-0x20,r24
  73:twi.c         ****     return OP_RUN;
 179               	.LM12:
 180 003e 81E0      		ldi r24,lo8(1)
 181 0040 90E0      		ldi r25,hi8(1)
  74:twi.c         **** }
 183               	.LM13:
 184 0042 0895      		ret
 185               	/* epilogue: frame size=0 */
 186               	/* epilogue: noreturn */
 187               	/* epilogue end (size=0) */
 188               	/* function TWI_RW size 34 (34) */
 190               	.Lscope0:
 192               	.global	__vector_17
 194               	__vector_17:
  75:twi.c         **** 
  76:twi.c         **** /*
  77:twi.c         **** TWI中断函数 
  78:twi.c         **** 	这个函数流程只是考虑了器件地址后有一个字节数据(命令)地址的IIC器件
  79:twi.c         **** 	(大部分IIC接口器件都是这种类型,常见的例如AT24C01/02/04/08/16,DS1307,DS1721等)
  80:twi.c         **** 	对于有两个字节数据地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),请稍作改动
  81:twi.c         ****  
  82:twi.c         **** //根据strTWI.SLA的最低位决定 
  83:twi.c         **** //bit0=1 TW_READ  读
  84:twi.c         **** //bit0=0 TW_WRITE 写
  85:twi.c         **** 
  86:twi.c         **** 	虽然中断服务程序很长,但每次只执行一个 case,所以耗时并不长。
  87:twi.c         **** */
  88:twi.c         **** SIGNAL(SIG_2WIRE_SERIAL)
  89:twi.c         **** {//IIC中断
 196               	.LM14:
 197               	/* prologue: frame size=0 */
 198 0044 1F92      		push __zero_reg__
 199 0046 0F92      		push __tmp_reg__
 200 0048 0FB6      		in __tmp_reg__,__SREG__
 201 004a 0F92      		push __tmp_reg__
 202 004c 1124      		clr __zero_reg__
 203 004e 2F93      		push r18
 204 0050 3F93      		push r19
 205 0052 4F93      		push r20
 206 0054 5F93      		push r21
 207 0056 8F93      		push r24
 208 0058 9F93      		push r25
 209 005a EF93      		push r30
 210 005c FF93      		push r31
 211               	/* prologue end (size=13) */
  90:twi.c         ****     uint8 action,state,status;
  91:twi.c         ****     action=strTWI.SLA&TW_READ;					//取操作模式
 213               	.LM15:
 214 005e 3091 0000 		lds r19,strTWI+1
 215 0062 532F      		mov r21,r19
 216 0064 5170      		andi r21,lo8(1)
  92:twi.c         ****     state=strTWI.STATE;
 218               	.LM16:
 219 0066 4091 0000 		lds r20,strTWI+8
  93:twi.c         ****     status=TWSR&0xF8;							//屏蔽预分频位
 221               	.LM17:
 222 006a 21B1      		in r18,33-0x20
 223 006c 287F      		andi r18,lo8(-8)
  94:twi.c         ****     if ((status>=0x60)||(status==0x00))
 225               	.LM18:
 226 006e 822F      		mov r24,r18
 227 0070 8150      		subi r24,lo8(-(-1))
 228 0072 8F35      		cpi r24,lo8(95)
 229 0074 08F0      		brlo .+2
 230 0076 BAC0      		rjmp .L3
  95:twi.c         ****     {//总线错误或从机模式引发的中断,不予处理
  96:twi.c         ****         return;
  97:twi.c         ****     }
  98:twi.c         ****     switch(state)
 232               	.LM19:
 233 0078 842F      		mov r24,r20
 234 007a 9927      		clr r25
 235 007c 8430      		cpi r24,4
 236 007e 9105      		cpc r25,__zero_reg__
 237 0080 09F4      		brne .+2
 238 0082 4AC0      		rjmp .L17
 239 0084 8530      		cpi r24,5
 240 0086 9105      		cpc r25,__zero_reg__
 241 0088 4CF4      		brge .L38
 242 008a 8230      		cpi r24,2
 243 008c 9105      		cpc r25,__zero_reg__
 244 008e B1F0      		breq .L9
 245 0090 8330      		cpi r24,3
 246 0092 9105      		cpc r25,__zero_reg__
 247 0094 24F5      		brge .L12
 248 0096 0197      		sbiw r24,1
 249 0098 61F0      		breq .L6
 250 009a 92C0      		rjmp .L37
 251               	.L38:
 252 009c 8630      		cpi r24,6
 253 009e 9105      		cpc r25,__zero_reg__
 254 00a0 09F4      		brne .+2
 255 00a2 43C0      		rjmp .L25
 256 00a4 8630      		cpi r24,6
 257 00a6 9105      		cpc r25,__zero_reg__
 258 00a8 E4F1      		brlt .L20
 259 00aa 0797      		sbiw r24,7
 260 00ac 09F4      		brne .+2
 261 00ae 65C0      		rjmp .L32
 262 00b0 87C0      		rjmp .L37
 263               	.L6:
  99:twi.c         ****     {
 100:twi.c         ****     case ST_START:	//START状态检查
 101:twi.c         ****         if(status==TW_START)
 265               	.LM20:
 266 00b2 2830      		cpi r18,lo8(8)
 267 00b4 09F0      		breq .+2
 268 00b6 84C0      		rjmp .L37
 102:twi.c         ****         {//发送start信号成功
 103:twi.c         ****             TWDR=strTWI.SLA&0xFE;				//发送器件地址写SLAW
 270               	.LM21:
 271 00b8 3E7F      		andi r19,lo8(-2)
 272 00ba 31C0      		rjmp .L48
 273               	.L9:
 104:twi.c         ****             TWCR=TW_ACT;         				//触发下一步动作,同时清start发送标志
 105:twi.c         ****         }
 106:twi.c         ****         else
 107:twi.c         ****         {//发送start信号出错
 108:twi.c         ****             state=ST_FAIL;
 109:twi.c         ****         }
 110:twi.c         ****         break;
 111:twi.c         ****     case ST_SLAW:	//SLAW状态检查
 112:twi.c         ****         if(status==TW_MT_SLA_ACK)
 275               	.LM22:
 276 00bc 2831      		cpi r18,lo8(24)
 277 00be 09F0      		breq .+2
 278 00c0 7FC0      		rjmp .L37
 113:twi.c         ****         {//发送器件地址成功
 114:twi.c         ****             TWDR=(strTWI.ADDR>>8);					//发送eeprom地址高位
 280               	.LM23:
 281 00c2 2091 0000 		lds r18,strTWI+2
 282 00c6 3091 0000 		lds r19,(strTWI+2)+1
 283 00ca 832F      		mov r24,r19
 284 00cc 9927      		clr r25
 285 00ce 83B9      		out 35-0x20,r24
 115:twi.c         **** 			strTWI.ADDR  <<=8;
 287               	.LM24:
 288 00d0 922F      		mov r25,r18
 289 00d2 8827      		clr r24
 290 00d4 9093 0000 		sts (strTWI+2)+1,r25
 291 00d8 8093 0000 		sts strTWI+2,r24
 292 00dc 68C0      		rjmp .L43
 293               	.L12:
 116:twi.c         ****             TWCR=TW_ACT;         				//触发下一步动作
 117:twi.c         ****         }
 118:twi.c         ****         else
 119:twi.c         ****         {//发送器件地址出错
 120:twi.c         ****             state=ST_FAIL;
 121:twi.c         ****         }
 122:twi.c         ****         break;
 123:twi.c         ****     case ST_WADDR:	//ADDR状态检查
 124:twi.c         ****         if(status==TW_MT_DATA_ACK)
 295               	.LM25:
 296 00de 2832      		cpi r18,lo8(40)
 297 00e0 09F0      		breq .+2
 298 00e2 6EC0      		rjmp .L37
 125:twi.c         ****         {//发送eeprom地址成功
 126:twi.c         ****             if (action==TW_READ)
 300               	.LM26:
 301 00e4 5130      		cpi r21,lo8(1)
 302 00e6 11F4      		brne .L14
 127:twi.c         ****             {//读操作模式
 128:twi.c         ****                 TWCR=(1<<TWSTA)|TW_ACT;			//发送restart信号,下一步将跳到RESTART分支
 304               	.LM27:
 305 00e8 85EA      		ldi r24,lo8(-91)
 306 00ea 62C0      		rjmp .L44
 307               	.L14:
 129:twi.c         ****             }
 130:twi.c         ****             else
 131:twi.c         ****             {//写操作模式
 132:twi.c         ****                 TWDR=*strTWI.pBUF++;         	//写第一个字节
 309               	.LM28:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -