这几天拿到了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 http://tiyubisai.com/video_news/news_135585.html */
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
;
}
}
http://blog.csdn.net/xiaoxiongli/article/details/49637785
http://blog.csdn.net/xiaoxiongli/