关于stm32 I2C的问题

2019-03-23 19:51发布

用的是stm32的I2C硬件,这是我的配置过程,有些是从网上抄的,但是调不通啊,请大家看看那里有毛病,假如我操作的是24c02
I2C_InitStructure.I2C_OwnAddress1 应该配置成什么啊; 这个地址应该是主机的吧,我看有些例子写得是0x00,这是为什么
还有后面写24c02的地址在发送从机的7位地址的时候  EEPROM_ADDRESS应该是是0xA2吗,那为什么我找过的一些例子吗,他们操作的是24c02,但这里却写得是0xa0那
另外在写数据的起始字节地址时,因为AT24C02容量为2048bits,所以地址范围应该是0x00~0xff吧,那我去0xfe,应该是正确的吧

void I2C_Configuration(void)
{
   I2C_InitTypeDef  I2C_InitStructure;
  /* I2C configuration */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //Tlow/Thigh=2
  I2C_InitStructure.I2C_OwnAddress1 = 0x00;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能I2C的应答
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//应答7位地址,这里是从机的地址
  I2C_InitStructure.I2C_ClockSpeed = 400000;//I2C速率为400KHz(快速模式),该值不能高于400KHz
  
   /* Apply I2C configuration after enabling it */
  I2C_Init(I2C1, &I2C_InitStructure);
  
  /* I2C Peripheral Enable */
  I2C_Cmd(I2C1, ENABLE);

}


void I2C_EE_Init()
{
  /* GPIO configuration */
GPIO_Configuration();//GPIO端口配置

  /* I2C configuration */
  I2C_Configuration();

}


void I2C_EE_SequentialWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0;    //页数
  u8 NumOfSingle = 0;  //不足一页字节数
  u8 Addr = 0;        //字节地址
  u8 count = 0;      //字节计数器

  Addr = WriteAddr % I2C_PageSize; //字节地址(不到一页)
  count = I2C_PageSize - Addr; //一页中的剩余字节数
  NumOfPage =  NumByteToWrite / I2C_PageSize; //欲写入数据所占的页数
  NumOfSingle = NumByteToWrite % I2C_PageSize;  //欲写入数据所占的字节数(不足一页)

  /* If WriteAddr is I2C_PageSize aligned  */
  if(Addr == 0) //起始地址为某页的第一个字节地址处
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0)//写入的数据字节数不足一页
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();//等待EEPROM自编程结束
    }
    /* If NumByteToWrite > I2C_PageSize */
    else//写入的数据超过一页
    {
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
            I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;//下一页起始地址
        pBuffer += I2C_PageSize;
      }

      if(NumOfSingle!=0)  //写入余下不足一页的数据
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }
  /* If WriteAddr is not I2C_PageSize aligned 写入数据的起始地址不在页的开始处 */
  else
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0)//不足一页的,直接写入。注意:当写到页边界时,将从该页的起始地址继续写入数据
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / I2C_PageSize;
      NumOfSingle = NumByteToWrite % I2C_PageSize;       
      
      if(count != 0)
      {  
        I2C_EE_PageWrite(pBuffer, WriteAddr, count); //将WriteAddr所在页的剩余空间写满
        I2C_EE_WaitEepromStandbyState();
        WriteAddr += count;  //地址指向下一页的起始处
        pBuffer += count;
      }
      
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
        I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize;  
      }
      if(NumOfSingle != 0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); //写入余下不足一页的数据
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }  
}
void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)
{
  /* While the bus is busy */
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));//等待I2C总线空闲
  
  /* Send STRAT condition */
  I2C_GenerateSTART(I2C1, ENABLE); //发送START后,MCU自动从从机模式变成主机模式

  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //等待START产生成功

  /* Send EEPROM address for write 发送从机器件地址*/
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
      
  /* Send the EEPROM's internal address to write to发送从机预写入的内部字节地址 */
  I2C_SendData(I2C1, WriteAddr);
  
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* Send the byte to be written */
  I2C_SendData(I2C1, *pBuffer);
   
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  
  /* Send STOP condition */
  I2C_GenerateSTOP(I2C1, ENABLE);
}

void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)  //看主发送器的时序图
{
  /* While the bus is busy */
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));//等待I2C总线空闲
  
  /* Send START condition */
  I2C_GenerateSTART(I2C1, ENABLE);//产生START后,MCU自动从从机模式变成主机模式
  
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //等待START产生成功
  
  /* Send EEPROM address for write */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  /* Send the EEPROM's internal address to write to */   
  I2C_SendData(I2C1, WriteAddr);  

  /* Test on EV8 and clear it等待发送数据寄存器空,即收到ACK */
  while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* While there is data to be written */
  while(NumByteToWrite--)  
  {
    /* Send the current byte */
    I2C_SendData(I2C1, *pBuffer);

    /* Point to the next byte to be written */
    pBuffer++;
  
    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  }

  /* Send STOP condition */
  I2C_GenerateSTOP(I2C1, ENABLE);//发送停止传输指令
}


void I2C_EE_SequentialRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{  
    /* While the bus is busy */
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
  
  /* Send START condition */
  I2C_GenerateSTART(I2C1, ENABLE);
  
  /* Test on EV5 and clear it 等待开始信号发送成功*/
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
   
  /* Send EEPROM address for write */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

  /* Test on EV6 and clear it等待设备地址发送成功 */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  
  /* Clear EV6 by setting again the PE bit */
  I2C_Cmd(I2C1, ENABLE);

  /* Send the EEPROM's internal address to write to */
  I2C_SendData(I2C1, ReadAddr);  

  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  
  /* Send STRAT condition a second time */  
  I2C_GenerateSTART(I2C1, ENABLE);
  
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
  
  /* Send EEPROM address for read */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);
  
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
  
  /* While there is data to be read */
  while(NumByteToRead)  
  {
    if(NumByteToRead == 1)   
    {
      /* Disable Acknowledgement */
      I2C_AcknowledgeConfig(I2C1, DISABLE);
      
      /* Send STOP Condition */
      I2C_GenerateSTOP(I2C1, ENABLE);
    }

    /* Test on EV7 and clear it 接收数据寄存器非空*/
    if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))  
    {      
      /* Read a byte from the EEPROM */
      *pBuffer = I2C_ReceiveData(I2C1);

      /* Point to the next location where the byte read will be saved */
      pBuffer++;
      
      /* Decrement the read bytes counter */
      NumByteToRead--;        
    }   
  }

  /* Enable Acknowledgement to be ready for another reception */
  I2C_AcknowledgeConfig(I2C1, ENABLE);//每接收到一个字节数据向从机发送一个ACK
} 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
1条回答
虚V界
1楼-- · 2019-03-24 01:06
/ 2C_InitStructure.I2C_OwnAddress1 是STM32 自己的地址,只有作为从机的时候才有用,做主机的话添什么都得。发送的时候把器件发送出去就行了

一周热门 更多>