📄 m16_twi_24cx.lst
字号:
__text_start:
__start:
002A E5CF LDI R28,0x5F
002B E0D4 LDI R29,4
002C BFCD OUT 0x3D,R28
002D BFDE OUT 0x3E,R29
002E 51C0 SUBI R28,0x10
002F 40D0 SBCI R29,0
0030 EA0A LDI R16,0xAA
0031 8308 STD Y+0,R16
0032 2400 CLR R0
0033 E6E0 LDI R30,0x60
0034 E0F0 LDI R31,0
0035 E011 LDI R17,1
0036 32E7 CPI R30,0x27
0037 07F1 CPC R31,R17
0038 F011 BEQ 0x003B
0039 9201 ST R0,Z+
003A CFFB RJMP 0x0036
003B 8300 STD Z+0,R16
003C E5E4 LDI R30,0x54
003D E0F0 LDI R31,0
003E E6A0 LDI R26,0x60
003F E0B0 LDI R27,0
0040 E010 LDI R17,0
0041 35E4 CPI R30,0x54
0042 07F1 CPC R31,R17
0043 F021 BEQ 0x0048
0044 95C8 LPM
0045 9631 ADIW R30,1
0046 920D ST R0,X+
0047 CFF9 RJMP 0x0041
0048 940E015D CALL _main
_exit:
004A CFFF RJMP _exit
_wt24c:
n --> R10
num --> R12
ad_dst --> R14
p_rsc --> Y+11
004B 940E021C CALL push_arg4
004D 940E0267 CALL push_gset5
004F 0179 MOVW R14,R18
0050 9721 SBIW R28,1
0051 84CF LDD R12,Y+15
0052 88D8 LDD R13,Y+16
FILE: E:\avr\m16_twi_24x\24Cxx.C
(0001) #include<iom16v.h>
(0002) #include<macros.h>
(0003) #include"xd.h"
(0004) #include"xdprj.h"
(0005)
(0006)
(0007)
(0008) //------在此设定芯片型号------
(0009) #define e2prom 1 // <---在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512
(0010)
(0011) #if e2prom==1
(0012) #define PAGE_SIZE 8
(0013) #define SIZE 0x007f
(0014) #elif e2prom==2
(0015) #define PAGE_SIZE 8
(0016) #define SIZE 0x00ff
(0017) #elif e2prom==4
(0018) #define PAGE_SIZE 16
(0019) #define SIZE 0x01ff
(0020) #elif e2prom==8
(0021) #define PAGE_SIZE 16
(0022) #define SIZE 0x03ff
(0023) #elif e2prom==16
(0024) #define PAGE_SIZE 16
(0025) #define SIZE 0x07ff
(0026) #elif e2prom==32
(0027) #define PAGE_SIZE 32
(0028) #define SIZE 0x0fff
(0029) #elif e2prom==64
(0030) #define PAGE_SIZE 32
(0031) #define SIZE 0x1fff
(0032) #elif e2prom==128
(0033) #define PAGE_SIZE 64
(0034) #define SIZE 0x3fff
(0035) #elif e2prom==256
(0036) #define PAGE_SIZE 64
(0037) #define SIZE 0x7fff
(0038) #elif e2prom==512
(0039) #define PAGE_SIZE 128
(0040) #define SIZE 0xffff
(0041) #endif
(0042) //--------------------------
(0043)
(0044) //--------在此设定芯片地址-------
(0045) #define W_ADD_COM 0xa0 //写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
(0046) #define R_ADD_COM 0xa1 //读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1
(0047) //-------------------------------
(0048)
(0049)
(0050)
(0051) #define SLAW 0x18 //SLA_W 已正常发送代码,判断器件是否正常应答的常量.
(0052)
(0053) //-----在此改变预置错误号-----
(0054) #define ERR_SLAW ERR_10 //写字节命令及器件地址错, 在此也就是读写器件错!!
(0055) //---------------------------
(0056)
(0057)
(0058)
(0059) //-----------4个I2总线公用函数, 可供其它I2总线器件的程序调用--------------
(0060) void i2cstart(void); //总线上起动开始条件
(0061) uchar i2cwt(uchar a); //把一个字节数据输入器件, 返回TWI状态
(0062) uchar i2crd(void); //i2c读要调用的函数
(0063) void i2cstop(void); //总线上起动停止条件
(0064) //------------------------------------------------------------------------
(0065)
(0066) uchar * wt24c_fc(uchar *p, uint ad, uchar n); //向24Cxx写入数据wt24c_h()所要调用的函数
(0067)
(0068) //向24Cxx写入数据
(0069) //参数: *p_rsc要输出数据的主机内存地址指针; ad_dst要写入数据的i2c的地址(双字节); num数据个数
(0070) //参数条件: ad_dst: ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
(0071) void wt24c(uchar *p_rsc, uint ad_dst, uint num)
(0072) { uint n;
(0073)
(0074) n=ad_dst/PAGE_SIZE; //确定地址与块地址的差
0053 0157 MOVW R10,R14
0054 94B6 LSR R11
0055 94A7 ROR R10
0056 94B6 LSR R11
0057 94A7 ROR R10
0058 94B6 LSR R11
0059 94A7 ROR R10
(0075) if(n) n=(ulong)PAGE_SIZE*(n+1)-ad_dst;
005A 20AA TST R10
005B F411 BNE 0x005E
005C 20BB TST R11
005D F0E1 BEQ 0x007A
005E 01C5 MOVW R24,R10
005F 9601 ADIW R24,1
0060 011C MOVW R2,R24
0061 2444 CLR R4
0062 2455 CLR R5
0063 E048 LDI R20,0x8
0064 E050 LDI R21,0
0065 E060 LDI R22,0
0066 E070 LDI R23,0
0067 925A ST R5,-Y
0068 924A ST R4,-Y
0069 923A ST R3,-Y
006A 922A ST R2,-Y
006B 018A MOVW R16,R20
006C 019B MOVW R18,R22
006D 940E0231 CALL empy32u
006F 0118 MOVW R2,R16
0070 0129 MOVW R4,R18
0071 0137 MOVW R6,R14
0072 2488 CLR R8
0073 2499 CLR R9
0074 1826 SUB R2,R6
0075 0837 SBC R3,R7
0076 0848 SBC R4,R8
0077 0859 SBC R5,R9
0078 0151 MOVW R10,R2
0079 C005 RJMP 0x007F
(0076) else n=PAGE_SIZE-ad_dst;
007A E088 LDI R24,0x8
007B E090 LDI R25,0
007C 015C MOVW R10,R24
007D 18AE SUB R10,R14
007E 08BF SBC R11,R15
(0077)
(0078) if(n>=num) //如果ad_dst所在的数据块的末尾地址 >= ad_dst + num, 就直接写入num个数据
007F 14AC CP R10,R12
0080 04BD CPC R11,R13
0081 F058 BCS 0x008D
(0079) { wt24c_fc(p_rsc, ad_dst, num);
0082 82C8 STD Y+0,R12
0083 0197 MOVW R18,R14
0084 850B LDD R16,Y+11
0085 851C LDD R17,Y+12
0086 D066 RCALL _wt24c_fc
(0080) if(syserr!=0) return;
0087 90200126 LDS R2,syserr
0089 2022 TST R2
008A F409 BNE 0x008C
008B C032 RJMP 0x00BE
008C C031 RJMP 0x00BE
(0081) }
(0082) else //如果ad_dst所在的数据块末尾地址 < ad_dst + num, 就先写入ad_dst所在的数据块末尾地址与 ad_dst 之差个数据
(0083) { p_rsc=wt24c_fc(p_rsc, ad_dst, n);
008D 82A8 STD Y+0,R10
008E 0197 MOVW R18,R14
008F 850B LDD R16,Y+11
0090 851C LDD R17,Y+12
0091 D05B RCALL _wt24c_fc
0092 871C STD Y+12,R17
0093 870B STD Y+11,R16
(0084) if(syserr!=0) return;
0094 90200126 LDS R2,syserr
0096 2022 TST R2
0097 F009 BEQ 0x0099
0098 C025 RJMP 0x00BE
(0085)
(0086) num-=n; //更新剩下数据个数
0099 18CA SUB R12,R10
009A 08DB SBC R13,R11
(0087) ad_dst+=n; //更新剩下数据的起始地址
009B 0CEA ADD R14,R10
009C 1CFB ADC R15,R11
009D C013 RJMP 0x00B1
(0088)
(0089) //把剩下数据写入器件
(0090) while(num>=PAGE_SIZE) //先按PAGE_SIZE为长度一页一页的写入
(0091) { p_rsc=wt24c_fc(p_rsc, ad_dst, PAGE_SIZE);
009E E088 LDI R24,0x8
009F 8388 STD Y+0,R24
00A0 0197 MOVW R18,R14
00A1 850B LDD R16,Y+11
00A2 851C LDD R17,Y+12
00A3 D049 RCALL _wt24c_fc
00A4 871C STD Y+12,R17
00A5 870B STD Y+11,R16
(0092) if(syserr!=0) return;
00A6 90200126 LDS R2,syserr
00A8 2022 TST R2
00A9 F009 BEQ 0x00AB
00AA C013 RJMP 0x00BE
(0093)
(0094) num-=PAGE_SIZE; //更新剩余数据个数
00AB 01C6 MOVW R24,R12
00AC 9708 SBIW R24,0x8
00AD 016C MOVW R12,R24
(0095) ad_dst+=PAGE_SIZE; //更新剩下数据的起始地址
00AE 01C7 MOVW R24,R14
00AF 9608 ADIW R24,0x8
00B0 017C MOVW R14,R24
00B1 01C6 MOVW R24,R12
00B2 3088 CPI R24,0x8
00B3 E0E0 LDI R30,0
00B4 079E CPC R25,R30
00B5 F740 BCC 0x009E
(0096) }
(0097)
(0098) if(num) //把最后剩下的小于一个PAGE_SIZE长度的数据写入器件
00B6 3080 CPI R24,0
00B7 0789 CPC R24,R25
00B8 F029 BEQ 0x00BE
(0099) wt24c_fc(p_rsc, ad_dst, num);
00B9 82C8 STD Y+0,R12
00BA 0197 MOVW R18,R14
00BB 850B LDD R16,Y+11
00BC 851C LDD R17,Y+12
00BD D02F RCALL _wt24c_fc
(0100) }
00BE 9621 ADIW R28,1
00BF 940E0264 CALL pop_gset5
00C1 9624 ADIW R28,4
00C2 9508 RET
_rd24c:
t --> R10
num --> R22
ad_rsc --> R12
p_dst --> R20
00C3 940E0269 CALL push_gset4
00C5 0169 MOVW R12,R18
00C6 01A8 MOVW R20,R16
00C7 8568 LDD R22,Y+8
00C8 8579 LDD R23,Y+9
(0101) }
(0102)
(0103)
(0104) //从24cxx读出数据
(0105) //参数: *p_dst要读入数据的主机内存地址指针; ad_rsc要输出数据的i2c的地址(整形); num数据个数(整形)
(0106) //参数条件: ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
(0107) void rd24c(uchar *p_dst, uint ad_rsc, uint num)
(0108) { uchar t=0;
00C9 24AA CLR R10
(0109)
(0110) #if e2prom<32
(0111) t=ad_rsc>>8;
00CA 0156 MOVW R10,R12
00CB 2CAB MOV R10,R11
00CC 24BB CLR R11
(0112) t<<=1;
00CD 0CAA LSL R10
(0113) #endif
(0114)
(0115) i2cstart(); //发送起始信号
00CE D045 RCALL _i2cstart
(0116)
(0117) if(i2cwt(W_ADD_COM+t)==SLAW)//发送SLA_W, 写字节命令及器件地址
00CF 2D0A MOV R16,R10
00D0 5600 SUBI R16,0x60
00D1 D048 RCALL _i2cwt
00D2 3108 CPI R16,0x18
00D3 F491 BNE 0x00E6
(0118) {
(0119) #if e2prom>16
(0120) i2cwt(ad_rsc>>8); //ad_rsc的高位, 发送要读出数据的地址
(0121) #endif
(0122) i2cwt(ad_rsc); //ad_rsc的低位
00D4 2D0C MOV R16,R12
00D5 D044 RCALL _i2cwt
(0123)
(0124) i2cstart(); //再发送起始信号
00D6 D03D RCALL _i2cstart
(0125) i2cwt(R_ADD_COM+t); //发送SLA_R, 读命令字节及器件地址
00D7 2D0A MOV R16,R10
00D8 550F SUBI R16,0x5F
00D9 D040 RCALL _i2cwt
(0126)
(0127) for(;num>0;num--)
00DA C007 RJMP 0x00E2
(0128) { *p_dst=i2crd(); //从器件读出一个字节
00DB D048 RCALL _i2crd
00DC 01FA MOVW R30,R20
00DD 8300 STD Z+0,R16
(0129) p_dst++;
00DE 5F4F SUBI R20,0xFF
00DF 4F5F SBCI R21,0xFF
00E0 5061 SUBI R22,1
00E1 4070 SBCI R23,0
00E2 3060 CPI R22,0
00E3 0767 CPC R22,R23
00E4 F7B1 BNE 0x00DB
(0130) }
(0131) }
00E5 C003 RJMP 0x00E9
(0132) else syserr=ERR_SLAW; //写字节命令及器件地址错或对方无应答
00E6 E08A LDI R24,0xA
00E7 93800126 STS syserr,R24
(0133)
(0134) i2cstop();
00E9 D041 RCALL _i2cstop
00EA 940E0261 CALL pop_gset4
00EC 9508 RET
_wt24c_fc:
t --> R12
n --> R22
ad --> R10
p --> R20
00ED 940E0269 CALL push_gset4
00EF 0159 MOVW R10,R18
00F0 01A8 MOVW R20,R16
00F1 8568 LDD R22,Y+8
(0135)
(0136) }
(0137)
(0138)
(0139)
(0140) //向24Cxx写入数据wt24c_h()所要调用的函数
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -