wtorek, 25 września 2018

MCCP i SCCP w PIC32MM - kopalnia skarbów

Moduł xCCP (Compare/Capture/PWM) jak określił  Paweł Borkowski w książce "Mikrokontrolery PIC w praktycznych zastosowaniach" to programistyczna kopalnią skarbów. Moduł występuje w dwóch odmianach SCCP(Single) i MCCP(Multi). Różnica sprowadza się do ilości sterowanych pinów i dodatkowych możliwości. W module Single możemy działać tylko na jednym wybranym pinie a w Multi na grupie pinów (maksymalnie do 6) i tutaj mamy dostępne dodatkowo, bardziej rozbudowane możliwości, od których może głowa rozboleć.

xCCP można najprościej opisać jako kombajn do kontroli czasu i zdarzeń. Jest to po CLC jeden z najciekawszych modułów w PIC32MM.
Żeby trochę liznąć ten niezwykle rozbudowany i ciekawy temat przybliżymy pojęcia składowe a więc co się kryje za określeniami   Compare/Capture/PWM :

Capture : jest to tryb pracy , który umożliwa nam  monitorowanie sygnału podanego na wybrane wejście MCU pod względem wystąpienia zdefiniowanych zdarzeń z możliwością pomiaru czasu ich wystąpienia. Zdarzeniem może być m.in zbocze narastające, opadające lub kombinacja tych stanów. Przykład zastosowania to np. pomiar okresu lub długości trwania impulsu :




Z praktycznych zastosowań , które mi na szybko przychodzą do głowy to np pomiar czasu nasłonecznienia za pomocą elementu światłoczułego. Progi reakcji ustawić możemy przez zastosowanie np.komparatorów.

Compare : tryb pracy, który umożliwa dowolne modelowanie przebiegu wyjściowego na wybranym pinie przy pomocy przerwań/eventów zależnych m.in od czasu. W tym trybie rozróżnić można cztery typowe zachowania :

- w reakcji na zdarzenie linia wyjściowa jest ustawiona w stan wysoki,
- w reakcji na zdarzenie linia wyjściowa jest ustawiona w stan niski,
- w reakcji na zdarzenie wywoływane jest przerwanie, stan lini bez zmian
- w reakcji na zdarzenie (Special Trigger Event) wywoływane jest przerwanie, zerowany Timer, stan lini bez zmian. 

Przez zdarzenie w trybie Compare rozumiemy np.wynik porównania zawartości rejestru CCPxTMR (32-Bit Timer/Counter register) z rejestrem CCPxPR (32-Bit Timer Period register)

Jednym z przykładów zastosowań tego trybu jest generowanie "tick rate" dla systemu RTOS i przydzielanie wielokrotności tego czasu dla poszczególnych zadań. Lub na przykład wywoływanie przerwań w zdefiniowanych odstępach czasu co zastępuje nam np.programowe timery używane często przezemnie.


PWM : najbardziej popularny tryb w "przyrodzie" - modulacja szerokości impulsu. W trybie tym modelujemy przebieg wyjściowy pod kątem wypełnienia i okresu :




Efekty działania tego trybu przedstawia symbolicznie rysunek poniżej :



To tyle słowem wstępu. Przybliżamy perspektywę. W PIC32MM0256GPM048 mamy 3 x MCCP i 6 x SCCP .Każdy moduł opisany jest z grubsza ośmioma rejestrami :

Rejestry konfiguracyjne :
CCPxCON1 -  kontroluje wiele funkcji wspólnych dla wszystkich trybów, w tym wybór zegara wejściowego, wstępne skalowanie bazy czasowej (preskaler), synchronizacja timera, operacje na Triggerze , wybór postskalera dla wszystkich trybów.  W tym  rejestrze ustawiamy również tryb pracy.
CCPxCON2  steruje automatycznym wyłączaniem i restartem, głównie dedykowany dla PWM, a także konfiguruje inne funkcje przechwytywania i porównywania wejść i wyjść, konfiguruje pracę wyjścia pomocniczego - AUX.
CCPxCON3  steruje wieloma wyjściami PWM i ustawia dead time, steruje wyjściami trybu Compare, wyjście i tryb PWM oraz konfiguruje tryb PWM Output Mode dla MCCP.

Rejestr statusowy :
CCPxSTAT  rejestr statusowy, odczytujemy statusy dla różnych operacji związanych z pracą modułów.

Każdy moduł zawiera również cztery rejestry typu bufor/licznik, które służą jako rejestry wartości timera lub rejestry bufora danych:

CCPxTMR 32-bitowy CCPx Timer/Licznik
CCPxPR 32-bitowy CCPx Timer Period register
CCPxR (podzielony na  CCPxRA i CCPxRB)32-bitowy CCPx Primary Data Buffer Register dla operacji Output Compare w tym PWM
CCPxBUF 32-bitowy CCPx Buffer register, używany w Input Capture FIFO
operations

W sumie o mudułach xCCP można pisać dużo a i tak nie zrozumiemy przy pierwszym podejściu o co chodzi, dlatego skupię się w dalszej części artykułu na aspekcie praktycznym czyli co, jak i gdzie aby zadziałało :)

Ponieważ najczęściej w praktyce amatorskiej wykorzystywany jest tryb PWM, spróbujemy zatem z nim podziałać. Skoro wchodzi w grę malowanie wykresu  to z krótkiego opisu trybów powyżej wiemy , że robimy to z grubsza w trybie Compare. Ogólnie rzecz ujmując potrzebujemy namalować zbocze narastające potem opadające , czast trwania wypełnienia PWM to różnica w czasie pomiedzy tymi zboczami. Do tego jeszcze przydałby się okres, po którym znowu będziemy malować zbocze narastające potem opadające i tak w koło Macieju.
Teraz musimy tylko dojść do tego jaki rejestr załatwi nam założoną funkcjonalność i przyporządkować go do poszczególnego zadania. Z pomocą przychodzi tutaj wykres wygrzebany z manuala , który zadziwiająco jest zbieżny z tym co chcemy uzyskać :


To nic , że wykres opisany jest jako Dual Edge Compare Mode a nie PWM, jesteśmy artyści malarze i do nas przemawia obraz a nie jego nazwa :)
Z wykresu możemy wywnioskować , że za namalowanie zbocza narastającego i umiejscowienie tego zbocza w osi czasu (oś czasu realizuje nam rejestr licznik  CCPxTMR popędzany zegarem systemowym lub innym tykaczem) odpowiada rejestr CCPxRA. Za namalowanie zbocza opadającego w osi czasu odpowiada rejestr CCPxRB. Fizycznie zbocza powstają tak, że zawartość rejestrów CCPxRA i CCPxRB jest porównywana z aktualną zawartością licznika w CCPxTMR. Jeśli zachodzi równość tych dwóch wartości to wyzwalany jest event powodujący namalowanie odpowiedniego zbocza na wybranym przez nas pinie. Za malowanie okresu naszego przebiegu odpowiada rejestr CCPxPR, który zeruje nam wartość licznika w CCPxTMR i powoduje zapętlenie całej operacji.

W sumie jak już wiemy jakie rejestry fizycznie odpowiadają za malowanie naszego wykresu PWM to już jesteśmy w domu a reszta to pierdolety w stylu ustawienie trybu, zerowanie licznika, wybranie pinu i przyporządkowanie go do modułu xCCP, tak myślę choć tego jeszcze na 100% nie wiem :). Pisząc ten artykuł sam się uczę.

Żeby zacząć grzebać w rejestrach musimy poczynić założenia dotyczące parametrów czasowych naszego przebiegu PWM, który chcemy namalować . Pewnie bez jakiś wzorów matematycznych się nie obędzie . Zajmijmy się najpierw okresem PWM , tutaj przydałby się jakiś zgrabny wzór , który wyliczy nam co musimy załadować do rejestru CCPxPR aby uzyskać zakładany okres PWM-a.

Zatem podaję wzór :

PR =  (OSC[Hz] / Preskaler) / Okres PWM[Hz]

gdzie :
PR - wartość ładowana do rejestru CCPxPR 
Okres PWM - częstotliwość okresu w Hz
OSC - wartość źródła taktowania w Hz (wybieramy wewnętrzny zegar 24MHz = 24000000 Hz)
Preskaler - wartość przez którą dzielimy OSC i spowalniamy tym samym , żródło taktowania modułu xCCP. Dostępne wartości to 1:1 / 1:4 / 1:16 / 1:64

Przyjmijmy zatem następujące założenia dla naszego PWM-a, który chcemy namalować :

Okres PWM = 100 Hz
OSC = 24 MHz = 24000000 Hz
Preskaler = 64

Wyliczamy wartość PR, którą wpiszemy do rejstru CCPxPR

PR = (24000000 / 64) / 100 = 3750

Teraz przejdźmy do drugiego parametru PWM czyli wypełnienia. Wypełnienie to inaczej czas trwania stanu wysokiego. Najwygodniej podawać ten parametr w postaci procentowej, czyli w jakim procencie wypełnienie , wypełnia okres PWM. Spróbujemy zatem wyrzeźbić jakiś wzór. Zaczniemy od postaci wzoru do wyliczenia wypełnienia w Hz  :


Wypełnienie PWM[Hz] = (OSC[Hz] / Preskaler) / CCPxRB<15:0>

gdzie :
CCPxRB<15:0> = 0....65535 co wynika z faktu, że rejestr CCPxRB, który zamyka nam zboczem opadającym wypełnienie PWM-a jest właśnie 16-bitowy. Mówimy wtedy , że PWM jest 16-bitowy.

