本帖最后由 NC_Zyang 于 2014-8-20 15:02 编辑
这个是在网上找的例程,有些不懂的地方望大侠们帮帮忙:
- #define READword(address) ((unsigned int)(*(volatile unsigned int *__near)(address)))
- #define DFLASH_LOWEST_START_PAGE 0x00 //定义data flash的起始页
- #define DFLASH_START 0x00100000 //定义data flash的起始地址
- #define DFLASH_PAGE_SIZE 0x0400 //定义data flash的大小为1K.
- #define DFLASH_PAGE_WINDOW_START 0x0800 //定义data flash页面窗口的起始地址
- #define LEDCPU PORTK_PK4
- #define LEDCPU_dir DDRK_DDRK4
- unsigned int Buffer[]={0x1111,0x2222,0x3333,0x4444};//数据缓存区,只能一次写入四个数据
- unsigned int data_Address=0x0000;
- unsigned int date_read[4];
复制代码- void DFlash_Init(void)
- {
- while(FSTAT_CCIF==0); //等待正在处理的FLASH操作完成
- FCLKDIV=0x0F; //外部晶振为16M.FLASH时钟不超过1M,具体参照手册
- FCNFG=0x00; //禁止中断
- while(FCLKDIV_FDIVLD==0); //等待时钟设置成功
- }
复制代码- void DFlash_Write(word ADDR16)
- {
- while(FSTAT_CCIF==0);
- if(FSTAT_ACCERR) //判断并清除标志位;
- FSTAT_ACCERR=1;
- if(FSTAT_FPVIOL) //判断并清除标志位;
- FSTAT_FPVIOL=1;
- FCCOBIX_CCOBIX=0x00;
- FCCOB=0x1110; //写入命令和高位地址
- FCCOBIX_CCOBIX=0x01; //地址后16位
- FCCOB=ADDR16; //写入低16位地址
- FCCOBIX_CCOBIX=0x02; //写入第一个数据
- FCCOB=Buffer[0];
- FCCOBIX_CCOBIX=0x03; //写入第二个数据
- FCCOB=Buffer[1];
- FCCOBIX_CCOBIX=0x04; //写入第三个数据
- FCCOB=Buffer[2];
- FCCOBIX_CCOBIX=0x05; //写入第四个数据
- FCCOB=Buffer[3];
-
- FSTAT_CCIF=1; //写入执行命令
- while(FSTAT_CCIF==0); //等待执行完毕
- }
复制代码
- word DFlash_Read (word destination)
- {
- byte lastepage; //用于存储EPAGE的值
- byte epage; //用于计算EPAGE的值
- unsigned int data; //读取出的数据
- lastepage = EPAGE; //保存EPAGE的值
- epage = (byte)((DFLASH_LOWEST_START_PAGE)+(destination >>10)); //计算EPAGE
- EPAGE=epage; //给EPAGE赋值
-
- data = READword((destination & (DFLASH_PAGE_SIZE - 1)) + DFLASH_PAGE_WINDOW_START); //读取页面窗口中的数据
- EPAGE= lastepage; //恢复EPAGE的值
- return(data);
- }
复制代码- void DFlash_Erase(word ADDR16)
- {
- while(FSTAT_CCIF==0);
- if(FSTAT_ACCERR) //判断并清除标志位;
- FSTAT_ACCERR=1;
- if(FSTAT_FPVIOL) //判断并清除标志位;
- FSTAT_FPVIOL=1;
-
- FCCOBIX_CCOBIX=0x00;
- FCCOB=0x1210; //写入擦除命令和高位地址
- FCCOBIX_CCOBIX=0x01;
- FCCOB=ADDR16; //写入低16位的地址
- FSTAT_CCIF=1; //启动执行命令
- while(FSTAT_CCIF==0); //等待执行完成
- }
复制代码- void main(void)
- {
- DisableInterrupts;
- LEDCPU_dir=1;
- LEDCPU=1;
- EnableInterrupts;
-
- DFlash_Init(); //初始化Flash
- DFlash_Erase(data_Address); //确保先擦除后写入
- DFlash_Write(data_Address);
- date_read[0]=DFlash_Read(data_Address);
- date_read[1]=DFlash_Read(data_Address+2);
- date_read[2]=DFlash_Read(data_Address+4);
- date_read[3]=DFlash_Read(data_Address+6);
-
- if(date_read[0]==0x1111&&date_read[1]==0x2222&&date_read[2]==0x3333&&date_read[3]==0x4444) //判断数据是否正确
- LEDCPU=0; //点亮指示灯
- for(;;)
- {
- }
- }
复制代码
这个DFlash_Write是写DFLASH的函数,从datasheet的599页知道这个全局地址是0x100000+ADDR16,这里的ADDR16写的是0x0000;那么这个起始写的地址就是0X100000吧,datasheet已经截图了。
从主函数可以知道第一个数据0x1111在地址0x100000里,0x2222在地址0x100002里,0x3333在地址0x100004里,0x4444在地址0x100006里,通过仿真也验证了全局地址里面存的数据就是对应的数据;
但是在 DFlash_Read读DLFASH函数中,(destination & (DFLASH_PAGE_SIZE - 1)) + DFLASH_PAGE_WINDOW_START这个却是0x8000,起始读地址就是从0x108000开始的?
#define READword(address) ((unsigned int)(*(volatile unsigned int *__near)(address)))这个用near指针,说明是在64k内,那么它所取地址范围就是0~0XFFFF内咯?怎么会知道0x100000里呢?
此外,在datasheet第137页里面可知道1KB的FLASH地址是从0x100800~0x100BFF的,但是上面的起始地址却是0x100000开始的?
上面的代码都是仿真过了的,而且正确。
请了解这个的帮我解答解答上面的疑问,谢谢。
这个怎么加(已解决)呢?没有弄过呢。
你已经加好了,就是编辑一楼,然后在标题后面加(已解决)。
你可以看到EPAGE的介绍,看的到全局地址的格式,然后你看低10位是CPU的Local Address,EPAGE就是设置它的页地址,因为我们DFLASH有256KB,在操作中给他分为了256个页,每页为1K,这么就有256KB的存储空间,在这里,256页就是用EPAGE来操作的,然后低10位就是CPU Local Address,就举个例子吧,我全局地址设置为0b00100 00000001
0100000000,16进制为0x100500,但是你访问肯定是访问CPU的当地地址,当地地址是0x100,这个时候如果是设置EPAGE为0,那么读取的地址就是0x100100,如果你设置EPAGE为1,那么读取的地址就是0x100500了。可能描述不是很清楚吧。大体意思是这样的。
这个主要飞思卡尔是这么设计的,如果要看其他MCU是否这么设计,需要看先关datasheet。然后就是哪个EPAGE不是CPU去控制,是我们程序去设置,就像你要读0x100500的话,那么你应该先把EPAGE设置成0x01,然后再去读地址0x100.
一周热门 更多>