修改FLASH数据通常需要很长时间,不像RAM那样可以实时操作。而且擦除、编程或读取FLASH数据需要遵循相当复杂的时序步骤。N76E003提供方便FALSH编程方式,可以帮助用户通过IAP方式,重新编程FLASH内容。IAP就是通过软件实现在线电擦除和编程的方法。
通过设置IAPEN(CHPCON.0受TA保护)使能IAP,并且设置IAPUEN寄存器的相应位,使能需要升级的FLASH区域(CONFIG、LDROM、APROM),用户将16位操作地址写入IAPAH和IAPAL,数据写入IAPFD,命令写入IAPCN。然后通过设置触发位IAPGO(IAPTRG.0),去执行IAP。注意:IAPTRG也受TA保护。此时,CPU保持程序计数器,内嵌IAP自动控制内部充电泵提高电压和信号时序。擦除和编程时间是内部控制的,与工作电压和频率无关。通常页擦除时间是5ms,字节编程时间是 3.5μs。IAP动作完成后,程序计数器继续运行之后的指令,IAPGO位将自动清零。IAPFF (CHPCON.6)是IAP错误标志,可以用来检查之前IAP操作成功与否。通过这些纯软件的设置,用户可以很方便对FLASH存储器进行擦除、编程和校验。

IAP可以方便用户更新FLASH内容,不过用户必须遵循一定规则,以确保IAP正确执行,否则可能引起不确定的结果,甚至损坏器件。此外,下文对于正确执行IAP有很好建议。
(1)没有IAP操作时,用户必须清IAPEN (CHPCON.0)位。可以防止系统意外触发IAP。此外,IAP需要使用内部HIRC振荡器。如果选择外部时钟源,禁止IAP将停止内部HIRC,可以达到省电的目的。注:写IAPEN受TA保护。
(2)当LOCK位(CONFIG0.1) 被激活,IAP读、写或擦除仍然有效。

在进行IAP时,如果中断打开应该临时清除EA位
擦除或编程的页不能是当前代码执行的页。否则会出现不可预计程序动作,甚至破坏存储的数据

使用flash存储器作为数据存储
在一般应用中,有时需要一些数据在断电情况下不能丢失,以便用户读回或更新,作为系统控制的参数。N76E003支持IAP功能并且存储在flash中的字节都可以用MOVC指令读取,所以很适合作为非易失数据存储器。Flash写次数为100,000次,以下参考应用代码:

汇编例程如下:
;******************************************************************************
; This code illustrates how to use IAP to make APROM 201h as a byte of
; Data Flash when user code is executed in APROM.
;******************************************************************************
PAGE_ERASE_AP EQU 00100010b
BYTE_PROGRAM_AP EQU 00100001b
ORG 0000h
MOV TA,#0Aah ;CHPCON is TA protected
MOV TA,#55h
ORL CHPCON,#00000001b ;IAPEN = 1, enable IAP mode
MOV TA,#0Aah ;IAPUEN is TA protected
MOV TA,#55h
ORL IAPUEN,#00000001b ;APUEN = 1, enable APROM update
MOV IAPCN,#PAGE_ERASE_AP ;Erase page 200h~27Fh
MOV IAPAH,#02h
MOV IAPAL,#00h
MOV IAPFD,#0FFh
MOV TA,#0Aah ;IAPTRG is TA protected
MOV TA,#55h
ORL IAPTRG,#00000001b ;write ‘1’ to IAPGO to trigger IAP process
MOV IAPCN,#BYTE_PROGRAM_AP ;Program 201h with 55h
MOV IAPAH,#02h
MOV IAPAL,#01h
MOV IAPFD,#55h

MOV TA,#0Aah
MOV TA,#55h
ORL IAPTRG,#00000001b
MOV TA,#0Aah
MOV TA,#55h
ANL IAPUEN,#11111110b ;APUEN = 0, disable APROM update
MOV TA,#0Aah
MOV TA,#55h
ANL CHPCON,#11111110b ;IAPEN = 0, disable IAP mode
MOV DPTR,#201h
CLR A
MOVC A,@A+DPTR ;Read content of address 201h
MOV P0,A
SJMP $

