[STM32L0] STm32L0x2自带EEPROM读写分享

[复制链接]
6289|11
 楼主| Larm1 发表于 2018-1-9 15:30 | 显示全部楼层 |阅读模式
       STM32L的EEPROM支持字、半字和字节的读写操作。写操作之前自动擦除,如果写的数据为0,则只执行擦除操作。

       使用STM32Cube库对自带的EEPROM进行操作,代码如下:
      

  1. #define                EPROM_WR_TYPE_BYTE                                ((UNS8)0x00)
  2. #define                EPROM_WR_TYPE_HALF_WORD                ((UNS8)0x01)
  3. #define                EPROM_WR_TYPE_WORD                                ((UNS8)0x02)

  4. #define                EPROM_TEST_ADDR                                (STM_EPROM_ADDR_BASE + 12)
  5. #define                EPROM_TESTE_ADDR                                (STM_EPROM_ADDR_BASE + 32)
  6. #define                EPROM_TESTEE_ADDR                                (STM_EPROM_ADDR_BASE + 61)

  7. //// Unlocks the data memory and FLASH_PECR register access
  8. //// ret :
  9. ////   OK       = 0x00U,
  10. ////   ERROR    = 0x01U,
  11. ////   BUSY     = 0x02U,
  12. ////   TIMEOUT  = 0x03U
  13. UNS8 StmL0xxEpromUnlock(void)
  14. {
  15.         UNS8                ret=0;
  16.         
  17.         ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Unlock();
  18.         
  19.         return ret;
  20. }

  21. //// Locks the Data memory and FLASH_PECR register access
  22. //// ret :
  23. ////   OK       = 0x00U,
  24. ////   ERROR    = 0x01U,
  25. ////   BUSY     = 0x02U,
  26. ////   TIMEOUT  = 0x03U
  27. UNS8 StmL0xxEpromLock(void)
  28. {
  29.         UNS8                ret=0;
  30.         
  31.         ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Lock();
  32.         
  33.         return ret;
  34. }

  35. //// Erase a word in data memory.
  36. //// To correctly run this function, the [url=home.php?mod=space&uid=144993]@ref[/url] StmL0xxEpromUnlock() function
  37. //// must be called before.
  38. //// addr -- specifies the address to be erased.
  39. //// ret :
  40. ////   OK       = 0x00U,
  41. ////   ERROR    = 0x01U,
  42. ////   BUSY     = 0x02U,
  43. ////   TIMEOUT  = 0x03U
  44. UNS8 StmL0xxEpromWordErase(UNS32 addr)
  45. {
  46.         UNS8                ret=0;
  47.         
  48.         if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
  49.         {
  50.                 return ret;
  51.         }
  52.         
  53.         ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Erase(addr);
  54.         
  55.         return ret;
  56. }

  57. //// Program data at a specified address
  58. //// type :
  59. ////   Byte -- 0x00
  60. ////   HalfWord -- 0x01
  61. ////   Word -- 0x02
  62. //// addr -- specifies the address to be erased.
  63. //// ret :
  64. ////   OK       = 0x00U,
  65. ////   ERROR    = 0x01U,
  66. ////   BUSY     = 0x02U,
  67. ////   TIMEOUT  = 0x03U
  68. UNS8 StmL0xxEpromSingleWrite(UNS8 type, UNS32 addr, UNS32 data)
  69. {
  70.         UNS8                ret=0;
  71.         
  72.         if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
  73.         {
  74.                 return ret;
  75.         }
  76.         
  77.         StmL0xxEpromUnlock();
  78.         ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Program((UNS32)type, addr, data); //// 库函数
  79.         StmL0xxEpromLock();
  80.         
  81.         return ret;
  82. }

  83. //// read a byte at a specified address
  84. //// addr -- specifies the address to be erased.
  85. //// ret :
  86. ////   OK       = 0x00U,
  87. ////   ERROR    = 0x01U,
  88. ////   BUSY     = 0x02U,
  89. ////   TIMEOUT  = 0x03U
  90. void StmL0xxEpromSingleByteRead(UNS32 addr, UNS8 *data)
  91. {
  92.         
  93.         if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
  94.         {
  95.                 return ;
  96.         }
  97.         
  98.         StmL0xxEpromUnlock();
  99.         *data = *(volatile uint8_t *)(addr);
  100.         StmL0xxEpromLock();
  101. }
