⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m16_twi_24cx.lst

📁 一个关于AVR单片机的例程
💻 LST
📖 第 1 页 / 共 3 页
字号:
__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 + -