?? twi.lst
字號:
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協(xié)議
12:twi.c **** (即IIC協(xié)議,請認(rèn)真參考IIC協(xié)議的內(nèi)容,否則根本就不能掌握)
13:twi.c **** 一主多從的應(yīng)用,M16作主機
14:twi.c **** (M16做從機和多主多從的應(yīng)用不多,請自行參考相關(guān)文檔)
15:twi.c **** 中斷模式
16:twi.c **** (因為AVR的速度很高,而IIC的速度相對較低,
17:twi.c **** 采用查詢模式會長時間獨占CPU,令CPU的利用率明顯下降。
18:twi.c **** 特別是IIC速度受環(huán)境影響只能低速通訊時,對系統(tǒng)的實時性產(chǎn)生嚴(yán)重的影響。
19:twi.c **** 查詢模式可以參考其它文檔和軟件模擬IIC的文檔)
20:twi.c **** AT24C02/04/08的操作特點
21:twi.c ****
22:twi.c **** 出于簡化程序考慮,各種數(shù)據(jù)沒有對外輸出,學(xué)習(xí)時建議使用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]; //緩沖區(qū),可以裝載整個AC24C02的數(shù)據(jù)
30:twi.c ****
31:twi.c **** struct str_TWI //TWI數(shù)據(jù)結(jié)構(gòu)
32:twi.c **** {
33:twi.c **** volatile uint8 STATUS; //TWI_操作狀態(tài)
34:twi.c **** uint8 SLA; //從設(shè)備的器件地址
35:twi.c **** uint16 ADDR; //從設(shè)備的數(shù)據(jù)地址
36:twi.c **** uint8 *pBUF; //數(shù)據(jù)緩沖區(qū)指針
37:twi.c **** uint16 DATALEN; //數(shù)據(jù)長度
38:twi.c **** uint8 STATE; //TWI讀寫操作步驟
39:twi.c **** uint8 FAILCNT; //失敗重試次數(shù)
40:twi.c **** };
41:twi.c ****
42:twi.c **** struct str_TWI strTWI; //TWI的數(shù)據(jù)結(jié)構(gòu)變量
43:twi.c ****
44:twi.c **** //仿真時在watch窗口,監(jiān)控這些全局變量。
45:twi.c ****
46:twi.c ****
47:twi.c **** //AT24C02的讀寫函數(shù)(包括隨機讀,連續(xù)讀,字節(jié)寫,頁寫)
48:twi.c **** //根據(jù)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 讀寫數(shù)據(jù)緩沖區(qū)
54:twi.c **** // len 讀數(shù)據(jù)長度(1~1024),寫數(shù)據(jù)長度(1 or 8 or 16)
55:twi.c **** // 返回值 是否能執(zhí)行當(dāng)前操作
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忙,不能進(jìn)行操作
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中斷函數(shù)
78:twi.c **** 這個函數(shù)流程只是考慮了器件地址后有一個字節(jié)數(shù)據(jù)(命令)地址的IIC器件
79:twi.c **** (大部分IIC接口器件都是這種類型,常見的例如AT24C01/02/04/08/16,DS1307,DS1721等)
80:twi.c **** 對于有兩個字節(jié)數(shù)據(jù)地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),請稍作改動
81:twi.c ****
82:twi.c **** //根據(jù)strTWI.SLA的最低位決定
83:twi.c **** //bit0=1 TW_READ 讀
84:twi.c **** //bit0=0 TW_WRITE 寫
85:twi.c ****
86:twi.c **** 雖然中斷服務(wù)程序很長,但每次只執(zhí)行一個 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; //屏蔽預(yù)分頻位
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 **** {//總線錯誤或從機模式引發(fā)的中斷,不予處理
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狀態(tài)檢查
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 **** {//發(fā)送start信號成功
103:twi.c **** TWDR=strTWI.SLA&0xFE; //發(fā)送器件地址寫SLAW
270 .LM21:
271 00b8 3E7F andi r19,lo8(-2)
272 00ba 31C0 rjmp .L48
273 .L9:
104:twi.c **** TWCR=TW_ACT; //觸發(fā)下一步動作,同時清start發(fā)送標(biāo)志
105:twi.c **** }
106:twi.c **** else
107:twi.c **** {//發(fā)送start信號出錯
108:twi.c **** state=ST_FAIL;
109:twi.c **** }
110:twi.c **** break;
111:twi.c **** case ST_SLAW: //SLAW狀態(tài)檢查
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 **** {//發(fā)送器件地址成功
114:twi.c **** TWDR=(strTWI.ADDR>>8); //發(fā)送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; //觸發(fā)下一步動作
117:twi.c **** }
118:twi.c **** else
119:twi.c **** {//發(fā)送器件地址出錯
120:twi.c **** state=ST_FAIL;
121:twi.c **** }
122:twi.c **** break;
123:twi.c **** case ST_WADDR: //ADDR狀態(tài)檢查
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 **** {//發(fā)送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; //發(fā)送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++; //寫第一個字節(jié)
309 .LM28:
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -