
用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; } } } |
串口DMA + 空闲中断收发 ?
F103RCT6芯片对AFIO->MAPR寄存器写入时出错
使用STM32捕获PWM时同时捕获2个通道时会出现捕获的频率值不准确的问题
WS2812B怎么显示任意字符 / 图案?
STM32F103RCT6 定位孔 镂空,会影响使用吗?
HAL库1.8.4在做破坏性测试的时候出现g_state永远为busy的情况导致串口通信发送卡死
L9663驱动开发
用rt_thread 环境编写,DAP-LINK 下载烧录,每一次空芯片下载之后就无法二次下载。求解
stm32cubemx F103芯片tim3 encoder模式pc6和pc7引脚,自动生成代码缺少gpio映射。
stm32的同一个定时器,不同的通道,可以不同时的输出pwm波形吗
24xx EEPROM芯片有一个间隔时间(有可能叫写周期,具体查下手册),前一次停止位到下一次的起始位之间需要延时,最大5ms。
在个器件手册中都有这个参数。
页写完后,必然会有一次停止位。那么在下次页写前,需要加个延时。根据实际测试情况,这个延时有可能比5ms小,最短的可能延时1ms都够用。如果加5ms延时,那么对于各厂家的24xx系列EEPROM都适用。
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
每写完一页都有延时10ms,
有检测I2C总结的忙标识
评分
查看全部评分
这些都知道,问题不是出在这,
把你的程序发出来看看,我都折腾了好多天了, 怀疑是我写完一页后中断事件处理有点问题,
楼主你好,我只能提供思路,解决方法。代码肯定不能共享的。网上有很多例程,你可以随便参考。
"保证E2重新收到了新的页地址",
这个E2是指?就这一小部分程序是怎么实现的,中断里是检测什么EV事件
评分
查看全部评分