I2C and MS5611 precision Barometer using STM32

I2C or ISP protocol, what chice?

Both options are okay, ISP protocol is faster, can run over 40 MHz, but sometimes we have more than one device, so it is better sometimes to use I2C protocol.  After all, ADC conversion on this device may take up to 10 mS, so faster protocol will not yield faster reading.

How to connect MS5611 to STM32

First we need to look at schematic diagram to know how to connect MS5611 to STM32 board(s). In our case of I2C interfacing, we should look at second part of the picture below. (I included whole datasheet even more below.  Note that in the case of I2C, pin CSB play different role than in ISP mode. Leave it unconnected for address 0x77, or connect to Vdd in the case you already have the same device, this time address will be 0x76. For STM32f10x family, SDA pin is connected to GPIO B7 and SCL to GPIO B6. As this page is intended for learning I2C protocol on STM32 micro-controllers, I will talk here only about this protocol. SPI will come later, and if you are subscribed to the website, you will get e-mail notification about updates. Back to connections – pin PS on MS5611 must be on Vdd, since it is Protocol Select. In the document it says that it is low voltage device, and 3V is mentioned, but absolute maximum rating is 4V, so if STM32 works on 3.3V, that is exactly what we want.


On the board GY-63, it is confusing where is SDI for SPI protocol. It is the same pin as SDA, but someone forget to add that pin name “SDA/SDI”. In both cases SDI/SDA gives us data, while SCL or SCLK as is on datasheet has clock. We here need for I2C  SDA and SCL only for communication. Vcc (or Vdd in the document) goes to +3.3V, GND to GND of STM32, and PS to Vdd bypass or separate wire to available +3.3V on the STM32 board.


Here is documentation abut MS5611 precision barometer:

Download (PDF, 579KB)

For complete work in Keil, we need 7 files, all seven should be in the same directory of the project with name, for example MS5611 barometer. It has thermometer too with two digits decimal precision. Your choice of project name, but name of individual component must be as is the name of .c and .h files, since it depends of ‘#include’ statements.  Here I will give you all 7 files, of which first is barometer.c (containing main() function), wire.c, wire.h, delayUs.c, delayUs.h, printMsg.c, printMsg.h . All MCU programming is done using ST-link dongle. For data transfer to the computer, you need FTDI usb dongle.

The codes:

Here is the video:

Some related documents

Download (PDF, 125KB)

External link for STM32f10x series.

STM32 USART sending and receiving data

Using USART for sending and receiving data

USART is the same in ‘Arduino world’ and Keil programming, but getting message out is bit different – instead using “Serial.print” we are using here custom made function “printMsg” which uses ‘vsprintf’ function for formatting whole message which is then transferred to the data register and shifted out by shift register.
For formatted print, there is cplusplus reference fro programmers.

Diagram from Reference manual RM0008:


No DMA yet, just manual TX/RX-ing

DMA on USART can help a lot, but for now I did not learn enough to give you an example how to use it. As I cover part by part of STM32 programming in Keil, I am trying to make it simple so that everyone can understand. DMA (Direct Memory Access) is one way to move data from one part of the MCU to another. But also, there is old ‘manual’ ways.

Using HTerm console


Instead Putty or Serial monitor from Arduino, I like rather to use HTerm, it is free and has everything one programmer need. You can debug your program and see output data in various formats: ASCII, decimal, hexadecimal and binary form. There are other things as is flow control, saving received data, sending saved or generated file out over the USART and many other nice things.

Here are example codes, you should to include all three files into your Keil project: main.c, pringMsg.c and printMsg.h – make it so that all three files are in the same folder. Don’t forget that we need FTDI adapter.

Example codes

main.c file:

printMsg.c file:

printMsg.h file:

In printMsg.c file is RCC->APB2ENR register with everything we need to provide clock to the USART and GPIO pins (A9 is TX, A10 is RX):

Note that this time GPIO port A9 uses ‘alternate’ function instead ‘general purpose’. If you set it incorrectly, it will not send data.

Next thing is setting USART speed in Bauds.  Here is example for 9600 Baud:

To get this number needed for Bit Rate Register BRR, You need to divide your clock with 9600, 72000000/9600=7500, but it is less confusing to use hexadecimal value at this place, so use your programmers calculator and convert 7500 into 0x1D4C. In printMsg.c file I calculated all mostly common using USART speeds, plus few not so common. The maximum speed HTerm can transmit and receive is 3000000 Bauds (~ 3 megabauds). Putty can’t cope with that, and did not tried Arduino serial monitor.

Inside printMsg() function, there is final sending part:

What id does, it send first byte from our array buff[] into register USART1->DR, then we should wait until it is transferred into shift register and send out. This means that we should make waiting while loop and ‘watch’ TXE flag to appear – sending of one byte is done, now we can continue loading next byte into USART1-DR data register.

Receiving part is little bit different. We first wait flag RXNE that told us that data register is filled with one byte and ready for read.

To recap: for sending byte out, we first send one byte, then wait flag XE, for receiving byte in, we first wait flag RXNE, then we can read.

On the console, there should be enabled one of three options – after typing message, when we press enter, all data are send, but we need extra byte or two to tell MCU that there is end of the message. Else, our loop may wait until whole buffer is full. So, enabling CR and/or LF (Carriage Return / Line Feed), with decimal values of 13 and 10 respectively. Inside for loop, there is:

Which checking whether received byte is either of those two options, CR and/or LF, then it exit or break loop. After that it just returns length of the message “return len;”. Since ‘buff[256]’ is global array, after returning back from readMsg() function, this buffer is filled with our data, and we need to know how much. Variable ‘len’ gives us exactly that number.

I made simple test ‘loopback’ code that sends everything back to the console:

Note that inside for() loop, there is ‘len+1’, that is because length of array is certain number, then we ad our CR and/or LF character that tells HTerm to go in new line.

Custom USART function

Sometimes we need just send data from our MCU inputs. For example potentiometer data. Then we have no need for formatted print or anything, just making some loop that read ADC for example, and send byte by byte out (and waiting TXE flag):

Where ‘pot_value’ is some data from ADC which measure voltage on your potentiometer.

If you want to externally change something by typing, then use this:


STM32 blink LED – first programming steps in Keil

STM32 first steps – blink LED

On board of STM32 (some people call it “blue pill”) there is green LED, or at other boards there is blue LED. First step is to get familiar with Keil environment, set everything properly and start programming. It is not difficult, but require some time to get used to this ‘new way’ aside ‘Arduino way’ or making ‘sketch’-es. This is true C programming, which is maybe less popular than Arduino, but Keil has some import functions so that you can import .ino file and convert it to new way. I found it works faster and has many cool functions. The problem is that there is almost no ‘helper’ libraries, or those are hidden or not available in free version of the Keil IDE.

Use ST-Link V2 programmer, support debug and goes up to 4 MHz uploat to the board with MCU. Do not forget ST-Link driver.

Before everything, here are links to reference manual and two MCUs (both STM32, different model) showed on the video below.

STM32F103C8  and


Main reference manual for STM32F101 to STM32f107.

First blink program:

Thee thing with enabling port, if you remember Arduino way it is ‘PinMode(13, OUTPUT);’, here is not the case, we can write in few ways, for example long one:


Which will ‘yield’ the same effect as simple expression:

GPIOC->CRH = 0x44344444;

Where numbers 4 are default or reset value which make pins input, floating – or least amount of current consumption. To make your task easier, use calculator in “Programmers” mode (at leas Windows has it). First type in the calculator HEX value you found in the datasheet for the register of interest, then click on icon next to DWORD (initially there is QWORD – click until DWORD appears), and it will show you map with groups of four bits – ‘nibbles’. One byte contains two nibbles. Click on that table to change values and compare with values that is needed for your application and compare it with the datasheet.  Here is how it looks after setting pin PC13 (or just C13) in the calculator:


To get this calculator in Windows, pres Windows key and type ‘calc’, or if it does not works, press and hold windows key and key ‘R’ to get command prompt, then type ‘calc’. On calculator, there is option ‘standard’, ‘scientific’, but we need ‘programmers’.

Another PWM blink program:

This time the same LED on board slowly going bright, then dim at the same rate on STM32 boards. So far, I have only two versions: STM32F103C8 and STM32F103VET6. Firs one is cheapo popular “Blue Pill”, while second one is some advanced version with more pins, more memory and what not. Also more expensive. And I did not found pinout of this board. For this purpose, you may wish to install CubeMX program. This program generates file for starting, but that is some weird “HAL” structure, which I am not familiar, nor want to mess with that, since it is so confusing. But, at least it has MCU with designations on each pin after you click on it. Example:

 STM32Note that this is not programming environment, just “initialization code generator” for STM32.

Be sure to use Notepad++ for saving copy of the codes. In this type of Notepad, if you save program as for example ‘.c’ extension, it will gives you ‘colored’ nice looking text. I usually print from this thing and also saving this code to another place on the disk in the case that I lost trace of the original program which is somewhere in Keil directory.

Continue reading STM32 blink LED – first programming steps in Keil

STM32 programming in Keil

STM32 MCUs programming in Keil

Not so long time ago, I decided to play with micro controllers. My first MCU was PIC and my first programs were in assembler code. That is because low memory space and need for fast execution. Later someone said that I should try to program it in C language. And that solved many problems, and things going faster. Then ‘hit the wall’ because of lack of information and examples how to do something. After that, some time spent in Arduino environment, which is fine for beginners and for really fast results. Just… after a while, there arrive need for something faster, and instead Atmel chips, I decided to use STM32 series. Luckily there are libraries and everything in Arduino IDE thing. But, some of the libraries does not behave as I wish. So, next logical choice is to use something that resembles ‘true C’ rather than ‘sketch’ things. Start is really difficult. For that reason, I want to share with you some experience in programming STM32 MCU family and Keil environment. Keil is free for use, but with limited options and with limited code use – maximum 32 kByte. For beginner like me, that is more than enough. Later will decide what will do – or buy (well, it is expensive), or switch to something else if exist at all.

Later will include some YouTube videos.


This page is still under construction…