OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4000|回复: 3

STM32+EEPROM 读数据遇到问题,求帮助

[复制链接]

1

主题

2

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2015-4-8
在线时间
2 小时
发表于 2016-7-7 17:21:31 | 显示全部楼层 |阅读模式
5金钱
本人今天在调试手里的一个25LC160(mircochip的一个SPI接口的EEPROM   16字节1页)发现,连续读不能跨256的倍数地址读数据比如我想从地址0 读取257个字节,前256字节读出来是正确的,最后一个字节读出来是FF。
除非分两次调用,才能完全读出。

可是芯片手册上并没收这一块的说明。大家遇到过这类问题吗?

附上代码

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:ReadWriteByte
* 参数: _dat:写入的数据
* 返回: 读到的数据
* 描述: 读写一个字节
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static u8 ReadWriteByte(u8 _dat) {
        while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
        SPI_I2S_SendData(SPI3, _dat);
        while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
        return SPI_I2S_ReceiveData(SPI3);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:ReadRegister
* 参数: NONE
* 返回: 寄存器的值
* 描述: 读取EEPROM寄存器的值
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static u8 ReadRegister(void) {
        u8 ret;
        M25LC_CS_ENABLE();
        ReadWriteByte(M25LC_READ_REGISTER);
        ret = ReadWriteByte(0xFF);
        M25LC_CS_DISABLE();
        return ret;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:WriteRegister
* 参数: _reg:寄存器的值
* 返回: NONE
* 描述: 写EEPROM寄存器的值
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static u8 WriteRegister(u8 _reg) {
        u8 ret = 0;
        M25LC_CS_ENABLE();
        ReadWriteByte(M25LC_WRITE_REGISTER);
        ret = ReadWriteByte(_reg);
        M25LC_CS_DISABLE();
        return ret;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:WriteEnable
* 参数: NONE
* 返回: NONE
* 描述: 写使能
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static void WriteEnable(void) {
        M25LC_CS_ENABLE();
        ReadWriteByte(M25LC_WRITE_ENABLE);
        M25LC_CS_DISABLE();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:WriteDisable
* 参数: NONE
* 返回: NONE
* 描述: 写失能
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static void WriteDisable(void) {
        M25LC_CS_ENABLE();
        ReadWriteByte(M25LC_WRITE_DISABLE);
        M25LC_CS_DISABLE();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:IsWriteBusy
* 参数: NONE
* 返回: NONE
* 描述: 写失能
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static BOOL IsWriteBusy(void) {
        BOOL isBusy = FALSE;
        if ((ReadRegister() & 0x01) == 0x01)
                isBusy = TRUE;
        return isBusy;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:WriteData
* 参数:
* 返回:
* 描述:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static void WritePageData(u16 _addr, byte *_datbuf, u16 _size) {
        u8 i = 0;

        if (_size > M25LC_PAGE_SIZE)
                return;      


        WriteEnable();

        M25LC_CS_ENABLE();

        ReadWriteByte(M25LC_WRITE_DATA);

        ReadWriteByte((u8) (_addr << 8));
        ReadWriteByte((u8) (_addr));

        for (i = 0; i < _size; i++) {
            ReadWriteByte(_datbuf[i]);
        }

        M25LC_CS_DISABLE();

        /*CS拉高后要等最少5ms*/
        while (IsWriteBusy() == TRUE);

        WriteDisable();
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:ReadData
* 参数:
* 返回:
* 描述:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void M25LC160ReadData(u16 _addr, byte *_datbuf, u16 _size) {
        u16 i;

        M25LC_CS_ENABLE();
        ReadWriteByte(M25LC_READ_DATA);

        ReadWriteByte((u8) (_addr << 8));
        ReadWriteByte((u8) (_addr));


        for (i = 0; i < _size; i++) {
                _datbuf[i] = ReadWriteByte(0xFF);
        }
        M25LC_CS_DISABLE();
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:WriteData  
* 参数:
* 返回:
* 描述:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void M25LC160WriteData(u16 _addr, byte *_datbuf, u16 _size) {

        u16 i = 0;
        u8 offset = _addr % M25LC_PAGE_SIZE; //页偏移地址
        u8 conut =
                        ((offset + _size) % M25LC_PAGE_SIZE == 0) ?
                                        (offset + _size) / M25LC_PAGE_SIZE : (offset + _size) / M25LC_PAGE_SIZE + 1; //需要写入的次数
        u16 nextaddr = _addr; //下一次写入地址
        byte *nextdata = _datbuf; //下一次写入数据指针

        if ((_addr + _size) > M25LC_MAX_SIZE)
                return;

        for (; i < conut; i++) {
                if (i == 0) //第一页
                                {
                        WritePageData(nextaddr, nextdata, conut == 1 ? _size : M25LC_PAGE_SIZE - offset);
                        nextaddr += M25LC_PAGE_SIZE - offset;
                        nextdata += M25LC_PAGE_SIZE - offset;
                } else if (i == conut - 1) //最后一页
                {
                        WritePageData(nextaddr, nextdata, _size - (M25LC_PAGE_SIZE * i - offset));
                } else //中间页面
                {
                        WritePageData(nextaddr, nextdata, M25LC_PAGE_SIZE);
                        nextaddr += M25LC_PAGE_SIZE;
                        nextdata += M25LC_PAGE_SIZE;
                }
        }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:RegisterConf
* 参数:
* 返回:
* 描述:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static void RegisterConf(void) {
        /*WPEN:被设置为1时,WP引脚才有效
         BP1 BP0:都设置为0时表示数据存储区没有写保护区域
         WEL:写使能标志位,1表示可以写,0表示不能写。写使能寄存器指令被执行时才会置1
         WIP:写操作忙标志位  1为忙 0为空闲
         */
        WriteRegister(0x00);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 函数名:M25LC160Init
* 参数:
* 返回:
* 描述:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void M25LC160Init(void) {
  byte writeBuf[1000];
//  byte writeBuf[10] = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0xAA,0xBB,0xCC,0xDD};  
  byte readBuf[1000];
  u16 i = 0;
        SPI_InitTypeDef SPI_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        // 使能相关时钟
        EEPROM_RCC_CONFIGURE();
        EEPROM_IO_CONFIGURE(&GPIO_InitStructure);

        //配置SPI端口
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI主模式
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //数据位8位
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //CLK常态为低电平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第一沿变化锁存数据
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //片选使用IO控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //分频  36M/16=2M
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //先传高位
        SPI_InitStructure.SPI_CRCPolynomial = 7;
        SPI_Init(SPI3, &SPI_InitStructure);

        SPI_Cmd(SPI3, ENABLE);

        M25LC_WP_DISABLE();
        M25LC_CS_DISABLE();

        RegisterConf();

        for(;i<sizeof(writeBuf);i++){
          writeBuf[i] = 0x11;
          readBuf[i] = 0;
        }

        M25LC160WriteData(0,writeBuf,sizeof(writeBuf));
        M25LC160ReadData(300,readBuf,sizeof(readBuf));   
//     M25LC160ReadData(256,readBuf+256,256);
}


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2015-4-8
在线时间
2 小时
 楼主| 发表于 2016-7-8 11:19:06 | 显示全部楼层
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2016-7-9 21:34:16 | 显示全部楼层
帮顶
回复

使用道具 举报

8

主题

136

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
428
金钱
428
注册时间
2015-4-24
在线时间
85 小时
发表于 2016-7-25 09:03:01 | 显示全部楼层
我用的事lc1024,上面有不能跨页直接操作,你可以看看。
Image 1.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 21:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表