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

📄 24cxx.s

📁 EEPROM读写程序: 先向EEPROM写入一幅图片数据
💻 S
字号:
	.module _24Cxx.C
	.area text(rom, con, rel)
	.dbfile E:\学习专区\AVR专区\个人创作区\AVR单片机开发平台\EEPROM读写演示程序\24Cxx.C
	.dbfunc e delay_EEPROM _delay_EEPROM fV
;              a -> R20,R21
;              b -> R22,R23
;              n -> R16
	.even
_delay_EEPROM::
	xcall push_gset2
	.dbline -1
	.dbline 12
; /**************************************************
;           EEPROM读写操作
; 		  晶振:内部   8M
; ***************************************************/
; #include<iom16v.h>
; #include<macros.h>
; #define uchar unsigned char 
; #define uint unsigned int 
; #define ulong unsigned long 
; uchar syserr;
; void delay_EEPROM(uchar n)   //延时
; {
	.dbline 14
;  	 unsigned int a,b;
; 	 for(a=0;a<n;a++)
	clr R20
	clr R21
	xjmp L5
L2:
	.dbline 15
; 	 for(b=0;b<100;b++)
	clr R22
	clr R23
	xjmp L9
L6:
	.dbline 16
L7:
	.dbline 15
	subi R22,255  ; offset = 1
	sbci R23,255
L9:
	.dbline 15
	cpi R22,100
	ldi R30,0
	cpc R23,R30
	brlo L6
L3:
	.dbline 14
	subi R20,255  ; offset = 1
	sbci R21,255
L5:
	.dbline 14
	mov R2,R16
	clr R3
	cp R20,R2
	cpc R21,R3
	brlo L2
	.dbline -2
L1:
	xcall pop_gset2
	.dbline 0 ; func end
	ret
	.dbsym r a 20 i
	.dbsym r b 22 i
	.dbsym r n 16 c
	.dbend
	.dbfunc e wt24c _wt24c fV
;              n -> R10,R11
;            num -> R12,R13
;         ad_dst -> R14,R15
;          p_rsc -> y+11
	.even
_wt24c::
	xcall push_arg4
	xcall push_gset5
	movw R14,R18
	sbiw R28,1
	ldd R12,y+15
	ldd R13,y+16
	.dbline -1
	.dbline 82
; 	 ;
; }
; //------在此设定芯片型号------
; #define e2prom 256	// <---在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512
; 
; #if e2prom==1
; 	#define PAGE_SIZE 8
; 	#define SIZE 0x007f
; #elif e2prom==2
; 	#define PAGE_SIZE 8
; 	#define SIZE 0x00ff
; #elif e2prom==4
; 	#define PAGE_SIZE 16
; 	#define SIZE 0x01ff
; #elif e2prom==8
; 	#define PAGE_SIZE 16
; 	#define SIZE 0x03ff
; #elif e2prom==16
; 	#define PAGE_SIZE 16
; 	#define SIZE 0x07ff
; #elif e2prom==32
; 	#define PAGE_SIZE 32
; 	#define SIZE 0x0fff
; #elif e2prom==64
; 	#define PAGE_SIZE 32
; 	#define SIZE 0x1fff
; #elif e2prom==128
; 	#define PAGE_SIZE 64
; 	#define SIZE 0x3fff
; #elif e2prom==256
; 	#define PAGE_SIZE 64
; 	#define SIZE 0x7fff
; #elif e2prom==512
; 	#define PAGE_SIZE 128
; 	#define SIZE 0xffff
; #endif
; //--------------------------
; 
; //--------在此设定芯片地址-------
; #define W_ADD_COM 0xa0	//写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
; #define R_ADD_COM 0xa1	//读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1
; //-------------------------------
; 
; 
; 
; #define SLAW	0x18	//SLA_W 已正常发送代码,判断器件是否正常应答的常量.
; 
; //-----在此改变预置错误号-----
; #define ERR_SLAW	10//写字节命令及器件地址错, 在此也就是读写器件错!!
; //---------------------------
; 
; 
; 
; //-----------4个I2总线公用函数, 可供其它I2总线器件的程序调用--------------
; void i2cstart(void);	//总线上起动开始条件
; uchar i2cwt(uchar a);	//把一个字节数据输入器件, 返回TWI状态
; uchar i2crd(void);		//i2c读要调用的函数
; void i2cstop(void);		//总线上起动停止条件 
; //------------------------------------------------------------------------
; 
; uchar * wt24c_fc(uchar *p, uint ad, uchar n);	//向24Cxx写入数据wt24c_h()所要调用的函数
; 
; //向24Cxx写入数据
; //参数: *p_rsc要输出数据的主机内存地址指针; ad_dst要写入数据的i2c的地址(双字节); num数据个数
; //参数条件: ad_dst: ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
; void wt24c(uchar *p_rsc, uint ad_dst, uint num)
; {   uint n;
	.dbline 84
; 
;     n=ad_dst/PAGE_SIZE;		//确定地址与块地址的差
	ldi R18,6
	ldi R19,0
	movw R16,R14
	xcall lsr16
	movw R10,R16
	.dbline 85
; 	if(n) 
	cpi R16,0
	cpc R16,R17
	breq L11
X0:
	.dbline 86
; 	n=(ulong)PAGE_SIZE*(n+1)-ad_dst;	
	movw R24,R10
	adiw R24,1
	movw R2,R24
	clr R4
	clr R5
	ldi R20,64
	ldi R21,0
	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 empy32u
	movw R2,R16
	movw R4,R18
	movw R6,R14
	clr R8
	clr R9
	sub R2,R6
	sbc R3,R7
	sbc R4,R8
	sbc R5,R9
	movw R10,R2
	xjmp L12
L11:
	.dbline 88
; 	else
; 	 n=PAGE_SIZE-ad_dst;
	ldi R24,64
	ldi R25,0
	movw R10,R24
	sub R10,R14
	sbc R11,R15
L12:
	.dbline 90
; 		
;     if(n>=num)		//如果ad_dst所在的数据块的末尾地址 >= ad_dst + num, 就直接写入num个数据
	cp R10,R12
	cpc R11,R13
	brlo L13
	.dbline 91
;     {	
	.dbline 92
; 		wt24c_fc(p_rsc, ad_dst, num);
	std y+0,R12
	movw R18,R14
	ldd R16,y+11
	ldd R17,y+12
	xcall _wt24c_fc
	.dbline 93
;     	if(syserr!=0) 
	lds R2,_syserr
	tst R2
	brne X3
	xjmp L14
X3:
	.dbline 94
; 		return;
	xjmp L10
X1:
	.dbline 95
;     }
L13:
	.dbline 97
;     else			//如果ad_dst所在的数据块末尾地址 < ad_dst + num, 就先写入ad_dst所在的数据块末尾地址与 ad_dst 之差个数据
;     {   
	.dbline 98
; 	p_rsc=wt24c_fc(p_rsc, ad_dst, n);
	std y+0,R10
	movw R18,R14
	ldd R16,y+11
	ldd R17,y+12
	xcall _wt24c_fc
	std y+12,R17
	std y+11,R16
	.dbline 99
;     	if(syserr!=0) 
	lds R2,_syserr
	tst R2
	breq L17
	.dbline 100
; 		return;
	xjmp L10
L17:
	.dbline 102
; 		
; 		num-=n;     //更新剩下数据个数
	sub R12,R10
	sbc R13,R11
	.dbline 103
;         ad_dst+=n;	//更新剩下数据的起始地址
	add R14,R10
	adc R15,R11
	xjmp L20
L19:
	.dbline 107
; 
;         //把剩下数据写入器件
;         while(num>=PAGE_SIZE)	//先按PAGE_SIZE为长度一页一页的写入
;         {	p_rsc=wt24c_fc(p_rsc, ad_dst, PAGE_SIZE);
	.dbline 107
	ldi R24,64
	std y+0,R24
	movw R18,R14
	ldd R16,y+11
	ldd R17,y+12
	xcall _wt24c_fc
	std y+12,R17
	std y+11,R16
	.dbline 108
;         	if(syserr!=0) return;
	lds R2,_syserr
	tst R2
	breq L22
	.dbline 108
	xjmp L10
L22:
	.dbline 110
	movw R24,R12
	subi R24,64
	sbci R25,0
	movw R12,R24
	.dbline 111
	movw R24,R14
	subi R24,192  ; offset = 64
	sbci R25,255
	movw R14,R24
	.dbline 112
L20:
	.dbline 106
	movw R24,R12
	cpi R24,64
	ldi R30,0
	cpc R25,R30
	brsh L19
	.dbline 114
;         	
;             num-=PAGE_SIZE;		//更新剩余数据个数
;         	ad_dst+=PAGE_SIZE;	//更新剩下数据的起始地址
; 		}
;         
; 		if(num)			//把最后剩下的小于一个PAGE_SIZE长度的数据写入器件
	cpi R24,0
	cpc R24,R25
	breq L24
X2:
	.dbline 115
; 			wt24c_fc(p_rsc, ad_dst, num);
	std y+0,R12
	movw R18,R14
	ldd R16,y+11
	ldd R17,y+12
	xcall _wt24c_fc
L24:
	.dbline 116
L14:
	.dbline -2
L10:
	adiw R28,1
	xcall pop_gset5
	adiw R28,4
	.dbline 0 ; func end
	ret
	.dbsym r n 10 i
	.dbsym r num 12 i
	.dbsym r ad_dst 14 i
	.dbsym l p_rsc 11 pc
	.dbend
	.dbfunc e port_init _port_init fV
	.even
_port_init::
	.dbline -1
	.dbline 124
;     }
; }
; 
; 
; //从24cxx读出数据
; //参数: *p_dst要读入数据的主机内存地址指针; ad_rsc要输出数据的i2c的地址(整形); num数据个数(整形)
; //参数条件:  ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
; void port_init(void)
; {
	.dbline 126
; 
;  	 PORTC = 0xFF; 
	ldi R24,255
	out 0x15,R24
	.dbline 127
; 	 DDRC &= 0xfc;
	in R24,0x14
	andi R24,252
	out 0x14,R24
	.dbline -2
L26:
	.dbline 0 ; func end
	ret
	.dbend
	.dbfunc e twi_init _twi_init fV
	.even
_twi_init::
	.dbline -1
	.dbline 132
; }
; //TWI initialize
; // bit rate:100
; void twi_init(void)
; {
	.dbline 133
;  	 TWCR= 0x00; //disable twi
	clr R2
	out 0x36,R2
	.dbline 134
; 	 TWBR= 0x20; //set bit rate
	ldi R24,32
	out 0x0,R24
	.dbline 135
; 	 TWSR= 0x00; //set prescale
	out 0x1,R2
	.dbline 136
; 	 TWAR= 0x00; //set slave address
	out 0x2,R2
	.dbline 137
; 	 TWCR= 0x04; //enable twi
	ldi R24,4
	out 0x36,R24
	.dbline -2
L27:
	.dbline 0 ; func end
	ret
	.dbend
	.dbfunc e rd24c _rd24c fV
;              t -> R10
;            num -> R22,R23
;         ad_rsc -> R12,R13
;          p_dst -> R20,R21
	.even
_rd24c::
	xcall push_gset4
	movw R12,R18
	movw R20,R16
	ldd R22,y+8
	ldd R23,y+9
	.dbline -1
	.dbline 140
; }
; void rd24c(uchar *p_dst, uint ad_rsc, uint num)
; {   
	.dbline 141
; 	uchar t=0;
	clr R10
	.dbline 146
; 	#if e2prom<32
; 	t=ad_rsc>>8;
; 	t<<=1;
; 	#endif
; 	i2cstart();					//发送起始信号
	xcall _i2cstart
	.dbline 147
; 	if(i2cwt(W_ADD_COM+t)==SLAW)//发送SLA_W, 写字节命令及器件地址
	mov R16,R10
	subi R16,96    ; addi 160
	xcall _i2cwt
	cpi R16,24
	brne L29
	.dbline 148
; 	{	
	.dbline 150
; 		#if e2prom>=32
; 		i2cwt(ad_rsc>>8);		//ad_rsc的高位,  发送要读出数据的地址
	movw R16,R12
	mov R16,R17
	clr R17
	xcall _i2cwt
	.dbline 152
; 		#endif
; 		i2cwt(ad_rsc);			//ad_rsc的低位
	mov R16,R12
	xcall _i2cwt
	.dbline 154
; 				
; 		i2cstart();				//再发送起始信号
	xcall _i2cstart
	.dbline 155
; 		i2cwt(R_ADD_COM+t);		//发送SLA_R, 读命令字节及器件地址
	mov R16,R10
	subi R16,95    ; addi 161
	xcall _i2cwt
	.dbline 157
; 				
; 		for(;num>0;num--)
	xjmp L34
L31:
	.dbline 158
	.dbline 159
	xcall _i2crd
	movw R30,R20
	std z+0,R16
	.dbline 160
	subi R20,255  ; offset = 1
	sbci R21,255
	.dbline 161
L32:
	.dbline 157
	subi R22,1
	sbci R23,0
L34:
	.dbline 157
	cpi R22,0
	cpc R22,R23
	brne L31
X4:
	.dbline 162
; 		{  
; 		 *p_dst=i2crd();		//从器件读出一个字节
; 			p_dst++;
; 		}
; 	}
	xjmp L30
L29:
	.dbline 164
; 	else 
; 	syserr=ERR_SLAW;		//写字节命令及器件地址错或对方无应答
	ldi R24,10
	sts _syserr,R24
L30:
	.dbline 166
; 		
; 	i2cstop();
	xcall _i2cstop
	.dbline -2
L28:
	xcall pop_gset4
	.dbline 0 ; func end
	ret
	.dbsym r t 10 c
	.dbsym r num 22 i
	.dbsym r ad_rsc 12 i
	.dbsym r p_dst 20 pc
	.dbend
	.dbfunc e wt24c_fc _wt24c_fc fpc
;              t -> R12
;              n -> R22
;             ad -> R10,R11
;              p -> R20,R21
	.even
_wt24c_fc::
	xcall push_gset4
	movw R10,R18
	movw R20,R16
	ldd R22,y+8
	.dbline -1
	.dbline 173
; 
; }
; //向24Cxx写入数据wt24c_h()所要调用的函数
; //返回写入n个字节后的主机内存指针
; 
; uchar * wt24c_fc(uchar *p, uint ad, uchar n)
; {	
	.dbline 174
; 	uchar t=0;
	clr R12
	.dbline 179
; 	#if e2prom<32
; 	t=ad>>8;
; 	t<<=1;
; 	#endif
; 	i2cstart();					//发送起始信号
	xcall _i2cstart
	.dbline 180
; 	if(i2cwt(W_ADD_COM+t)==SLAW)//发送SLA_W, 写字节命令及器件地址
	mov R16,R12
	subi R16,96    ; addi 160
	xcall _i2cwt
	cpi R16,24
	brne L36
	.dbline 181
; 	{	
	.dbline 183
; 		#if e2prom>=32
; 		i2cwt(ad>>8);			//ad_dst的高位到器件
	movw R16,R10
	mov R16,R17
	clr R17
	xcall _i2cwt
	.dbline 185
; 		#endif
; 		i2cwt(ad);				//ad_dst的低位到器件
	mov R16,R10
	xcall _i2cwt
	.dbline 187
; 			
; 		for(;n>0;n--)			//发送要写入的数据
	xjmp L41
L38:
	.dbline 188
	.dbline 188
	movw R30,R20
	ldd R16,z+0
	xcall _i2cwt
	.dbline 189
	subi R20,255  ; offset = 1
	sbci R21,255
	.dbline 190
L39:
	.dbline 187
	dec R22
L41:
	.dbline 187
	clr R2
	cp R2,R22
	brlo L38
	.dbline 191
; 		{   i2cwt(*p);
; 			p++;
; 		}
; 	}
	xjmp L37
L36:
	.dbline 192
; 	else syserr=ERR_SLAW;		//写字节命令及器件地址错
	ldi R24,10
	sts _syserr,R24
L37:
	.dbline 194
; 	
; 	i2cstop();
	xcall _i2cstop
	.dbline 195
; 	delay_EEPROM(10);					//延时6ms
	ldi R16,10
	xcall _delay_EEPROM
	.dbline 197
; 	
; 	return(p);
	movw R16,R20
	.dbline -2
L35:
	xcall pop_gset4
	.dbline 0 ; func end
	ret
	.dbsym r t 12 c
	.dbsym r n 22 c
	.dbsym r ad 10 i
	.dbsym r p 20 pc
	.dbend
	.dbfunc e i2cstart _i2cstart fV
	.even
_i2cstart::
	.dbline -1
	.dbline 206
; }
; 
; 
; 
; //-------------------------------以下为其它I2总线器件可调用的函数--------------------------
; 
; //总线上起动开始条件
; void i2cstart(void)
; { 
	.dbline 207
; 	TWCR= BIT(TWINT) | BIT(TWSTA) | BIT(TWEN); 
	ldi R24,164
	out 0x36,R24
L43:
	.dbline 208
L44:
	.dbline 208
;    	while (!(TWCR & BIT(TWINT)));
	in R2,0x36
	sbrs R2,7
	rjmp L43
	.dbline -2
L42:
	.dbline 0 ; func end
	ret
	.dbend
	.dbfunc e i2cwt _i2cwt fc
;              a -> R16
	.even
_i2cwt::
	.dbline -1
	.dbline 213
; } 
; 
; //把一个字节数据输入器件, 返回TWI状态
; uchar i2cwt(uchar a)
; { 
	.dbline 214
; 	TWDR = a; 
	out 0x3,R16
	.dbline 215
;    	TWCR = BIT(TWINT) | BIT(TWEN); 
	ldi R24,132
	out 0x36,R24
L47:
	.dbline 216
L48:
	.dbline 216
;    	while (!(TWCR & BIT(TWINT)));
	in R2,0x36
	sbrs R2,7
	rjmp L47
	.dbline 217
;    	_NOP();
	nop
	.dbline 218
;    	return(TWSR&0b11111000);
	in R16,0x1
	andi R16,248
	.dbline -2
L46:
	.dbline 0 ; func end
	ret
	.dbsym r a 16 c
	.dbend
	.dbfunc e i2crd _i2crd fc
	.even
_i2crd::
	.dbline -1
	.dbline 224
; } 
; 
; //i2c读要调用的函数
; //从器件读出一个字节
; uchar i2crd(void)
; {
	.dbline 225
;    	TWCR= BIT(TWINT) | BIT(TWEA) | BIT(TWEN); 
	ldi R24,196
	out 0x36,R24
L51:
	.dbline 226
L52:
	.dbline 226
;    	while (!(TWCR & BIT(TWINT)));
	in R2,0x36
	sbrs R2,7
	rjmp L51
	.dbline 227
;    	return(TWDR);
	in R16,0x3
	.dbline -2
L50:
	.dbline 0 ; func end
	ret
	.dbend
	.dbfunc e i2cstop _i2cstop fV
	.even
_i2cstop::
	.dbline -1
	.dbline 234
; 	
; } 
; 
; 
; //总线上起动停止条件 
; void i2cstop(void) 
; { 
	.dbline 235
;    TWCR = BIT(TWINT) | BIT(TWSTO) | BIT(TWEN); 
	ldi R24,148
	out 0x36,R24
	.dbline -2
L54:
	.dbline 0 ; func end
	ret
	.dbend
	.area bss(ram, con, rel)
	.dbfile E:\学习专区\AVR专区\个人创作区\AVR单片机开发平台\EEPROM读写演示程序\24Cxx.C
_syserr::
	.blkb 1
	.dbsym e syserr _syserr c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -