stm32f3的i2c使用小結
這幾天拿到了stm32f3discovery,拿到手的第一件事就是測試了硬件i2c,使用stm32cube生成庫,測試對象為AD5934與ADG715。經過兩天的調試,完美調通。中間也碰到了些問題。
1、一開始用的I2C1,一仿真就會出現(xiàn)死機的情況。
由于I2C1與swd接口重合,所以調用HAL_I2C_Init()函數后就死機,改成I2C2后問題解決。
2、無法訪問指定地址的設備
庫函數中的入口地址并不是7bit地址,需要輸入8bit。我的設備地址為13,始終無法訪問設備,改為26后解決。
3、可以讀寫單個地址的數據,但是不能多字節(jié)讀寫。
(1)、對于多字節(jié)寫, 庫函數中的
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_tMemAddSize, uint8_t*pData, uint16_t Size, uint32_t Timeout)
其中MemAddSize表示地址的位數,0表示7bit地址,1表示10bit地址。我誤認為這個寫的字節(jié)數,所以導致在寫多字節(jié)的時候出錯。
(2)、對于多字節(jié)讀,由于AD5934的讀操作與庫函數的讀操作有些出入,所以導致一直讀錯誤。在庫函數中寫完讀的內存地址就開始讀,而AD5934中寫完block read后接著還要再寫一個number bytes read然后才開始讀。所以需要對庫函數進行修改,新增一個函數,以適合AD5934的block read.
stm32f3的i2c有三種模式:Reload、AutoEnd、SoftEnd模式。
i2c每發(fā)送完一個字節(jié),就會產生TXIS標志,當發(fā)送完最后一個字節(jié)時:
對于Reload模式,當字節(jié)大于255字節(jié)時,必須使用此模式,此模式下發(fā)送結束后,會產生tcr標志。
對于AutoEnd模式,發(fā)送后最后一個字節(jié)時,會自動產生STOP。
對于SoftEnd模式,發(fā)送完最后一個字節(jié)時,會產生tc標志,對于發(fā)送過程中需要Restart的需要使用此模式。
對于AD5934的讀操作,可以事先工作在SoftEnd模式,發(fā)送完block read與number bytes read字節(jié)后,再轉入AutoEnd模式進行Restart,讀取完指定的字節(jié)后自動產生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;
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 andgenerate 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 isautomatically 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;
}
}
http://blog.csdn.net/xiaoxiongli/article/details/49637785
http://blog.csdn.net/xiaoxiongli/
|