[STM32F103][STM32F401]Pierwsze kroki.

Tu możesz pisać o swoich problemach z pisaniem programów w języku C/C++ dla STM.
Awatar użytkownika
Zegar
User
User
Posty: 316
Rejestracja: wtorek 02 lip 2019, 14:42

[STM32F103][STM32F401]Pierwsze kroki.

Postautor: Zegar » wtorek 21 kwie 2020, 01:47

Dobry wieczór!

Postanowiłem oderwać się od moich zabawek, bo już śniły mi się po nocach. Jednak nie lubię bezczynności, więc wyciągnąłem z szuflady Blue Pill. Trochę już tam poleżał, bo wpadł mi w ręce MBC2. Żeby nie było zbyt dużo nowych rzeczy na raz, podłączyłem STM-a do IDE Arduino. Nie było łatwo. Przeczytałem kilka poradników, w każdym znajdowałem coś innego, ale ciągle bez rezultatu. Wgrałem bootloader, ale i tak USB nie było widoczne...
Niektóre fragmenty nie brzmiały zachęcająco. Np. "Programming AVRs was a walk in the park... Compared to that, developing for ARM is like trying to stroll in the middle of a raging battlefield." - Mahesh Venkitachalam, albo - "Jeśli po wgraniu bootloadera oraz zainstalowaniu sterowników Arduino IDE widzi w Portach twoją płytkę, ale nie może na nią wgrać programu, najwyraźniej miałeś pecha." (to z Elektrody). Poddałem się.

Wyciągnąłem Black Pill. Teraz było błyskawicznie. Wgrałem bootloader, od razu płytka się odezwała. Prosty "skecz" też działał, jednak okazało się, że to co chciałem zrobić, nie da się skompilować... Znowu porażka. Nigdzie nie znalazłem opisu, jak dostać się do rejestrów GPIO. Na pewno inaczej niż w F103. Ale kiedy przestawiłem z powrotem na GenericSTM32F103... kompilacja się udała. Wgrywanie też w końcu opanowałem - ST-Link sobie poradził, mimo że USB milczał. Po wgraniu programu na USB pojawił się Mapple Mini... Nic z tego nie rozumiem. W końcu podłączyłem konwerter TTL-USB i jakoś wszystko ruszyło. Jednak to, co na AVR działa bez zarzutu na "pierwsze kopnięcie", wymagało wiele zachodu. Kombinowałem na różne sposoby. Pomogło dopiero sprawdzanie, czy na pinach nadal jest to samo po upływie 1 milisekundy. Bez tego wyświetlacz pomigał i gasł zupełnie. Teraz też trochę miga, ale coś widać. Oczywiście wykorzystałem mój sprawdzony kod, który wysyła na terminal wyświetlacz CA80.
https://www.youtube.com/watch?v=DEdjRc4j2BU&feature=youtu.be

Tak wygląda schemat połączeń:

Kod: Zaznacz cały

// ------------------------------------------------------------------------------
//  Wyswietlacz CA80 na terminalu via BluePill
// ------------------------------------------------------------------------------
// CA80 ZW: 1 (+5V)     NC  BluePill
//          2 (c)   --> PB10   //Żeby nie machać bitami
//          3 (d)   --> PB11   //na prawo i lewo
//          4 (b)   --> PB9   //wolę pobawić się kabelkami
//          5 (e)   --> PB12   // ;-)
//          6 (a)   --> PB8
//          7 (f)   --> PB13
//          8 (g)   --> PB14
//          9 (k)   --> PB15
//          10 (PC5)--> PB3
//          11 (PC6)--> PB4
//          12 (PC7)--> PB6
//          13 (GND)--> GND
// ------------------------------------------------------------------------------


A tak "battlefield":
IMG_20200421_004536.jpg


Najważniejsza część kodu wygląda tak:

Kod: Zaznacz cały

void readCA80disp()
{
  word CA80_display = (GPIOB->regs->IDR) & 0xFF58;   //PB 15-8,6,4,3
   delay(1);                  //Tu jest zmiana w stosunku do ATmegi
  if (CA80_display == (GPIOB->regs->IDR) & 0xFF58);
  {
    byte d = 0 | (((CA80_display & 0x40) >> 4 ) | ((CA80_display & 0x10) >> 3 ) | ((CA80_display & 0x8) >> 3));
    if (d != lastDispNum)               //czy inna cyfra niz poprzednio (zmiana co 2 ms)
    {     
      byte k = ((CA80_display & 0xFF00) >> 8);             //Biorę starszy bajt
      k = k ^ 0xFF;                   //(negacja bo zapalony segment = 0)
      lastDispNum = d;                //numeracja od lewej (w CA80 odwrotnie)
      if (bufDisp[7 - d] != k)        //czy zawartosc sie zmienila
      {
        bufDisp[7 - d] = k;
        change = true;
      }
    }
  }
}

Czy ktoś może coś doradzi? Może nie powinienem używać niektórych pinów? Wybrałem te, które mają FT w opisie. W F401 wszystkie w PB tolerują 5 V, ale w F103 musiałem ominąć najmłodsze. Siedzę już trzeci dzień od świtu do zmierzchu... albo odwrotnie ;-)
CA80_BluePill_Terminal.zip
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
"If A = success, then the formula is A = X + Y + Z.
X is work. Y is play. Z is keep your mouth shut."
A. Einstein

Awatar użytkownika
Zegar
User
User
Posty: 316
Rejestracja: wtorek 02 lip 2019, 14:42

Re: [STM32F103][STM32F401]Pierwsze kroki.

Postautor: Zegar » wtorek 21 kwie 2020, 12:34

