STM32 Controller
STM32 Controller: I2C
STM32 Controller: I2C
The I2C or Inter-Inter Peripheral bus is primarily known for its use accessing IC’s such as EEPROM memory and in some cases other relatively slow peripherals & sensors (i.e. Digital Compasses). It’s typical bus speed is 100kbps (standard mode), but later revisions of the protocol have pushed it upwards: 400kbps (fast mode) and 1Mbps (fast mode plus). It can go faster, but even the latter fast versions of the protocol are not that widely supported by peripherals. Thus typically today most people run I2C at or around 100kbps.
Getting it to work on the STM32
This was a pretty straightforward task, the peripheral hardware for I2C in the STM32 is not as complex a module as that found in say Texas Instruments 28xx Series of processors – a gift and a curse all at once. It’s quicker to get going, but also not as processor efficient once the core code is done (for example the STM32’s I2C module does not handle Start/Stop conditions on your behalf, it is down to the software to drive this part of the protocol engine).
Hooking the STM32 up to an EEPROM
Although the I2C on the STM32small controller board was brought out primarily for compass interfaces and/or other such sensors. To verify the hardware design it’s easiest to start with a common little EEPROM.
Below is a 2K NXP PCF8582C-2P EEPROM, wired up to the STM32small controller.

A few things to note in the picture above:
- The near side of the breadboard is SDA/SCL & Vcc Side of the Chip
- The far side of the breadboard is Address Lines & Vdd (ground)
- This particular chip gives you 3 I/O lines that allow customisation of the chips I2C address, so note that for this test on the far side there are 3 (1k) resistors going from each of these pins to ground. This gives the chip the most common EEPROM address of 0xA0.
- On the near side you can see two further (1k) resistors, pulling the SDA and SCL lines high, as per the I2C bus protocol. This might seem strange at first, why are they not on the controller itself? Well provision for pull-up resistors is on the PCB, they simply weren’t fitted as I didn’t know what I’d be testing out first and some sensor boards etc. have pull-ups already fitted so having them on the controller is not always necessary (depends what you have on your bus basically). Thus I’ve fitted these resistors on the breadboard.
Acknowledging Data
Historically I2C doesn't like me and I've never been a huge fan of it (which is cause and which is consequence is yet to be determined). However it is another good case where I'll bang my logic analyzer drum and say that unless you're dealing with a controller you know well and have some proven I2C library code you could be in for a painful experience of wondering "why does it not work!" unless you have either an oscilloscope or logic analyzer to figure out the initial mystery.
Oscilloscopes have their place, but logic analyzers are better for most digital protocols – bring out the scope when you have a propagation delay issue or your 3.3V rail isn’t rising fast enough to power sequence your microchips correctly. For digital work you want to be able to see the raw signals and save time decoding the data by having the analyzer doing that for you.
Anyway, the most frustrating period of working with I2C is typically when the device you're hooked up to simply refuses to acknowledge (pull the SDA line down in the ACK period or 9th clock cycle).
A quick look at just what a non-acknowledged signal will look like (forgive the fact I've messed up my decoder channel settings here so you can't see the clock line - it'll be clearer in later shots):

Now remember earlier I said this EEPROM has an address of 0xA0 well note above that we've sent a START, followed by a Write operation to Address 0x50 (wrong address for this chip). As a result we're not addressing the EEPROM, so it doesn't acknowledge our request, thus the NA (NACK if we'd zoomed in closer on the signal).
Now let's try that again, this time with the analyzer set-up properly and also with the correct address going out on the bus:

Now notice the address is correct (0xA0) and that as a result we now get our sought after ACK (the 'A' you can see on the 9th clock cycle). Finally our STM32small controller sends a stop condition at the end of this message..... The code is currently setup to poll for I2C devices, all that we really need at this time to verify the hardware.
The Mk.1 Design Mistake
The Mk.1 design as you can read on the Mk.2 Objectives page has had almost no PCB errors, mostly minor tweaks. However the I2C was not as lucky, while the hardware all works my intended pinout was tracked out wrong and at some stage there was a mix up on the SDA (Data) and SCL (Clock) lines.
So instead of having a dedicated I2C header with: SCL, SDA, 3.3V, Ground
I actually have the pinout as: SDA, SCL, 3.3V, Ground.
If you're working with external components and boards via wiring, then this is a non-issue because you just swap the two wires round and you're done - everything works as you can see above.
However, I specifically wanted the above pinout because it is common to a lot of sensor boards and is the most typically found pinout of I2C devices/break out boards.
Still, this is why there's a Mk.1 design, it can be very quickly fixed in the Mk.2
Other then that...
Well it works and we can talk to our EEPROM and other sensors just fine, my only grumble with the STM32 peripheral library code for I2C at the moment is that it is written with no real appreciation shown for fault tolerance. A lot of the example code simply shows infinite loops while waiting for an event (such as an Acknowledge) to occur - but of course if you send the wrong address or get your MSB and LSB's mixed up or similar silly mistakes, you won't get this event and your code will just hang in the infinite loop. More reading of the registers and datasheet required - but what I do want to avoid is the solution I've seen discussed on other sites of using error interrupts, typically you should keep your interrupts to a total minimum if you can or the system quickly becomes complex and difficult to effectively measure and/or ensure throughput performance.


