[综合信息] KF8F4156 Flash的读写操作

[复制链接]
373|0
 楼主 | 2017-7-31 15:55 | 显示全部楼层 |阅读模式
  1. /*************************************************************************************
  2.      标         题: Flash的读写操作
  3. * 项  目  名: W-R_FLASH_TEST
  4. * 开发环境:ChipON IDE
  5. * 使用芯片:KF8F4156
  6. * 作          者:上海芯旺微电子技术有限公司
  7. * 功能简述:  如程序所示,对相应的地址进行操作,操作结果通过断电 使用PRO读取。
  8. *
  9. * 跳线接法:只需给单片机供电即可,为了观看数据操作是否完成,可以连接P12和J21 ,当D4灯闪烁时表示操作完成。可断电读取数据。
  10. *
  11. * 特殊说明: 程序会占用不确定的FLASH地址,因此你需要确定用于自写的块或确保当前使用地址为非程序区
  12. *                         当前芯片的可自写范围:800H~1FDFH,
  13. *                         实现方法在该项目目录中建立occupancy.txt的文件,添加地址占用描述使编译器跳过该段区域的实现
  14. *                         格式:
  15. *                        一行一条记录,一条记录由3部分组成标识、起始地址、结束地址。
  16. *                        文件可以包含任意多条记录
  17. *                        标识用于标记占用数据段还是代码段,可以是code或者是data。
  18. *                        起始地址结束地址使用十六进制表示。
  19. *                        占用包含起始和结束地址。
  20. *
  21. *                        例如
  22. *                        data 0x180 0x190
  23. *                        code 0x800 0x810
  24. *************************************************************************************/
  25. #include <KF8F4156.h>
  26. //====================////////////////////FLASH相关声明/////////////////==============//////////
  27.                                 /*参数传递说明见函数实现位置*/
  28. #define                        FLASH_BUFFER_MAX        32                // 数据的大小与单次操作量相关,这里int型,16,32,除非不用写操作或不关心一些数据。
  29. #define         LED  P1LR2
  30. unsigned int         FLASH_BUFFER[FLASH_BUFFER_MAX];

  31. unsigned int    FLASH_READ_BUF;        //当单字读函数使用非全嵌汇编模式时,使用该值获取读取结果值
  32. unsigned int         FLASH_READ_ONE        (unsigned int address);        //读一个字
  33. void                         FLASH_READ_FUN        (unsigned int address,unsigned char length);//读多个数据到数据缓存区,建议最多量为1个页即32个数据,同时建议不跨页操作,与写函数对应
  34. void                         FLASH_WRITE_ONE        (unsigned int address,unsigned int value);  // 过程封装
  35. void                         FLASH_WRITE_FUN        (unsigned int address,unsigned char length); //将缓存区数据写到对应位置,从第一个开始
  36. ///=========================================================================================///
  37. void init_mcu()
  38. {
  39.         OSCCTL = 0x60;                           //设置为8M
  40.         /*********端口初始化***********/
  41.         TR0 = 0x04;                                                 //设置P0端口         1100 1111
  42.         TR1 = 0x00;                                                 //设置P1端口        0000 0000
  43.         TR2 = 0x00;                                                 //设置P2端口        0011 1111
  44.         P0 = 0x00;
  45.         P1 = 0x80;                        //P1.6 P1.7 指示运行结束灯
  46.         P2 = 0xF0;
  47. }

  48. void main()
  49. {
  50.         unsigned char i;
  51.         unsigned int temp=0;
  52.         init_mcu();
  53. //--- 准备待写入的数据0x0000 0x1111 0x2222...0xFFFF  0x1110  0x2221  0x3332 ...0xFFFE 0x110F
  54.         for (i = 0; i < FLASH_BUFFER_MAX; i++)
  55.         {
  56.                 FLASH_BUFFER[i] = temp;
  57.                 temp += 0x1111;
  58.         }

  59. //---setp 1                 写入到0x1E60 和0x1E80的FLASH空间 (页的首地址)
  60.         FLASH_WRITE_FUN(0x1E60,FLASH_BUFFER_MAX);
  61.         FLASH_WRITE_FUN(0x1E80,FLASH_BUFFER_MAX);


  62. //--- setp 2                 读取 0x1E71,并写入到0x1EB5
  63.         // 读取所需到缓存
  64.         temp=FLASH_READ_ONE(0x1E71);
  65.         // 非需要段的任意数据填充
  66.         for (i = 0; i < 16; i++)
  67.         {
  68.                 FLASH_BUFFER[i] = 0x0000;
  69.         }
  70.         //应该擦除0x1EA0页的数据 以便后续以0x1EB0开始的块写,如果确定该页为0xFFFF,可以跳过
  71.         FLASH_WRITE_FUN(0x1EA0,16);
  72.         // 修改要写入的值
  73.         FLASH_BUFFER[5]=temp;
  74.         FLASH_BUFFER[6]=0xFF33; //验证 用 0x1FB6
  75.         // 执行0x0F98块的写入
  76.         FLASH_WRITE_FUN(0x1EB0,16);


  77. //--- setp 3        将OX0F69中的数据修改为0X55AA
  78. #if 1        // 0 或  1
  79.         FLASH_WRITE_ONE(0x1E69,0x55AA);
  80. #else
  81.         FLASH_READ_FUN(0x1E60,FLASH_BUFFER_MAX);        //缓存必须满足操作对应大小,不满足整页时,后续数据被删空
  82.         FLASH_BUFFER[9]=0x55AA;
  83.         FLASH_WRITE_FUN(0x1E60,FLASH_BUFFER_MAX);
  84. #endif


  85. //----------------------------------------- setp 4  end display
  86.         while(1)
  87.         {
  88.                 temp++;
  89.                 if(temp>30000)
  90.                 {
  91.                         temp=0;
  92.                         LED = !LED;
  93.                 }

  94.         }
  95. }
  96. /***********************************************************************************
  97. * 函数名     :FLASH_READ_ONE
  98. * 函数功能:以设定地址开始,读取一个数的FLASH数据并返回结果
  99. * 入口参数:起始地址
  100. * 返回          :无
  101. **********************************************************************************/
  102. unsigned int FLASH_READ_ONE(unsigned int address)
  103. {
  104. #if  1          // 1 选用C语言表达  0 选用嵌汇编表达,嵌汇编效率更高,但提示传递参数未使用和函数无返回,可以忽略

  105.         // FLASH_READ_BUF;  需要定义全局的该变量,获取值用于返回,或直接使用
  106.         //; 参数的使用
  107.         NVMADDRH=(unsigned char)(address>>8);
  108.         NVMADDRL=(unsigned char)address;
  109.         __asm
  110.                 ;//备份中断使能寄存器
  111.                         BANKSEL _INTCTL
  112.                         MOV                R1,_INTCTL
  113.                 ;//关闭中断,操作不可打断
  114.                         CLR                _INTCTL,_AIE
  115.                         JNB                _INTCTL,_AIE
  116.                         JMP                $-2
  117.                 ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
  118.                         MOV                R0,#0x30
  119.                         MOV                R2,_OSCCTL
  120.                         MOV                _OSCCTL,R0
  121.                 ;//硬件使能读操作
  122.                         BANKSEL _NVMCTL0
  123.                         MOV         R5,#0x81
  124.                         MOV         _NVMCTL0,R5
  125.                         NOPZ
  126.                         NOPZ
  127.                         NOPZ
  128.                         NOPZ
  129.                 ;//时钟与中断使能的还原
  130.                         MOV                _OSCCTL,R2
  131.                         AND         R1,#0xC0        ;//中断使能仅关系高2位
  132.                         ORL         INTCTL,R1
  133.                 ;//操作结果赋值到变量,用于返回
  134.                         BANKSEL        _NVMDATAL
  135.                         MOV        R6,_NVMDATAL
  136.                         MOV        R7,_NVMDATAH
  137.                         BANKSEL _FLASH_READ_BUF
  138.                         MOV (_FLASH_READ_BUF),R6
  139.                         MOV (_FLASH_READ_BUF+1),R7
  140.         __endasm;
  141.         return         FLASH_READ_BUF;
  142. #else
  143.         // 参数的传递使用  编译器自动变量 STK00  和 R0 ,其中R0为高位,返回使用STK00  和 R0 ,其中R0为高位
  144.         __asm
  145.         ;//传递操作地址
  146.                 BANKSEL _NVMADDRH
  147.                 MOV                _NVMADDRH,R0
  148.                 BANKSEL STK00
  149.                 MOV                R0,STK00
  150.                 BANKSEL _NVMADDRL
  151.                 MOV                _NVMADDRL,R0
  152.         ;//备份中断使能寄存器
  153.                 BANKSEL _INTCTL
  154.                 MOV                R1,_INTCTL
  155.         ;//关闭中断,操作不可打断
  156.                 CLR                _INTCTL,_AIE
  157.                 JNB                _INTCTL,_AIE
  158.                 JMP                $-2
  159.         ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
  160.                 MOV                R0,#0x30
  161.                 MOV                R2,_OSCCTL
  162.                 MOV                _OSCCTL,R0
  163.         ;//硬件使能读操作
  164.                 BANKSEL _NVMCTL0
  165.                 MOV         R5,#0x81
  166.                 MOV         _NVMCTL0,R5
  167.                 NOPZ
  168.                 NOPZ
  169.                 NOPZ
  170.                 NOPZ
  171.         ;//时钟与中断使能的还原
  172.                 MOV                _OSCCTL,R2
  173.                 AND         R1,#0xC0        ;//中断使能仅关系高2位
  174.                 ORL         _INTCTL,R1
  175.         ;//操作结果提供形式 整型数据返回结果使用  编译器自动变量 STK00  和 R0 ,其中R0为高位
  176.                 BANKSEL        _NVMDATAL
  177.                 MOV                R0,NVMDATAL
  178.                 BANKSEL STK00
  179.                 MOV                STK00,R0

  180.                 BANKSEL        _NVMDATAH
  181.                 MOV                R0,NVMDATAH
  182.         __endasm;
  183. #endif

  184. }
  185. /***********************************************************************************
  186. * 函数名     :FLASH_READ_FUN
  187. * 函数功能:以设定地址开始,读取一定个数的FLASH数据放置到数值FLASH_BUFFER[x]中
  188. * 入口参数:起始地址,操作个数
  189. * 返回          :无
  190. **********************************************************************************/
  191. void FLASH_READ_FUN(unsigned int address,unsigned char length)
  192. {
  193. #if 1             //  1时效率比0小   1 使用传递参数   0 按编译器全嵌汇编实现,但编译提示参数未使用,可以忽略
  194.         //; 参数的使用
  195.         NVMADDRH=(unsigned char) (address>>8);
  196.         NVMADDRL=address;

  197.         __asm
  198.         ;//备份中断使能寄存器
  199.                 BANKSEL _INTCTL
  200.                 MOV                R1,_INTCTL
  201.         ;//关闭中断,操作不可打断
  202.                 CLR                _INTCTL,_AIE
  203.                 JNB                _INTCTL,_AIE
  204.                 JMP                $-2
  205.         ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
  206.                 MOV                R0,#0x30
  207.                 MOV                R2,_OSCCTL
  208.                 MOV                _OSCCTL,R0
  209.         ;//读取结果的存放起始RAM地址,即数组缓存区  FLASH_BUFFER[x]
  210.                 MOV                R3,#_FLASH_BUFFER
  211.         __endasm;

  212.         while(length--)        // 仅使用R0,不改变R1
  213.         {
  214.                 __asm
  215.                 ;//硬件读
  216.                 BANKSEL _NVMCTL0
  217.                 MOV         R5,#0x81
  218.                 MOV         _NVMCTL0,R5
  219.                 NOPZ
  220.                 NOPZ
  221.                 NOPZ                                ;//至少2条
  222.                 NOPZ
  223.                 ;//读结果处理
  224.                 BANKSEL        _NVMDATAL
  225.                 MOV        R6,_NVMDATAL
  226.                 MOV        R7,_NVMDATAH

  227.                 BANKSEL _FLASH_BUFFER
  228.                 ST                [R3],R6
  229.                 INC                R3
  230.                 ST                [R3],R7
  231.                 INC                R3
  232.                 ;//指向下一操作地址,建议每次操作内容在一个块中,此时不需要处理_BADDRL进位的_BADDRH+1操作
  233.                 BANKSEL _NVMADDRL
  234.                 INC                _NVMADDRL
  235.                 JNB                _PSW,_Z
  236.                 INC                _NVMADDRH
  237.                 __endasm;
  238.         }

  239.         __asm
  240.                 ;//时钟与中断使能的还原
  241.                 BANKSEL _OSCCTL
  242.                 MOV                _OSCCTL,R2
  243.                 AND         R1,#0xC0        ;//中断使能仅关系高2位
  244.                 ORL         _INTCTL,R1
  245.         __endasm;
  246. #else
  247.         // 参数1的传递使用  编译器自动变量 STK00  和 R0 ,其中R0为高位
  248.         // 参数2的传递使用  编译器自动变量 STK01
  249.         // 整体实现的嵌汇编会提示参数未被使用,可以忽略
  250. __asm
  251.         ;//传递操作地址
  252.         BANKSEL _NVMADDRH
  253.         MOV                _NVMADDRH,R0
  254.         BANKSEL STK00
  255.         MOV                R0,STK00
  256.         BANKSEL _NVMADDRL
  257.         MOV                _NVMADDRL,R0
  258.         ;//备份中断使能寄存器
  259.         BANKSEL _INTCTL
  260.         MOV                R1,_INTCTL
  261.         ;//关闭中断,操作不可打断
  262.         CLR                _INTCTL,_AIE
  263.         JNB                _INTCTL,_AIE
  264.         JMP                $-2
  265.         ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
  266.         MOV                R0,#0x30
  267.         MOV                R2,_OSCCTL
  268.         MOV                _OSCCTL,R0
  269.         ;//读取结果的存放起始RAM地址,即数组缓存区  FLASH_BUFFER[x]
  270.         MOV                R0,#_FLASH_BUFFER

  271. FLASH_READ_FUN_LOOP:
  272.         ;//硬件读
  273.         BANKSEL _NVMCTL0
  274.         MOV         R5,#0x81
  275.         MOV         _NVMCTL0,R5
  276.         NOPZ
  277.         NOPZ
  278.         NOPZ                                        ;//至少2条
  279.         NOPZ
  280.         ;//读结果处理
  281.         BANKSEL        _NVMDATAL
  282.         MOV        R6,_NVMDATAL
  283.         MOV        R7,_NVMDATAH

  284.         BANKSEL _FLASH_BUFFER
  285.         ST                [R0],R6
  286.         INC                R0
  287.         ST                [R0],R7
  288.         INC                R0
  289.         ;//指向下一操作地址,建议每次操作内容在一个块中,此时不需要处理_BADDRL进位的_BADDRH+1操作
  290.         BANKSEL _NVMADDRL
  291.         INC                _NVMADDRL
  292.         JNB                _PSW,_Z
  293.         INC                _NVMADDRH
  294.         ;//读数量的判断
  295.         BANKSEL STK01
  296.         DECJZ        STK01
  297.         JMP                FLASH_READ_FUN_LOOP

  298.         ;//时钟与中断使能的还原
  299.         BANKSEL _OSCCTL
  300.         MOV                _OSCCTL,R2
  301.         AND         R1,#0xC0        ;//中断使能仅关系高2位
  302.         ORL         _INTCTL,R1
  303. __endasm;
  304. #endif
  305. }
  306. /***********************************************************************************
  307. * 函数名     :FLASH_WRITE_FUN
  308. * 函数功能:按块或按页写入数据到FLASH,个数参数只能为16,32 ,地址必须为块的首地址 如十六进制下结尾00 20 40 60 80 A0 C0 E0
  309. *                         如果地址不是页的首地址,必须确定后续块结果为0xFFFF,或前面操作过块首写,使后续块值被0xFFFF,否则写结果异常。
  310. * 入口参数:待写地址,待写地址的数据
  311. * 返回          :无
  312. * 写时间说明:除去代码,以整页FLASH为例,操作完第一块需要6ms,另外3块需要3ms。即第一块执行整页的擦除后写自身块,其他块直接写。
  313. **********************************************************************************/
  314. void FLASH_WRITE_FUN(unsigned int address,unsigned char length)
  315. {
  316. #if 1             //  1时效率比0小   1 使用传递参数   0 按编译器全嵌汇编实现,但编译提示参数未使用,可以忽略
  317.         //; 参数的使用
  318.         NVMADDRH=(unsigned char) (address>>8);
  319.         NVMADDRL=address;

  320.         __asm
  321.         ;//备份中断使能寄存器
  322.                 BANKSEL _INTCTL
  323.                 MOV                R1,_INTCTL
  324.         ;//关闭中断,操作不可打断
  325.                 CLR                _INTCTL,_PUIE
  326.                 CLR                _INTCTL,_AIE
  327.                 JNB                _INTCTL,_AIE
  328.                 JMP                $-2
  329.         ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
  330.                 MOV                R0,#0x30
  331.                 MOV                R2,_OSCCTL
  332.                 MOV                _OSCCTL,R0
  333.         ;//读取结果的存放起始RAM地址,即数组缓存区  FLASH_BUFFER[x]
  334.                 MOV                R3,#_FLASH_BUFFER
  335.         __endasm;

  336.         while(length--)                // 仅使用R0,不改变R1
  337.         {
  338.                 __asm

  339.                 ;//加载待写数据
  340.                 BANKSEL _FLASH_BUFFER
  341.                 LD                R6,[R3]
  342.                 INC                R3
  343.                 LD                R7,[R3]
  344.                 INC                R3
  345.                 BANKSEL _NVMDATAH
  346.                 MOV _NVMDATAH,R7
  347.                 MOV _NVMDATAL,R6
  348.                 ;//硬件写
  349.                 MOV         R5 ,#0x84
  350.                 MOV         _NVMCTL0,R5
  351.                 MOV         R5,#0x69
  352.                 MOV         _NVMCTL1,R5
  353.                 MOV         R5,#0x96
  354.                 MOV         _NVMCTL1,R5
  355.                 SET         _NVMCTL0 , 1        ;// 写存在高压,高压还原添加空指令确保后续运行正常
  356.                 NOPZ
  357.                 NOPZ
  358.                 NOPZ
  359.                 NOPZ
  360.                 NOPZ
  361.                 NOPZ                                                ;// 建议10条,至少2条
  362.                 NOPZ
  363.                 NOPZ
  364.                 NOPZ
  365.                 NOPZ
  366.                 MOV         R5,#0X80
  367.                 MOV         _NVMCTL0,R5
  368.                 ;//指向下一操作地址,这里不考虑高位,特性要求只能操作一页内的数据,不能跨页
  369.                 BANKSEL _NVMADDRL
  370.                 INC                _NVMADDRL
  371.                 __endasm;
  372.         }

  373.         __asm
  374.                 ;//时钟与中断使能的还原
  375.                 BANKSEL _OSCCTL
  376.                 MOV                _OSCCTL,R2
  377.                 AND         R1,#0xC0        ;//中断使能仅关系高2位
  378.                 ORL         _INTCTL,R1
  379.         __endasm;
  380. #else
  381.         // 参数1的传递使用  编译器自动变量 STK00  和 R0 ,其中R0为高位
  382.         // 参数2的传递使用  编译器自动变量 STK01
  383.         // 整体实现的嵌汇编会提示参数未被使用,可以忽略
  384. __asm
  385.         ;//传递操作的地址(块首)
  386.         BANKSEL _NVMADDRH
  387.         MOV                _NVMADDRH,R0
  388.         BANKSEL STK00
  389.         MOV                R0,STK00
  390.         BANKSEL _NVMADDRL
  391.         MOV                _NVMADDRL,R0
  392.         ;//备份中断使能寄存器
  393.         BANKSEL        _INTCTL
  394.         MOV                R1,_INTCTL
  395.         ;//关闭中断,操作不可打断
  396.         CLR                _INTCTL,_PUIE
  397.         CLR                _INTCTL,_AIE
  398.         JNB                _INTCTL,_AIE
  399.         JMP                $-2
  400.         ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
  401.         MOV                R0,#0x30
  402.         MOV                R2,_OSCCTL
  403.         MOV                _OSCCTL,R0
  404.         ;//待写数据的存放起始RAM地址,即数组缓存区  FLASH_BUFFER[x]
  405.         MOV                R0,#_FLASH_BUFFER

  406. FALSH_WRITE_PAGE_LOOP:
  407.         ;//加载待写数据
  408.         BANKSEL _FLASH_BUFFER
  409.         LD                R6,[R0]
  410.         INC                R0
  411.         LD                R7,[R0]
  412.         INC                R0

  413.         BANKSEL _NVMDATAH
  414.         MOV _NVMDATAH,R7
  415.         MOV _NVMDATAL,R6

  416.         ;//硬件写
  417.         MOV         R5 ,#0x84
  418.         MOV         _NVMCTL0,R5
  419.         MOV         R5,#0x69
  420.         MOV         _NVMCTL1,R5
  421.         MOV         R5,#0x96
  422.         MOV         _NVMCTL1,R5
  423.         SET         _NVMCTL0 , 1        ;// 写存在高压,高压还原添加空指令确保后续运行正常
  424.         NOPZ
  425.         NOPZ
  426.         NOPZ
  427.         NOPZ
  428.         NOPZ
  429.         NOPZ                                                ;// 建议10条,至少2条
  430.         NOPZ
  431.         NOPZ
  432.         NOPZ
  433.         NOPZ
  434.         MOV         R5,#0X80
  435.         MOV         _NVMCTL0,R5
  436.         ;//指向下一操作地址,这里不考虑高位,特性要求只能操作一页内的数据,不能跨页
  437.         BANKSEL _NVMADDRL
  438.         INC                _NVMADDRL

  439.         BANKSEL STK01
  440.         DECJZ        STK01
  441.         JMP                FALSH_WRITE_PAGE_LOOP

  442.         ;//时钟与中断使能的还原
  443.         BANKSEL _OSCCTL
  444.         MOV                _OSCCTL,R2
  445.         AND         R1,#0xC0        ;//中断使能仅关系高2位
  446.         ORL         _INTCTL,R1
  447. __endasm;
  448. #endif
  449. }

  450. /***********************************************************************************
  451. * 函数名     :FLASH_WRITE_ONE
  452. * 函数功能:向某一地址写入一个字,不建议使用,实际执行从页首读出,经对应地址的缓存修改,在页起始回写,因此地址与页首偏移量需要数组大小满足需求。
  453. * 建议:         可采用FLASH_WRITE_FUN的传递个数为16,32 对应连续操作地址开始的第一块 第二块
  454. *                          但地址必须是某块的开始
  455. * 入口参数:待写地址,待写地址的数据
  456. * 返回          :无
  457. **********************************************************************************/
  458. void FLASH_WRITE_ONE(unsigned int address,unsigned int value)
  459. {
  460.         // 读出当前页到数据缓存,要求缓存大小必须满足写地址的偏移量要求
  461.         FLASH_READ_FUN(address&0xFFE0,FLASH_BUFFER_MAX);
  462.         // 修改待写数据在按照页排序中位置数据结果
  463.         FLASH_BUFFER[address&0x1F] = value;
  464.         // 整页数据回写
  465.         FLASH_WRITE_FUN(address&0xFFE0,FLASH_BUFFER_MAX);
  466. }
复制代码


扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表