📄 twi.s
字号:
; i -> R20
; ReadAaddress -> R22
.even
_twiReadByte::
rcall push_gset3
mov R22,R16
.dbline -1
.dbline 154
; //************** twi主机接收,从地址为ReadAaddress的从机接收1个字节*************
; // 入口参数1:ReadAaddress:从机地址
; // TWDR中存放的高七位为地址,最低位表示读写控制,0为写,1为读
; //******************************************************************************
; void twiReadByte(unsigned char ReadAaddress)
; {
.dbline 156
; unsigned char TWCR_state;
; char i=0;
clr R20
.dbline 157
; error_state=0;
clr R2
sts _error_state,R2
.dbline 160
;
; //初始化 twi
; twi_init();
rcall _twi_init
.dbline 163
;
; //发送START信号
; start();
rcall _start
.dbline 164
; TWCR_state = TWCR & 0x80;
in R24,0x36
andi R24,128
mov R10,R24
rjmp L42
L41:
.dbline 166
; while((TWCR_state == 0x00))
; {
.dbline 167
; i++;
inc R20
.dbline 168
; if(i>=10){error_state=7;break;}
cpi R20,10
brlo L44
.dbline 168
.dbline 168
ldi R24,7
sts _error_state,R24
.dbline 168
rjmp L43
L44:
.dbline 169
in R24,0x36
andi R24,128
mov R10,R24
.dbline 170
L42:
.dbline 165
tst R10
breq L41
L43:
.dbline 173
; TWCR_state = TWCR & 0x80; //轮循等待START信号发送完成
; }
;
; //若START信号发送完成,发送读地址,并读取数据
; if(error_state==0)
lds R2,_error_state
tst R2
brne L46
.dbline 174
; {
.dbline 175
; TWDR = ReadAaddress; //发地址
out 0x3,R22
.dbline 176
; _NOP();
nop
.dbline 177
; _NOP();
nop
.dbline 178
; TWCR = (1 << TWINT) | (1 << TWEN)|( 1<<TWIE )|(1 << TWEA);
ldi R24,197
out 0x36,R24
rjmp L49
L48:
.dbline 180
.dbline 180
inc R20
.dbline 180
ldi R24,150
cp R24,R20
brsh L51
.dbline 180
.dbline 180
ldi R24,9
sts _error_state,R24
.dbline 180
rjmp L50
L51:
.dbline 180
L49:
.dbline 179
; while(error_state==0)
lds R2,_error_state
tst R2
breq L48
L50:
.dbline 180
; {i++;if(i>150){error_state=9;break;}};
.dbline 181
; }
L46:
.dbline 184
;
; //发送STOP,退出总线控制
; stop();
rcall _stop
.dbline -2
.dbline 185
; }
L40:
rcall pop_gset3
.dbline 0 ; func end
ret
.dbsym r TWCR_state 10 c
.dbsym r i 20 c
.dbsym r ReadAaddress 22 c
.dbend
.dbfunc e twi_isr _twi_isr fc
; TWSR_state -> R16
.even
_twi_isr::
st -y,R2
st -y,R16
st -y,R17
st -y,R24
st -y,R25
st -y,R30
in R2,0x3f
st -y,R2
.dbline -1
.dbline 190
; //************** twi 中断例程,接收数据 ****************************************
; //******************************************************************************
; //twi中断服务程序
; char twi_isr(void)
; {
.dbline 192
; unsigned char TWSR_state;
; TWSR_state = TWSR & 0xf8;
in R16,0x1
andi R16,248
.dbline 193
; switch(TWSR_state)
clr R17
cpi R16,128
ldi R30,0
cpc R17,R30
brne X4
rjmp L58
X4:
ldi R24,128
ldi R25,0
cp R24,R16
cpc R25,R17
brge X5
rjmp L73
X5:
L72:
cpi R16,72
ldi R30,0
cpc R17,R30
brne X6
rjmp L63
X6:
ldi R24,72
ldi R25,0
cp R24,R16
cpc R25,R17
brlt L75
L74:
cpi R16,56
ldi R30,0
cpc R17,R30
brne X7
rjmp L61
X7:
ldi R24,56
ldi R25,0
cp R24,R16
cpc R25,R17
brlt L77
L76:
cpi R16,0
cpc R16,R17
brne X8
rjmp L71
X8:
X1:
rjmp L55
L77:
cpi R16,64
ldi R30,0
cpc R17,R30
brne X9
rjmp L62
X9:
rjmp L55
L75:
cpi R16,88
ldi R30,0
cpc R17,R30
brne X10
rjmp L65
X10:
ldi R24,88
ldi R25,0
cp R24,R16
cpc R25,R17
brlt L79
L78:
cpi R16,80
ldi R30,0
cpc R17,R30
brne X11
rjmp L64
X11:
rjmp L55
L79:
cpi R16,96
ldi R30,0
cpc R17,R30
brne X12
rjmp L57
X12:
rjmp L55
L73:
cpi R16,184
ldi R30,0
cpc R17,R30
brne X13
rjmp L67
X13:
ldi R24,184
ldi R25,0
cp R24,R16
cpc R25,R17
brlt L81
L80:
cpi R16,160
ldi R30,0
cpc R17,R30
brne X14
rjmp L60
X14:
ldi R24,160
ldi R25,0
cp R24,R16
cpc R25,R17
brlt L83
L82:
cpi R16,136
ldi R30,0
cpc R17,R30
breq L59
rjmp L55
L83:
cpi R16,168
ldi R30,0
cpc R17,R30
brne X15
rjmp L66
X15:
rjmp L55
L81:
cpi R16,200
ldi R30,0
cpc R17,R30
brne X16
rjmp L69
X16:
ldi R24,200
ldi R25,0
cp R24,R16
cpc R25,R17
brlt L85
L84:
cpi R16,192
ldi R30,0
cpc R17,R30
brne X17
rjmp L68
X17:
rjmp L55
L85:
cpi R16,248
ldi R30,0
cpc R17,R30
brne X18
rjmp L55
X18:
rjmp L55
X2:
.dbline 194
; {
L57:
.dbline 196
; //从机接收模式下的中断程序
; case 0x60: TWCR=0xc5;break; // SLA+W已经接收,ACK已返回(从机被寻址,等待主机发送数据)
ldi R24,197
out 0x36,R24
.dbline 196
rjmp L55
L58:
.dbline 197
; case 0x80: receive_data = TWDR;TWCR=0xc5;break; // 数据已接收,ACK已返回(接收数据)
in R2,0x3
sts _receive_data,R2
.dbline 197
ldi R24,197
out 0x36,R24
.dbline 197
rjmp L55
L59:
.dbline 198
; case 0x88: TWCR=0xc5;break; // 数据已接收,NOT ACK已返回(下一步:退出总线)
ldi R24,197
out 0x36,R24
.dbline 198
rjmp L55
L60:
.dbline 199
; case 0xA0: TWCR=0xc5;break; // 接收到STOP或重复的START信号(停止接收数据)
ldi R24,197
out 0x36,R24
.dbline 199
rjmp L55
L61:
.dbline 202
;
; //主机接收模式下的中断程序
; case 0x38: error_state=4;TWCR=0xc5;break; // SLA+R或NOT ACK仲裁失败(下一步:退出总线)
ldi R24,4
sts _error_state,R24
.dbline 202
ldi R24,197
out 0x36,R24
.dbline 202
rjmp L55
L62:
.dbline 203
; case 0x40: TWCR=0xc5; break; // SLA+R已发送,接收到ACK(从机被寻址,主机等待接收数据)
ldi R24,197
out 0x36,R24
.dbline 203
rjmp L55
L63:
.dbline 204
; case 0x48: error_state=5;TWCR=0xc5;break; // SLA+R已发送,接收到NOT ACK(下一步:退出总线)
ldi R24,5
sts _error_state,R24
.dbline 204
ldi R24,197
out 0x36,R24
.dbline 204
rjmp L55
L64:
.dbline 205
; case 0x50: receive_data = TWDR;_NOP();_NOP();error_state=8;TWCR = 0xc4;break; // 接收到数据,ACK已返回(接收数据)
in R2,0x3
sts _receive_data,R2
.dbline 205
nop
.dbline 205
nop
.dbline 205
ldi R24,8
sts _error_state,R24
.dbline 205
ldi R24,196
out 0x36,R24
.dbline 205
rjmp L55
L65:
.dbline 206
; case 0x58: receive_data = TWDR;_NOP();_NOP();error_state=8;TWCR = 0xc4;break; // 接收到数据,NOT ACK已返回(下一步:退出总线)
in R2,0x3
sts _receive_data,R2
.dbline 206
nop
.dbline 206
nop
.dbline 206
ldi R24,8
sts _error_state,R24
.dbline 206
ldi R24,196
out 0x36,R24
.dbline 206
rjmp L55
L66:
.dbline 209
;
; //从机发送模式
; case 0xA8: TWDR= send_data;_NOP();_NOP();TWCR= 0x85; break; // SLA+R已接收,ACK已返回(从机被寻址,开送发送数据)
lds R2,_send_data
out 0x3,R2
.dbline 209
nop
.dbline 209
nop
.dbline 209
ldi R24,133
out 0x36,R24
.dbline 209
rjmp L55
L67:
.dbline 210
; case 0xB8: TWCR= 0xc5;break; // TWDR里的数据已发送,接受到ACK(主机接收到数据,继续发送数据)
ldi R24,197
out 0x36,R24
.dbline 210
rjmp L55
L68:
.dbline 211
; case 0xC0: TWCR= 0xc5;break; // TWDR里的数据已发送,接受到NOT ACK(下一步:退出总线)
ldi R24,197
out 0x36,R24
.dbline 211
rjmp L55
L69:
.dbline 212
; case 0xC8: TWCR= 0xc5;break; // TWEA=0,接收到ACK(停止发送数据,退出发送)
ldi R24,197
out 0x36,R24
.dbline 212
rjmp L55
X3:
.dbline 215
;
; //其他状态码
; case 0xf8: break; // 等待或进行当前传输
L71:
.dbline 216
; case 0x00: TWCR= 0x95;break; // 非法的START或STOP引起的总线错误(释放总线)
ldi R24,149
out 0x36,R24
.dbline 216
.dbline 217
; default: break;
L55:
.dbline 219
; }
; return receive_data; // 返回接收到的数据
lds R16,_receive_data
.dbline -2
L53:
ld R2,y+
out 0x3f,R2
ld R30,y+
ld R25,y+
ld R24,y+
ld R17,y+
ld R16,y+
ld R2,y+
.dbline 0 ; func end
reti
.dbsym r TWSR_state 16 c
.dbend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -