Adafruit STM32F411 BlackPill and STM32F405 Feather Development Boards

STM32F405 Feather Description

The STM32F405 Feather that Adafruit designed runs at 168MHz. It has a STEMMA QT/Qwiic port on it so you can easily plug and play I2C sensors. It is usable with the Arduino IDE or STM32Cube IDE. This Feather board has lots of features:

  • STM32F405 Cortex M4 with FPU and 1MB Flash, 168MHz speed
  • 192KB RAM total – 128 KB RAM for general usage + 64 KB program-only/cache RAM
  • 3.3V logic, but almost all pins are 5V compliant!
  • USB C power and data – our first USB C Feather!
  • LiPo connector and charger
  • SD socket on the bottom, connected to SDIO port
  • 2 MB SPI Flash chip
  • Built in NeoPixel indicator
  • I2C, UART, GPIO, ADCs, DACs
  • Qwiic/STEMMA-QT connector for fast I2C connectivity
  • Built-in USB DFU bootloader to load firmware.

Arduino is supported through STM32duino.There’s no auto-reset support, so you have to pull the BOOT0 pin high and manually reset before uploading.

One of the shortcomings of the vey small feather packaging is that several of the pins were not brought out to connectors. Specifically, PA0, PA1, PA2, PA3, PA8, PA9, PA10, PA0, PA1 and PC13 have been excluded. Additionally, the SD card and SPI Flash consume a total of 11 other pins. So, pin shortage could be a really issue with this board.

Blackpill Description

This simple development board features an STM32F411CEU6 chip with 512 KB of flash, 128 KB of SRAM, and runs at 100 MHz. The board features a USB C connector, with a 3.3V 100mA LDO regulator. There are both 25mhz and 32.768 KHz crystals. There are a few handy buttons: a BOOT button for entering the ROM DFU bootloader, a reset button, and a generic button on PA0 for users. One power LED and one user-controllable LED on PC13. The STM32F411 chip itself has multiple UART, I2C, SPI, I2S, and timer peripherals (datasheet). The USB is full speed. There’s a single ADC multiplexed to 10 inputs. There is also a spot on the bottom for SOIC flash memory chip, like a GD25Q16 – 2MB SPI Flash.

Again, thanks to the STM bootloader in ROM, you don’t need a programmer to load binary firmware, and you can use STM32duino for Arduino IDE support.

Simple Neopixel Demonstration on the STM32F405 Feather

// Simple neopixel color cycle demo on stm32f405 feather.
#include <Adafruit_NeoPixel.h>

#define PIXEL_PIN    8 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT  1 // Number of NeoPixels

// Declare our NeoPixel strip object.
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  initializeLED();
  strip.begin();           // Initialize NeoPixel strip object 
  strip.show();            // Initialize all pixels to 'off'
  strip.setBrightness(50); // Set BRIGHTNESS (max = 255)
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() { 
  const uint8_t rgb[6] = { B100, B101, B001, B011, B010, B110 };
  
  for (int i=0; i<6; i++) {
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_1);
    for (uint8_t j=0x11; j<0xff; j+=0x11) {
      strip.setPixelColor(0, (rgb[i]&B001 ? j : 0), (rgb[i]&B010 ? j : 0), 
                          (rgb[i]&B100 ? j : 0));
      strip.show();
      delay(50);
    }
  }
}

Simple Neopixel Demonstration on the STM32F405 Feather Using FreeRTOS

#include <STM32FreeRTOS.h>
#include <queue.h>
#include <Adafruit_NeoPixel.h>

#define PIXEL_PIN    8 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT  1 // Number of NeoPixels

// Declare our NeoPixel strip object.
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

struct rgb {
  uint8_t red;
  uint8_t green;
  uint8_t blue;
};

QueueHandle_t q = 0;

void producer(void* p) {
  while (1) {
    const uint8_t rgbMix[6] = { B100, B101, B001, B011, B010, B110 };
    struct rgb color = { 0, 0, 0 };
  
    for (int i=0; i<6; i++)  {
      for (uint8_t j=0x11; j<0xff; j+=0x11)  {
        color.red =   rgbMix[i] & B001 ? j : 0;
        color.green = rgbMix[i] & B010 ? j : 0;
        color.blue =  rgbMix[i] & B100 ? j : 0;
        if (!xQueueSend(q, &color, 100)) 
            while (1);
        vTaskDelay(50);
      }
    }
  }
}

void consumer(void* p) {
  strip.begin();           // Initialize NeoPixel strip object 
  strip.show();            // Initialize all pixels to 'off'
  strip.setBrightness(50); // Set BRIGHTNESS (max = 255)

  while (1) {
    struct rgb led;
    
    if (!xQueueReceive(q, &led, 100)) 
      while (1);
    else {
      strip.setPixelColor(0, led.red, led.green, led.blue);
      strip.show();
    }
  }
}

void setup() {
  portBASE_TYPE s1, s2;

  q = xQueueCreate(1, sizeof(struct rgb));
  s1 = xTaskCreate(producer, "tx", 128, 0, 1, 0);
  s2 = xTaskCreate(consumer, "rx", 128, 0, 1, 0);
  
  if (q == NULL || s1 != pdPASS || s2 != pdPASS) 
    while(1);
  
  vTaskStartScheduler();
  while (1);
}

void loop() { }

About Jim Eli

µC experimenter
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s