C 语言例程如下:
//******************************************************************************
// This code illustrates how to use IAP to make APROM 201h as a byte of
// Data Flash when user code is executed in APROM.
//******************************************************************************
#define PAGE_ERASE_AP 0x22
#define BYTE_PROGRAM_AP 0x21
/*Data Flash, as part of APROM, is read by MOVC. Data Flash can be defined as
128-element array in “code” area from absolute address 0x0200 */
volatile unsigned char code Data_Flash[128] _at_ 0x0200;
Main (void)
{
TA = 0xAA; //CHPCON is TA protected
TA = 0x55;
CHPCON |= 0x01; //IAPEN = 1, enable IAP mode
TA = 0xAA; //IAPUEN is TA protected
TA = 0x55;
IAPUEN |= 0x01; //APUEN = 1, enable APROM update
IAPCN = PAGE_ERASE_AP; //Erase page 200h~27Fh
IAPAH = 0x02;
IAPAL = 0x00;
IAPFD = 0xFF;
TA = 0xAA; //IAPTRG is TA protected
TA = 0x55;
IAPTRG |= 0x01; //write ‘1’ to IAPGO to trigger IAP process
IAPCN = BYTE_PROGRAM_AP; // Program 201h with 55h
IAPAH = 0x02;
IAPAL = 0x01;

IAPFD = 0x55;

TA = 0xAA;
TA = 0x55;
IAPTRG |= 0x01; //write ‘1’ to IAPGO to trigger IAP process
TA = 0xAA; //IAPUEN is TA protected
TA = 0x55;
IAPUEN &= ~0x01; //APUEN = 0, disable APROM update
TA = 0xAA; //CHPCON is TA protected
TA = 0x55;
CHPCON &= ~0x01; //IAPEN = 0, disable IAP mode
P0 = Data_Flash[1]; //Read content of address 200h+1
while(1);
}

N76E003 APROM程序DATAFLASH为EEPROM方式

#include <stdio.h>
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_Define.h" bit BIT_TMP; //-------------------------------------------------------------------------
UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
{
UINT8 rdata;
rdata = *u16_addr>>;
return rdata;
}
//------------------------------------------------------------------------- /*****************************************************************************************************************
write_DATAFLASH_BYTE :
user can copy all this subroutine into project, then call this function in main.
******************************************************************************************************************/
void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
{
UINT8 looptmp=,u8_addrl_r;
unsigned char code *cd_longaddr;
unsigned char xdata *xd_tmp; //Check page start address
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r = ;
}
else
{
u8_addrl_r = 0x80;
}
//Save APROM data to XRAM
xd_tmp = 0x80;
cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;
while (xd_tmp !=0x100)
{
*xd_tmp = *cd_longaddr;
looptmp++;
xd_tmp++;
cd_longaddr++;
}
// Modify customer data in XRAM
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
xd_tmp = u8_addrl_r+0x80;
}
else
{
xd_tmp = u8_addrl_r+;
}
*xd_tmp = u8_data;
//Erase APROM DATAFLASH page
IAPAL = u16_addr;
IAPAH = u16_addr>>;
IAPFD = 0xFF;
set_IAPEN;
set_APUEN;
IAPCN = 0x22;
set_IAPGO;
//Save changed RAM data to APROM DATAFLASH
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r =;
}
else
{
u8_addrl_r = 0x80;
}
xd_tmp = 0x80;
IAPAL = u8_addrl_r;
IAPAH = u16_addr>>;
set_IAPEN;
set_APUEN;
IAPCN = 0x21;
while (xd_tmp !=0xFF)
{
IAPFD = *xd_tmp;
set_IAPGO;
IAPAL++;
xd_tmp++;
}
clr_APUEN;
clr_IAPEN;
}
/******************************************************************************************************************/ void main (void)
{
UINT8 datatemp;
/* -------------------------------------------------------------------------*/
/* Dataflash use APROM area */
/* APROM 0x3800~0x38FF demo as dataflash */
/* Please use Memory window key in C:0x3800 to check earse result */
/* -------------------------------------------------------------------------*/ //call write byte
write_DATAFLASH_BYTE (0x3881,0x55);
write_DATAFLASH_BYTE (0x3882,0x56);
write_DATAFLASH_BYTE (0x3855,0xaa);
write_DATAFLASH_BYTE (0x3856,0x66);
//call read byte
datatemp = read_APROM_BYTE(0x3882);
while();
}

下面针对每一个调用函数进行讲解

void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
{
UINT8 looptmp=,u8_addrl_r;
unsigned char code *cd_longaddr;
unsigned char xdata *xd_tmp; //Check page start address
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r = ;
}
else
{
u8_addrl_r = 0x80;
}
//Save APROM data to XRAM
xd_tmp = 0x80;
cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;
while (xd_tmp !=0x100)
{
*xd_tmp = *cd_longaddr;
looptmp++;
xd_tmp++;
cd_longaddr++;
}
// Modify customer data in XRAM
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
xd_tmp = u8_addrl_r+0x80;
}
else
{
xd_tmp = u8_addrl_r+;
}
*xd_tmp = u8_data;
//Erase APROM DATAFLASH page
IAPAL = u16_addr;
IAPAH = u16_addr>>;
IAPFD = 0xFF;
set_IAPEN;
set_APUEN;
IAPCN = 0x22;
set_IAPGO;
//Save changed RAM data to APROM DATAFLASH
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r =;
}
else
{
u8_addrl_r = 0x80;
}
xd_tmp = 0x80;
IAPAL = u8_addrl_r;
IAPAH = u16_addr>>;
set_IAPEN;
set_APUEN;
IAPCN = 0x21;
while (xd_tmp !=0xFF)
{
IAPFD = *xd_tmp;
set_IAPGO;
IAPAL++;
xd_tmp++;
}
clr_APUEN;
clr_IAPEN;
}

上面这个函数,是对DATAFLASH  EEPROM进行读写,有主函数给出地址和数据,由该函数进行处理


void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
{
UINT8 looptmp=,u8_addrl_r;
unsigned char code *cd_longaddr;
unsigned char xdata *xd_tmp; //Check page start address
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r = 0;
}
else
{
u8_addrl_r = 0x80;
}
//Save APROM data to XRAM
xd_tmp = 0x80;
cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;
while (xd_tmp !=0x100)
{
*xd_tmp = *cd_longaddr;
looptmp++;
xd_tmp++;
cd_longaddr++;
}
// Modify customer data in XRAM
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
xd_tmp = u8_addrl_r+0x80;
}
else
{
xd_tmp = u8_addrl_r+0;
}
*xd_tmp = u8_data;
//Erase APROM DATAFLASH page
IAPAL = u16_addr;
IAPAH = u16_addr>>8;
IAPFD = 0xFF;
set_IAPEN;
set_APUEN;
IAPCN = 0x22;
set_IAPGO;
//Save changed RAM data to APROM DATAFLASH
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r =0;
}
else
{
u8_addrl_r = 0x80;
}
xd_tmp = 0x80;
IAPAL = u8_addrl_r;
IAPAH = u16_addr>>8;
set_IAPEN;
set_APUEN;
IAPCN = 0x21;
while (xd_tmp !=0xFF)
{
IAPFD = *xd_tmp;
set_IAPGO;
IAPAL++;
xd_tmp++;
}
clr_APUEN;
clr_IAPEN;
}

标红部分涉及到两个寄存器IAPL与IAPH,这起什么作用呢?看一下手册

由此可知,这两个寄存器是写入16位地址字节的,也就是说u8_addrl_r这个变量的含义是给寄存器提供地址,因此,需要一些数据的分析和处理,

 u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r = 0;
}
else
{
u8_addrl_r = 0x80;
}
//Save APROM data to XRAM
xd_tmp = 0x80;
cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;
while (xd_tmp !=0x100)
{
*xd_tmp = *cd_longaddr;
looptmp++;
xd_tmp++;
cd_longaddr++;
}
Save APROM data to XRAM

首先查看N76E003的数据手册得知这颗芯片的XRAM的大小为:768字节i ,即大小为0x300,另外还可知道Flash每一页的大小为128字节即0x80。这段历程划分区域到0X100(256)。

// Modify customer data in XRAM
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
xd_tmp = u8_addrl_r+0x80;
}
else
{
xd_tmp = u8_addrl_r+;
}
*xd_tmp = u8_data;
//Erase APROM DATAFLASH page
IAPAL = u16_addr;
IAPAH = u16_addr>>;
IAPFD = 0xFF;
set_IAPEN;
set_APUEN;
IAPCN = 0x22;
set_IAPGO;
 Modify customer data in XRAM
在XRAM中修改客户数据

//Save changed RAM data to APROM DATAFLASH
u8_addrl_r = u16_addr;
if (u8_addrl_r<0x80)
{
u8_addrl_r =;
}
else
{
u8_addrl_r = 0x80;
}
xd_tmp = 0x80;
IAPAL = u8_addrl_r;
IAPAH = u16_addr>>;
set_IAPEN;
set_APUEN;
IAPCN = 0x21;
while (xd_tmp !=0xFF)
{
IAPFD = *xd_tmp;
set_IAPGO;
IAPAL++;
xd_tmp++;
}
clr_APUEN;
clr_IAPEN;
}

这部分比较复杂,我后续会有更新,如果有什么意见或建议,欢迎评论

知识没有学完的时候,我只能保证明天的自己跟今天不一样,各个方面,无论是做人还是做事,无论是专业素质,还是为人处世,待人接物。

N76E003之IAP的更多相关文章

  1. 单片机成长之路(51基础篇) - 022 N76e003 APROM模拟EEPROM驱动

    N76e003单片机内部没有EEPROM,但是可以使用 APROM模拟EEPROM功能,代码如下: eeprom.h #ifndef _EEPROM_H_ #define _EEPROM_H_ //E ...

  2. N76E003之ISP

    Flash存储器支持硬件编程和应用编程(IAP).如果产品在研发阶段或产品需要更新软固件时,硬件编程就显得不太方便,采用在系统编程(ISP)方式,可使这一过程变得方便.执行ISP不需要将控制器从系统板 ...

  3. 几款一元单片机对比:CMS8S5880、STM8S003、N76E003

    大概17年开始,STM8S003的价格被贸易商炒货,变得很不稳定,一度上涨到2~3元,因为市场需求大增,小家电.无线充和一些简单功能的产品,本人就有在空气净化器.433M触摸开关.数据收发模块.红外控 ...

  4. LPC43xx系列使用IAP的注意事项

    LPC43xx系列使用IAP的注意事项 Tags: LPC43xx IAP 单片机 LPC43xx IAP函数的调用 一般MCU的IAP是,厂商固化一段代码在芯片的某个区域,然后告诉你这个代码的入口地 ...

  5. IAP

    release_check_url := "https://buy.itunes.apple.com/verifyReceipt" debug_check_url := " ...

  6. [Amazon] Amazon IAP for Unity

    1> 下载amazon IAP3.0 for unity plugin 2> 根据 https://developer.amazon.com/public/apis/earn/in-app ...

  7. [Android] Google IAP unmaneged items服务器校验

    android IAP unmaneged items 服务器校验 当成功IAP以后, 会在google服务器记录此次购买的状态. 可以通过Google Play Android Developer ...

  8. <转>iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!

    原文地址:http://blog.csdn.net/xiaominghimi/article/details/6937097 //——2012-12-11日更新   获取"产品付费数量等于0 ...

  9. iOS应用内付费(IAP)开发步骤列表

    iOS应用内付费(IAP)开发步骤列表 前两天和服务端同事一起,完成了应用内付费(以下简称IAP, In app purchase)的开发工作.步骤繁多,在此把开发步骤列表整理如下.因为只是步骤列表, ...

随机推荐

  1. 关于Unity中天空盒的使用

    天空盒 是一个盒子,一个正方形的盒子.其实本身也是一种shader,需要材质球做载体. 1: 一个场景是由6幅正方形的纹理图无缝拼接而成, 在视野看来位于真实的视野一样;2: 两种天空盒: 场景天空盒 ...

  2. ITSM运营实施案例 - 汽车行业

    M公司是在汽车行业知名TOP企业,在日常运营过程中有如下问题: ******************************************************************** ...

  3. MySQL库和表的管理

    MySQL数据库服务配置好后,系统会有4个默认的数据库. information_schema:虚拟对象,其对象都保存在内存中performance_schema:服务器性能指标库mysql:记录用户 ...

  4. js 闭包实例

    var db = (function() { // 创建一个隐藏的object, 这个object持有一些数据 // 从外部是不能访问这个object的 var data = {}; // 创建一个函 ...

  5. spark 非常好的学习内容

    http://homepage.cs.latrobe.edu.au/zhe/ZhenHeSparkRDDAPIExamples.html

  6. font-awesome 使用方法

    需要引入文件 font-awesome.css <link rel="stylesheet" href="{$yf_theme_path}public/font-a ...

  7. 非抢占式RCU中的一些概念

    该记录着重介绍下:2.6.34版本中非抢占式RCU的基本概念. RCU保护的是指针,因为指针的赋值可以使用原子操作完成: 在非抢占式RCU中: 对于读者,RCU仅需要抢占失效,因此获得读锁和释放读锁分 ...

  8. 自建Nuger Server拾遗

    企业内部的包需要通过nuget来管理发布,或者一些不允许上外网的企业,通过自己的nuget服务器来使用nuget,都会考虑到自建一个nuget服务器.本文整理了一些有用的链接和使用心得,以备不时之需. ...

  9. vs技巧总结

    工欲善其事,必先利其器,作为一个优秀的程序员很重要的一点就是要善用工具.最近专注于工具开发的我,最近觉得工具的使用,站在巨人的肩膀上进行劳作,而不是不断的造轮子,是非常重要的. 时间最贵,因为对于每个 ...

  10. 土办法 填充NAS空间

    最近需要把一个1.8TB的NAS 塞满,网上东拼西凑,找了个办法 写脚本,然后保存为tt40.sh, 并上传到NAS中. #!/bin/sh echo "space2->space11 ...