Wygląda na to, że kompilator oszukuje... W CA80 co 2 milisekundy zmienia się stan na złączu wyświetlacza. Jestem tego pewien. Zmieniłem wartość opóźnienia na 3 ms, więc warunek po tym czasie nigdy nie powinien być spełniony. Jednak nadal cyfry migają i wyświetla się aktualny czas...
Czy jest na to jakaś rada?
"If A = success, then the formula is A = X + Y + Z.
X is work. Y is play. Z is keep your mouth shut."
A. Einstein

Awatar użytkownika
Zegar
User
User
Posty: 316
Rejestracja: wtorek 02 lip 2019, 14:42

Re: [STM32F103][STM32F401]Pierwsze kroki.

Postautor: Zegar » wtorek 21 kwie 2020, 14:36

Poradziłem sobie...

Kod: Zaznacz cały

void readCA80disp()
{
  volatile word CA80_display = (GPIOB->regs->IDR) & 0x7FD8;
  byte d = 0 | (((CA80_display & 0x40) >> 4 ) | ((CA80_display & 0x10) >> 3 ) | ((CA80_display & 0x8) >> 3));
  delayMicroseconds(50);  //delay(1);    //
  volatile word CA80_display_R = (GPIOB->regs->IDR) & 0x7FD8;
  if (CA80_display == CA80_display_R)
  {
    if (d != lastDispNum)               //czy inna cyfra niz poprzednio (zmiana co 2 ms)
    {
      byte k = ((CA80_display & 0x7F80) >> 7);             //readCA80dispDigit();
      k = k ^ 0xFF;                   //(negacja bo zapalony segment = 0)
      lastDispNum = d;                //numeracja od lewej (w CA80 odwrotnie)
      if (bufDisp[7 - d] != k)        //czy zawartosc sie zmienila
      {
        bufDisp[7 - d] = k;
        change = true;
      }
    }
  }
}

Zacząłem od przesunięcia się na inne wejścia, ale nic to nie dało. Zmiana deklaracji zmiennej na volatile jeszcze nie pomogła. Dodałem zmienną pomocniczą i dopiero wtedy był efekt. Bez opóźnienia nie działa prawidłowo, ale zmniejszałem aż do 50 us i nadal jest OK. Z ATmegą nie było problemu, bo z powodu braku wolnych pinów użyłem ekspander i inaczej sprawdzałem, czy dane są godne zaufania. :-)
"If A = success, then the formula is A = X + Y + Z.
X is work. Y is play. Z is keep your mouth shut."
A. Einstein

Awatar użytkownika
Zegar
User
User
Posty: 316
Rejestracja: wtorek 02 lip 2019, 14:42

Re: [STM32F103][STM32F401]Pierwsze kroki.

Postautor: Zegar » środa 22 kwie 2020, 10:59

Dlaczego "wyświetlacz" gasł w czasie pracy pierwszej wersji programu?
Żeby to wyjaśnić, trzeba przemyśleć kilka spraw:

1. Jak działa wyświetlacz CA80.
2. Jak długo trwają poszczególne fazy operacji.
3. Jak szybki jest STM.

Znowu odpowiedź przyszła w nocy - wniosek: jestem maniakiem...

1. Display CA80 działa multipleksowo. Co dwie milisekundy na złączu ZW pojawia się kolejna cyfra. Nie jest to proces atomowy, bo Z80 jest ośmiobitowy. Najpierw gaszone są segmenty, potem zmieniany numer cyfry i na koniec zapalane segmenty nowej cyfry.

2. Z80 jest taktowany CLK = 4 MHz. Rozkazy trwają kilka cykli maszynowych, każdy po 3 lub 4 takty zegara. Można przyjąć, że średnio 10 taktów na rozkaz, czyli 10 rozkazów (bez analizy szczegółowej) zajmie około 25 mikrosekund. Można przyjąć, że tak długo wyświetlacz jest wygaszony. STM jest taktowany CLK = 72 MHZ. Do tego jest 32 bitowy. Czas wykonania rozkazu jest nieporównywalnie krótszy. Trochę czasu zajmuje tylko wysłanie danych do terminala. Program cyklicznie odczytuje PB dopiero gdy trafi na zmianę, sprawdza czy dotyczy ona numeru wyświetlacza. Jeżeli nie, czeka nadal. Zawsze, gdy zmieni się numer cyfry, segmenty są wygaszone, więc nowa wartość będzie zerowa. Ponieważ coś się zmieniło, nastąpi odświeżenie obrazu na terminalu. Po tej operacji numer wyświetlacza na ZW będzie prawdopodobnie inny, więc jest szansa, że od razu trafimy na "coś do wyświetlenia". Jednak kolejne cyfry będą wygaszane i w końcu program będzie ciągle w fazie czekania na zmianę. Jedyne co mu się uda wykryć, to zmiana numeru cyfry, bo zawsze wtedy segmenty są wyzerowane... Kiedy wstawimy opóźnienie między odczytami, ominiemy ten "ślepy zaułek".

3. STM jest za szybki... zastosowałem go, bo chciałem wyeliminować ekspander, a czas odczytu po I2C był potrzebny do poprawnej pracy programu.

Przygodę z STM odkładam na później. Za mało wiem, nie mam narzędzi, a IDE Arduino działa coraz wolniej - kompilacja krótkiego programu to dwie minuty. Dopiero po tym czasie okazuje się, że brakuje przecinka czy innego znaku. W efekcie tracę czas... Idę robić coś innego.
"If A = success, then the formula is A = X + Y + Z.
X is work. Y is play. Z is keep your mouth shut."
A. Einstein


Wróć do „Programowanie STM w C/C++”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 2 gości