Index
- Eclipse IDE and JTAG
- Unlock STM32F103 with JTAG
- Flash firmware using Bluetooth
- Serial Port Bluetooth
- Serial Port Plot
- SM32F103C8T6 use 128kbytes flash
- Observer
- Shane Colton documentation and firmware
- Firmware
- Part 1: Field-Oriented
- Part 2: Field-Oriented
- Sensorless Pneu Scooter - part 1
- Sensorless Pneu Scooter - part 2
- Sensorless Pneu Scooter - part 3
- Texas Instruments videos
- Chinese controllers code
- Chinese balance group reference design
- Kerry D. Wong -- A Self-Balancing Robot
- Self balance bicycle
- PID
- LQR
- PID and LQR, MATLAB
- Steve Brunton videos
01
https://electronics.stackexchange.com/questions/267972/i2c-busy-flag-strange-behaviourST has released an errata sheet called:
STM32F100xC, STM32F10 0xD and STM32F100xE high-density value line device limitations
http://www.st.com/content/ccc/resource/technical/document/errata_sheet/7f/05/b0/bc/34/2f/4c/21/CD00288116.pdf/files/CD00288116.pdf/jcr:content/translations/en.CD00288116.pdf
The interesting point here is:
2.9.7 I2C analog filter may provide wrong value, locking BUSY flag and preventing master mode entry
There is a detailed 15 step workaround that worked for me, surprisingly for an STM32F446, so I2C peripherals of every STM32 CORTEX-M series might be affected.
During this operation, the lines must not be actively pulled up or down by a bus member. So if you connect two I2C interfaces of the same MCU to the bus, first set up the pins of both to Alternate Function/Open Drain, then call the routine, as a transition of logical levels is required.
Here is an example with HAL libraries I use after the first initialization and during runtime, if an error occurs. As said above, this is for STM32F4, libraries for SMT32F1 might differ a bit.
struct I2C_Module
{
I2C_HandleTypeDef instance;
uint16_t sdaPin;
GPIO_TypeDef* sdaPort;
uint16_t sclPin;
GPIO_TypeDef* sclPort;
};
void I2C_ClearBusyFlagErratum(struct I2C_Module* i2c)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 1. Clear PE bit.
i2c->instance.Instance->CR1 &= ~(0x0001);
// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStructure.Alternate = I2C_PIN_MAP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Pin = i2c->sclPin;
HAL_GPIO_Init(i2c->sclPort, &GPIO_InitStructure);
HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_SET);
GPIO_InitStructure.Pin = i2c->sdaPin;
HAL_GPIO_Init(i2c->sdaPort, &GPIO_InitStructure);
HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_SET);
// 3. Check SCL and SDA High level in GPIOx_IDR.
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
{
asm("nop");
}
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
{
asm("nop");
}
// 4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_RESET);
// 5. Check SDA Low level in GPIOx_IDR.
while (GPIO_PIN_RESET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
{
asm("nop");
}
// 6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_RESET);
// 7. Check SCL Low level in GPIOx_IDR.
while (GPIO_PIN_RESET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
{
asm("nop");
}
// 8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_SET);
// 9. Check SCL High level in GPIOx_IDR.
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
{
asm("nop");
}
// 10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_SET);
// 11. Check SDA High level in GPIOx_IDR.
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
{
asm("nop");
}
// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Alternate = I2C_PIN_MAP;
GPIO_InitStructure.Pin = i2c->sclPin;
HAL_GPIO_Init(i2c->sclPort, &GPIO_InitStructure);
GPIO_InitStructure.Pin = i2c->sdaPin;
HAL_GPIO_Init(i2c->sdaPort, &GPIO_InitStructure);
// 13. Set SWRST bit in I2Cx_CR1 register.
i2c->instance.Instance->CR1 |= 0x8000;
asm("nop");
// 14. Clear SWRST bit in I2Cx_CR1 register.
i2c->instance.Instance->CR1 &= ~0x8000;
asm("nop");
// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
i2c->instance.Instance->CR1 |= 0x0001;
// Call initialization function.
HAL_I2C_Init(&(i2c->instance));
}