📄 24cxx.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 + -