colinluan的笔记 https://bbs.21ic.com/?544170 [收藏] [复制] [RSS]

日志

stm32f3的i2c使用小结

已有 3030 次阅读2015-4-26 20:27 |个人分类:IAR for ARM|系统分类:ARM| stm32cube, i2c, i2c

这几天拿到了stm32f3discovery,拿到手的第一件事就是测试了硬件i2c,使用stm32cube生成库,测试对象为AD5934与ADG715。经过两天的调试,完美调通。中间也碰到了些问题。
1、一开始用的I2C1,一仿真就会出现死机的情况。
        由于I2C1与swd接口重合,所以调用HAL_I2C_Init()函数后就死机,改成I2C2后问题解决。
2、无法访问指定地址的设备
        库函数中的入口地址并不是7bit地址,需要输入8bit。我的设备地址为13,始终无法访问设备,改为26后解决。
3、可以读写单个地址的数据,但是不能多字节读写。
       (1)、对于多字节写, 库函数中的
        HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
       其中MemAddSize表示地址的位数,0表示7bit地址,1表示10bit地址。我误认为这个写的字节数,所以导致在写多字节的时候出错。
       (2)、对于多字节读,由于AD5934的读操作与库函数的读操作有些出入,所以导致一直读错误。在库函数中写完读的内存地址就开始读,而AD5934中写完block read后接着还要再写一个number bytes read然后才开始读。所以需要对库函数进行修改,新增一个函数,以适合AD5934的block read.

        stm32f3的i2c有三种模式:Reload、AutoEnd、SoftEnd模式。

        i2c每发送完一个字节,就会产生TXIS标志,当发送完最后一个字节时:

        对于Reload模式,当字节大于255字节时,必须使用此模式,此模式下发送结束后,会产生tcr标志。

        对于AutoEnd模式,发送后最后一个字节时,会自动产生STOP。

        对于SoftEnd模式,发送完最后一个字节时,会产生tc标志,对于发送过程中需要Restart的需要使用此模式。

        对于AD5934的读操作,可以事先工作在SoftEnd模式,发送完block read与number bytes read字节后,再转入AutoEnd模式进行Restart,读取完指定的字节后自动产生STOP。操作流程如下:






HAL_StatusTypeDef HAL_I2C_Mem_Read_AD5934_Block(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  
uint32_t Sizetmp = 0;

  
/* Check the parameters */
  
assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
  
  
if(hi2c->State == HAL_I2C_STATE_READY)
  
{   
   
if((pData == NULL) || (Size == 0))
   
{
      
return  HAL_ERROR;                                    
   
}

   
if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
   
{
      
return HAL_BUSY;
   
}

   
/* Process Locked */
   
__HAL_LOCK(hi2c);
   
   
hi2c->State = HAL_I2C_STATE_MEM_BUSY_RX;
   
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
   
/*
    //Send Slave Address and Memory Address
    if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout) != HAL_OK)
    {
      if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      {
        // Process Unlocked
        __HAL_UNLOCK(hi2c);
        return HAL_ERROR;
      }
      else
      {
        // Process Unlocked
        __HAL_UNLOCK(hi2c);
        return HAL_TIMEOUT;
      }
    }*/

   
   
I2C_TransferConfig(hi2c,DevAddress,MemAddSize+1, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
      
   
/* Wait until TXIS flag is set */
   
if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK)
   
{
      
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      
{
        
return HAL_ERROR;
      
}
      
else
      
{
        
return HAL_TIMEOUT;
      
}
   
}
   
   
/* If Memory address size is 8Bit */
   
if(MemAddSize == I2C_MEMADD_SIZE_8BIT)
   
{
      
/* Send Memory Address */
      
hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_LSB(MemAddress);   
   
}      
   
/* If Mememory address size is 16Bit */
   
else
   
{
      
/* Send MSB of Memory Address */
      
hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_MSB(MemAddress);
      
      
/* Wait until TXIS flag is set */
      
if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK)
      
{
        
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
        
{
         
return HAL_ERROR;
        
}
        
else
        
{
         
return HAL_TIMEOUT;
        
}
      
}
      
      
/* Send LSB of Memory Address */
      
hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_LSB(MemAddress);  
   
}
   
   
/* Wait until TXIS flag is set */
   
if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK)
   
{
      
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      
{
        
return HAL_ERROR;
      
}
      
else
      
{
        
return HAL_TIMEOUT;
      
}
   
}
   
   
hi2c->Instance->TXDR = Size;
   
   
/* Wait until TC flag is set */
   
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout) != HAL_OK)      
   
{
      
return HAL_TIMEOUT;
   
}   
   
   
/* Send Slave Address */
   
/* Set NBYTES to write and reload if size > 255 and generate RESTART */
   
/* Size > 255, need to set RELOAD bit */
   
if(Size > 255)
   
{
      
I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
      
Sizetmp = 255;
   
}
   
else
   
{
      
I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
      
Sizetmp = Size;
   
}
   
   
do
   
{  
      
/* Wait until RXNE flag is set */
      
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK)      
      
{
        
return HAL_TIMEOUT;
      
}
         
      
/* Read data from RXDR */
      
(*pData++) = hi2c->Instance->RXDR;

      
/* Decrement the Size counter */
      
Sizetmp--;
      
Size--;   

      
if((Sizetmp == 0)&&(Size!=0))
      
{
        
/* Wait until TCR flag is set */
        
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout) != HAL_OK)      
        
{
         
return HAL_TIMEOUT;
        
}
        
        
if(Size > 255)
        
{
         
I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
         
Sizetmp = 255;
        
}
        
else
        
{
         
I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
         
Sizetmp = Size;
        
}
      
}

   
}while(Size > 0);

   
/* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
   
/* Wait until STOPF flag is reset */
   
if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != HAL_OK)
   
{
      
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      
{
        
return HAL_ERROR;
      
}
      
else
      
{
        
return HAL_TIMEOUT;
      
}
   
}

   
/* Clear STOP Flag */
   
__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
   
   
/* Clear Configuration Register 2 */
   
__HAL_I2C_RESET_CR2(hi2c);
   
   
hi2c->State = HAL_I2C_STATE_READY;
   
   
/* Process Unlocked */
   
__HAL_UNLOCK(hi2c);
   
   
return HAL_OK;
  
}
  
else
  
{
   
return HAL_BUSY;
  
}
}



路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)