打印
[STM32L0]

STm32L0x2自带EEPROM读写分享

[复制链接]
5461|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Larm1|  楼主 | 2018-1-9 15:30 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
       STM32L的EEPROM支持字、半字和字节的读写操作。写操作之前自动擦除,如果写的数据为0,则只执行擦除操作。

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

#define                EPROM_WR_TYPE_BYTE                                ((UNS8)0x00)
#define                EPROM_WR_TYPE_HALF_WORD                ((UNS8)0x01)
#define                EPROM_WR_TYPE_WORD                                ((UNS8)0x02)

#define                EPROM_TEST_ADDR                                (STM_EPROM_ADDR_BASE + 12)
#define                EPROM_TESTE_ADDR                                (STM_EPROM_ADDR_BASE + 32)
#define                EPROM_TESTEE_ADDR                                (STM_EPROM_ADDR_BASE + 61)

//// Unlocks the data memory and FLASH_PECR register access
//// ret :
////   OK       = 0x00U,
////   ERROR    = 0x01U,
////   BUSY     = 0x02U,
////   TIMEOUT  = 0x03U
UNS8 StmL0xxEpromUnlock(void)
{
        UNS8                ret=0;
        
        ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Unlock();
        
        return ret;
}

//// Locks the Data memory and FLASH_PECR register access
//// ret :
////   OK       = 0x00U,
////   ERROR    = 0x01U,
////   BUSY     = 0x02U,
////   TIMEOUT  = 0x03U
UNS8 StmL0xxEpromLock(void)
{
        UNS8                ret=0;
        
        ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Lock();
        
        return ret;
}

//// Erase a word in data memory.
//// To correctly run this function, the [url=home.php?mod=space&uid=144993]@ref[/url] StmL0xxEpromUnlock() function
//// must be called before.
//// addr -- specifies the address to be erased.
//// ret :
////   OK       = 0x00U,
////   ERROR    = 0x01U,
////   BUSY     = 0x02U,
////   TIMEOUT  = 0x03U
UNS8 StmL0xxEpromWordErase(UNS32 addr)
{
        UNS8                ret=0;
        
        if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
        {
                return ret;
        }
        
        ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Erase(addr);
        
        return ret;
}

//// Program data at a specified address
//// type :
////   Byte -- 0x00
////   HalfWord -- 0x01
////   Word -- 0x02
//// addr -- specifies the address to be erased.
//// ret :
////   OK       = 0x00U,
////   ERROR    = 0x01U,
////   BUSY     = 0x02U,
////   TIMEOUT  = 0x03U
UNS8 StmL0xxEpromSingleWrite(UNS8 type, UNS32 addr, UNS32 data)
{
        UNS8                ret=0;
        
        if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
        {
                return ret;
        }
        
        StmL0xxEpromUnlock();
        ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Program((UNS32)type, addr, data); //// 库函数
        StmL0xxEpromLock();
        
        return ret;
}

//// read a byte at a specified address
//// addr -- specifies the address to be erased.
//// ret :
////   OK       = 0x00U,
////   ERROR    = 0x01U,
////   BUSY     = 0x02U,
////   TIMEOUT  = 0x03U
void StmL0xxEpromSingleByteRead(UNS32 addr, UNS8 *data)
{
        
        if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
        {
                return ;
        }
        
        StmL0xxEpromUnlock();
        *data = *(volatile uint8_t *)(addr);
        StmL0xxEpromLock();
}
测试代码如下:      
void EpromTest(void)
{
        UNS8        tmp[8] = {1, 2, 3, 4, 5, 6, 7, 8};
        UNS8        read[8] = {0}, num=0, time=1;
        
        while(5>time)
        {
                for (num=0; num<8; num++)
                {
                        tmp[num] *= time;
                        StmL0xxEpromSingleWrite(EPROM_WR_TYPE_BYTE, EPROM_TEST_ADDR+num, (uint32_t)tmp[num]);
                }
               
                for (num=0; num<8; num++)
                {
                        StmL0xxEpromSingleByteRead(EPROM_TEST_ADDR+num, &read[num]);
                        if (tmp[num]!=read[num])
                        {
                                time = 10;
                        }
                }
        
////                StmL0xxEpromSingleWrite(EPROM_WR_TYPE_HALF_WORD, EPROM_TESTEE_ADDR, *(uint16_t *)(&tmp[0])); //// 进入异常中断
////                StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTEE_ADDR, *(uint32_t *)(&tmp[0]));//// 进入异常中断
                StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTE_ADDR, *(uint32_t *)(&tmp[0]));
                StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTE_ADDR+4, *(uint32_t *)(&tmp[4]));
                StmL0xxEpromSingleByteRead(EPROM_TESTE_ADDR+0, (UNS32*)(&read[0]));
                StmL0xxEpromSingleByteRead(EPROM_TESTE_ADDR+4, (UNS32*)(&read[4]));
               
                time ++;
        }
}
总结:
     1. 字节操作时,传入任何地址参数都可以,读写操作正常;
     2. 但是当半字操作时,如果地址不是2对齐的,则调用函数StmL0xxEpromSingleWrite时进入HardFault中断;
     3. 但是当字操作时,如果地址不是4对齐的,则调用函数StmL0xxEpromSingleWrite时进入HardFault中断;
                 
     调试发现调用HAL_FLASHEx_DATAEEPROM_Program函数时进入异常中断。
     原因是EEPROM在内存结构上实际是以字为单位的:     
    然可以进行字节、半字的参数,但是必须保证地址的对其方式——半字操作以2对齐,字操作以4对齐,否则会出错。

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

沙发
mmuuss586| | 2018-4-6 19:57 | 只看该作者
感谢分享;

使用特权

评论回复
板凳
kkzz| | 2018-4-6 22:29 | 只看该作者
硬件iic?

使用特权

评论回复
地板
hudi008| | 2018-4-6 22:29 | 只看该作者
感觉不如模拟的IIC好实用。

使用特权

评论回复
5
lzmm| | 2018-4-6 22:30 | 只看该作者
自带EEPROM

使用特权

评论回复
6
minzisc| | 2018-4-6 22:30 | 只看该作者
使用中断了吗

使用特权

评论回复
7
selongli| | 2018-4-6 22:31 | 只看该作者
这个是STM32Cube库?

使用特权

评论回复
8
kkzz| | 2018-4-6 22:32 | 只看该作者
从来没有读写成功过。

使用特权

评论回复
9
hudi008| | 2018-4-6 22:32 | 只看该作者
模拟IIC的代码一直更简单。

使用特权

评论回复
10
lzmm| | 2018-4-6 22:32 | 只看该作者
跟着学一下自带EEPROM。

使用特权

评论回复
11
minzisc| | 2018-4-6 22:32 | 只看该作者
是不是可以直接DMA操作?

使用特权

评论回复
12
selongli| | 2018-4-6 22:32 | 只看该作者
还真是没有用过自带的EEPROM读写

使用特权

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

本版积分规则

个人签名:大爱无疆

53

主题

389

帖子

0

粉丝