IAP的方式是写入到程序Flash区保持数据不丢失
写之前要保证区域内没有会被执行到的程序。否则写入数据后会导致程序死机会不断重启。
支持IAP的单片机类型比较多,请提供具体型号
以IAP15F2K61S2为例(STC官方代码)
//IAP特殊功能寄存器:sfr IAP_DATA = 0xC2 //IAP数据寄存器
sfr IAP_ADDRH = 0xC3 //IAP地址寄存器高字节
sfr IAP_ADDRL = 0xC4 //IAP地址寄存器低字节
sfr IAP_CMD = 0xC5 //IAP命令寄存器
sfr IAP_TRIG = 0xC6 //IAP命令触发寄存器
sfr IAP_CONTR = 0xC7 //IAP控制寄存器
//IAP工作模式
#define CMD_IDLE 0 //空闲模式
#define CMD_READ 1 //IAP字节读命令
#define CMD_PROGRAM 2 //IAP字节编程命令
#define CMD_ERASE 3 //IAP扇区擦除命令
//单片机运行频率
//#define ENABLE_IAP 0x80 //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81 //if SYSCLK<24MHz
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
//#define ENABLE_IAP 0x83 //if SYSCLK<12MHz
//#define ENABLE_IAP 0x84 //if SYSCLK<6MHz
//#define ENABLE_IAP 0x85 //if SYSCLK<3MHz
//#define ENABLE_IAP 0x86 //if SYSCLK<2MHz
//#define ENABLE_IAP 0x87 //if SYSCLK<1MHz
//测试地址
#define IAP_ADDRESS 0x0400
/*----------------------------
扇区擦除
----------------------------*/
void IapEraseSector(WORD addr)//擦除扇区是以512字节为单位
{
IAP_CONTR = ENABLE_IAP //使能IAP
IAP_CMD = CMD_ERASE //设置IAP命令
IAP_ADDRL = addr //设置IAP低地址
IAP_ADDRH = addr >> 8 //设置IAP高地址
IAP_TRIG = 0x5a //写触发命令(0x5a)
IAP_TRIG = 0xa5 //写触发命令(0xa5)
_nop_() //等待ISP/IAP/EEPROM *** 作完成
IapIdle()
}
/*----------------------------
写一字节数据到ISP/IAP区域
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP //使能IAP
IAP_CMD = CMD_PROGRAM //设置IAP命令
IAP_ADDRL = addr //设置IAP低地址
IAP_ADDRH = addr >> 8 //设置IAP高地址
IAP_DATA = dat //写ISP/IAP/EEPROM数据
IAP_TRIG = 0x5a //写触发命令(0x5a)
IAP_TRIG = 0xa5 //写触发命令(0xa5)
_nop_() //等待ISP/IAP/EEPROM *** 作完成
IapIdle()
}
/*----------------------------
从ISP/IAP/EEPROM区域读取一字节
----------------------------*/
BYTE IapReadByte(WORD addr)//由于在程序储存区内也可以用MOVC指令读取
{
BYTE dat //数据缓冲区
IAP_CONTR = ENABLE_IAP //使能IAP
IAP_CMD = CMD_READ //设置IAP命令
IAP_ADDRL = addr //设置IAP低地址
IAP_ADDRH = addr >> 8 //设置IAP高地址
IAP_TRIG = 0x5a //写触发命令(0x5a)
IAP_TRIG = 0xa5 //写触发命令(0xa5)
_nop_() //等待ISP/IAP/EEPROM *** 作完成
dat = IAP_DATA //读ISP/IAP/EEPROM数据
IapIdle() //关闭IAP功能
return dat //返回
}
/*----------------------------
关闭IAP
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0 //关闭IAP功能
IAP_CMD = 0 //清除命令寄存器
IAP_TRIG = 0 //清除触发寄存器
IAP_ADDRH = 0x80 //将地址设置到非IAP区域
IAP_ADDRL = 0
}
通过以上代码即可对Flash区进行写入 *** 作
stc普通芯片跟iap芯片读取eerom是不一样的。普通芯片,有专门的EEPROM区,使用专用的寄存器和指令来读写的。
而IAP是没有专门的EEPROM区的,全部的FLASH的程序区都可以作为EEPROM来读写,而且在运行程序的过程中,随时可以修改程序,但千万别把程序改乱了,造成死机哟。
以下是我曾经做过的东东中的有关EEPROM读写的一段程序,供参考。-------------------写参数到EEROM-----------------------------
PARAPUT:
MOV DPTR,#0000H
LCALL IAP_Erase
MOV DPTR,#0000H
MOV R0,#60H
MOV R1,#16
PARAPUT1:
MOV A,@R0
LCALL IAP_WRITE
INC R0
INC DPTR
DJNZ R1,PARAPUT1
RET
-------------------从EEROM中读出参数-----------------------------
PARAGET:
MOV DPTR,#0000H
MOV R0,#60H
MOV R1,#16
PARAGET1:
LCALL IAP_READ
MOV @R0,A
INC R0
INC DPTR
DJNZ R1,PARAGET1
RET
------------------------------------------------
读一字节,调用前需打开 IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
IAP_READ:
MOV IAP_CONTR,#ENABLE_IAP 打开 IAP 功能, 设置 Flash *** 作等待时间
MOV IAP_CMD,#ISP_IAP_BYTE_READ 设置为IAP/ISP/EEPROM字节读模式命令
MOV IAP_ADDRH,DPH 设置目标单元地址的高8位地址
MOV IAP_ADDRL,DPL 设置目标单元地址的低8位地址
CLR EA
MOV IAP_TRIG,#5AH 先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG,#0A5H送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV A,IAP_DATA读出的数据在IAP_DATA单元中,送入累加器A
SETBEA
LCALL IAP_Disable 关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关
RET
------------------------------------------------
字节编程,调用前需打开 IAP 功能,入口:DPTR = 字节地址, A=须编程字节的数据
IAP_WRITE:
MOV IAP_CONTR,#ENABLE_IAP 打开 IAP 功能, 设置 Flash *** 作等待时间
MOV IAP_CMD,#ISP_IAP_BYTE_PROGRAM 设置为IAP/ISP/EEPROM字节编程模式命令
MOV IAP_ADDRH,DPH 设置目标单元地址的高8位地址
MOV IAP_ADDRL,DPL 设置目标单元地址的低8位地址
MOV IAP_DATA,A 要编程的数据先送进ISP_DATA寄存器
CLR EA
MOV IAP_TRIG,#5AH 先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG,#0A5H送完A5h后,ISP/IAP命令立即被触发起动
NOP
SETB EA
LCALL IAP_Disable 关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关
RET
------------------------------------------------
擦除扇区, 入口:DPTR = 扇区地址
IAP_Erase:
MOV IAP_CONTR,#ENABLE_IAP 打开 IAP 功能, 设置 Flash *** 作等待时间
MOV IAP_CMD,#03H 设置为IAP/ISP/EEPROM扇区擦除模式命令
MOV IAP_ADDRH,DPH 设置目标单元地址的高8位地址
MOV IAP_ADDRL,DPL 设置目标单元地址的低8位地址
CLR EA
MOV IAP_TRIG,#5AH 先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG,#0A5H 送完A5h后,ISP/IAP命令立即被触发起动
NOP
SETB EA
LCALL IAP_Disable 关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关
RET
------------------------------------------------
IAP_Disable:
关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关
MOV IAP_CONTR,#0 关闭 IAP 功能
MOV IAP_CMD,#0 清命令寄存器,使命令寄存器无命令,此句可不用
MOV IAP_TRIG,#0 清命令触发寄存器,使命令触发寄存器无触发,此句可不用
MOV IAP_ADDRH,#0FFH送地址高字节单元为00,指向非EEPROM区
MOV IAP_ADDRL,#0FFH送地址低字节单元为00,防止误 *** 作
RET
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)