[通用8051核FLASH系列] HC89S003F4的Flash可以作EEPROM吗?

[复制链接]
 楼主| haixianhaixian 发表于 2018-4-5 15:37 | 显示全部楼层 |阅读模式
本帖最后由 芯圣电子官方QQ 于 2023-7-25 10:51 编辑

如题,具体怎么做?谢谢!
xyz549040622 发表于 2018-4-6 07:18 | 显示全部楼层
手册上是这么说的【在应用编程(IAP)支持用户自定义启动代码和类EEPROM 区 】,官方的例程也提供了类EEPROM读写的例程的,你可以参考看看。
  1. /**
  2. *   ************************************************************************************
  3. *                                                                上海芯圣电子股份有限公司
  4. *                                                                    www.holychip.cn
  5. *        ************************************************************************************
  6. *        @Examle Version                V1.0.1.0
  7. *        [url=home.php?mod=space&uid=1102]@demo[/url]         Version                V1.0.2.0
  8. *        @Date                                2017.12.21
  9. *        ************************************************************************************
  10. *                                                                         模块性能介绍
  11. *        1、Flash擦写次数10万次以上
  12. *        2、扇区擦除时间约4.2ms,且擦除时不响应任何中断,但会置相关标志位,擦除完成后响应
  13. *        3、可设置应用程序读保护,应用程序写保护(以4K字节为保护单位)
  14. *        4、可以设置仿真器扇区读保护,扇区写保护(以4K字节为保护单位)
  15. *        5、设置保护后无法擦写程序,读取的数据全为零
  16. *   6、每一颗MCU在出厂时会固化一个CHIP_ID,一共8个字节,一颗芯片一个ID,不会重复
  17. *        ************************************************************************************
  18. *                                                                         应用注意事项
  19. *        1、CPU时钟需要配置为1-16MHz之间的正整数,且Flash擦写之前需要配置FREQ_CLK寄存器,该寄
  20. *           存器值即为当前CPU时钟频率。
  21. *        2、扇区擦除写入过程中不能被打断
  22. *        3、数据存放地址需要在程序存放地址之后
  23. *        4、第二复位向量使能时,无法在仿真环境下查看code区数据
  24. *   5、Flsah操作最低电压限制为2.0V,所以建议进行Flash操作前进行电压检测或者打开BOR,BOR电
  25. *      压建议设置为2.4V及2.4V以上
  26. *        6、建议在进行Flash擦写操作前关闭中断,擦写完成后再打开中断
  27. *        ************************************************************************************
  28. *                                                                         客户服务
  29. *        感谢您使用我们的单片机,若发现错误或对函数的使用存在疑问。请添加上海芯圣电子官方QQ群
  30. *        ****************************技术支持群:201030494***********************************
  31. *   ************************************************************************************
  32. **/

  33. #define ALLOCATE_EXTERN
  34. #include "HC89S003F4.h"

  35. void Flash_EraseBlock(unsigned int fui_Address);//扇区擦除
  36. void Flash_WriteArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr);
  37. void Flash_ReadArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr);

  38. unsigned char guc_Write_a[5] = {0x11,0x12,0x13,0x14,0x15};        //写入数据
  39. unsigned char guc_Read_a[5] = {0x00};                        //用于存放读取的数据
  40. unsigned char guc_Uartflag = 0;                                        //发送标志位
  41. unsigned char guc_Uartcnt = 0;                                        //发送计数
  42. unsigned char guc_Uartbuf_a[2] = {0x00};                //缓存数组

  43. /***************************************************************************************
  44.   * @实现效果        在地址0x2B00到0x2B04连续写入5个数据,通过串口工具发送地址可以读取相对应
  45.                                   的数据。
  46.   * @操作步骤   接上RXD TXD短路帽,通过串口工具向单片机发送以0x2B为帧头的数据,返回对应
  47.                 对应地址的数据。
  48. ***************************************************************************************/
  49. int main()
  50. {
  51. /************************************系统初始化****************************************/
  52.         WDTCCR = 0x00;                                                //关闭看门狗
  53.         while((CLKCON&0x20)!=0x20);                        //等待内部高频RC起振
  54.         CLKSWR = 0x51;                                                //选择内部高频时钟为主时钟,内部高频RC2分频,Fosc=16MHz
  55.         while((CLKSWR&0xC0)!=0x40);                        //等待内部高频切换完成
  56.         CLKDIV = 0x01;                                                //Fosc1分频得到Fcpu,Fcpu=16MHz
  57. /**********************************相关配置初始化**************************************/
  58.         P2M0 = P2M0&0x0F|0x80;                                //P21设置为推挽输出
  59.         P0M1 = P0M1&0x0F|0x20;                                //P03设置为上拉输出
  60.         TXD_MAP = 0x21;                                                //TXD映射P21
  61.         RXD_MAP = 0x03;                                                //RXD映射P03               
  62.         T4CON = 0x06;                                                //T4工作模式:UART1波特率发生器
  63.     TH4 = 0xFF;
  64.         TL4 = 0x98;                                                        //波特率9600
  65.         SCON2 = 0x02;                                                //8位UART,波特率可变
  66.         SCON = 0x10;                                                //允许串行接收
  67.         IE |= 0x10;                                                        //使能串口中断
  68. /**********************************Flash配置初始化*************************************/
  69.         FREQ_CLK = 0x10;                                        //指明当前系统时钟
  70.         Flash_EraseBlock(0x2B00);                        //擦除地址0x2B00所在扇区
  71.         Flash_WriteArr(0x2B00,5,guc_Write_a);//在地址0x2B00写入数据
  72.         Flash_ReadArr(0x2B00,5,guc_Read_a);        //读取地址0x2B00所在扇区
  73.         EA = 1;                                                                //使能总中断
  74.         while(1)
  75.         {
  76.                 if(guc_Uartflag)
  77.                 {
  78.                         IE &=~ 0x10;                                //失能UART1中断
  79.                         if(guc_Uartbuf_a[0] == 0x2B)
  80.                         {
  81.                                 switch(guc_Uartbuf_a[1])
  82.                                 {
  83.                                         case 0x00:        SBUF = guc_Read_a[0];//发送8位串口数据
  84.                                                                 break;
  85.                                         case 0x01:        SBUF = guc_Read_a[1];//发送8位串口数据
  86.                                                                 break;
  87.                                         case 0x02:        SBUF = guc_Read_a[2];//发送8位串口数据
  88.                                                                 break;
  89.                                         case 0x03:        SBUF = guc_Read_a[3];//发送8位串口数据
  90.                                                                 break;
  91.                                         case 0x04:        SBUF = guc_Read_a[4];//发送8位串口数据
  92.                                                                 break;
  93.                                         default:break;
  94.                                         while(!(SCON&0x02));        //等待发送完毕
  95.                                         SCON &=~ 0x02;;                        //清除发送中断标志位
  96.                                 }
  97.                         IE |= 0x10;                                                //UART1中断使能
  98.                         guc_Uartflag = 0;                                //标志位清零
  99.                         guc_Uartcnt = 0;                                //标志位清零
  100.                         SCON |= 0x10;                                        //UART1接收使能       
  101.                         }
  102.                 }
  103.         }
  104.     return 0;
  105. }

  106. /***************************************************************************************
  107.   * @说明          UART1中断服务函数
  108.   *        @参数        无
  109.   * @返回值 无
  110.   * @注                无
  111. ***************************************************************************************/
  112. void UART1_Rpt(void) interrupt UART1_VECTOR
  113. {
  114.         if(SCON&0x01)                                                        //判断接收中断标志位
  115.         {
  116.                 guc_Uartbuf_a[guc_Uartcnt++] = SBUF;//转存8位串口接收数据
  117.                 if(guc_Uartcnt >= 2)
  118.                 {
  119.                         SCON &=~ 0x10;                                        //失能UART1接收
  120.                         guc_Uartflag = 1;
  121.                 }
  122.                 SCON &=~ 0x01;                                                //清除接收中断标志位
  123.         }
  124. }
  125. /**
  126.   * @说明          扇区擦除,约消耗4.2ms的时间
  127.   * @参数          fui_Address :被擦除的扇区内的任意一个地址
  128.   *                        取值范围:0x0000-0x3FFF
  129.   * @返回值 无
  130.   * @注                只要操作扇区里面的任意一个地址,就可以擦除此扇区
  131.   */
  132. void Flash_EraseBlock(unsigned int fui_Address)
  133. {
  134.         EA = 0;
  135.         IAP_CMD = 0xF00F;                                //Flash解锁
  136.         IAP_ADDR = fui_Address;                        //写入擦除地址
  137.         IAP_CMD = 0xD22D;                                //选择操作方式, 扇区擦除
  138.         IAP_CMD = 0xE11E;                                 //触发后IAP_ADDRL&IAP_ADDRH指向0xFF,同时自动锁定
  139.         EA = 1;
  140. }

  141. /**
  142.   * @说明          写入任意长度的数据到FLASH里面
  143.   * @参数          fui_Address :FLASH起始地址
  144.   *                        取值范围:0x0000-0x3FFF
  145.   *        @参数        fuc_Length : 写入数据长度
  146.   *                        取值范围:0x00-0xFF
  147.   *        @参数        *fucp_SaveArr:写入的数据存放区域的首地址
  148.   * @返回值 无
  149.   * @注                写之前必须先对操作的扇区进行擦除
  150.   */
  151. void Flash_WriteArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr)
  152. {       
  153.         EA = 0;
  154.         while(fuc_Length--)
  155.         {                
  156.                 IAP_DATA=*fucp_SaveArr;         //待编程数据,写入数据寄存器必须放在解锁之前
  157.                 IAP_CMD=0xF00F;                                //Flash解锁
  158.                 IAP_ADDR=fui_Address;                //写入地址
  159.                 IAP_CMD=0xB44B;                                //字节编程
  160.                 IAP_CMD=0xE11E;                                //触发一次操作
  161.                 fui_Address++;                                //地址加一
  162.                 fucp_SaveArr++;                                //数据后移一位
  163.         }
  164.         EA = 1;
  165. }

  166. /**
  167.   * @说明          从FLASH里面读取任意长度的数据
  168.   * @参数          fui_Address :FLASH起始地址
  169.   *                        取值范围:0x0000-0x3FFF
  170.   *        @参数        fuc_Length : 读取数据长度
  171.   *                        取值范围:0x00-0xFF
  172.   *        @参数        *fucp_SaveArr:读取数据存放的区域首地址
  173.   * @返回值 无
  174.   * @注                无
  175.   */
  176. void Flash_ReadArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr)
  177. {
  178.         while(fuc_Length--)
  179.         *(fucp_SaveArr++)=*((unsigned char code *)(fui_Address++));//读取数据
  180. }
 楼主| haixianhaixian 发表于 2018-4-6 09:16 | 显示全部楼层
谢谢,
magicoctoy 发表于 2018-4-24 16:28 | 显示全部楼层
xyz549040622 发表于 2018-4-6 07:18
手册上是这么说的【在应用编程(IAP)支持用户自定义启动代码和类EEPROM 区 】,官方的例程也提供了类EEPRO ...

谢谢分享。
Bruing 发表于 2018-4-26 22:49 | 显示全部楼层
支持下,flash模拟eeprom,还不如像STC一样,直接开个eeprom区域呢,省的模拟麻烦
wakayi 发表于 2018-7-14 21:11 | 显示全部楼层
存在自然是有道理的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

12

帖子

0

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

6

主题

12

帖子

0

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