51单片机如何利用IAP实现数据掉电不丢失?相应程序怎么写?

51单片机如何利用IAP实现数据掉电不丢失?相应程序怎么写?,第1张

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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7948338.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-11
下一篇 2023-04-11

发表评论

登录后才能评论

评论列表(0条)

保存