测试代码如下:      
  1. void EpromTest(void)
  2. {
  3.         UNS8        tmp[8] = {1, 2, 3, 4, 5, 6, 7, 8};
  4.         UNS8        read[8] = {0}, num=0, time=1;
  5.         
  6.         while(5>time)
  7.         {
  8.                 for (num=0; num<8; num++)
  9.                 {
  10.                         tmp[num] *= time;
  11.                         StmL0xxEpromSingleWrite(EPROM_WR_TYPE_BYTE, EPROM_TEST_ADDR+num, (uint32_t)tmp[num]);
  12.                 }
  13.                
  14.                 for (num=0; num<8; num++)
  15.                 {
  16.                         StmL0xxEpromSingleByteRead(EPROM_TEST_ADDR+num, &read[num]);
  17.                         if (tmp[num]!=read[num])
  18.                         {
  19.                                 time = 10;
  20.                         }
  21.                 }
  22.         
  23. ////                StmL0xxEpromSingleWrite(EPROM_WR_TYPE_HALF_WORD, EPROM_TESTEE_ADDR, *(uint16_t *)(&tmp[0])); //// 进入异常中断
  24. ////                StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTEE_ADDR, *(uint32_t *)(&tmp[0]));//// 进入异常中断
  25.                 StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTE_ADDR, *(uint32_t *)(&tmp[0]));
  26.                 StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTE_ADDR+4, *(uint32_t *)(&tmp[4]));
  27.                 StmL0xxEpromSingleByteRead(EPROM_TESTE_ADDR+0, (UNS32*)(&read[0]));
  28.                 StmL0xxEpromSingleByteRead(EPROM_TESTE_ADDR+4, (UNS32*)(&read[4]));
  29.                
  30.                 time ++;
  31.         }
  32. }
总结:
     1. 字节操作时,传入任何地址参数都可以,读写操作正常;
     2. 但是当半字操作时,如果地址不是2对齐的,则调用函数StmL0xxEpromSingleWrite时进入HardFault中断;
     3. 但是当字操作时,如果地址不是4对齐的,则调用函数StmL0xxEpromSingleWrite时进入HardFault中断;
                 
     调试发现调用HAL_FLASHEx_DATAEEPROM_Program函数时进入异常中断。
     原因是EEPROM在内存结构上实际是以字为单位的:      Eprom.png
    然可以进行字节、半字的参数,但是必须保证地址的对其方式——半字操作以2对齐,字操作以4对齐,否则会出错。

     !!!!这个代码的对其方式怎么跟贴代码之前不一样呢,完全左对齐了!!!

mmuuss586 发表于 2018-4-6 19:57 | 显示全部楼层
感谢分享;
kkzz 发表于 2018-4-6 22:29 | 显示全部楼层
硬件iic?
hudi008 发表于 2018-4-6 22:29 | 显示全部楼层
感觉不如模拟的IIC好实用。
lzmm 发表于 2018-4-6 22:30 | 显示全部楼层
自带EEPROM
minzisc 发表于 2018-4-6 22:30 | 显示全部楼层
使用中断了吗
selongli 发表于 2018-4-6 22:31 | 显示全部楼层
这个是STM32Cube库?
kkzz 发表于 2018-4-6 22:32 | 显示全部楼层
从来没有读写成功过。
hudi008 发表于 2018-4-6 22:32 | 显示全部楼层
模拟IIC的代码一直更简单。
lzmm 发表于 2018-4-6 22:32 | 显示全部楼层
跟着学一下自带EEPROM。
minzisc 发表于 2018-4-6 22:32 | 显示全部楼层
是不是可以直接DMA操作?
selongli 发表于 2018-4-6 22:32 | 显示全部楼层
还真是没有用过自带的EEPROM读写
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:大爱无疆

53

主题

389

帖子

0

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