📄 twi.s
字号:
.module TWI.c
.area data(ram, con, rel)
_Twi_SendBuffer::
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkw 1
.area idata
.word _Twi_SendData
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 5
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.dbstruct 0 9 .1
.dbfield 0 front c
.dbfield 1 rear c
.dbfield 2 count c
.dbfield 3 data pc
.dbfield 5 queuesize c
.dbfield 6 errorcode c
.dbfield 7 status c
.dbfield 8 memo c
.dbend
.dbsym e Twi_SendBuffer _Twi_SendBuffer S[.1]
_Twi_ReceiveBuffer::
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkw 1
.area idata
.word _Twi_ReceiveData
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 5
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.dbsym e Twi_ReceiveBuffer _Twi_ReceiveBuffer S[.1]
_Twi_LocalBuffer::
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkw 1
.area idata
.word _LocalBuffer
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 5
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.dbsym e Twi_LocalBuffer _Twi_LocalBuffer S[.1]
.area text(rom, con, rel)
.dbfile D:\桌面\mp3\TWI\TWI.c
.dbfunc e Delay _Delay fV
; i -> R20
; n -> R16
.even
_Delay::
xcall push_gset1
.dbline -1
.dbline 92
; /*********************************************************************************************************
; ** TWI 驱动程序
; ** (c) Copyright 2006-2008, limaokui
; ** All Rights Reserved
; **
; ** V1.0.0
; **
; **
; **--------------文件信息--------------------------------------------------------------------------------
; **文 件 名:TWI.h
; **创 建 人: 李茂奎
; **最后修改日期: 2006年8月29日
; **描 述: TWI驱动程序
; **
; **--------------历史版本信息----------------------------------------------------------------------------
; ** 创建人: 李茂奎
; ** 版 本: V1.00
; ** 日 期: 2006年8月29日
; ** 描 述: 原始版本
; **
; **------------------------------------------------------------------------------------------------------
; ** 修改人: 李茂奎
; ** 版 本:
; ** 日 期:
; ** 描 述:
; **
; **--------------当前版本修订------------------------------------------------------------------------------
; ** 修改人: 李茂奎
; ** 日 期: 2006年9月1日
; ** 描 述:
; **
; **------------------------------------------------------------------------------------------------------
; *********************************************************************************************************/
; /*
; 说明:1、本驱动程序已经实现了TWI中断通讯的四种模式:MT、MR、ST、SR。
; 2、MT方式调用Twi_MasterSend()函数,用到了Twi_SendBuffer队列,
; 最大单次发送255Btye,理论上两次发送间隔5MS以上。
; 3、MR方式调用Twi_MasterRecive()函数,用到了Twi_ReceiveBuffer队列,
; 最大单次发送255Btye,理论上两次发送间隔5MS以上。
; 4、SR方式用户不必关心何时中断,在中断结束后,调用Twi_SlaveReceiveService()函数,
; 此函数将接收到的数据传给上层缓冲区Twi_LocalBuffer,用到了Twi_ReceiveBuffer、Twi_LocalBuffer队列,
; 最大单次发送255Btye。上层程序仅需检测Twi_LocalBuffer中的status即可,即若status值
; TWI_DATA_READY,就可以读取数据,读完后设置LocalBuffer的Status为TWI_DATA_FREE。
; 5、ST方式用户不必关心何时中断,在中断结束后,调用Twi_TransmintReceiveService()函数S玫搅薚wi_ReceiveBuffer、Twi_LocalBuffer队列,
; 如果想使能从机发送则可将要发数据传入LocalBuffer中并设置Status为TWI_DATA_SEND,在写
; LocalBuffer之前,应检测STATUS是否为Status为TWI_DATA_FREE。
; 6、非中断模式的接收发送没有经过验证。使用时请注意。
; 7、使用时首先调用TwiInit()进行初始化,(循环队列的长度可以自己修改对应的数组和结构中的queuesize),
; 然后打开中断即可。对于不同的单片机,此驱动中通过定义CPU_TYPE实现切换。对应的定义在config中。
; */
; #include "config.h"
; // Twi标准波特率:
; // 低速 100KHz
; // 高速 400KHz
;
; // Twi_ 状态和地址变量
; static volatile eTwi_StateType Twi_State; // 用于独占TWI的资源分配的信号量机制
; static volatile uint8 Twi_DeviceAddrRW;
; // 发送缓冲区
; static uint8 Twi_SendData[TWI_SEND_DATA_BUFFER_SIZE];
; CirQueue Twi_SendBuffer={0,0,0,Twi_SendData,TWI_SEND_DATA_BUFFER_SIZE,QUEUE_OK,TWI_DATA_FREE,0};
; // 接收缓冲区
; static uint8 Twi_ReceiveData[TWI_RECEIVE_DATA_BUFFER_SIZE];
; CirQueue Twi_ReceiveBuffer={0,0,0,(uint8 *)Twi_ReceiveData,TWI_RECEIVE_DATA_BUFFER_SIZE,QUEUE_OK,TWI_DATA_FREE,0};
; //本地缓冲区,当为从机时,与TWI接口
; static uint8 LocalBuffer[TWI_LOCAL_DATA_BUFFER_SIZE];
; CirQueue Twi_LocalBuffer={0,0,0,LocalBuffer,TWI_LOCAL_DATA_BUFFER_SIZE,QUEUE_OK,TWI_DATA_FREE,0};
; //错误代码
; static volatile uint8 TwiErrorCode;
;
; // 指向接收处理函数的指针,当本机被选中从接收时调用函数:Twi_SlaveReceive
; static void (*Twi_SlaveReceive)(uint8 receiveDataLength, uint8* recieveData);
; // 指向发送处理函数的指针,当本机被选中从发送时调用函数:ITwi_SlaveTransmit
; static uint8 (*Twi_SlaveTransmit)(uint8 transmitDataLengthMax, uint8* transmitData);
;
;
;
; /*************************************************************************************
; **延时公式
; ** i*500-100 US (8>i>2)
; ** i*500 (255>i>8)
; ** i=1精确延时100us
; ** i=2 精确延时660US
; ** i=6 精确延时2.9ms
; ** i=10 精确延时5ms
; ** i=20 10ms
; ** i=100 50ms
; ** i=200 100ms
; ** i=255 128ms
; **************************************************************************************/
; void Delay(uint8 n)
; {
.dbline 94
; uint8 i;
; for(i=36;n!=0;n--)
ldi R20,36
xjmp L11
X0:
.dbline 95
; {
L12:
.dbline 96
L13:
.dbline 96
mov R24,R20
subi R24,1
mov R20,R24
tst R24
brne L12
.dbline 97
wdr
.dbline 98
L9:
.dbline 94
dec R16
L11:
.dbline 94
tst R16
brne L13
.dbline -2
L7:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r i 20 c
.dbsym r n 16 c
.dbend
.dbfunc e Twi_SetBitrate _Twi_SetBitrate fV
; bitrate_div -> R10
; bitrateKHz -> R10,R11
.even
_Twi_SetBitrate::
xcall push_gset3
movw R10,R16
.dbline -1
.dbline 111
; while(--i);
; WDR(); //喂狗;
; }
; }
; /*********************************************************************************************************
; ** 函数名称:Twi_SetBitrate
; ** 功能描述:设置TWI总线的速率
; ** 输 入: bitrateKHZ : 总线速率
; ** 输 出:
; ** 全局变量:
; ** 调用模块: 无
; ** 说明:
; ** 注意:
; ** 日 期: 2006年8月29日
; ********************************************************************************************************/
; void Twi_SetBitrate(uint16 bitrateKHz){
.dbline 113
; uint8 bitrate_div;
; WDR(); //喂狗;
wdr
.dbline 119
; // SCL freq = F_CPU/(16+2*TWBR))
; #ifdef TWPS0
; // 对于用速率分频的AVR (mega128)
; // SCL freq = F_CPU/(16+2*TWBR*4^TWPS)
; // set TWPS to zero
; TWSR&=~(1<<TWPS0);
cbi 0x1,0
.dbline 120
; TWSR&=~(1<<TWPS1);
cbi 0x1,1
.dbline 123
; #endif
; // 计算分频
; bitrate_div = ((F_CPU/1000)/bitrateKHz);
movw R2,R10
clr R4
clr R5
ldi R20,153
ldi R21,57
ldi R22,0
ldi R23,0
st -y,R5
st -y,R4
st -y,R3
st -y,R2
movw R16,R20
movw R18,R22
xcall div32s
mov R10,R16
.dbline 124
; if(bitrate_div >= 16)
mov R24,R10
cpi R16,16
brlo L16
.dbline 125
; bitrate_div = (bitrate_div-16)/2;
subi R24,16
mov R10,R24
lsr R10
L16:
.dbline 126
; TWBR = bitrate_div;
out 0x0,R10
.dbline -2
L15:
xcall pop_gset3
.dbline 0 ; func end
ret
.dbsym r bitrate_div 10 c
.dbsym r bitrateKHz 10 i
.dbend
.dbfunc e Twi_MasterSend _Twi_MasterSend fc
; result -> R20
; i -> R22
; data -> R10,R11
; length -> R12
; deviceAddr -> R14
.even
_Twi_MasterSend::
xcall push_gset5
mov R12,R18
mov R14,R16
ldd R10,y+10
ldd R11,y+11
.dbline -1
.dbline 143
; }
; /*********************************************************************************************************
; ** 函数名称:Twi_MasterSend
; ** 功能描述:主发送
; ** 输 入: deviceAddr:从机地址
; ** length:数据长度
; ** * data:发送缓冲区指针
; **
; ** 输 出: 发送的字节数
; ** 全局变量:
; ** 调用模块:
; ** 说明:
; ** 注意:
; ** 日 期: 2006年8月29日
; ********************************************************************************************************/
; uint8 Twi_MasterSend(uint8 deviceAddr, uint8 length, uint8* data)
; {
.dbline 144
; uint8 i,result=0;
clr R20
.dbline 145
; WDR(); //喂狗;
wdr
L19:
.dbline 147
L20:
.dbline 147
; // 等待总线准备完成
; while(Twi_State); //此处为独占TWI的信号量机制
lds R2,_Twi_State
tst R2
brne L19
.dbline 149
; // 设置状态
; Twi_State = TWI_MASTER_TX;
ldi R24,2
sts _Twi_State,R24
.dbline 151
; // 准备数据
; Twi_DeviceAddrRW = (deviceAddr & 0xFE); // RW 为0: 写操作
mov R24,R14
andi R24,254
sts _Twi_DeviceAddrRW,R24
.dbline 152
; if(Twi_SendBuffer.status==TWI_DATA_FREE)
lds R2,_Twi_SendBuffer+7
tst R2
brne L22
.dbline 153
; {
.dbline 154
; InitQueue(&Twi_SendBuffer); //清空上次发送的信息
ldi R16,<_Twi_SendBuffer
ldi R17,>_Twi_SendBuffer
xcall _InitQueue
.dbline 155
; Twi_SendBuffer.status=TWI_DATA_SEND;
ldi R24,2
sts _Twi_SendBuffer+7,R24
.dbline 156
; }
L22:
.dbline 157
; for(i=0; (i<length)&&(Twi_SendBuffer.errorcode!=QUEUE_OVERFLOW); i++)
clr R22
xjmp L29
L26:
.dbline 158
movw R30,R10
ld R18,Z+
movw R10,R30
ldi R16,<_Twi_SendBuffer
ldi R17,>_Twi_SendBuffer
xcall _EnQueue
L27:
.dbline 157
inc R22
L29:
.dbline 157
cp R22,R12
brsh L31
lds R24,_Twi_SendBuffer+6
cpi R24,1
brne L26
L31:
.dbline 159
; EnQueue(&Twi_SendBuffer,*data++);
; result=i;
mov R20,R22
.dbline 162
;
; // 发送开始条件
; Twi_Start();
in R24,0x36
andi R24,15
ori R24,160
out 0x36,R24
.dbline 163
; WDR(); //喂狗;
wdr
L32:
.dbline 164
L33:
.dbline 164
; while(Twi_State);
lds R2,_Twi_State
tst R2
brne L32
.dbline 165
; WDR(); //喂狗;
wdr
.dbline 166
; i=0;
clr R22
xjmp L36
L35:
.dbline 168
; while(((TwiErrorCode==TW_MT_SLA_NACK)||(TwiErrorCode==TW_MT_ARB_LOST)||(TwiErrorCode==TW_MT_DATA_NACK))&&i<TWI_FAIL_MAX) //器件不响应或总线仲裁失败
; {
.dbline 169
; i++;
inc R22
.dbline 170
; if((TwiErrorCode==TW_MT_DATA_NACK)&&(Twi_SendBuffer.count==0))
lds R24,_TwiErrorCode
cpi R24,48
brne L38
lds R2,_Twi_SendBuffer+2
tst R2
brne L38
.dbline 171
; {
.dbline 172
; break;
xjmp L37
L38:
.dbline 174
; }
; Delay(255);
ldi R16,255
xcall _Delay
.dbline 175
; Twi_State = TWI_MASTER_TX;
ldi R24,2
sts _Twi_State,R24
.dbline 176
; Twi_Start();
in R24,0x36
andi R24,15
ori R24,160
out 0x36,R24
.dbline 177
; WDR(); //喂狗;
wdr
L41:
.dbline 178
L42:
.dbline 178
lds R2,_Twi_State
tst R2
brne L41
.dbline 179
wdr
.dbline 180
L36:
.dbline 167
lds R24,_TwiErrorCode
cpi R24,32
breq L46
lds R24,_TwiErrorCode
cpi R24,56
breq L46
lds R24,_TwiErrorCode
cpi R24,48
brne L44
L46:
cpi R22,20
brlo L35
L44:
L37:
.dbline 181
; while(Twi_State);
; WDR(); //喂狗;
; }
; Twi_SendBuffer.status=TWI_DATA_FREE;
clr R2
sts _Twi_SendBuffer+7,R2
.dbline 182
; if(i>=TWI_FAIL_MAX)
cpi R22,20
brlo L48
.dbline 183
; {
.dbline 184
; return (FALSE);
clr R16
xjmp L18
L48:
.dbline 187
; }
; else
; {
.dbline 188
; return (result-Twi_SendBuffer.count);
lds R2,_Twi_SendBuffer+2
mov R16,R20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -