Mercurial > public > ostc4
changeset 328:4fe5400567e7 I2C_Improvment
Set I2C speed to 88kHz, use digital filter only and reworked idle clock recovery
The errata describes a possible problem in operation between 88kHz and 100kHz => Set speed as recommended as work around.
Based on reference implementation only one filter should be use. Choice was digital because only drawback is lag of wakeup functionality which is not used
I2C communication may be randomly interrupted e.g. by a RTE reset or firmware update => reworked recovery function to get I2C devices in idle state again (Clk and SDA HIGH)
author | ideenmodellierer |
---|---|
date | Wed, 17 Jul 2019 22:42:15 +0200 |
parents | abec171c2c4b |
children | da5b91b1e20e |
files | Small_CPU/Src/i2c.c |
diffstat | 1 files changed, 30 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/Small_CPU/Src/i2c.c Wed Jul 17 22:41:31 2019 +0200 +++ b/Small_CPU/Src/i2c.c Wed Jul 17 22:42:15 2019 +0200 @@ -31,39 +31,51 @@ void HAL_I2C_Send_One_CLOCK(void) { HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_RESET); - HAL_Delay(10); + HAL_Delay(1); HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_SET); - HAL_Delay(10); + HAL_Delay(1); } GPIO_PinState MX_I2C1_TestAndClear(void) { + GPIO_PinState retval; + uint8_t repeatcnt = 3; + I2C_DeInit(); HAL_I2C_ManualControl_MspInit(); - for(int i=0; i<9;i++) + +/* The SDA line is expected to be HIGH if no com is pending => send dummy clock signals if that is not the case */ + do { - if(HAL_I2C_Read_Data_PIN() == GPIO_PIN_RESET) - HAL_I2C_Send_One_CLOCK(); - else - break; - } - return HAL_I2C_Read_Data_PIN(); + for(int i=0; i<20;i++) + { + if(HAL_I2C_Read_Data_PIN() == GPIO_PIN_RESET) + HAL_I2C_Send_One_CLOCK(); + else + break; + } + retval = HAL_I2C_Read_Data_PIN(); + }while ((repeatcnt-- > 0) && (retval != GPIO_PIN_SET)); + + return retval; } HAL_StatusTypeDef MX_I2C1_Init(void) { - I2cHandle.Instance = I2Cx; + I2cHandle.Instance = I2Cx; I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - I2cHandle.Init.ClockSpeed = 100000;//400000; REDUCED for compatibility with HMC5583L + MMA8452Q - I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; - I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; + I2cHandle.Init.ClockSpeed = 88000; /* Reduced to avoid behavior described in errata: Mismatch on the “Setup time for a repeated Start condition” */ + I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; /* don't care if not in fast mode */ I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; - I2cHandle.Init.OwnAddress1 = 0x01; + I2cHandle.Init.OwnAddress1 = 0x01; /* don't care because of master mode */ + +/* According to documentation setting filters before I2C initialization is recommended */ + /* HAL_I2CEx_AnalogFilter_Config(&I2cHandle, I2C_ANALOGFILTER_ENABLED); */ + HAL_I2CEx_ConfigDigitalFilter(&I2cHandle,0x0F); global.I2C_SystemStatus = HAL_I2C_Init(&I2cHandle); - HAL_I2CEx_AnalogFilter_Config(&I2cHandle, I2C_ANALOGFILTER_ENABLED); - HAL_I2CEx_ConfigDigitalFilter(&I2cHandle,0x0F); if(global.dataSendToSlavePending) { @@ -85,12 +97,13 @@ i2c_errors++; } + HAL_StatusTypeDef I2C_Master_Transmit( uint16_t DevAddress, uint8_t *pData, uint16_t Size) { if(global.I2C_SystemStatus != HAL_OK) return global.I2C_SystemStatus; - global.I2C_SystemStatus = HAL_I2C_Master_Transmit(&I2cHandle, DevAddress, pData, Size, 2); + global.I2C_SystemStatus = HAL_I2C_Master_Transmit(&I2cHandle, DevAddress, pData, Size, 10); if(global.I2C_SystemStatus != HAL_OK) { I2C_Error_count();