本帖最后由 zcxhe 于 2010-6-26 10:20 编辑
stm8s103有没有试过块操作?今天试了好久都不行!单字节跟字写可能,块操作不行!
仔细看了资料,STM8的FLASH擦除确实是写0:
“要擦除一个字节,向对应的字节简单写入’0x00’即可。”
但实际上还是存在擦除操作,:
“自动快速字节编程
根据目标地址的初始化内容的不同,编程持续时间可能也有所不同。如果字(4个字节)中包含不 为空的字节,在编程前整个字会被自动擦除。相反,如果字为空,由于不会执行擦除操作从而 编程时间变短(请参考tPROG参数,在数据手册的”Flash program memory”表中)。
然而,可以通过对FLASH_CR1中的FIX位置1来强迫执行系统擦除操作而不管其内容是否为 空,从而使编程时间固定(请参考FLASH控制寄存器)。编程总时间随之被规定为擦除时间和写 操作时间的和(请参考tPROG参数,在数据手册的”Flash program memory”表中)。
注意:为了快速写一个字节(没有擦除操作),将要被写入数据的整个字(4个字节)必须被预先擦除。因此不 可能对同一个字做连续两次快速写操作(在第二次写之前没有擦除操作):第一次写字节操作将是 快速操作但针对另外一个字节的第二次写操作将需要一个擦除操作。”
标准块写也有自动擦除作动!只有快速块写没有!注意这段话:
“一共有三种可能的块操作:
● 块编程(也叫标准块编程):整个块在编程前被自动擦除。
● 快速块编程:在编程前没有预先的块擦除操作。
● 块擦除。 在块编程时,中断被硬件自动屏蔽。
标准块编程 块编程操作允许一次对整个块进行编程,整个块在编程前被自动擦除。 为了对整个块编程,FLASH_CR2和FLASH_NCR2中的PRG/NPRG位必须预先置位/清零来使
能标准块编程(请参考4.9.2 FLASH控制寄存器2(FLASH_CR2)和4.9.3 FLASH互补控制寄存器
2(FLASH_NCR2))。然后需要向主程序存储器或DATA区域的目标地址依次写入要编程的数据,
这样数据会被锁存在内部缓存中。为编程整个块,块中的所有字节都需要被写入数据。但要注意,所有被写入缓存的数据必须位于同一个块中,这意味着这些数据必须有同样的高位地址:仅仅低6位的地址可以不一样。当目标块的最后一个字节被装载到缓存后,编程就自动开始了。编程前首先会自动执行一次擦除操作。
”
验证的关键在快速块编程这里:
“快速块编程
快速块编程允许不擦除存储器内容就对块进行编程,因此快速块编程的编程速度是标准块编程 的两倍。该模式仅用于被编程部分已经被擦除过的情况,同时这种模式对向空白部分写入完整的应用代码特别有用,因为这种模式可以节省相当可观的时间。
快速块编 程的步骤 和标准 块 编程的步 骤大致一 样, FLASH_CR2 和 FLASH_NCR2 中的
FPRG/NFPRG 位必须预先置位 / 清 零来使能快 速块编程 ( 请参考 4.9.2 FLASH 控制寄存器
2(FLASH_CR2)和4.9.3 FLASH互补控制寄存器2(FLASH_NCR2))。
FLASH_IAPSR中的EOP与WR_PG_DIS控制位和FLASH中断相配合,可用于检查快速块编程 操作是否被正确执行完毕。
以下这句话最关键:
警告:在执行快速块编程之前如果这个块不是空的话,不能保证写入的数据无误。”
不过我现在的程序对块操作执行不了,不知道那里不对!
针对目前已经测试的字节与字操作,STM8的FLASH确实已经可以当EEPROM用了!有点怀疑这FLASH是否是EEPROM装的?当然要用快速块编程来测试!如果确实是FLASH的,那么它事实上最小的页就该是四个字节,而不是64字节,推测写字节的时候芯片内部是先把四个字节的数据读出到内部缓冲器修改数据,然后执行擦除操作,最后再写回去!
/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
#include "cst_h\STM8S103F3P.h" //寄存器定义
volatile unsigned char tmp1 @0x9700;
volatile unsigned char tmp2 @0x9701;
volatile unsigned char tmp3[4] @0x9700;
volatile unsigned char tmp4[64] @0x9700;
#define FLASHMASS1 0x56
#define FLASHMASS2 0xAE
void subpr_flash_enable_write(void)
{
IWDG_KR = 0xAA;
FLASH_PUKR = FLASHMASS1; //锁1密钥
FLASH_PUKR = FLASHMASS2; //锁2密钥
while ((unsigned char)!(unsigned char)(FLASH_IAPSR & 0x02))
{
_asm("NOP"); //等待解密就绪
}
}
void subpr_flash_disenable_write(void)
{
FLASH_IAPSR &= (unsigned char)~0x02;
}
main()
{
volatile unsigned char i;
while (1)
{
//字节写
subpr_flash_enable_write();
FLASH_CR2 = 0x00;
FLASH_NCR2 = 0xff;
_asm("NOP");
tmp1=0xaa;
_asm("NOP");
tmp2=0x55;
_asm("NOP");
tmp1=0x55;
_asm("NOP");
tmp2=0xaa;
_asm("NOP");
//字写
//subpr_flash_enable_write();
FLASH_CR2 = 0x40;
FLASH_NCR2 = (unsigned char)~0x40;
_asm("NOP");
tmp3[0] = 0xaa;
tmp3[1] = 0x00;
tmp3[2] = 0x55;
tmp3[3] = 0xff;
_asm("NOP");
//以下单步执行可以,连续运行就出错!有懂的给个正确代码,谢谢!
//标准块编程
//subpr_flash_enable_write();
FLASH_CR2 = 0x01;
FLASH_NCR2 = (unsigned char)~0x01;
_asm("NOP");
for (i = 0; i <64; i++)
{
tmp4 = i;
}
_asm("NOP");
//快速块编程
//subpr_flash_enable_write();
FLASH_CR2 = 0x10;
FLASH_NCR2 = (unsigned char)~0x10;
_asm("NOP");
for (i = 0; i <64; i++)
{
tmp4 = (unsigned char)(64 - i);
}
_asm("NOP");
//块擦除
//subpr_flash_enable_write();
FLASH_CR2 = 0x20;
FLASH_NCR2 = (unsigned char)~0x20;
_asm("NOP");
for (i = 0; i <16; i++)
{
tmp4[(unsigned char)(i * 4)] = 0x00000000;
}
_asm("NOP");
subpr_flash_disenable_write();
_asm("NOP");
}
}
|