Serwisy partnerskie:
Close icon
Serwisy partnerskie

Piszemy prosty program dla ARM Cortex M4, czyli jak skomplikować prostą rzecz w przykładach

Article Image
Każdy programista mikrokontrolerów zaczynał swoją przygodę od prostych programów, na przykład błyskających diodą LED. Nieważne, czy ktoś zaczynał od PIC16F628 i Assemblera, czy od ATMegi i Bascoma, czy w końcu od Arduino (jak większość ludzi w ostatniej dekadzie), pierwszym programem jest prosta pętla zapalająca i gasząca diodę LED. Takie „Hello world!” świata mikrokontrolerów. Sam zaczynałem od programowania PIC16F628A i PIC18F45K50 za pomocą XC8, mikroPascala czy PICBasica, i zawsze pierwszym programem było proste „machanie nóżką” w nieskończonej pętli.

Ostatnio postanowiłem wyjść poza swoją strefę komfortu i spróbować swych sił w programowaniu dużo potężniejszych układów – padło na płytkę WeAct Studio BlackPill z układem STM32F401CCU6. Jest to przedstawiciel rodziny ARM Cortex M4, oferujący duży przyrost wydajności względem ośmiobitowych braci mniejszych, funkcje DSP znane z szesnastobitowych braci mniejszych i moduł FPU do obliczeń zmiennoprzecinkowych. Wszystko to na płytce za około 30 złotych. Ba, domyślnie jest wgrany program przyciemniający i rozjaśniający diodę LED, który robi to prawie płynnie. Zróbmy to jednak po swojemu.

Witaj, okrutny świecie!

Na początek przydałoby się jakieś IDE. Trzy główne opcje to STM32Cube IDE, Arduino IDE oraz PlatformIO. Arduino IDE nie znoszę – przez lata cierpiało na chroniczne braki użytecznych funkcji, a i wygląd też mi się nie widzi. STM32Cube IDE wydaje się dobrą opcją, ale taka „kobyła” do jednego układu mi nie jest potrzebna. Padło więc na PlatformIO, które to środowisko jest rozszerzeniem do Microsoft VisualStudio Code. Nie będę przedstawiał procesu instalacji, ani konfiguracji pierwszego projektu z BlackPill. Jako framework wybrałem Arduino, bo jestem leniwy, jak każdy programista. Jedna uwaga, do pliku PlatformIO.ini trzeba dopisać jedną linijkę zmieniającą tryb programowania na DFU. Listing 1 pokazuje, jak to powinno wyglądać.

Dzięki temu wystarczy mieć kabel USB typu C by zaprogramować układ. Domyślnie potrzebny byłby programator ST-LINK V2, który przy okazji udostępnia nam opcje debugowania, ale moim zdaniem nie są one nam potrzebne. Ale w praktyce nie jest jednak tak łatwo. Z jakiegoś powodu tryb DFU nie zawsze startuje poprawnie, system widzi wtedy urządzenie USB bez deskryptorów opisujących, czym ono jest. Nawet jak połączenie zostanie nawiązane poprawnie, to urządzenie jest widziane jako STM32_BOOTLOADER, ale VisualStudio Code nie rozpoznaje go. Potrzebny jest program instalujący sterowniki urządzeń USB, np. Zadig, by nasza „czarna pigułka” dawała się zaprogramować. No, ale tak działa USB, zwłaszcza pod Windowsem – miało być „od ręki” i bez instalowania sterowników, ale to działa tylko dla urządzeń z prostymi deskryptorami. Wszystko, czego nie objęła standardowa specyfikacja USB wymaga sterowników, i nie każde sterowniki system może automatycznie pobrać.

Listing 2. „Hello World!” w wersji podstawowej

#include <Arduino.h>

void setup() {
  // put your setup code here, to run once:
  pinMode(PC13, OUTPUT);
}

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

  digitalWrite(PC13, HIGH);
  delay(500);
  digitalWrite(PC13, LOW);
  delay(500);
}

Podstawowy program „Hello, World!” przedstawia listing 2. Kod ten sprawia, że dioda LED podłączona do pinu oznaczonego jako PC13 zacznie migać z częstotliwością 1 Hz. No ale przedtem dioda prawie płynnie zmieniała jasność. A tu tylko sobie mruga. Czy da się lepiej? Tak! Na początek umieścimy ten kod w pętli, by nie działał w kółko. Potem dopiszemy programowe PWM. Przy okazji dodamy jeszcze jeden kawałek kodu na początek, by sprawdzić, jak szybko STM32F401CC6U pod kontrolą Arduino „macha nóżką”. Kompletny kod po kilku iteracjach (dawno nie pisałem w C(++) i trochę pozapominałem) przedstawia listing 3. Warto wspomnieć, iż cały ten kod zabiera 1152 bajty pamięci RAM i 11508 bajtów pamięci Flash. Stanowi to odpowiednio 1,8% dostępnego RAMu i 4,4% dostępnej pamięci programu. Większość tego „zjada” sam framework potrzebny do wykonania aplikacji użytkownika. Dla STM32 jest trochę większy od wersji dla ośmiobitowców, bo bardziej złożony układ wymaga więcej do uruchomienia.

Listing 3. „Hello World!” po kilku iteracjach

#include <Arduino.h>

void setup() {
  // put your setup code here, to run once:
  pinMode(PC13, OUTPUT);
}

void loop() {
  unsigned char k = 0;
  // put your main code here, to run repeatedly:
  for(unsigned int a = 0; a <1000; a++){
    digitalWrite(PC13, HIGH);
    digitalWrite(PC13, LOW);
  }
  delay(1000);
  for(unsigned char i = 0; i < 10; i++){
    digitalWrite(PC13, HIGH);
    delay(500);
    digitalWrite(PC13, LOW);
    delay(500);
  }
  unsigned char l = 0;
  for(unsigned int j = 0; j <= 1000; j++){
    for(unsigned char k = 0; k < 100; k++){
      if(l <= k) digitalWrite(PC13, HIGH);
      if(l > k) digitalWrite(PC13, LOW);
      delayMicroseconds(250);
    }
    delayMicroseconds(750);
    l++;
    if(l == 101) l = 0;
  }
  delay(1000); 
}
Aby przeczytać ten artykuł kup e-wydanie
Kup teraz
Firma:
Tematyka materiału: Hello world, PIC16F628, Assembler, ATMega, Bascom, STM32Cube IDE, Arduino IDE, PlatformIO, PIC16F628A, PIC18F45K50, XC8, mikroPascal, PICBasic, Arduino, ST-LINK V2, VisualStudio Code, Zadig, STM32F401CC6U, ATMega328, C++, STM32Duino, LED, WS2812B
AUTOR
Źródło
Elektronika dla Wszystkich marzec 2024
Udostępnij
Zobacz wszystkie quizy
Quiz weekendowy
Edukacja
1/10 Jak działa rezystor LDR?
UK Logo
Elektronika dla Wszystkich
Zapisując się na nasz newsletter możesz otrzymać GRATIS
najnowsze e-wydanie magazynu "Elektronika dla Wszystkich"