这几天拿到了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 ;
- }
- }
复制代码
|