STM32 "for the rest of us"

bigplik: any chance you would make some code for I2C for OLED displays? I'll tried your SPI example and it is working very well ;), error was because of linux, would like to use bigger display like 1.3" or 2"+ OLED for my maple mini all of the I have are I2C unfortunately

To some degree, we have: I2C example

I have also used I2C with the BMP180 and that works well. So, it boils down to the display and library you intend on using.

If an Adafruit library, much of the work is already done since Adafruit uses a common GFX interface and only the display driver has to be updated. If you are proficient, you can use the existing OLED code as a template.

If another author, it is a new effort, but should not be impossible- just a bit more difficult unless one has the exact display for testing.



In general, here is how it all fits together using the SSD1306 as an example. In Adafruit_SSD1306.h you will see the prototypes for the class member functions:

class Adafruit_SSD1306 : public Adafruit_GFX {
  Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);     // Software SPI
  Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS);                              // Hardware SPI
  Adafruit_SSD1306(int8_t RST);                                                    // I2C

In Adafruit_SSD1306.cpp, you will see:

Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
  cs = CS;
  rst = RST;
  dc = DC;
  sclk = SCLK;
  sid = SID;
  hwSPI = false;

// constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset 
Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
  dc = DC;
  rst = RST;
  cs = CS;
  hwSPI = true;

Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) {
  cs = CS;
  rst = RST;
  dc = DC;
  sclk = SCLK;
  sid = SID;
  hwSPI = false;

You will notice, that the Adafruit_SSD1306::Adafruit_SSD1306 is common 3 times, but only one can be used: h/w SPI, s/w SPI, or I2C. This methodology is called "overloading":

An overloaded declaration is a declaration that had been declared with the same name as a previously declared declaration in the same scope, except that both declarations have different arguments and obviously different definition (implementation).

When you call an overloaded function or operator, the compiler determines the most appropriate definition to use by comparing the argument types you used to call the function or operator with the parameter types specified in the definitions. The process of selecting the most appropriate overloaded function or operator is called overload resolution.

Study both my SPI and madias's I2C examples. That should get you a head-start on making necessary changes to existing libraries.

Good luck,


I have tested another generic board, this time from Shenzhen Technologies Please see here

It seems to do all that my first one did and seems to be well made - just a bit bigger but all pins well labeled.

There is a schematic on my notes page.

If any developers with spare time drop in here please help with PWM.

I have an Arduino speaking wav speech files from a SD card and using PWM to create audio.

Now trying to do the same on STM32.

SD reading seems OK but any Arduino PWM code fails. I do see a built in Maple PWM option

I have yet to fully understand it.

Pulse Width Modulation - next for the user community??? :confused:

What Pwm support do you use on avrs? I would not have thought that the default pwm would be high enough in frequency for speech.


This is not going to work for you.

Use PWMWrite

To make AnalogWrite compatible with the AVR, the pin mode is set to PWM inside AnalogWrite, so its not going to be fast enough for speech

Set the pin mode as in the leaflabs docs and then call pwmwrite

I'm pretty sure its working, as I thought the servo library uses it

However, I'm not sure how you are going to output speech on 400Hz PWM

Your code must be doing something AVR specific to change the pwm rate, and you'll need to do something different to the AVR code to change the PWM rate on the STM

The chips are just too different for the code to just work.

Some of the wav playing Arduino files do use PWM but (I was wrong) the one I pasted in for my system seems to just drive output pins in a "home build" PWM. I will do some work and try to ask a better informed question.

.....or just hope for ready made STM32 wav player code to appear spontaneously ........ :smiling_imp:

(I once wrote some real C code to make my router talk - :astonished: - but I think I may have lost too many brain cells since then) Bottom of page

Hi Sunspot,

I just wrote a nice long technical repsonse but I hit a wrong keystroke and it was all gone in a flash :-(

Anyway, here goes again, but expurgated.

Here is some code I use to generate a high frequency square wave

void setup() {
  // put your setup code here, to run once:

void loop() {
  // put your main code here, to run repeatedly:


void setupCameraClock(int pin)
  #define CLOCK_COUNT 3
  timer_dev *timerDevice  = PIN_MAP[pin].timer_device;
  uint8 timerChannel         = PIN_MAP[pin].timer_channel;
  timer_set_compare(timerDevice, timerChannel, CLOCK_COUNT);

I forget the precise frequiency, but its at least 8Mhz

So if you adapt that code, you can get the PWM on your audio output in running at a nice value e.g. 100Khz

Then if you look at PWM write it does this

void pwmWrite(uint8 pin, uint16 duty_cycle) {
    if (pin >= BOARD_NR_GPIO_PINS) {
    timer_dev *dev = PIN_MAP[pin].timer_device;
    uint8 cc_channel = PIN_MAP[pin].timer_channel;
    ASSERT(dev && cc_channel);
    timer_set_compare(dev, cc_channel, duty_cycle);

And looking at what set_timer_compare does

static inline void timer_set_compare(timer_dev *dev,
                                     uint8 channel,
                                     uint16 value) {
    __io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1);
    *ccr = value;

So if you cache *ccr in to a global variable in setup, and just write new values you can adjust the PWM very quickly

So to play from SD, once Victor gets the SD DMA working, you should be able to double buffer DMA into ram, then use another timer interrupt to take the data from the double buffer and play it.

You also need a low pass audio filter, perhaps with the 3dB point at around 5kHz would probably do

However, this isn't the simplest of projects.

Roger Thanks for the response. Low pass with solder!

STM32 .WAV playing.

This is the AVR code that I was trying to convert

PWM but perhaps "not as we know it"

Good luck with porting that code.

Unfortunately its full of direct register access stuff to AVR which isn't going to be the same on STM32 or any other hardware.

I hope it has enough comments, as you are going to need to go back to first principals to work out what the AVR code actually does, and then recode again in STM specific code.

It's probably doing some soft of adaptive pulse with modulation, either on a fixed or dynamic timer interrupt.

Personally, I'd just write a basic test program first using a sine wave table eg. 1k of ints. And try to get that to work, before I'd attempt all the complexity of SD card reading at the same time

Problems w/ OneWire and DS18B20

UPDATE: independently confirm to be an issue with Maple & Maple Mini clones - but not an issue on generic boards. This has been placed on the issues list and will be prioritized for research and correction. I'll report here when corrected.

Response to @turkogluky: link

Summary: the current version of OneWire appears to freeze the Maple uC.

Test procedure: I used a Nano to prove the DS18B20 was working; the 4.7K pull-up was required at 5V.

I used a new STM32 Maple Mini clone tested with my blink-count script to confirm the Maple Mini was fully functional.

When I went to the \Documents\Arduino\hardware\STM32\STM32F1\libraries\OneWire\examples\DS18x20_Temperature script, it would not compile on my Windows 8.1 box.

The error was traced to the fact that for some crazy reason, the OneWire lib was being pulled from: \Documents\Arduino\libraries\OneWire\ and not from \Documents\Arduino\hardware\STM32\STM32F1\libraries\OneWire\

I fixed that by including the entire path:

include "\Documents\Arduino\hardware\STM32\STM32F1\libraries\OneWire\OneWire.h"

The program compiled: (1.6.1 shipping)

Sketch uses 15,388 bytes (14%) of program storage space. Maximum is 108,000 bytes.
Global variables use 4,528 bytes of dynamic memory.

HOWEVER: The instantiation of OneWire causes the uC to either freeze or appear to freeze. Pressing RESET goes into DFU but when the user program starts, nothing. Worst, the COMn port does not enumerate on Windows, so no debug output.

I changed Serial. to Serial1. and got a clean compile, but again, OneWire freezes the uC.


Just a note that the Beestore Maple Mini clone (whose PCB is a different layout than the original or Baite version) also works fine with the STM32 repo. Have had a couple for a while but never got around to trying them until this week, when I made a big push to get a fresh 1.6.1 install running all of the STM32/core13/TinyCore1/esp8266 cores.

Just a quick update

OneWire only seems to work on generic STM32 boards

I have posted a fix to the main thread, but it involves a slight difference in the way the OneWire class is initialised - I won't bore you with the technical details

There were various issues with OneWire, so it has now been renamed to OneWireSTM

See the other thread for the technical details, or just download the relevant files and enjoy :wink:

hi, is there any tutorial how to use ST-Link with arduinoIDE to program STM32? i can do it by usb, but if want to program single STM32 chip on custom board don't know how to set it

Stm32 to flash. Board type had STLink option on windows

There are no tutorials for this on the arduino but there may be general tutorials for stm32 in general e.g. On YouTube

I've checked YT, still didn't manage, there were some programming stuff about discovery boards and different than arduinoIDE program uploaders, some ST-Link tools, I have an option on my IDE for upload method as ST-Link, but it shown me a message that it can't connect into st-link device - however windows seen st-link in device manager

bigplik: I've checked YT, still didn't manage, there were some programming stuff about discovery boards and different than arduinoIDE program uploaders, some ST-Link tools, I have an option on my IDE for upload method as ST-Link, but it shown me a message that it can't connect into st-link device - however windows seen st-link in device manager

The original implementation of the STM32 core project was directed toward the Maple and the Maple Mini clones. The project grew to address a larger population of STM32 boards based on the STM32F103.

The project was never intended to be a "newbie" project as a replacement for the Arduino 8-bit UNO, Mini, Nano, etc. It was intended for more experienced experimenters who for some reason had outgrown the 8-bit capacity but did not want to rush to the Due; that is, an inexpensive alternative based on easy to obtain Chinese clones of the Maple and Maple Mini.

Some of the boards (Maple Mini) support USB programming and connectivity much the same way that the ProMicro (32U4) does - it enumerates itself as a COMx port under the OS. With Windows, this requires drivers to be installed; instructions are in the Github wiki.

Other development boards or boards that do not enumerate to a COMx port are usually programmed using ST-Link which requires that you purchase a programming device that goes into the PC USB port and connects to the ST-Link header on the board. You can read through the long thread on the devices ordered and that worked (or did not work well.) I use Windows can cannot recommend one.

This is very important and I am going to repeat this again: The STM32 core is not a beginner's project and while the core is working there are some serious issues documented on the github wiki. Just as the issue with OneWire did not appear until a few days ago, I am sure there are other issues which will need work-arounds and fixes. BUT, this is a hobby project and there is no guarantee that compatibility will occur - if you order an STM32 board and utilize the core, you need to know that you are on your own and the core is always in flux - as of this week, a few commands from LeafLabs were removed to align more toward the Arduino commands.

Many AVR 3rd party libraries will not work unchanged - consider this a warning. If you do not understand how to hack a library or are not competent to look into a Due or Teensy3.1 library and ferret the logic - avoid the library. You can check here on github to see if the core team has provided a replacement: Ported-Working libraries for the STM32 (all functions may not work.)

When things are found that do not work (not libraries, basic Arduino commands) someone will hopefully have the hardware to validate the issue and the issue will be placed on the github wiki. Roger will address the priority and determine if a workaround or fix will be appropriate - OR, the issue may simply be documented and left the way it is... depending on the impact. There are no guarantees.

Ray My Projects

Just to clarify

The STM32F1/libraries folder now contains a new folder called OneWireSTM

I have removed the old OneWire folder, as it was not getting found by the IDE (and I don't have time to debug the IDE)

Examples for OneWireSTM are in the examples folder



The updated examples reference the new folder name and new header name OneWireSTM.h

I have compiled and tested the DS18B20 example using pin 10 on my Maple board and it worked fine. I also tested on pin 15 and it was also OK.


I try to make a "Hello World" with STM32 and I2C_LCD, but it dont work.


// Set the LCD address to 0x20 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x20, 16, 2);

void setup()
    // initialize the LCD
    // Turn on the blacklight and print a message.

void loop()
  lcd.print("Hello, world!");


The address is confirmed with BusPirate and I can se the signal with my oscilloscope.

The display works with Arduino board.

It looks like the init is going wrong, as I can see flicker every time I send the string.

STM32F103RC and IDE ver. 1.6.3