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

📄 eeprom读写演示程序.lst

📁 EEPROM读写程序: 先向EEPROM写入一幅图片数据
💻 LST
📖 第 1 页 / 共 5 页
字号:
_delay_EEPROM:
  a                    --> R20
  b                    --> R22
  n                    --> R16
    050A 940E06A5  CALL	push_gset2
FILE: E:\学习专区\AVR专区\个人创作区\AVR单片机开发平台\EEPROM读写演示程序\24Cxx.C
(0001) /**************************************************
(0002)           EEPROM读写操作
(0003) 		  晶振:内部   8M
(0004) ***************************************************/
(0005) #include<iom16v.h>
(0006) #include<macros.h>
(0007) #define uchar unsigned char 
(0008) #define uint unsigned int 
(0009) #define ulong unsigned long 
(0010) uchar syserr;
(0011) void delay_EEPROM(uchar n)   //延时
(0012) {
(0013)  	 unsigned int a,b;
(0014) 	 for(a=0;a<n;a++)
    050C 2744      CLR	R20
    050D 2755      CLR	R21
    050E C00B      RJMP	0x051A
(0015) 	 for(b=0;b<100;b++)
    050F 2766      CLR	R22
    0510 2777      CLR	R23
    0511 C002      RJMP	0x0514
    0512 5F6F      SUBI	R22,0xFF
    0513 4F7F      SBCI	R23,0xFF
    0514 3664      CPI	R22,0x64
    0515 E0E0      LDI	R30,0
    0516 077E      CPC	R23,R30
    0517 F3D0      BCS	0x0512
    0518 5F4F      SUBI	R20,0xFF
    0519 4F5F      SBCI	R21,0xFF
    051A 2E20      MOV	R2,R16
    051B 2433      CLR	R3
    051C 1542      CP	R20,R2
    051D 0553      CPC	R21,R3
    051E F380      BCS	0x050F
    051F 940E0693  CALL	pop_gset2
    0521 9508      RET
_wt24c:
  n                    --> R10
  num                  --> R12
  ad_dst               --> R14
  p_rsc                --> Y+11
    0522 940E0614  CALL	push_arg4
    0524 940E069F  CALL	push_gset5
    0526 0179      MOVW	R14,R18
    0527 9721      SBIW	R28,1
    0528 84CF      LDD	R12,Y+15
    0529 88D8      LDD	R13,Y+16
(0016) 	 ;
(0017) }
(0018) //------在此设定芯片型号------
(0019) #define e2prom 256	// <---在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512
(0020) 
(0021) #if e2prom==1
(0022) 	#define PAGE_SIZE 8
(0023) 	#define SIZE 0x007f
(0024) #elif e2prom==2
(0025) 	#define PAGE_SIZE 8
(0026) 	#define SIZE 0x00ff
(0027) #elif e2prom==4
(0028) 	#define PAGE_SIZE 16
(0029) 	#define SIZE 0x01ff
(0030) #elif e2prom==8
(0031) 	#define PAGE_SIZE 16
(0032) 	#define SIZE 0x03ff
(0033) #elif e2prom==16
(0034) 	#define PAGE_SIZE 16
(0035) 	#define SIZE 0x07ff
(0036) #elif e2prom==32
(0037) 	#define PAGE_SIZE 32
(0038) 	#define SIZE 0x0fff
(0039) #elif e2prom==64
(0040) 	#define PAGE_SIZE 32
(0041) 	#define SIZE 0x1fff
(0042) #elif e2prom==128
(0043) 	#define PAGE_SIZE 64
(0044) 	#define SIZE 0x3fff
(0045) #elif e2prom==256
(0046) 	#define PAGE_SIZE 64
(0047) 	#define SIZE 0x7fff
(0048) #elif e2prom==512
(0049) 	#define PAGE_SIZE 128
(0050) 	#define SIZE 0xffff
(0051) #endif
(0052) //--------------------------
(0053) 
(0054) //--------在此设定芯片地址-------
(0055) #define W_ADD_COM 0xa0	//写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
(0056) #define R_ADD_COM 0xa1	//读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1
(0057) //-------------------------------
(0058) 
(0059) 
(0060) 
(0061) #define SLAW	0x18	//SLA_W 已正常发送代码,判断器件是否正常应答的常量.
(0062) 
(0063) //-----在此改变预置错误号-----
(0064) #define ERR_SLAW	10//写字节命令及器件地址错, 在此也就是读写器件错!!
(0065) //---------------------------
(0066) 
(0067) 
(0068) 
(0069) //-----------4个I2总线公用函数, 可供其它I2总线器件的程序调用--------------
(0070) void i2cstart(void);	//总线上起动开始条件
(0071) uchar i2cwt(uchar a);	//把一个字节数据输入器件, 返回TWI状态
(0072) uchar i2crd(void);		//i2c读要调用的函数
(0073) void i2cstop(void);		//总线上起动停止条件 
(0074) //------------------------------------------------------------------------
(0075) 
(0076) uchar * wt24c_fc(uchar *p, uint ad, uchar n);	//向24Cxx写入数据wt24c_h()所要调用的函数
(0077) 
(0078) //向24Cxx写入数据
(0079) //参数: *p_rsc要输出数据的主机内存地址指针; ad_dst要写入数据的i2c的地址(双字节); num数据个数
(0080) //参数条件: ad_dst: ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
(0081) void wt24c(uchar *p_rsc, uint ad_dst, uint num)
(0082) {   uint n;
(0083) 
(0084)     n=ad_dst/PAGE_SIZE;		//确定地址与块地址的差
    052A E026      LDI	R18,6
    052B E030      LDI	R19,0
    052C 0187      MOVW	R16,R14
    052D 940E06E3  CALL	lsr16
    052F 0158      MOVW	R10,R16
(0085) 	if(n) 
    0530 3000      CPI	R16,0
    0531 0701      CPC	R16,R17
    0532 F0E1      BEQ	0x054F
(0086) 	n=(ulong)PAGE_SIZE*(n+1)-ad_dst;	
    0533 01C5      MOVW	R24,R10
    0534 9601      ADIW	R24,1
    0535 011C      MOVW	R2,R24
    0536 2444      CLR	R4
    0537 2455      CLR	R5
    0538 E440      LDI	R20,0x40
    0539 E050      LDI	R21,0
    053A E060      LDI	R22,0
    053B E070      LDI	R23,0
    053C 925A      ST	R5,-Y
    053D 924A      ST	R4,-Y
    053E 923A      ST	R3,-Y
    053F 922A      ST	R2,-Y
    0540 018A      MOVW	R16,R20
    0541 019B      MOVW	R18,R22
    0542 940E0663  CALL	empy32s
    0544 0118      MOVW	R2,R16
    0545 0129      MOVW	R4,R18
    0546 0137      MOVW	R6,R14
    0547 2488      CLR	R8
    0548 2499      CLR	R9
    0549 1826      SUB	R2,R6
    054A 0837      SBC	R3,R7
    054B 0848      SBC	R4,R8
    054C 0859      SBC	R5,R9
    054D 0151      MOVW	R10,R2
    054E C005      RJMP	0x0554
(0087) 	else
(0088) 	 n=PAGE_SIZE-ad_dst;
    054F E480      LDI	R24,0x40
    0550 E090      LDI	R25,0
    0551 015C      MOVW	R10,R24
    0552 18AE      SUB	R10,R14
    0553 08BF      SBC	R11,R15
(0089) 		
(0090)     if(n>=num)		//如果ad_dst所在的数据块的末尾地址 >= ad_dst + num, 就直接写入num个数据
    0554 14AC      CP	R10,R12
    0555 04BD      CPC	R11,R13
    0556 F058      BCS	0x0562
(0091)     {	
(0092) 		wt24c_fc(p_rsc, ad_dst, num);
    0557 82C8      STD	Y+0,R12
    0558 0197      MOVW	R18,R14
    0559 850B      LDD	R16,Y+11
    055A 851C      LDD	R17,Y+12
    055B D077      RCALL	_wt24c_fc
(0093)     	if(syserr!=0) 
    055C 902000AE  LDS	R2,syserr
    055E 2022      TST	R2
    055F F409      BNE	0x0561
    0560 C034      RJMP	0x0595
(0094) 		return;
    0561 C033      RJMP	0x0595
(0095)     }
(0096)     else			//如果ad_dst所在的数据块末尾地址 < ad_dst + num, 就先写入ad_dst所在的数据块末尾地址与 ad_dst 之差个数据
(0097)     {   
(0098) 	p_rsc=wt24c_fc(p_rsc, ad_dst, n);
    0562 82A8      STD	Y+0,R10
    0563 0197      MOVW	R18,R14
    0564 850B      LDD	R16,Y+11
    0565 851C      LDD	R17,Y+12
    0566 D06C      RCALL	_wt24c_fc
    0567 871C      STD	Y+12,R17
    0568 870B      STD	Y+11,R16
(0099)     	if(syserr!=0) 
    0569 902000AE  LDS	R2,syserr
    056B 2022      TST	R2
    056C F009      BEQ	0x056E
(0100) 		return;
    056D C027      RJMP	0x0595
(0101) 		
(0102) 		num-=n;     //更新剩下数据个数
    056E 18CA      SUB	R12,R10
    056F 08DB      SBC	R13,R11
(0103)         ad_dst+=n;	//更新剩下数据的起始地址
    0570 0CEA      ADD	R14,R10
    0571 1CFB      ADC	R15,R11
    0572 C015      RJMP	0x0588
(0104) 
(0105)         //把剩下数据写入器件
(0106)         while(num>=PAGE_SIZE)	//先按PAGE_SIZE为长度一页一页的写入
(0107)         {	p_rsc=wt24c_fc(p_rsc, ad_dst, PAGE_SIZE);
    0573 E480      LDI	R24,0x40
    0574 8388      STD	Y+0,R24
    0575 0197      MOVW	R18,R14
    0576 850B      LDD	R16,Y+11
    0577 851C      LDD	R17,Y+12
    0578 D05A      RCALL	_wt24c_fc
    0579 871C      STD	Y+12,R17
    057A 870B      STD	Y+11,R16
(0108)         	if(syserr!=0) return;
    057B 902000AE  LDS	R2,syserr
    057D 2022      TST	R2
    057E F009      BEQ	0x0580
    057F C015      RJMP	0x0595
(0109)         	
(0110)             num-=PAGE_SIZE;		//更新剩余数据个数
    0580 01C6      MOVW	R24,R12
    0581 5480      SUBI	R24,0x40
    0582 4090      SBCI	R25,0
    0583 016C      MOVW	R12,R24
(0111)         	ad_dst+=PAGE_SIZE;	//更新剩下数据的起始地址
    0584 01C7      MOVW	R24,R14
    0585 5C80      SUBI	R24,0xC0
    0586 4F9F      SBCI	R25,0xFF
    0587 017C      MOVW	R14,R24
    0588 01C6      MOVW	R24,R12
    0589 3480      CPI	R24,0x40
    058A E0E0      LDI	R30,0
    058B 079E      CPC	R25,R30
    058C F730      BCC	0x0573
(0112) 		}
(0113)         
(0114) 		if(num)			//把最后剩下的小于一个PAGE_SIZE长度的数据写入器件
    058D 3080      CPI	R24,0
    058E 0789      CPC	R24,R25
    058F F029      BEQ	0x0595
(0115) 			wt24c_fc(p_rsc, ad_dst, num);
    0590 82C8      STD	Y+0,R12
    0591 0197      MOVW	R18,R14
    0592 850B      LDD	R16,Y+11
    0593 851C      LDD	R17,Y+12
    0594 D03E      RCALL	_wt24c_fc
(0116)     }
    0595 9621      ADIW	R28,1
    0596 940E069C  CALL	pop_gset5
    0598 9624      ADIW	R28,4
    0599 9508      RET
(0117) }
(0118) 
(0119) 
(0120) //从24cxx读出数据
(0121) //参数: *p_dst要读入数据的主机内存地址指针; ad_rsc要输出数据的i2c的地址(整形); num数据个数(整形)
(0122) //参数条件:  ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
(0123) void port_init(void)
(0124) {
(0125) 
(0126)  	 PORTC = 0xFF; 
_port_init:
    059A EF8F      LDI	R24,0xFF
    059B BB85      OUT	0x15,R24
(0127) 	 DDRC &= 0xfc;
    059C B384      IN	R24,0x14
    059D 7F8C      ANDI	R24,0xFC
    059E BB84      OUT	0x14,R24
    059F 9508      RET
(0128) }
(0129) //TWI initialize
(0130) // bit rate:100
(0131) void twi_init(void)
(0132) {
(0133)  	 TWCR= 0x00; //disable twi
_twi_init:
    05A0 2422      CLR	R2
    05A1 BE26      OUT	0x36,R2
(0134) 	 TWBR= 0x20; //set bit rate
    05A2 E280      LDI	R24,0x20
    05A3 B980      OUT	0x00,R24
(0135) 	 TWSR= 0x00; //set prescale
    05A4 B821      OUT	0x01,R2
(0136) 	 TWAR= 0x00; //set slave address
    05A5 B822      OUT	0x02,R2
(0137) 	 TWCR= 0x04; //enable twi
    05A6 E084      LDI	R24,4
    05A7 BF86      OUT	0x36,R24
    05A8 9508      RET
_rd24c:
  t                    --> R10
  num                  --> R22
  ad_rsc               --> R12
  p_dst                --> R20
    05A9 940E06A1  CALL	push_gset4
    05AB 0169      MOVW	R12,R18
    05AC 01A8      MOVW	R20,R16
    05AD 8568      LDD	R22,Y+8
    05AE 8579      LDD	R23,Y+9
(0138) }
(0139) void rd24c(uchar *p_dst, uint ad_rsc, uint num)
(0140) {   
(0141) 	uchar t=0;
    05AF 24AA      CLR	R10
(0142) 	#if e2prom<32
(0143) 	t=ad_rsc>>8;
(0144) 	t<<=1;
(0145) 	#endif
(0146) 	i2cstart();					//发送起始信号
    05B0 D049      RCALL	_i2cstart
(0147) 	if(i2cwt(W_ADD_COM+t)==SLAW)//发送SLA_W, 写字节命令及器件地址
    05B1 2D0A      MOV	R16,R10
    05B2 5600      SUBI	R16,0x60
    05B3 D04C      RCALL	_i2cwt
    05B4 3108      CPI	R16,0x18
    05B5 F4B1      BNE	0x05CC
(0148) 	{	
(0149) 		#if e2prom>=32
(0150) 		i2cwt(ad_rsc>>8);		//ad_rsc的高位,  发送要读出数据的地址
    05B6 0186      MOVW	R16,R12
    05B7 2F01      MOV	R16,R17
    05B8 2711      CLR	R17
    05B9 D046      RCALL	_i2cwt
(0151) 		#endif
(0152) 		i2cwt(ad_rsc);			//ad_rsc的低位
    05BA 2D0C      MOV	R16,R12
    05BB D044      RCALL	_i2cwt
(0153) 				
(0154) 		i2cstart();				//再发送起始信号
    05BC D03D      RCALL	_i2cstart
(0155) 		i2cwt(R_ADD_COM+t);		//发送SLA_R, 读命令字节及器件地址
    05BD 2D0A      MOV	R16,R10
    05BE 550F      SUBI	R16,0x5F
    05BF D040      RCALL	_i2cwt
(0156) 				
(0157) 		for(;num>0;num--)
    05C0 C007      RJMP	0x05C8
(0158) 		{  
(0159) 		 *p_dst=i2crd();		//从器件读出一个字节
    05C1 D048      RCALL	_i2crd
    05C2 01FA      MOVW	R30,R20
    05C3 8300      STD	Z+0,R16
(0160) 			p_dst++;
    05C4 5F4F      SUBI	R20,0xFF
    05C5 4F5F      SBCI	R21,0xFF
    05C6 5061      SUBI	R22,1
    05C7 4070      SBCI	R23,0
    05C8 3060      CPI	R22,0
    05C9 0767      CPC	R22,R23
    05CA F7B1      BNE	0x05C1
(0161) 		}
(0162) 	}
    05CB C003      RJMP	0x05CF
(0163) 	else 
(0164) 	syserr=ERR_SLAW;		//写字节命令及器件地址错或对方无应答
    05CC E08A      LDI	R24,0xA
    05CD 938000AE  STS	syserr,R24
(0165) 		
(0166) 	i2cstop();
    05CF D041      RCALL	_i2cstop
    05D0 940E0699  CALL	pop_gset4
    05D2 9508      RET
_wt24c_fc:
  t                    --> R12

⌨️ 快捷键说明

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