你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F1 I2C中断方式一次写多页数据问题

[复制链接]
wdshuang09 提问时间:2019-4-26 22:25 /

用STMF103 I2C2中断读写24C32,读指定长度数据没有问题,
但写超过多余一页的数据,多余一页的数据有时能写进去,有时只写了一页数据后面的数据没有写进去。
如:I2C_EE_IRQ_Writ(buf, 0, 255);只能写到32字节(24C32 page为32Bbyte),后面的数据都没有写进去,
仿真时每写完一页数据都能进EV8-2事件中,进行写总数据减、地址增加等直到255字节的数据写完,但读出来发现,只有前面32个字节数据写进去了。
现在没有想到问题出在哪里?
下面是各个子函数:
//EEPROM写数据函数
void I2C_EE_IRQ_Write(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
  Addr = WriteAddr % I2C_PageSize;
  count = I2C_PageSize - Addr;
  NumOfPage =  NumByteToWrite / I2C_PageSize;
  NumOfSingle = NumByteToWrite % I2C_PageSize;
  I2C2Buf.NumByteWritingNow=0;
  if(Addr == 0)   /* If WriteAddr is I2C_PageSize aligned  */
  {
    if(NumOfPage == 0)  /* If NumByteToWrite < I2C_PageSize */
    {
      I2C_EE_IRQ_PageWrite(pBuffer, WriteAddr, NumOfSingle);
     I2C2Buf.NumByteWritingNow=NumOfSingle;
    }
    else  /* If NumByteToWrite > I2C_PageSize */
    {
        I2C_EE_IRQ_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
        I2C2Buf.NumByteWritingNow=I2C_PageSize;
    }
  }
  else   /* If WriteAddr is not I2C_PageSize aligned  */
  {
    if(NumOfPage== 0)     /* If NumByteToWrite < I2C_PageSize */
    {
      I2C_EE_IRQ_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C2Buf.NumByteWritingNow=NumOfSingle;
    }
    else/* If NumByteToWrite > I2C_PageSize */
    {
        if(count != 0)
       {  
          I2C_EE_IRQ_PageWrite(pBuffer, WriteAddr, count);
          I2C2Buf.NumByteWritingNow=count;
       }
    }
  }  
}

//EEPROM页写入函数
void I2C_EE_IRQ_PageWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
        I2C2Buf.MasterDirection= Transmitter;
        I2C2Buf.MasterWComplete=0;
        I2C2Buf.Wdatalen=NumByteToWrite;
        I2C2Buf.SlaveADDR= EEPROM_ADDRESS;
        I2C2Buf.Device_AddrOffset= WriteAddr;
        I2C2Buf.Device_Addr_OffsetDone=0;
        I2C_AcknowledgeConfig(I2C2, ENABLE);
        I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
        /* Send START condition */
        if(I2C2->CR1 & 0x200)I2C2->CR1 &= 0xFDFF;
        I2C_GenerateSTART(I2C2, ENABLE);
}