Przyjmijmy sobie założenie, że chcemy uzyskać wypełnienie np. 50%. Co oznacza, że 50% czasu trwania okresu będziemy mieć stan wysoki na wyjściu PWM. Teraz trzeba podumać jakimi fikołkami matematycznymi do tego dojdziemy. Założyliśmy , że okres PWM wynosi 100 Hz, zatem 50 % mniej lub raczej szybciej :) to będzie 200 Hz. Naszym celem jest uzyskanie wartości jaką trzeba wpisać w rejestr CCPxRB generujący zbocze opadające, aby takie zbocze było generowane po każdej 0,005 s (lub inaczej co 200 Hz) w jednym okresie. Musimy zatem przekształcić nasz ostatni wzór :

CCPxRB<15:0> = (OSC[Hz] / Preskaler) / Wypełnienie PWM[Hz]

podstawiamy wartości :

CCPxRB<15:0> = (24000000 / 64) / 200 = 1875

Rejestr który odpowiada za zbocze narastające CCPxRA ustawiamy na 0

Mamy zatem wartości jakie trzeba wpisać do rejestrów CCPxRA, CCPxRB, CPxPR aby uzyskać na wybranym pinie przebieg PWM o okresie 100 Hz i wypełnieniu 50%. Podsumujmy ustawienia poznanych rejestrów:

CCPxRA = 0
CCPxRB = 1875 = 0x753
CCPxPR = 3750 = 0xEA6
Żródło taktowania = wewnętrzny zegar 24MHz
Preskaler = 64


Przechodzimy teraz do tych pozostałych aspektów związanych z konfiguracjami i tymi tzw pierdoletami. Przyjmuję , ze sygnał PWM będę malował na pinie RB8. Niestety tam gdzie na mojej płytce developerskiej dla PIC32MM mam podłączoną diodę LED na RB6, moduł xCCP w trybie Compare Output nie działa. Choć w sumie i tak efekt pracy będę obrazował na analizatorze stanów logicznych, więc LED jest zbędny. Moduły xCCP dostępne w PIC32MM0256GPM048 mają następującą numerację :

MCCP1,MCCP2,MCCP3
SCCP4,SCCP5,SCCP6,SCCP7,SCCP8,SCCP9

Ja skorzystam do testów z modułu SCCP4. Konfiguracji ustawień dokonamy w MCC, tak będzie przy pierwszym podejściu najłatwiej, podejrzymy jak jest robiona konfiguracja od strony rejestrów i jak jest zrobione przyporządkowanie wybranego pinu do SCCP4. Zatem jak nasze ustawienia powinny wyglądać w MCC , moim zdaniem tak :




Po wygenerowaniu projektu z MCC , możemy zacząć sobie zerkać na ustawienia rejestrów , funkcja inicjalizująca moduł SCCP4 wygląda następująco :



Widać z niej , że większość akcji od strony rejestrów rozgrywa się w rejestrze CCPxCON1: Capture/Compare/PWMx Control 1 Register

A teraz zerknijmy jak jest przyporządkowany pin RB8 do modułu SCCP4 :



Widzimy, że jest to zwykłe przyporządkowanie za pomocą PPS (Peripheral Pin Select), a jak to się robi fizycznie przeczytamy w data sheet PIC32MM0256GPM048 od strony 118

W sumie teraz wypadałoby sprawdzić czy to działa. No i nie działa :) Czyli to co Witek napisał w komentarzach pod artykułem , że nie udało mu się tego PWM-a uruchomić jest jak najbardziej zasadne. Ponieważ mam taki charakter , że jak zderzę się z jakimś problemem technicznym to mam koszmary nocne :) zatem aby ich nie mieć przed godziną snu, problem muszę rozgryźć. Czyli zamieniem się w sapera i szukam miny :) Choć w wojsku miałem kompletnie inną specjalizację :)

Zerkam wnikliwiej w manuala i znajduję tam trop w postaci tekstu na stronie 41 :


Po zapoznaniu się z powyższym tekstem zerkam do funkcji konfiguracyjnej SCCP4_COMPARE_Initialize() wygenerowanej przez MCC i patrzę jak ten rejestr jest ustawiony, przy okazji zerkam jak wygląda pole bitowe OCAEN w rejestrze CCPxCON2. A ustawiony jest tak :

/*ASDGM disabled; ICGSM Level-Sensitive mode; ICS ICM4; SSDG disabled; AUXOUT Disabled; ASDG 0; PWMRSEN disabled; OCAEN disabled; OENSYNC disabled; */
CCP4CON2 = 0x0;

Co oznacza, że moduł SCCP4 nie kontroluje pinu podpiętego do modułu. No i okazało się, że to była ta mina, aby ją rozbroić należy użyć takiego zapisu :

/*ASDGM disabled; ICGSM Level-Sensitive mode; ICS ICM4; SSDG disabled; AUXOUT Disabled; ASDG 0; PWMRSEN disabled; OCAEN enabled; OENSYNC disabled; */
CCP4CON2 = 0x1000000;
czyli bit OCAEN ustawić na 1


Poniżej pełny obraz funkcji konfiguracyjnej z naniesioną zmianą :


Pytanie dlaczego w MCC w okienku obrazkowym Easy Setup dla modułu SCCP4 brakuje takiego istotnego niuansu ??? bez , którego nie zobaczymy na wyjściu przebiegu. Widocznie Microchip nie chce aby użytkownik jego aplikacji był sennym znudzonym programistą, gdzie wszystko jest nudne i przewidywalne, który jak małpa klika w ikonki. Microchip preferuje programistów spiętych kreatywnie i gotowych do boju saperów :) Ja powiem tak , dzięki minom więcej się nauczyłem i jestem bardziej  świadomym użytkownikiem, czyli co niby mam podziękować Microchipowi :).

Poniżej przebieg na pinie RB8 jaki na obecną chwilę się generuje :


Z odczytów czasowych widzimy ładnie namalowany okres ok.100 Hz, i wypełnienie ok. 50% co widać gołym okiem, nie są to dokładnie co do piksela zakładane wartości bo takich raczej nie osiągniemy co wynika m.in z zaokrągleń . Widzimy zatem, że moduł SCCP4 działa zgodnie z oczekiwaniem co cieszy.

Warto wspomnieć ,że moduł xCCP ma dwa błędy w siliconie co jest wykazane w erracie. Poniżej te błędy :



W artykule liznąłem tylko mały kawałek góry lodowej jaką jest moduł xCCP. Za pomocą tego modułu możemy tworzyć niespotykane w kosmosie kształty przebiegów, czy przyjmować na klatę i analizować czasowo najbardziej skomplikowane wytwory ludziej wyobraźni. Sterowanie silnikami BLDC to pikuś z tym modułem. Zresztą nasza wyobraźnia nawet nie sięgnie możliwości tego modułu. Do zalet xCCP w stosunku do rozwiązań spotykanych u innych producentów MCU, należy fakt, że moduł nie angażuje Timerów sprzętowych tylko ma swój wewnętrzny Timer. Warto też odnotować, że moduł xCCP współpracuje doskonale z komórkami CLC i można w tym duecie np. modelować przebiegi komplementarne.
Na razie pozostaniemy przy PWM a z czasem jak wpadnie jakaś potrzeba wykorzystania tego modułu do innych celów do uzupełnię artykuł.

W linkach zamieszczam gotowy projekt do MPLABX-IDE , który generuje przebieg PWM o okresie 100Hz i wypełnieniu 50% na pinie RB8 wykorzystując moduł SCCP4. W przypadku gdy chcemy taki sam przebieg podać do większej ilości pinów (maksymalnie do 6) to korzystamy wtedy z modułu MCCP1..3.

Projekt może nie jest zbyt ambitny ale pokazuje to co trzeba od strony konfiguracji i użycia xCCP.

Pozdrawiam
picmajster.blog@gmail.com



Linki :
MCCP/SCCP - manual
Using the CCP Module
CCP Tips and Tricks
CCP Modules - Zasoby wiedzy z Mikroelektroniki
MCCP implementacja sterowania silnikiem BLDC 
PWM / SCCP4 -  projekt do MPLABX-IDE na GitHub

8 komentarzy:

  1. to dobrze że ten temat bo na pic32mm064 nie poszło mi uruchomienie PWM, na wersji 256 jeszcze nie sprawdzałem

    OdpowiedzUsuń
  2. Spoko Witek, ja nie sprawdzałem jeszcze na żadnym PIC :) i mam nadzieję, że się uda. A jak się nie uda to będziemy dotąd drążyć aż się uda lub padniemy. Howgh

    OdpowiedzUsuń
  3. zlutowałem płytkę , ściągnąłem z githuba i PWM ruszył na rb8.

    OdpowiedzUsuń
  4. no to chyba brawo jak ruszył :) i wreszcie coś zlutowałeś a nie na pająka :)

    OdpowiedzUsuń
  5. ciekawe czy przy użyciu CLC i PWM można sterować diodami WS2812?

    OdpowiedzUsuń
  6. wygląda na to,że się da zerknij tutaj : http://ww1.microchip.com/downloads/en/AppNotes/00001606A.pdf

    OdpowiedzUsuń
  7. masz tu jeszcze artykuł z elektroniki praktycznej : https://ep.com.pl/artykuly/11608-Sterowanie_span_classfWSspan_nowe_podejscie.html

    OdpowiedzUsuń