📄 twi.s
字号:
.module twi.c
.area data(ram, con, rel)
_ORGDATA::
.blkb 2
.area idata
.byte 170,165
.area data(ram, con, rel)
.blkb 2
.area idata
.byte 'U,'Z
.area data(ram, con, rel)
.blkb 2
.area idata
.byte 1,2
.area data(ram, con, rel)
.blkb 2
.area idata
.byte 3,4
.area data(ram, con, rel)
.dbfile D:\myavrproject\icc\twi\twi.c
.dbsym e ORGDATA _ORGDATA A[8:8]c
.area text(rom, con, rel)
.dbfile D:\myavrproject\icc\twi\twi.c
.dbfunc e twi_init _twi_init fV
.even
_twi_init::
.dbline -1
.dbline 22
; //ICC-AVR application builder : 2007-1-9 16:35:49
; // Target : M8
; // Crystal: 8.0000Mhz
;
; #include <iom8v.h>
; #include <macros.h>
;
; #include "twi.h"
;
;
; //TWI的数据结构变量
; struct str_TWI strTWI;
; //定义全局变量
; unsigned char ORGDATA[8]={0xAA,0xA5,0x55,0x5A,0x01,0x02,0x03,0x04}; //原始数据
; //unsigned char CMPDATA[8]; //比较数据
;
;
; //TWI initialize
; // bit rate:72
; //50KHZ
; void twi_init(void)
; {
.dbline 23
; TWCR= 0X00; //disable twi
clr R2
out 0x36,R2
.dbline 24
; TWBR= 0x48; //set bit rate
ldi R24,72
out 0x0,R24
.dbline 25
; TWSR= 0x00; //set prescale
out 0x1,R2
.dbline 26
; TWAR= 0x21; //set slave address
ldi R24,33
out 0x2,R24
.dbline 28
; //TWAR= 0x31; //set slave address
; TWCR= 0x45; //enable twi
ldi R24,69
out 0x36,R24
.dbline -2
L1:
.dbline 0 ; func end
ret
.dbend
.dbfunc e TWI_RW _TWI_RW fc
; i -> <dead>
; len -> y+0
; ptr -> R18,R19
; sla_rw -> R16
.even
_TWI_RW::
.dbline -1
.dbline 34
; }
;
; //
;
; unsigned char TWI_RW(unsigned char sla_rw,unsigned char *ptr,unsigned char len)
; {
.dbline 36
; unsigned char i;
; if (strTWI.STATUS==TW_BUSY)
lds R2,_strTWI
tst R2
brne L3
.dbline 37
; {
.dbline 39
; //TWI忙,不能进行操作
; return OP_BUSY;
clr R16
rjmp L2
L3:
.dbline 41
; }
; strTWI.STATUS=TW_BUSY;
clr R2
sts _strTWI,R2
.dbline 42
; strTWI.SLA=sla_rw;
sts _strTWI+1,R16
.dbline 43
; strTWI.DATALEN=len;
ldd R0,y+0
sts _strTWI+4,R0
.dbline 44
; strTWI.pBUF=ptr;
sts _strTWI+2+1,R19
sts _strTWI+2,R18
.dbline 45
; strTWI.STATE=ST_START;
ldi R24,1
sts _strTWI+5,R24
.dbline 46
; strTWI.FAILCNT=0;
sts _strTWI+6,R2
.dbline 47
; TWCR=(1<<TWSTA)|TW_ACT; //启动start信号
ldi R24,165
out 0x36,R24
.dbline 48
; return OP_RUN;
ldi R16,1
.dbline -2
L2:
.dbline 0 ; func end
ret
.dbsym l i 1 c
.dbsym l len 0 c
.dbsym r ptr 18 pc
.dbsym r sla_rw 16 c
.dbend
.area vector(rom, abs)
.org 34
rjmp _twi_isr
.area text(rom, con, rel)
.dbfile D:\myavrproject\icc\twi\twi.c
.dbfunc e twi_isr _twi_isr fV
; action -> R10
; state -> R20
; status -> R22
.even
_twi_isr::
rcall push_lset
rcall push_gset4
.dbline -1
.dbline 53
; }
;
; #pragma interrupt_handler twi_isr:18
; void twi_isr(void)
; {
.dbline 59
; //twi event
; //根据strTWI.SLA的最低位决定
; //bit0=1 TW_READ 读
; //bit0=0 TW_WRITE 写
; unsigned char action,state,status;
; action=strTWI.SLA&TW_READ; //取操作模式
lds R24,_strTWI+1
andi R24,1
mov R10,R24
.dbline 60
; state=strTWI.STATE;
lds R20,_strTWI+5
.dbline 61
; status=TWSR&0xF8; //屏蔽预分频位
in R22,0x1
andi R22,248
.dbline 62
; putchar(0xdd);
ldi R16,221
ldi R17,0
rcall _putchar
.dbline 63
; if ((status>=0x60)&&(status!=0x00))
cpi R22,96
brlo L13
tst R22
breq L13
.dbline 64
; {
.dbline 65
; switch(state)
mov R12,R20
clr R13
rjmp L14
X0:
.dbline 66
; {
.dbline 70
; //case ST_START: //START状态检查
;
; }
; }
L13:
.dbline 71
; else if((status<0x60)&&(status!=0x00))
cpi R22,96
brlo X2
rjmp L10
X2:
tst R22
brne X3
rjmp L10
X3:
.dbline 72
; {
.dbline 73
; switch(state)
mov R12,R20
clr R13
movw R24,R12
cpi R24,1
ldi R30,0
cpc R25,R30
breq L23
cpi R24,2
ldi R30,0
cpc R25,R30
breq L27
cpi R24,3
ldi R30,0
cpc R25,R30
breq L30
cpi R24,4
ldi R30,0
cpc R25,R30
brne X4
rjmp L37
X4:
cpi R24,5
ldi R30,0
cpc R25,R30
brne X5
rjmp L41
X5:
cpi R24,6
ldi R30,0
cpc R25,R30
brne X6
rjmp L47
X6:
cpi R24,7
ldi R30,0
cpc R25,R30
brne X7
rjmp L57
X7:
rjmp L20
X1:
.dbline 74
; {
L23:
.dbline 76
; case ST_START: //START状态检查
; if(status==TW_START)
cpi R22,8
brne L24
.dbline 77
; {//发送start信号成功
.dbline 78
; TWDR=strTWI.SLA&0xFE; //发送器件地址写SLAW
lds R24,_strTWI+1
andi R24,254
out 0x3,R24
.dbline 79
; TWCR=TW_ACT; //触发下一步动作,同时清start发送标志
ldi R24,133
out 0x36,R24
.dbline 80
; }
rjmp L21
L24:
.dbline 82
; else
; {//发送start信号出错
.dbline 83
; state=ST_FAIL;
clr R20
.dbline 84
; }
.dbline 85
; break;
rjmp L21
L27:
.dbline 87
; case ST_SLAW: //SLAW状态检查
; if(status==TW_MT_SLA_ACK)
cpi R22,24
brne L28
.dbline 88
; {//发送器件地址成功
.dbline 89
; TWDR=0xab;
ldi R24,171
out 0x3,R24
.dbline 90
; TWCR=TW_ACT; //触发下一步动作
ldi R24,133
out 0x36,R24
.dbline 91
; }
rjmp L21
L28:
.dbline 93
; else
; {//发送器件地址出错
.dbline 94
; state=ST_FAIL;
clr R20
.dbline 95
; }
.dbline 96
; break;
rjmp L21
L30:
.dbline 98
; case ST_WADDR: //ADDR状态检查
; if(status==TW_MT_DATA_ACK)
cpi R22,40
brne L31
.dbline 99
; {//发送eeprom地址成功
.dbline 100
; if (action==TW_READ)
mov R24,R10
cpi R24,1
brne L33
.dbline 101
; {//读操作模式
.dbline 102
; TWCR=(1<<TWSTA)|TW_ACT; //发送restart信号,下一步将跳到RESTART分支
ldi R24,165
out 0x36,R24
.dbline 103
; }
rjmp L21
L33:
.dbline 105
; else
; {//写操作模式
.dbline 106
; TWDR=*strTWI.pBUF++; //写第一个字节
lds R30,_strTWI+2
lds R31,_strTWI+2+1
ld R2,Z+
sts _strTWI+2+1,R31
sts _strTWI+2,R30
out 0x3,R2
.dbline 107
; strTWI.DATALEN--;
lds R24,_strTWI+4
subi R24,1
sts _strTWI+4,R24
.dbline 108
; state=ST_WDATA-1; //下一步将跳到WDATA分支
ldi R20,6
.dbline 109
; TWCR=TW_ACT; //触发下一步动作
ldi R24,133
out 0x36,R24
.dbline 110
; }
.dbline 111
; }
rjmp L21
L31:
.dbline 113
; else
; {//发送eeprom地址出错
.dbline 114
; state=ST_FAIL;
clr R20
.dbline 115
; }
.dbline 116
; break;
rjmp L21
L37:
.dbline 118
; case ST_RESTART: //RESTART状态检查,只有读操作模式才能跳到这里
; if(status==TW_REP_START)
cpi R22,16
brne L38
.dbline 119
; {//发送restart信号成功
.dbline 120
; TWDR=strTWI.SLA; //发器件地址读SLAR
lds R2,_strTWI+1
out 0x3,R2
.dbline 121
; TWCR=TW_ACT; //触发下一步动作,同时清start发送标志
ldi R24,133
out 0x36,R24
.dbline 122
; }
rjmp L21
L38:
.dbline 124
; else
; {//重发start信号出错
.dbline 125
; state=ST_FAIL;
clr R20
.dbline 126
; }
.dbline 127
; break;
rjmp L21
L41:
.dbline 129
; case ST_SLAR: //SLAR状态检查,只有读操作模式才能跳到这里
; if(status==TW_MR_SLA_ACK)
cpi R22,64
brne L42
.dbline 130
; {//发送器件地址成功
.dbline 131
; if (strTWI.DATALEN--)
lds R2,_strTWI+4
mov R24,R2
subi R24,1
sts _strTWI+4,R24
tst R2
breq L44
.dbline 132
; {//多个数据
.dbline 133
; TWCR=(1<<TWEA)|TW_ACT; //设定ACK,触发下一步动作
ldi R24,197
out 0x36,R24
.dbline 134
; }
rjmp L21
L44:
.dbline 136
; else
; {//只有一个数据
.dbline 137
; TWCR=TW_ACT; //设定NAK,触发下一步动作
ldi R24,133
out 0x36,R24
.dbline 138
; }
.dbline 139
; }
rjmp L21
L42:
.dbline 141
; else
; {//发送器件地址出错
.dbline 142
; state=ST_FAIL;
clr R20
.dbline 143
; }
.dbline 144
; break;
rjmp L21
L47:
.dbline 146
; case ST_RDATA: //读取数据状态检查,只有读操作模式才能跳到这里
; state--; //循环,直到读完指定长度数据
dec R20
.dbline 147
; if(status==TW_MR_DATA_ACK)
cpi R22,80
brne L48
.dbline 148
; {//读取数据成功,但不是最后一个数据
.dbline 149
; *strTWI.pBUF++=TWDR;
in R2,0x3
lds R30,_strTWI+2
lds R31,_strTWI+2+1
st Z+,R2
sts _strTWI+2+1,R31
sts _strTWI+2,R30
.dbline 150
; if (strTWI.DATALEN--)
lds R2,_strTWI+4
mov R24,R2
subi R24,1
sts _strTWI+4,R24
tst R2
breq L51
.dbline 151
; {//还有多个数据
.dbline 152
; TWCR=(1<<TWEA)|TW_ACT; //设定ACK,触发下一步动作
ldi R24,197
out 0x36,R24
.dbline 153
; }
rjmp L21
L51:
.dbline 155
; else
; {//准备读最后一个数据
.dbline 156
; TWCR=TW_ACT; //设定NAK,触发下一步动作
ldi R24,133
out 0x36,R24
.dbline 157
; }
.dbline 158
; }
rjmp L21
L48:
.dbline 159
; else if(status==TW_MR_DATA_NACK)
cpi R22,88
brne L54
.dbline 160
; {//已经读完最后一个数据
.dbline 161
; *strTWI.pBUF++=TWDR;
in R2,0x3
lds R30,_strTWI+2
lds R31,_strTWI+2+1
st Z+,R2
sts _strTWI+2+1,R31
sts _strTWI+2,R30
.dbline 162
; TWCR=(1<<TWSTO)|TW_ACT; //发送停止信号,不会再产生中断了
ldi R24,149
out 0x36,R24
.dbline 163
; strTWI.STATUS=TW_OK;
ldi R24,1
sts _strTWI,R24
.dbline 164
; }
rjmp L21
L54:
.dbline 166
; else
; {//读取数据出错
.dbline 167
; state=ST_FAIL;
clr R20
.dbline 168
; }
.dbline 169
; break;
rjmp L21
L57:
.dbline 171
; case ST_WDATA: //写数据状态检查,只有写操作模式才能跳到这里
; state--; //循环,直到写完指定长度数据
dec R20
.dbline 172
; if(status==TW_MT_DATA_ACK)
cpi R22,40
brne L58
.dbline 173
; {//写数据成功
.dbline 174
; if (strTWI.DATALEN)
lds R2,_strTWI+4
tst R2
breq L60
.dbline 175
; {//还要写
.dbline 176
; TWDR=*strTWI.pBUF++;
lds R30,_strTWI+2
lds R31,_strTWI+2+1
ld R2,Z+
sts _strTWI+2+1,R31
sts _strTWI+2,R30
out 0x3,R2
.dbline 177
; strTWI.DATALEN--;
lds R24,_strTWI+4
subi R24,1
sts _strTWI+4,R24
.dbline 178
; TWCR=TW_ACT; //触发下一步动作
ldi R24,133
out 0x36,R24
.dbline 179
; }
rjmp L21
L60:
.dbline 181
; else
; {//写够了
.dbline 182
; TWCR=(1<<TWSTO)|TW_ACT; //发送停止信号,不会再产生中断了
ldi R24,149
out 0x36,R24
.dbline 183
; strTWI.STATUS=TW_OK;
ldi R24,1
sts _strTWI,R24
.dbline 186
; //启动写命令后需要10ms(最大)的编程时间才能真正的把数据记录下来
; //编程期间器件不响应任何命令
; }
.dbline 187
; }
rjmp L21
L58:
.dbline 189
; else
; {//写数据失败
.dbline 190
; state=ST_FAIL;
clr R20
.dbline 191
; }
.dbline 192
; break;
rjmp L21
L20:
.dbline 195
; default:
; //错误状态
; state=ST_FAIL;
clr R20
.dbline 196
; break;
L21:
.dbline 199
; }
;
; if (state==ST_FAIL)
tst R20
brne L65
.dbline 200
; {//错误处理
.dbline 201
; strTWI.FAILCNT++;
lds R24,_strTWI+6
subi R24,255 ; addi 1
sts _strTWI+6,R24
.dbline 202
; if (strTWI.FAILCNT<FAIL_MAX)
cpi R24,20
brsh L68
.dbline 203
; {//重试次数未超出最大值,
.dbline 204
; TWCR=(1<<TWSTA)|TW_ACT; //发生错误,启动start信号
ldi R24,165
out 0x36,R24
.dbline 205
; }
rjmp L69
L68:
.dbline 207
; else
; {//否则停止
.dbline 208
; TWCR=(1<<TWSTO)|TW_ACT; //发送停止信号,不会再产生中断了
ldi R24,149
out 0x36,R24
.dbline 209
; strTWI.STATUS=TW_FAIL;
ldi R24,2
sts _strTWI,R24
.dbline 210
; }
L69:
.dbline 211
; }
L65:
.dbline 212
; state++;
inc R20
.dbline 213
; strTWI.STATE=state; //保存状态
sts _strTWI+5,R20
.dbline 214
; }
.dbline 216
; else
; {
.dbline 218
; //总线错误或从机模式引发的中断,不予处理
; return;
L19:
L14:
.dbline -2
L10:
rcall pop_gset4
rcall pop_lset
.dbline 0 ; func end
reti
.dbsym r action 10 c
.dbsym r state 20 c
.dbsym r status 22 c
.dbend
.area bss(ram, con, rel)
.dbfile D:\myavrproject\icc\twi\twi.c
_strTWI::
.blkb 7
.dbsym e strTWI _strTWI X
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -