现在ISP已经很常用了,有那位先生能讲讲IAP的应用,或者

[复制链接]
2007|5
手机看帖
扫描二维码
随时随地手机跟帖
jerkoh| | 2008-8-28 11:07 | 显示全部楼层

re

关注

使用特权

评论回复
dld2| | 2008-8-28 11:14 | 显示全部楼层

貌似不是问题

使用特权

评论回复
lyjian| | 2008-8-28 11:30 | 显示全部楼层

ISP和IAP是两回事

支持ISP的MCU不一定支持IAP
ISP/IAP看一下相应的规格书就知道怎么用了
ZLGMCU网站有些ISP/IAP相关的**,可以参考一下
如《ISP技术及在智能仪器中的应用》

使用特权

评论回复
iammercy| | 2008-8-28 11:53 | 显示全部楼层

IAP的應用

中穎單片機79Fxxx系列 

SH79Fxxx Flash use as EEPROM
79Fxxx的flash可以当EEPROM用
原理:79Fxxx的flash rom是由数个sector组成,每个sector大小为2kB
如 79F161,有16K rom, 则有8个sector
可以划分一个sector作为flash eeprom,节省外围的eeprom器件,如24C02
从而节省成本。

79Fxxx Flash ROM的擦写寿命最少有1万次,若每次只需要保存8个字节,
可以把整个sector 2k空间划分为256页,每页8个字节,
当写满256页才进行擦除,这样理论上寿命可以达到128万次,大大提高可靠性能

由于每次写保存到flash rom的地址都不一样,例如采用sector 6
第一次保存数据是保存到 0x3000~0x3007,第二次写flash后数据则保存到0x3008~0x300f,
例子中通过二分法算法查询上次保存的那8个数据保存到第几页,以便读出最新写入的数据,或者继续写数据到后续空页处,
二分法算法大大提高索引效率。

程序提供2个函数,方便对flash读写操作
void WriteFlash(Byte *ptr)        //ptr is the head pointer of the write buffer
void ReadFlash(Byte *ptr)        //ptr is the head pointer of the read buffer

注意的地方:
Flash ROM的第一个sector和最后一个sector不能用作flash eeprom
因为第一个sector(即程序code区0x0000~0x0fff)包含中断向量入口,
最后一个sector的最后64个Bytes被硬件屏蔽,
eg:对于79F161,Sector 1,2,3,4,5,6可以用作flash eeprom,而Sector0和Sector7则不能用作flash eeprom

振荡器频率为8M,写周期为30us(写入一个Byte),擦周期为60ms(擦除整个Sector)
也可以根据需要使用其它振荡器频率,擦Flash和写Flash周期设置为符合规格书要求即可

具体说明及设置请查看源程序注释
程序解釋
SSP實現Flash當EEPROM驅動:
79Fxxx的flash rom是由数个sector组成,每个sector大小为2kB,79F161有16K rom, 共8个sector
程序中劃分sector6作为flash eeprom,节省外围的eeprom器件,如24C02,从而节省成本。
        
Flash ROM的第一个sector和最后一个sector不能用作flash eeprom用途
因为第一个sector包含中断向量入口,最后一个sector的最后64个Bytes被硬件屏蔽,对于79F161,Sector 1,2,3,4,5,6可以用作flash eeprom,而Sector0和Sector7则不能用作flash eeprom
#define        SECTOR1         0x0800                        //0800~0fff
#define        SECTOR2         0x1000                        //1000~17ff
#define        SECTOR3         0x1800                        //1800~1fff
#define        SECTOR4         0x2000                        //2000~27ff
#define        SECTOR5         0x2800                        //2800~2fff
#define        SECTOR6         0x3000                        //3000~37ff
#define        SECTOR         SECTOR6                        //劃分SECTOR6作為EEPROM
79Fxxx Flash ROM的擦写寿命有1萬次,程序中把整个sector 2k空间划分为256页,每页8个字节,当写满256页才进行擦除,这样理论上數據保存可以达到128万次,大大提高壽命及可靠性能
#define FLASH_PAGE_BYTES                8        //    this value divide exactly by 2048
#define FLASH_PAGE_COUNT                2048/FLASH_PAGE_BYTES        
//allocate flash eeprom area at ROM sector 6 (C:0x3000~C:0x37ff)
typedef struct 
{
                Byte        ROM[FLASH_PAGE_BYTES];
}FLASH_MEMORY;                                                                                                //flash Page datastructure
FLASH_MEMORY        code        Flash[FLASH_PAGE_COUNT]         _at_        SECTOR;                //flash eeprom datastructure
        
每次寫數據即寫一個Byte時間必須設定在30us左右,每次擦除即整個Sector清零時間必須設定在60ms左右
#define                PROGRAM_CLK                (65536 - 30)                                //*** 30us/(8*125ns) = 30us
#define                ERASE_CLK                        (65536 - 60000)                                //*** 60ms/(8*125ns) = 60000us
        
每次寫時寫到上次寫的那頁的后一頁,每次讀時返回最新寫的那一頁的數據,由于每次写保存到flash rom的地址都不一样,采用sector 6,第一次保存数据是保存到 0x3000~0x3007,第二次写flash后数据则保存到0x3008~0x300f,通过二分法算法求得上次保存的数据保存到第几页,以便读出最新写入的数据,或者继续写数据到后續的空页处,二分法算法大大提供索引效率。
        
                
判斷某一頁是否為NULL
bit        CheckFlashPageNull(Byte index)                
{
                        Byte i;
                        for(i=0;i<FLASH_PAGE_BYTES;i++)
                        {
                                if(Flash[index].ROM)
                                {
                                        return 1;
                                }        
                        }
                        return 0;
}        
        

二分法求得有效數據的頁索引號,并返回有效數據是否為NULL標記
bit        GetFlashPageIndex(Byte *index)                
{
                        Byte low  = 0;
                        Byte high = FLASH_PAGE_COUNT-1;                                
                        Byte mid;
                        bit         flag;
                
                        while(1)
                        {                
                                mid  = low+(high-low)/2;
                                flag = CheckFlashPageNull(mid);
                                if(mid == low)
                                {
                                        break;
                                }
                                if(flag)
                                {
                                        low = mid;
                                }
                                else
                                {
                                        high = mid;
                                }
                        }
                        if(CheckFlashPageNull(high))
                        {
                                *index = high;
                                return 1;
                        }
                        else
                        {
                                *index = low;
                                return        flag;        
                        }
}
SSP寫Flash函數
void        ProgramFlash(Byte pageIndex,Byte *ptr)
{
        Word        FlashAddr=Flash;
        Byte         i;
        Bit                EA_BAK = EA;                
        //---------------------------------------
        for(i=0;i<pageIndex;i++)        
        {
                FlashAddr +=FLASH_PAGE_BYTES;
        }
        EA = 0;                                                                //step 1
        IB_CLK1        =        (PROGRAM_CLK>>8)&0xff;        //step 2
        IB_CLK0        =        (PROGRAM_CLK)&0xff;
        for(i=0;i<FLASH_PAGE_BYTES;i++)
        {
                XPAGE          = HIBYTE(FlashAddr);        //step 3
                IB_OFFSET= LOBYTE(FlashAddr);
                IB_DATA         = *(ptr+i);                        //step 4
                IB_CON1         = 0x6E;                                //step 5
                IB_CON2         = 0x05;
                IB_CON3         = 0x0A;
                IB_CON4         = 0x09;
                IB_CON5         = 0x06;
                _nop_();                                                //step 6
                _nop_();
                _nop_();
                _nop_();
                FlashAddr ++;                                        //step 7
        }                                
        //---------------------------------------
        EA = EA_BAK;
}
SSP擦除Flash函數
void        EraseFlash(void)
{
                Word        FlashAddr=Flash;
                Bit                EA_BAK = EA;
                //---------------------------------------
                EA = 0;                                                                //step 1
                IB_CLK1         = (ERASE_CLK>>8)&0xff;        
                IB_CLK0         = (ERASE_CLK)&0xff;                //step 2
                XPAGE          = HIBYTE(FlashAddr);                //step 3
                IB_OFFSET= LOBYTE(FlashAddr);
                IB_CON1         = 0xE6;                                        //step 4
                IB_CON2         = 0x05;
                IB_CON3         = 0x0A;
                IB_CON4         = 0x09;
                IB_CON5         = 0x06;
                _nop_();                                                        //step 5
                _nop_();
                _nop_();
                _nop_();        
                //---------------------------------------
                EA = EA_BAK;
}
寫數據
第1次寫數據時,由于之前從未寫過數據,返回的索引號為0,且該頁為NULL,于是便把數據寫到第0頁。
第2次寫數據時,返回的索引號為0,該頁非NULL,于是便把數據保存到第1頁
….
第256次寫數據時,返回的頁索引號為0xff,該頁非NULL,先擦除整個SECTOR,再把數據寫到第0頁
void Driver_WriteFlash(Byte *ptr)
{
                bit        flag;
                Byte index;
                flag = GetFlashPageIndex(&index);
                if(index == (FLASH_PAGE_COUNT-1))
                {
                        EraseFlash();
                        index =0;
                }
                else if(flag)
                {
                        index ++;
                }
                ProgramFlash(index,ptr);
}
讀數據
根據索引值讀出有效數據,有待后續校驗
void Driver_ReadFlash(Byte *ptr)
{
        Byte i;
        Byte index;
        GetFlashPageIndex(&index);        
        for(i=0;i<FLASH_PAGE_BYTES;i++)
        {
                *ptr = Flash[index].ROM;
                ptr ++;
        }
}
 
 

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

113

帖子

1

粉丝