📄 mt.lst
字号:
__text_start:
__start:
0019 E5CF LDI R28,0x5F
001A E0D4 LDI R29,4
001B BFCD OUT 0x3D,R28
001C BFDE OUT 0x3E,R29
001D 51C0 SUBI R28,0x10
001E 40D0 SBCI R29,0
001F EA0A LDI R16,0xAA
0020 8308 STD Y+0,R16
0021 2400 CLR R0
0022 E6EC LDI R30,0x6C
0023 E0F0 LDI R31,0
0024 E010 LDI R17,0
0025 36ED CPI R30,0x6D
0026 07F1 CPC R31,R17
0027 F011 BEQ 0x002A
0028 9201 ST R0,Z+
0029 CFFB RJMP 0x0025
002A 8300 STD Z+0,R16
002B E2E6 LDI R30,0x26
002C E0F0 LDI R31,0
002D E6A0 LDI R26,0x60
002E E0B0 LDI R27,0
002F E010 LDI R17,0
0030 33E2 CPI R30,0x32
0031 07F1 CPC R31,R17
0032 F021 BEQ 0x0037
0033 95C8 LPM
0034 9631 ADIW R30,1
0035 920D ST R0,X+
0036 CFF9 RJMP 0x0030
0037 D225 RCALL _main
_exit:
0038 CFFF RJMP _exit
FILE: E:\iccavr\无线+I2C\test1--mt\twi.c
(0001)
(0002) /*函数的使用说明:
(0003) 1.该twi模块包含四种工作模式,主发,主收,从收,从发,其中主发由
(0004) twiWriteByte(从机地址,要发送的数据)实现,主收由twiReadByte(从机地址)实现,从机
(0005) 的发送与接收均通过中断实现
(0006) 2.在从机模式下,需调用twi_init()来使能并初始化twi总线
(0007) 3.在主机模式下,调用twiWriteByte(从机地址,要发送的数据)向指定的从机写入数据,
(0008) 调用twiReadByte(从机地址)从指定的从机读取数据,然后可通过查询错误状态error_state
(0009) 的值决定下一步如何操作。
(0010) */
(0011)
(0012) //************************* 头文件 ******************************************
(0013) #include "twi.h"
(0014)
(0015) //TWI同程序的接口参数
(0016) //receive_data,error_state不用设置
(0017) extern char receive_data; // 接收到的数据
(0018) extern char error_state; // twi错误状态
(0019) //以下三个参数根据需求进行设置
(0020) extern char slave_address; // 设置从机地址,Bits 7..1:存放从机地址,Bit 0:最低位为广播识别使能位
(0021) extern char bit_race; // 设置主机模式的比特率,SCL=CPU频率/(16+2*(TWBR)*4TWPS),TWPS在4的指数位置
(0022) extern char send_data; // 从机发送模式下从机向主机发送的数据
(0023)
(0024) //*************************** twi错误状态说明*********************************
(0025) // 0:twi传送无错误
(0026) // 1:在主发模式下,SLA+W已发送,返回NOT ACK
(0027) // 2:在主发模式下,DATA已发送,返回NOT ACK
(0028) // 3:在主发模式下,SLA+W或者数据的仲裁失败
(0029) // 4:在主收模式下,SLA+R或者数据的仲裁失败
(0030) // 5:在主收模式下,SLA+R已发送,返回NOT ACK
(0031) // 6:在主发模式下,START信号发送不成功
(0032) // 7:在主收模式下,START信号发送不成功
(0033) // 8:在主收模式下,数据接受完成
(0034) // 9:在主收模式下,数据接受不成功
(0035) //*****************************************************************************
(0036)
(0037) //*************************** twi stop 信号延时时间 ****************************
(0038) //******************************************************************************
(0039) void StopDelay(void)
(0040) {
(0041) unsigned int i;
(0042) for(i = 0;i < 20;i ++);
_StopDelay:
i --> R16
0039 2700 CLR R16
003A 2711 CLR R17
003B C002 RJMP 0x003E
003C 5F0F SUBI R16,0xFF
003D 4F1F SBCI R17,0xFF
003E 3104 CPI R16,0x14
003F E0E0 LDI R30,0
0040 071E CPC R17,R30
0041 F3D0 BCS 0x003C
(0043) }
0042 9508 RET
(0044) //******************************* twi 启动总线*********************************
(0045) //******************************************************************************
(0046) void start(void)
(0047) {
(0048) TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); //发出start信号
_start:
0043 EA84 LDI R24,0xA4
0044 BF86 OUT 0x36,R24
(0049) _NOP();
0045 0000 NOP
(0050) _NOP();
0046 0000 NOP
(0051) }
0047 9508 RET
(0052) //************************** twi 释放总线************************************
(0053) //***************************************************************************
(0054) void stop(void)
(0055) {
(0056) TWCR = (1 << TWINT) |(1 << TWEN)|(1 << TWSTO); //发出stop信号
_stop:
0048 E984 LDI R24,0x94
0049 BF86 OUT 0x36,R24
(0057) StopDelay(); //等待总线恢复
004A DFEE RCALL _StopDelay
(0058) TWCR= 0x45;
004B E485 LDI R24,0x45
004C BF86 OUT 0x36,R24
(0059) }
004D 9508 RET
(0060) //****************************** twi 初始化*************************************
(0061) // TWCR: 控制寄存器,用来控制TWI操作,说明如下:
(0062) // Bit 7-TWINT:中断标志位,Bit 6-TWEA:使能应答位,Bit 5-TWSTA:START状态位
(0063) // Bit 4-TWSTO:STOP状态位,Bit 3-TWWC: 写冲突标志,Bit 2-TWEN:TWI使能位
(0064) // Bit 1-RES:保留,Bit 0-TWIE:中断使能
(0065) // TWSR: 状态寄存器,Bits 7..3:表示了TWI总线的当前状态,读取时需屏蔽低三位的值,Bits 1..0-TWPS:TWI预分频位
(0066) // TWBR: 比特率寄存器,用来设置TWI的工作频率,计算公式为:SCL=CPU频率/(16+2*(TWBR)*4TWPS),TWPS在4的指数位置
(0067) // TWAR: 从机地址寄存器,Bits 7..1:存放从机地址,Bit 0:最低位为广播识别使能位
(0068) // TWDR: 数据寄存器,用来存放接收或要发送的地址和数据
(0069) //******************************************************************************
(0070) void twi_init(void)
(0071) {
(0072) TWCR= 0x00; //disable twi
_twi_init:
004E 2422 CLR R2
004F BE26 OUT 0x36,R2
(0073) TWBR= bit_race; //set bit rate
0050 90200063 LDS R2,0x63
0052 B820 OUT 0x00,R2
(0074) TWSR= 0x00; //set prescale为1
0053 2422 CLR R2
0054 B821 OUT 0x01,R2
(0075) TWAR= slave_address; //set slave address
0055 90200062 LDS R2,0x62
0057 B822 OUT 0x02,R2
(0076) TWCR= 0x45; //enable twi
0058 E485 LDI R24,0x45
0059 BF86 OUT 0x36,R24
(0077) }
005A 9508 RET
(0078) //************************** 检测发送时的状态码 ****************************
(0079) //**************************************************************************
(0080) void checkstate(void)
(0081) {
(0082) unsigned char TWSR_state;
(0083) TWSR_state = TWSR & 0xf8; //屏蔽第三位读取状态
_checkstate:
TWSR_state --> R16
005B B101 IN R16,0x01
005C 7F08 ANDI R16,0xF8
(0084) switch(TWSR_state)
005D 2711 CLR R17
005E 3200 CPI R16,0x20
005F E0E0 LDI R30,0
0060 071E CPC R17,R30
0061 F169 BEQ 0x008F
0062 E280 LDI R24,0x20
0063 E090 LDI R25,0
0064 1780 CP R24,R16
0065 0791 CPC R25,R17
0066 F06C BLT 0x0074
0067 3008 CPI R16,0x8
0068 E0E0 LDI R30,0
0069 071E CPC R17,R30
006A F0E1 BEQ 0x0087
006B 3008 CPI R16,0x8
006C E0E0 LDI R30,0
006D 071E CPC R17,R30
006E F17C BLT 0x009E
006F 3108 CPI R16,0x18
0070 E0E0 LDI R30,0
0071 071E CPC R17,R30
0072 F0C1 BEQ 0x008B
0073 C02A RJMP 0x009E
0074 3300 CPI R16,0x30
0075 E0E0 LDI R30,0
0076 071E CPC R17,R30
0077 F0F9 BEQ 0x0097
0078 E380 LDI R24,0x30
0079 E090 LDI R25,0
007A 1780 CP R24,R16
007B 0791 CPC R25,R17
007C F02C BLT 0x0082
007D 3208 CPI R16,0x28
007E E0E0 LDI R30,0
007F 071E CPC R17,R30
0080 F091 BEQ 0x0093
0081 C01C RJMP 0x009E
0082 3308 CPI R16,0x38
0083 E0E0 LDI R30,0
0084 071E CPC R17,R30
0085 F0A9 BEQ 0x009B
0086 C017 RJMP 0x009E
(0085) {
(0086) case 0x08:error_state=0;break; // START已发送
0087 2422 CLR R2
0088 92200061 STS 0x61,R2
008A C013 RJMP 0x009E
(0087) case 0x18:error_state=0;break; // SLA+W已发送,接收到ACK
008B 2422 CLR R2
008C 92200061 STS 0x61,R2
008E C00F RJMP 0x009E
(0088) case 0x20:error_state=1;break; // SLA+W已发送,接收到NOT ACK
008F E081 LDI R24,1
0090 93800061 STS 0x61,R24
0092 C00B RJMP 0x009E
(0089) case 0x28:error_state=0;break; // 数据已发送,接收到ACK
0093 2422 CLR R2
0094 92200061 STS 0x61,R2
0096 C007 RJMP 0x009E
(0090) case 0x30:error_state=2;break; // 数据已发送,接收到NOT ACK
0097 E082 LDI R24,2
0098 93800061 STS 0x61,R24
009A C003 RJMP 0x009E
(0091) case 0x38:error_state=3;break; // SLA+W或数据的仲裁失败
009B E083 LDI R24,3
009C 93800061 STS 0x61,R24
(0092) default: break;
(0093) }
(0094) TWCR=0x45;
009E E485 LDI R24,0x45
009F BF86 OUT 0x36,R24
(0095) }
00A0 9508 RET
_twiWriteByte:
i --> R12
TWCR_state --> R20
data --> R22
WriteAddress --> R10
00A1 D1FB RCALL push_gset4
00A2 2F62 MOV R22,R18
00A3 2EA0 MOV R10,R16
(0096) //********** twi主机发送,向地址为WriteAddress的从机发送1个字节数据************
(0097) // 入口参数1:WriteAddress:从机地址
(0098) // TWDR中存放的高七位为地址,最低位表示读写控制,0为写,1为读
(0099) // 入口参数2:data,向从机写的数据
(0100) //******************************************************************************
(0101) void twiWriteByte(unsigned char WriteAddress,char data)
(0102) {
(0103) unsigned char TWCR_state;
(0104) char i=0;
00A4 24CC CLR R12
(0105) error_state=0;
00A5 2422 CLR R2
00A6 92200061 STS 0x61,R2
(0106)
(0107) //初始化 twi
(0108) twi_init();
00A8 DFA5 RCALL _twi_init
(0109)
(0110) //发送START信号
(0111) start();
00A9 DF99 RCALL _start
(0112) TWCR_state = TWCR & 0x80;
00AA B746 IN R20,0x36
00AB 7840 ANDI R20,0x80
00AC C00A RJMP 0x00B7
(0113) while((TWCR_state == 0x00))
(0114) {
(0115) i++;
00AD 94C3 INC R12
(0116) if(i>=10){error_state=6;break;}
00AE 2D8C MOV R24,R12
00AF 308A CPI R24,0xA
00B0 F020 BCS 0x00B5
00B1 E086 LDI R24,6
00B2 93800061 STS 0x61,R24
00B4 C004 RJMP 0x00B9
(0117) TWCR_state = TWCR & 0x80; //轮循等待START信号发送完成
00B5 B746 IN R20,0x36
00B6 7840 ANDI R20,0x80
00B7 2344 TST R20
00B8 F3A1 BEQ 0x00AD
(0118) }
(0119)
(0120) //若START发送成功,发送从机地址
(0121) if(error_state==0)
00B9 90200061 LDS R2,0x61
00BB 2022 TST R2
00BC F469 BNE 0x00CA
(0122) {
(0123) TWDR = WriteAddress; //发地址
00BD B8A3 OUT 0x03,R10
(0124) _NOP();
00BE 0000 NOP
(0125) _NOP();
00BF 0000 NOP
(0126)
(0127) TWCR = (1 << TWINT) | (1 << TWEN);
00C0 E884 LDI R24,0x84
00C1 BF86 OUT 0x36,R24
(0128) TWCR_state = TWCR & 0x80;
00C2 B746 IN R20,0x36
00C3 7840 ANDI R20,0x80
00C4 C002 RJMP 0x00C7
(0129) while(TWCR_state == 0x00)
(0130) {TWCR_state = TWCR & 0x80;} //轮循查询地址是否发送
00C5 B746 IN R20,0x36
00C6 7840 ANDI R20,0x80
00C7 2344 TST R20
00C8 F3E1 BEQ 0x00C5
(0131) checkstate();
00C9 DF91 RCALL _checkstate
(0132) }
(0133)
(0134) //若从机地址发送成功,向从机发送数据
(0135) if(error_state==0)
00CA 90200061 LDS R2,0x61
00CC 2022 TST R2
00CD F469 BNE 0x00DB
(0136) {
(0137) TWDR = data; //发数据
00CE B963 OUT 0x03,R22
(0138) _NOP();
00CF 0000 NOP
(0139) _NOP();
00D0 0000 NOP
(0140) TWCR = (1 << TWINT) | (1 << TWEN);
00D1 E884 LDI R24,0x84
00D2 BF86 OUT 0x36,R24
(0141) TWCR_state = TWCR & 0x80;
00D3 B746 IN R20,0x36
00D4 7840 ANDI R20,0x80
00D5 C002 RJMP 0x00D8
(0142) while(TWCR_state == 0x00) TWCR_state = TWCR & 0x80; //轮循查询数据是否发送
00D6 B746 IN R20,0x36
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -