引言
本应用笔记的目的是说明如何从应用程序写FLASH。在应用编程(IAP)允许将FLASH用于非易失性信息的存储(例如配置参数),还可以允许采用JTAG接日之外的另一种接日(例如UART)进行在系统引导装载。本笔记的最后给出了如何读和写FLASH的‘C’代码。
关键点
- 在应用编程(IAP)允许将FLASH用于非易失性信息的存储,这一点与EPROM类似。
- FLASH写/擦除寿命在-40~ + 85℃的工业温度范围内保证在10000次以上。
- FLASH存储器用MOVC指令读取(MOVC A, @A+DPTR)。
- FLASH存储器用MOVX指令写入(MOVX @A+DPTR, A)。
- FLASH页以512字节分界(0200h, 0400h,依此类推)。
- FLASH写操作只能写入0。因此在写一个FLASH字节之前,包含该字节的页必须首先被擦除(使该页中的所有位都为1)。
- 在进行FLASH写或擦除之前,必须根据当前的系统时钟设置FLSCL中的LASCL位。
- 在进行FLASH写之前,必须将PSWE置1
- 在进行FLASH擦除之前,必须将PSWE和PSEE置1。
- FLASH页的擦除操作是将PSWE和PSEE置1并向该页512字节中的任一字节进行写操作。
- 含有读锁定字节和写/擦除锁定字节的FLASH页不能由用户软件擦除(但是,该页可以由用户软件写入)。该页只能通过JTAG接口擦除。
过程
FLASH是按一系列512字节的页组织的。另外还有一个128字节的页,该页位于FLASH的顶部,起始地址为0x8000。由于写一个FLASH字节只能对各位写入0,因此在写一个FLASH字节之前,该字节必须被初始化为OxFF。一个FLASH擦除操作将一页内的所有字节初始化为OxFF。
擦除一个FLASH页
一个FLASH页可以通过下述过程擦除:
1.根据当前系统时钟频率值按C8051F000数据表的说明设置FLSCL(当使用缺省的2MHz内部振荡器时,FLSCL=0x86 )。
2.通过向PSCTL写入03h使PSWE和PSEE置1。
3.向待擦除页内的任一字节写入任意值:
- ;初始化DP丁R,使其指向待擦除页内的地址
- mov DPTR, #address
- ;启动擦除过程
- movx @DPTR, a
4.如果不再进行擦除操作,将PSEE设置为'0'。
擦除每个页击要10到20ms的时间。注意:CPU内核在FLASH擦除过程中停止工作,但外设(象ADC, UAR丁、SMBus和定时器)仍然工作。在擦除过程中产生的千日可中断都将被挂起,直到该过程结束。在写一个FLASH字节期间CPU的工作情况与此相同。
写一个FLASH字节
下述过程用于写一个FLASH字节:
1.根据当前系统时钟频率值按C8051F000数据表的说明设置FLSCL(当使用缺省的2MHz内部振荡器时,FLSCL=0x86)。
2.通过向PSCTL写入01h使PSWE置1 (PSEE必须为'0')
3.写入字节数据。
- ;初始化DPTR,
- mov DPTR
- 使其指向待写字节的地址
- #address
- ;将待写字节装入acc
- mov a, #value
- ;启动写操作
- movx
- @DPTR, a
4.如果不再进行写操作,将PSWE设置为'0'。
每个FLASH字节的写操作击要20到40μs的时间。
更新FLASH中的数据
当保存一组配置信息时,经常需要在一组字节中单独改变某个字节的数值。单独更新某个字节(或字节子集)的一般过程如下:
1.将FLASH页拷贝到一个临时存储区(RAM或一个己被擦除的‘临时’FLASH页)
2.擦除FLASH页的数据
3.将前面存储在临时存储区的内容复制到FLASH页中。
用'C'代码访问FLASH
所附的小例代码说明了如何用`C'程序擦除、写和读FLASH内容。由于FLASH读操作是用MOVC指令实现的,因此用于读操作的FLASH指针必须是CODE类型。由于FLASH写操作是用MOVX指令实现的,所以用于写(或擦除)操作的FLASH指针必须是XDATA类型。
软件示例
- //-----------------------------------------------------------------------------------------------------------------------
- //FLASH_1.c
- //-----------------------------------------------------------------------------------------------------------------------
- //
- //作者BW
- //
- //本示例程序给出了用C程序擦除写和读FLASH存储器的例子
- //
- //目标器件C8051F000或C8051F010
- //开发工具KEIL C51
- //
- //-----------------------------------------------------------------------------
- //包含文件
- //-----------------------------------------------------------------------------
- #include<c8051f000.h>//SFR声明
- #include<stdio.h>
- //-----------------------------------------------------------------------------
- //Function PROTOTYPES
- //-----------------------------------------------------------------------------
- void main(void){
- unsigned char test_string[]="Howdy!";//将被拷贝到FLASH中的字符串
- unsigned char xdata*pwrite;//程序存储器空间的指针FLASH指向待写地址
- unsigned char code*pread;//程序存储器空间的指针FLASH指向待读地址
- unsigned char*pgen;//一般指针
- char test;//测试字符
- //禁止看门狗定时器
- WDTCN=0xde;
- WDTCN=0xad;
- //擦除128字节的信息页位于0x8000
- FLSCL=0x86;//设置FLASH标度寄存器对2MHz系统时钟
- PSCTL=0x03;//将PSWE和PSEE置1 MOVX指令对应
- //的FLASH页
- pwrite=0x8000;//将指针指向待擦除页
- *pwrite=0;//启动擦除过程
- PSCTL=0x01;//清除PSEE PSWE仍然置1
- //MOVX指令将写到对应的地址
- //现在我们要拷贝字符串<test_string>的内容到FLASH页从地址0x8000开始
- pgen=test_string;//pgen指向源字符串
- do{
- *pwrite++=*pgen++;//拷贝字节
- }while(*pgen!='\0');//直到NULL结束符
- *pwrite=NULL;//用NULL结束目的字符串
- PSCTL=0;//禁止FLASH写
- FLSCL=0x8f;//禁止FLASH写
- //现在我们读写入的字符串
- pread=0x8000;//初始化CODE读指针为字符串起始地址
- test=0x5a;
- do{
- test=*pread++;
- }while(test!='\0');
- while(1){//原地循环
- }
- }