2019-05-21 04:25 AM
I want to use a STM32L151RDT6 as I2C slave and a USB to I2C bridge from FTDI as master.
Reading command with the slave from the master is possible. But when i try to transmit data to the master the slave is releasing the SDA Line after the acknowledge. But the master expected a low SDA line bevor he start clocking for the databyte.
I had oriented on the example code: STM32Cube/Repository/STM32Cube_FW_L1_V1.9.0/Projects/NUCLEO-L152RE/Examples/I2C/I2C_TwoBoards_RestartComIt
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(LED_gn_GPIO_Port, LED_gn_Pin, SET);
/* The board receives the message and sends it back */
/*##-3- Put I2C peripheral in listen mode process ###########################*/
if (HAL_I2C_EnableListen_IT(&hi2c1) != HAL_OK) {
/* Transfer error in reception process */
Error_Handler();
}
/*##-4- Wait Address Match Code event ######################################*/
/* Before starting a transfer, you need to wait a Master request event.
For simplicity reasons, this example is just waiting till an Address callback event,
but application may perform other tasks while transfer operation is ongoing. */
while (uwTransferRequested != 1) {
}
/*##-3- Put I2C peripheral in reception process ############################*/
if (HAL_I2C_Slave_Seq_Receive_IT(&hi2c1,aRxBuffer,
RXBUFFERSIZE, I2C_FIRST_FRAME) != HAL_OK) {
/* Transfer error in reception process */
Error_Handler();
}
/*##-4- Wait for the end of the transfer ###################################*/
/* Before starting a new communication transfer, you need to check the current
state of the peripheral; if it’s busy you need to wait for the end of current
transfer before starting a new one.
For simplicity reasons, this example is just waiting till the end of the
transfer, but application may perform other tasks while transfer operation
is ongoing. */
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){
}
/*##-5- Start the transmission process #####################################*/
/* While the I2C in reception process, user can transmit data through
"aTxBuffer" buffer */
aTxBuffer[0] = 13;
if (HAL_I2C_Slave_Seq_Transmit_IT(&hi2c1,aTxBuffer,
TXBUFFERSIZE, I2C_LAST_FRAME) != HAL_OK) {
/* Transfer error in transmission process */
Error_Handler();
}
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY) {
}
/* USER CODE END 2 *
/* USER CODE BEGIN 4 */
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle) {
/* Turn LED2 off: Transfer in transmission process is correct */
HAL_GPIO_WritePin(LED_gb_GPIO_Port, LED_gb_Pin, RESET);
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle) {
/* Turn LED2 on: Transfer in reception process is correct */
HAL_GPIO_WritePin(LED_gb_GPIO_Port, LED_gb_Pin, SET);
}
/**
* @brief Slave Address Match callback.
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2C.
* @param TransferDirection: Master request Transfer Direction (Write/Read), value of @ref I2C_XferOptions_definition
* @param AddrMatchCode: Address Match Code
* @retval None
*/
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection,
uint16_t AddrMatchCode) {
uwTransferRequested = 1;
}
/**
* @brief Listen Complete callback.
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2C.
* @retval None
*/
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) {
}
/**
* @brief I2C error callbacks.
* @param I2cHandle: I2C handle
* @note This example shows a simple way to report transfer error, and you can
* add your own implementation.
* @retval None
*/
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle) {
/** Error_Handler() function is called when error occurs.
* 1- When Slave don't acknowledge it's address, Master restarts communication.
* 2- When Master don't acknowledge the last data transferred, Slave don't care in this example.
*/
if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF) {
Error_Handler();
}
}
/* USER CODE END 4 */
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 26;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}