I’m using a chinese STM32 board to control a PCF8574 (8bit port expander) and a PCA9685 (16x 12bits PWM Driver) over I2C.
It works, but I don’t understand why the I2C speed is running at strange 70Khz (checked on a scope).
I would like to change the I2C speed to standard speed (100khz, ideally at 400khz).
I read about CCR & TRISE, and tried to figure out how to set these in I2C.h but I didn’t succeed as this is a bit beyond my current knowledge level.
Can anybody help ?
Thanks
or
google i2c set clock speed site:http://www.stm32duino.com
<…>
I’m using a chinese STM32 board to control a PCF8574 (8bit port expander) and a PCA9685 (16x 12bits PWM Driver) over I2C.
It works, but I don’t understand why the I2C speed is running at strange 70Khz (checked on a scope).
I would like to change the I2C speed to standard speed (100khz, ideally at 400khz).
Hardwire is exact speed, but must be used on the pins that are dedicated to I2c.
See this thread. The way to use hardwire and set the clock to exactly 100 or 400kHz is in there.
I re-downloaded the most recent master zip (the one I had was 2 months old). No change.
@fredbox
reading through the thread, I realized I’m using software bit-bangeg I2C.
Ref : https://github.com/rogerclarkmelbourne/ … 4e7a0c6c0b
So my module is one of those who requires Soft_Standard = 16 instead of 27 to run at 100Khz,
And Soft_Fast = 0 only reach around 260Khz instead of 400Khz on my module.
OK that’s one good thing, I now understand that.
Now to run at 400Khz I’ll need to use the hardware I2C.
My problem is I’m not calling directly the I2C library as I’m using these library (they both worked OK as is on the STM32) :
http://blog.iharder.net/2014/08/08/msp4 … -expander/ (for the PCF8574)
and
https://github.com/adafruit/Adafruit-PW … er-Library (for the PCA9685)
So my understanding is I’ll have to edit these library so they call the hardware I2C instead of software I2C library (please recall I’m a beginner).
Is this OK ?
Can anyone give me some rough instructions how to do this ?.
Thanks for your help.
This is a common problem. A significant number of libraries only work with AVR and have to be modified to work with the STM32 ( and non AVR boards in general)
This has been discussed in various other threads on the forum.
But to cut to the chase…
Copy the library into your sketch folder and change the include to “./LIBRARYNAME/LIBRARYNAME.H”
Then edit the library files themselves and change instances of Wire to Hardwire
(you may need to make other changes, e.g. to make the global instance of Wire
but the changes will depend on the library)
I am afraid you will probably need to enhance your programming skills if you are an absolute beginner, because the STM32 is a step up from the basic functionality of the AVR.
You can modify the libraries to get different speeds, but if you read the docs & read the library code of how the registers are setup, you can just change it in your code.
After initializing the I2C device via hardwire, you can manipulate the registers before sending the address to start off the I2C communication.
For manipulating the speed, i’d assume you’d have to play around with the CCR (clock control register), or maybe CR2 (control register 2).
The first one contains a value to reach the right i2c frequency compared to the other settings, the second contains a value that indicates the clock of your microcontroller (will now be 100100, = 36 for the board running at 72Mhz, if you put it to 18 for example, i’d expect your I2C frequency to double. but if you want to slow it down, then it can’t be done via this, since 36 is the highest value allowed in this register).
Read up on it in the documentation (page 787 for the CCR), and in code:
I2C1->regs->CCR = <new value> (although, be careful you only change the bits you need to change, only the lower 11 bits are related to the frequency
I2C1->regs->CR2= <new value> (although, be careful you only change the bits you need to change, only the lower 6 bits are related to the frequency
Both Ray and I have tested this, and Unfortunately, libraries in sub folders (inside the sketch folder) Do Not work ![]()
This is a bug in the IDE that has been present for several years
I am not sure the best solution for the OP. Perhaps just modify the Wire library in the core so that it uses HardWire rather than the normal bit banged version
I wonder how many people actually use I2C on any other pins. I defaulted it to the hardware I2C pins.
Perhaps I should change the development branch so that Wire uses Hardwire???
<…>
Both Ray and I have tested this, and Unfortunately, libraries in sub folders (inside the sketch folder) Do Not work
This is a bug in the IDE that has been present for several years
Probably a topic for a survey
I gave this an unsuccessful try and I’ve decided that for now I’ll simply stick to software I2C (unfortunately running around 260KHz instead of 400Khz), and won’t spend more time on this as I can’t stand to stay blocked for too long with this project.
I’ll reserve my time to bring my project forward, after all the motivation to learn also comes from those projects we do…
May be in a year I’ll be back on this topic, and hopefully better equipped to face the challenge.
Thanks again.
PS
1) If anybody has a quick fix at this other than going for soft I2C, feel free to post, I’ll always be interested.
2) Also, current soft I2C implentation seems limited to around 260KHz, any plan for improvement up to 400Khz ?
It is definitely possible. The speed limitation is being caused because of the call overhead to digitalWrite, and the call to the set_sda() and set_scl() functions
If you want to try a few quick tricks you could change
void TwoWire::set_sda(bool state) {