//进入下面中断事件处理
void i2c2_evt_isr(void)
{  
        uint32_t lastevent=  I2C_GetLastEvent(I2C2);
        switch (lastevent)
        {
                /************************** Master Invoke**************************************/
                case I2C_EVENT_MASTER_MODE_SELECT: // 0x00030001. 发送启动条件时产生的事件: EV5      
                {/* EV5 */
                        if (I2C2Buf.MasterDirection == Receiver)//I2C主模式接收
                        {
                                if (!I2C2Buf.Device_Addr_OffsetDone)
                                {
                                        I2C_Send7bitAddress(I2C2,I2C2Buf.SlaveADDR,I2C_Direction_Transmitter);
                                }
                                else
                                {
                                        /* Send slave Address for read */
                                        I2C_Send7bitAddress(I2C2,I2C2Buf.SlaveADDR,I2C_Direction_Receiver);
                                        I2C2Buf.Device_Addr_OffsetDone=0;                                       
                                }
                        }
                        else//I2C主模式发送
                        {
                               I2C_Send7bitAddress(I2C2, I2C2Buf.SlaveADDR, I2C_Direction_Transmitter);
                        }
                        I2C_ITConfig(I2C2, I2C_IT_BUF , ENABLE);
                        break;
                }
                /********************** Master Receiver events ********************************/
                case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: // 0x00030002. 发出读指定I2C从设备时产生的事件:EV6
                {/* EV6 */
                        break;
                }
                case I2C_EVENT_MASTER_BYTE_RECEIVED: //0x00030040主收到一个字节时产生的事件:EV7
                {/* EV7 */
                        I2C2Buf.RBuf[I2C2Buf.RCount++] = I2C_ReceiveData (I2C2);//I2C2中断读取数据
                        if(I2C2Buf.RCount == (I2C2Buf.Rdatalen - 1))//判断是否为倒数第2个数据
                        {
                                I2C_AcknowledgeConfig(I2C2, DISABLE);
                                I2C_GenerateSTOP(I2C2, ENABLE);
                        }
                        if(I2C2Buf.RCount == I2C2Buf.Rdatalen)//读到最后一个数据       
                        {
                                I2C_EE_ReadClearStatus();
                                I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_ERR , DISABLE);
                        }
                        break;
                }
                /************************* Master Transmitter events **************************/
                case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:  // 0x00070082. 发出写指定I2C从设备时产生的事件:EV8 just after EV6   
                {/* EV8 just after EV6 */
                        #if (EE_ADDRESS_NUM>1)//EEPROM内部地址是16位
                                I2C2Buf.Addr_Count++;       
                                if (I2C2Buf.Addr_Count < (EE_ADDRESS_NUM))
                                {
                                        I2C_SendData(I2C2, I2C2Buf.Device_AddrOffset>>8);
                                }
                        #else//EEPROM内部地址是8位
                                I2C_SendData(I2C2, I2C2Buf.Device_AddrOffset);
                                I2C2Buf.RegAddr_OffsetDone=1;//EEPROM内部地址写完
                        #endif
                        break;
                }
                case I2C_EVENT_MASTER_BYTE_TRANSMITTING: // 0x00070080. 正在发送数据中......
                { /* EV8 */
                        #if (EE_ADDRESS_NUM>1)
                        if (!I2C2Buf.Device_Addr_OffsetDone)
                        {
                                if (I2C2Buf.Addr_Count < (EE_ADDRESS_NUM))
                                {
                                        I2C_SendData(I2C2, I2C2Buf.Device_AddrOffset);
                                        I2C2Buf.Addr_Count++;
                                }
                                else
                                {
                                        I2C2Buf.Addr_Count=0;
                                        I2C2Buf.Device_Addr_OffsetDone=1;       
                                }
                                break;
                        }
                        #endif
                        if (I2C2Buf.MasterDirection == Receiver)
                        {
                                I2C_ITConfig(I2C2, I2C_IT_BUF , DISABLE);
                                I2C_GenerateSTART(I2C2, ENABLE);//I2C总线重启
                                break;
                        }
                        else
                        {
                                if(I2C2Buf.WCount < I2C2Buf.Wdatalen)
                                {
                                        I2C_SendData(I2C2, buf[I2C2Buf.WCount++]);
                                }
                                else //小于或等于一页的数据写完成
                                {      
                                        I2C_ITConfig(I2C2,I2C_IT_BUF, DISABLE);
                                }
                                break;
                        }
                }
                case I2C_EVENT_MASTER_BYTE_TRANSMITTED:   // 0x00070084. 一个字节数据发送完成.           
                {/* EV8-2 */
                        if (I2C2Buf.MasterDirection == Receiver)
                        {
                                break;
                        }
                        else
                        {
                                I2C_GenerateSTOP(I2C2, ENABLE);
                                I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF |I2C_IT_ERR, DISABLE);
                                while(I2C_GetFlagStatus(I2C2 , I2C_FLAG_BUSY));//等待页写完
                                I2C2Buf.WBuf+= I2C2Buf.NumByteWritingNow;//写地址偏移上次写完数据的个数
                                I2C2Buf.WriteAddr+= I2C2Buf.NumByteWritingNow;//写地址偏移上次写的数据的个数
                                I2C2Buf.NumByteToWrite-= I2C2Buf.NumByteWritingNow;//写总的数据减去当前写的数据个数
                                if(I2C2Buf.NumByteToWrite>0)//判断数据是否写完
                                {
                                        delay_ms(10);
                                        I2C_EE_IRQ_Write(I2C2Buf.WBuf,I2C2Buf.WriteAddr,I2C2Buf.NumByteToWrite);//再次调入写数据函数
                                }
                                else
                                {
                                        WriteComplete = 1;
                                        I2C_EE_WriteClearStatus();
                                }
                        }
                        break;
                }
        }
}

收藏 评论12 发布时间:2019-4-26 22:25

举报

12个回答
toofree 回答时间:2019-4-27 00:32:59
本帖最后由 toofree 于 2019-4-27 00:34 编辑

24xx EEPROM芯片有一个间隔时间(有可能叫写周期,具体查下手册),前一次停止位到下一次的起始位之间需要延时,最大5ms。
在个器件手册中都有这个参数。
页写完后,必然会有一次停止位。那么在下次页写前,需要加个延时。根据实际测试情况,这个延时有可能比5ms小,最短的可能延时1ms都够用。如果加5ms延时,那么对于各厂家的24xx系列EEPROM都适用。

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

回答时间:2019-4-27 08:59:04
楼主,多页写入时,每次只能写入一页,需要多次写入。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

stm1024 回答时间:2019-4-27 10:21:12
你在写之前有没有做check Busy呢?或者调试一下,看看EV的值,在翻页的时候是否会有变化?

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

wdshuang09 回答时间:2019-4-27 20:43:07
toofree 发表于 2019-4-27 00:32
24xx EEPROM芯片有一个间隔时间(有可能叫写周期,具体查下手册),前一次停止位到下一次的起始位之间需要 ...

每写完一页都有延时10ms,
wdshuang09 回答时间:2019-4-27 20:57:20
stm1024 发表于 2019-4-27 10:21
你在写之前有没有做check Busy呢?或者调试一下,看看EV的值,在翻页的时候是否会有变化? ...

有检测I2C总结的忙标识
tgw860910 回答时间:2019-4-28 11:11:05
你在写超过32个字节的数据时要把数据拆分开,不仅仅是每次只能写入32字节,而且写入地址也要跟着变,因为24C32一次只能写入32字节

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

wdshuang09 回答时间:2019-4-28 16:20:07
tgw860910 发表于 2019-4-28 11:11
你在写超过32个字节的数据时要把数据拆分开,不仅仅是每次只能写入32字节,而且写入地址也要跟着变,因为24 ...

这些都知道,问题不是出在这,
1.jpg
回答时间:2019-4-28 21:38:28
楼主,我们使用过程中,都是每一页进行一次写入操作。要重新开始,保证E2重新收到了新的页地址。
wdshuang09 回答时间:2019-4-29 08:02:43
安 发表于 2019-4-28 21:38
楼主,我们使用过程中,都是每一页进行一次写入操作。要重新开始,保证E2重新收到了新的页地址。 ...

把你的程序发出来看看,我都折腾了好多天了, 怀疑是我写完一页后中断事件处理有点问题,
12下一页

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版