📄 twi.s
字号:
cpc R23,R30
brne X37
xjmp L148
X37:
xjmp L147
X2:
.dbline 446
; {
L150:
.dbline 451
; // 主方式
; case TW_START: // 0x08: START 已发送
; case TW_REP_START: // 0x10: 重复START 已发送
; // 发送器件地址
; Twi_SendByte(Twi_DeviceAddrRW);
.dbline 451
lds R2,_Twi_DeviceAddrRW
out 0x3,R2
.dbline 451
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 451
.dbline 451
.dbline 452
; break;
xjmp L148
L151:
.dbline 456
; // 主发送,主接收状态码
; case TW_MT_SLA_ACK: // 0x18: SLA+W 已发送;接收到ACK
; case TW_MT_DATA_ACK: // 0x28: 数据已发送;接收到ACK
; if((Twi_SendBuffer.count>0)&&(Twi_SendBuffer.status==TWI_DATA_SEND))
clr R2
lds R3,_Twi_SendBuffer+2
cp R2,R3
brsh L152
lds R24,_Twi_SendBuffer+7
cpi R24,2
brne L152
.dbline 457
; {
.dbline 459
; // 发送数据
; Twi_SendByte( DeQueue(&Twi_SendBuffer));
.dbline 459
ldi R16,<_Twi_SendBuffer
ldi R17,>_Twi_SendBuffer
xcall _DeQueue
out 0x3,R16
.dbline 459
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 459
.dbline 459
.dbline 460
; }
xjmp L148
L152:
.dbline 462
; else
; {
.dbline 464
; // 发送停止条件,保持TWEA以便从接收
; Twi_Stop();
in R24,0x36
andi R24,15
ori R24,208
out 0x36,R24
.dbline 466
; // 设置状态
; Twi_State = TWI_IDLE;
clr R2
sts _Twi_State,R2
.dbline 467
; }
.dbline 468
; break;
xjmp L148
L156:
.dbline 471
; case TW_MR_DATA_NACK: // 0x58: 接收到数据;NOT ACK 已返回
; // 保存最终数据
; EnQueue(&Twi_ReceiveBuffer,TWDR);
in R18,0x3
ldi R16,<_Twi_ReceiveBuffer
ldi R17,>_Twi_ReceiveBuffer
xcall _EnQueue
L157:
.dbline 477
; //继续发送条件
; case TW_MR_SLA_NACK: // 0x48: SLA+R 已发送,接收到NOT ACK
; case TW_MT_SLA_NACK: // 0x20: SLA+W 已发送,接收到NOT ACK
; case TW_MT_DATA_NACK: // 0x30: 数据已发送,接收到NOT ACK
; // 发送停止条件,保持TWEA以便从接收
; Twi_Stop();
in R24,0x36
andi R24,15
ori R24,208
out 0x36,R24
.dbline 479
; // 设置状态
; Twi_State = TWI_IDLE;
clr R2
sts _Twi_State,R2
.dbline 480
; break;
xjmp L148
L158:
.dbline 483
; case TW_MT_ARB_LOST: // 0x38: SLA+W 或数据的仲裁失败
; // 释放总线
; TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT);
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 485
; // 设置状态
; Twi_State = TWI_IDLE;
clr R2
sts _Twi_State,R2
.dbline 486
; break;
xjmp L148
L159:
.dbline 489
; case TW_MR_DATA_ACK: // 0x50: 接收到数据,ACK 已返回
; // 保存接收到的数据位
; EnQueue(&Twi_ReceiveBuffer,TWDR);
in R18,0x3
ldi R16,<_Twi_ReceiveBuffer
ldi R17,>_Twi_ReceiveBuffer
xcall _EnQueue
L160:
.dbline 492
; // 检查是否接收完
; case TW_MR_SLA_ACK: // 0x40: SLA+R 已发送,接收到ACK
; if(!FullQueue(&Twi_ReceiveBuffer)&&(Twi_ReceiveBuffer.count<(Twi_ReceiveBuffer.memo-1))&&(Twi_ReceiveBuffer.status==TWI_DATA_RECEIVE))
lds R2,_Twi_ReceiveBuffer+5
lds R3,_Twi_ReceiveBuffer+2
cp R3,R2
breq L161
lds R24,_Twi_ReceiveBuffer+8
subi R24,1
cp R3,R24
brsh L161
lds R24,_Twi_ReceiveBuffer+7
cpi R24,1
brne L161
.dbline 494
; // 数据位将接收 , 回复 ACK (传送更多字节)
; Twi_Ack();
in R24,0x36
andi R24,15
ori R24,192
out 0x36,R24
xjmp L148
L161:
.dbline 497
; else
; // 数据位将接收 , 回复 NACK (传送最后字节)
; Twi_NoAcK();
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 498
; break;
xjmp L148
L168:
.dbline 506
; // 从接收状态码
; case TW_SR_SLA_ACK: // 0x60: 自己的SLA+W 已经被接收,ACK 已返回
; case TW_SR_ARB_LOST_SLA_ACK:// 0x68: SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收,ACK 已返回
; case TW_SR_GCALL_ACK: // 0x70: 接收到广播地址,ACK 已返回
; case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: SLA+R/W 作为主机的仲裁失败;接收到广播地址,ACK 已返回
; // 被选中为从写入 (数据将从主机接收)
; // 设置状态
; Twi_State = TWI_SLAVE_RX;
ldi R24,5
sts _Twi_State,R24
.dbline 508
; // 缓冲准备
; if ((Twi_ReceiveBuffer.status==TWI_DATA_FREE)&&(Twi_LocalBuffer.status==TWI_DATA_RECEIVE))
lds R2,_Twi_ReceiveBuffer+7
tst R2
brne L169
lds R24,_Twi_LocalBuffer+7
cpi R24,1
brne L169
.dbline 509
; {
.dbline 510
; InitQueue(&Twi_ReceiveBuffer);
ldi R16,<_Twi_ReceiveBuffer
ldi R17,>_Twi_ReceiveBuffer
xcall _InitQueue
.dbline 511
; Twi_ReceiveBuffer.status=TWI_DATA_RECEIVE;
ldi R24,1
sts _Twi_ReceiveBuffer+7,R24
.dbline 513
; // 接收数据,回应 ACK
; Twi_Ack(); // notice 自己增加,为适应缓冲区独占
in R24,0x36
andi R24,15
ori R24,192
out 0x36,R24
.dbline 514
; }
xjmp L148
L169:
.dbline 517
; else
; // 拒绝接收数据,回应 NACK
; Twi_NoAcK(); // notice 自己增加,为适应缓冲区独占
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 518
; break;
xjmp L148
L174:
.dbline 522
; case TW_SR_DATA_ACK: // 0x80: 以前以自己的 SLA+W 被寻址;数据已经被接收,ACK 已返回
; case TW_SR_GCALL_DATA_ACK: // 0x90: 以前以广播方式被寻址;数据已经被接收,ACK 已返回
;
; EnQueue(&Twi_ReceiveBuffer,TWDR);
in R18,0x3
ldi R16,<_Twi_ReceiveBuffer
ldi R17,>_Twi_ReceiveBuffer
xcall _EnQueue
.dbline 524
; //检查接收缓冲区状态
; if(!FullQueue(&Twi_ReceiveBuffer))
lds R2,_Twi_ReceiveBuffer+5
lds R3,_Twi_ReceiveBuffer+2
cp R3,R2
breq L175
.dbline 525
; {
.dbline 527
; // 接收数据,回应 ACK
; Twi_Ack();
in R24,0x36
andi R24,15
ori R24,192
out 0x36,R24
.dbline 528
; }
xjmp L148
L175:
.dbline 530
; else
; {
.dbline 532
; // 接收数据,回应 NACK
; Twi_NoAcK();
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 533
; }
.dbline 534
; break;
xjmp L148
L179:
.dbline 538
; case TW_SR_DATA_NACK: // 0x88: 以前以自己的 SLA+W 被寻址;数据已经被接收,NOT ACK 已返回
; case TW_SR_GCALL_DATA_NACK: // 0x98: 以前以广播方式被寻址;数据已经被接收,NOT ACK 已返回
; // 接收数据,回应 NACK
; Twi_NoAcK();
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 539
; break;
xjmp L148
L180:
.dbline 541
; case TW_SR_STOP: // 0xA0: 在以从机工作时接收到STOP或重复START
; Twi_Ack();
in R24,0x36
andi R24,15
ori R24,192
out 0x36,R24
.dbline 543
; // Twi_ 接收完成
; Twi_SlaveReceiveService();
xcall _Twi_SlaveReceiveService
.dbline 545
; // 设置状态
; Twi_State = TWI_IDLE;
clr R2
sts _Twi_State,R2
.dbline 546
; break;
xjmp L148
L181:
.dbline 552
; // 从发送
; case TW_ST_SLA_ACK: // 0xA8: 自己的SLA+R 已经被接收,ACK 已返回
; case TW_ST_ARB_LOST_SLA_ACK:// 0xB0: SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收,ACK 已返回
; // 被选中为从读出 (数据将从传回主机)
; // 设置状态
; Twi_State = TWI_SLAVE_TX;
ldi R24,4
sts _Twi_State,R24
.dbline 555
; // 数据请求
;
; Twi_SlaveTransmitService();
xcall _Twi_SlaveTransmitService
L182:
.dbline 558
; case TW_ST_DATA_ACK: // 0xB8: TWDR 里数据已经发送,接收到ACK
; // 发送数据位
; if(Twi_SendBuffer.count>1)
ldi R24,1
lds R2,_Twi_SendBuffer+2
cp R24,R2
brsh L183
.dbline 560
; // 回应 ACK
; { TWDR=DeQueue(&Twi_SendBuffer);
.dbline 560
ldi R16,<_Twi_SendBuffer
ldi R17,>_Twi_SendBuffer
xcall _DeQueue
out 0x3,R16
.dbline 561
; Twi_Ack();
in R24,0x36
andi R24,15
ori R24,192
out 0x36,R24
.dbline 562
; }
xjmp L148
L183:
.dbline 565
; else
; // 回应 NACK
; { TWDR=DeQueue(&Twi_SendBuffer);
.dbline 565
ldi R16,<_Twi_SendBuffer
ldi R17,>_Twi_SendBuffer
xcall _DeQueue
out 0x3,R16
.dbline 566
; Twi_NoAcK();
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 567
; }
.dbline 568
; break;
xjmp L148
L186:
.dbline 574
; case TW_ST_DATA_NACK: // 0xC0: TWDR 里数据已经发送接收到NOT ACK
; case TW_ST_LAST_DATA: // 0xC8: TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK
;
; // 全部完成
; // 从方式开放
; Twi_Ack();
in R24,0x36
andi R24,15
ori R24,192
out 0x36,R24
.dbline 576
; // 设置状态
; Twi_SendBuffer.status=TWI_DATA_FREE;
clr R2
sts _Twi_SendBuffer+7,R2
.dbline 577
; Twi_State = TWI_IDLE;
sts _Twi_State,R2
.dbline 578
; break;
xjmp L148
X3:
.dbline 581
; case TW_NO_INFO: // 0xF8: 没有相关的状态信息;TWINT = “0”
; // 无操作
; break;
L189:
.dbline 585
; case TW_BUS_ERROR: // 0x00: 由于非法的START 或STOP 引起的总线错误
;
; // 内部硬件复位,释放总线
; TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTO)|(1<<TWEA);
in R24,0x36
andi R24,15
ori R24,208
out 0x36,R24
.dbline 587
; // 设置状态
; Twi_State = TWI_IDLE;
clr R2
sts _Twi_State,R2
.dbline 588
; break;
L147:
L148:
.dbline 590
; }
; TwiErrorCode=status;
sts _TwiErrorCode,R20
.dbline -2
L146:
xcall pop_gset2
xcall pop_lset
.dbline 0 ; func end
reti
.dbsym r status 20 c
.dbend
.dbfunc e Twi_Init _Twi_Init fV
.even
_Twi_Init::
.dbline -1
.dbline 606
; }
;
; /*********************************************************************************************************
; ** 函数名称:Twi_Init
; ** 功能描述:TWI总线初始化
; ** 输 入:
; ** 输 出:
; ** 全局变量:
; ** 调用模块: Twi_SetBitrate()
; ** 说明:
; ** 注意:
; ** 日 期: 2006年8月29日
; ********************************************************************************************************/
;
; void Twi_Init(void)
; {
.dbline 607
; WDR(); //喂狗;
wdr
.dbline 616
; //设置总线上拉 此处注意:如果有外部上拉,可以不使用内部弱上拉
; #if (CPU_TYPE == M64) || (CPU_TYPE == M128)
; DDRD&=~(1<<0);
; DDRD&=~(1<<1);
; PORTD|=(1<<0); // Twi_ SCL on ATmega128,64
; PORTD|=(1<<1); // Twi_ SDA on ATmega128,64
; #endif
; #if (CPU_TYPE == M32) || (CPU_TYPE == M16)
; DDRC&=~(1<<0);
cbi 0x14,0
.dbline 617
; DDRC&=~(1<<1);
cbi 0x14,1
.dbline 618
; PORTC|=(1<<0); // Twi_ SCL on ATmega163,323,16,32,等
sbi 0x15,0
.dbline 619
; PORTC|=(1<<1); // Twi_ SDA on ATmega163,323,16,32,等
sbi 0x15,1
.dbline 629
; #endif
; #if (CPU_TYPE == M8)
; DDRC&=~(1<<5);
; DDRC&=~(1<<4);
; PORTC|=(1<<5); // Twi_ SCL on ATmega163,323,16,32,等
; PORTC|=(1<<4); // Twi_ SDA on ATmega163,323,16,32,等
;
; #endif
; // 设置 Twi_ 波特率为 100KHz
; Twi_SetBitrate(80);
ldi R16,80
ldi R17,0
xcall _Twi_SetBitrate
.dbline 632
;
; // 清空从发送和从接收
; Twi_SlaveReceive = 0;
clr R2
clr R3
sts _Twi_SlaveReceive+1,R3
sts _Twi_SlaveReceive,R2
.dbline 633
; Twi_SlaveTransmit = 0;
sts _Twi_SlaveTransmit+1,R3
sts _Twi_SlaveTransmit,R2
.dbline 635
;
; InitQueue(&Twi_SendBuffer);
ldi R16,<_Twi_SendBuffer
ldi R17,>_Twi_SendBuffer
xcall _InitQueue
.dbline 636
; InitQueue(&Twi_ReceiveBuffer);
ldi R16,<_Twi_ReceiveBuffer
ldi R17,>_Twi_ReceiveBuffer
xcall _InitQueue
.dbline 637
; InitQueue(&Twi_LocalBuffer);
ldi R16,<_Twi_LocalBuffer
ldi R17,>_Twi_LocalBuffer
xcall _InitQueue
.dbline 639
; // 状态设置
; Twi_State = TWI_IDLE;
clr R2
sts _Twi_State,R2
.dbline 646
;
;
; //设置从接收函数句柄(此函数在被选中为从接收时执行)
; //Twi_SetSlaveReceiveHandler( Twi_SlaveReceiveService );
; //设置从发送函数句柄(此函数在被选中为从发送时执行)
; // Twi_SetSlaveTransmitHandler( Twi_SlaveTransmitService );
; Twi_SetLocalDeviceAddr(0x50, 0);
ldi R24,80
out 0x2,R24
.dbline 648
; // 开Twi_中断和回应 Twi_总线使能
; TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWEA);
ldi R24,69
out 0x36,R24
.dbline 649
; SEI(); // 开中断
sei
.dbline -2
L216:
.dbline 0 ; func end
ret
.dbend
.area bss(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
_Twi_SlaveTransmit:
.blkb 2
.dbsym s Twi_SlaveTransmit _Twi_SlaveTransmit pfc
_Twi_SlaveReceive:
.blkb 2
.dbsym s Twi_SlaveReceive _Twi_SlaveReceive pfV
_TwiErrorCode:
.blkb 1
.dbsym s TwiErrorCode _TwiErrorCode c
_LocalBuffer:
.blkb 5
.dbsym s LocalBuffer _LocalBuffer A[5:5]c
_Twi_ReceiveData:
.blkb 5
.dbsym s Twi_ReceiveData _Twi_ReceiveData A[5:5]c
_Twi_SendData:
.blkb 5
.dbsym s Twi_SendData _Twi_SendData A[5:5]c
_Twi_DeviceAddrRW:
.blkb 1
.dbsym s Twi_DeviceAddrRW _Twi_DeviceAddrRW c
_Twi_State:
.blkb 1
.dbsym s Twi_State _Twi_State c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -