logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[stm32] Timer2 i DMA - jak przypisać wartości do TIM2->CCR dla trzech kanałów?

Bruum 04 Paź 2010 09:52 5376 28
REKLAMA
  • #1 8581670
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Witam! Chcę wygenerować trzy przebiegi, zsynchronizowane czasowo, składające się z dwóch paczek po 10 impulsów .
    Planuję zrobić to na trzech kanałach jednego timera, akurat nr2. Wyjścia oc toggle.
    Potrzebuję do tego DMA. Mam taką wątpliwość:
    Jak przekazać kontrolerowi dma, gdzie akurat ma daną wartość wpisać, tzn. do którego TIM2->CCR? Żądania zgłaszać może każdy z kanałów, któremu na to pozwolimy.
    W przypadku przerwań są sprawdzane wywołania, a jak jest przy dma? Potrzebuję, żeby na wywołanie danego kanału dma wpisało z tablicy nową wartość do ccr tego kanału nie ruszając innych, które robą swoje aż do wystąpienia compare i zgłoszenia żądania na co dma powinno znowu wpisać co trzeba gdzie trzeba. Da się?
  • REKLAMA
  • #3 8581846
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Powinno się dać

    Konfigurujesz 3 kanały DMA odpowiednie dla każdego kanału timera
    TIM2_CH1 - DMA1-5
    TIM2_CH2 - DMA1-7
    TIM2_CH3 - DMA1-1
    DMA konfigurujesz jako transfer pamięć -> peryferial, z inkrementacją tylko pamięci, podajesz adres tablicy, adres rejestru CCR, ilość transferów, rozmiar danych i tryb kołowy,
    W timerze zezwalasz na żądanie DMA (rejestr TIM2_DIER)
    i jeszcze musisz odpowiednio ustawić bit CCDS w rejestrze TIM2_CR2
    no i jeszcze musisz właczyć te 3 kanały DMA.
  • #5 8581973
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Freddie Chopin napisał:
    Tyle że timer może wysyłać tylko JEDNO żądanie do DMA, więc... nie da się (tym sposobem).

    No ale chyba właśnie o to chodzi. Następuje zdarzenie od kanału timera, DMA przesyła JEDNĄ nową wartość do CCR tego kanału, przy której osiągnięciu przez licznik timera nastąpi nowe zdarzenie i tak w kółko. Chyba, że ja źle zrozumiałem zamiar Bruum.
  • #6 8582012
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Witam! Jakie to szczęście że was widzę w swoim topicu-wiadomo, że coś z tego wyjdzie.
    Z natury urządzenia wynika, że zmiany stanów wyjść, a więc i OCxREF nie będą równoczesne, a więc i żadania do dma też. W jednym czasie będzie potrzebny transfer do jednego tylko CCR. Nie wiem tylko czy i jak da się dany kanał dma przekonać, że ma reagować na dane zgłoszenie od danego kanału. Pozostałe kanały czekać powinny na swoje wywołania. Czy przypadkiem kontroler dma nie widzi wywołania jako od tim2 bez rozróżnienia od którego podukładu wewnętrznego to jest. I jeszcze kwestia trybu kołowego. Wydaje mi się, że tu nie pasuje. Każde zdarzenie ma inkrementować adres a po wygenerowaniu dwóch paczek timer się resetuje i czeka na kolejne wyzwolenie. Teoretycznie powinno wszystko startować od początku. Chociaż może taka uroda dma? Moja pierwsza z tym przygoda.
  • REKLAMA
  • Pomocny post
    #7 8582052
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #8 8582066
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Bruum napisał:
    Witam! Jakie to szczęście że was widzę w swoim topicu-wiadomo, że coś z tego wyjdzie.
    Z natury urządzenia wynika, że zmiany stanów wyjść, a więc i OCxREF nie będą równoczesne, a więc i żadania do dma też. W jednym czasie będzie potrzebny transfer do jednego tylko CCR. Nie wiem tylko czy i jak da się dany kanał dma przekonać, że ma reagować na dane zgłoszenie od danego kanału. Pozostałe kanały czekać powinny na swoje wywołania. Czy przypadkiem kontroler dma nie widzi wywołania jako od tim2 bez rozróżnienia od którego podukładu wewnętrznego to jest.

    To są trzy odrębne sprzętowe kanały, nawet jeśli żądanie od każdego z kanałów timera nastąpi równocześnie to o kolejności transferu decyduje arbiter DMA.



    Bruum napisał:

    I jeszcze kwestia trybu kołowego. Wydaje mi się, że tu nie pasuje. Każde zdarzenie ma inkrementować adres a po wygenerowaniu dwóch paczek timer się resetuje i czeka na kolejne wyzwolenie. Teoretycznie powinno wszystko startować od początku. Chociaż może taka uroda dma? Moja pierwsza z tym przygoda.


    No to tylko taka różnica że za każdym razem będziesz musiał na nowo skonfigurować DMA
  • REKLAMA
  • #9 8582106
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Dzięki Panowie!
    Cytat:

    No to tylko taka różnica że za każdym razem będziesz musiał na nowo skonfigurować DMA


    Tej drobnej różnicy nie wiedziałem a wiele może zmienić.

    Popatrzyłem jeszcze w RM i znalazłem tabelkę jak w załączniku-to chyba klucz do rozwiązania? Swoją drogą chcąc dma wykorzystać do paru rzeczy trzeba się nagimnastykować przez to wielokrotne przyporządkowanie HW_reqest-ów do różnych urządzeń? Jak na przykład kanał 7 gdzie od tim2 jest ch2 i 4? Szczęśliwie czterech kanałów timera nie potrzebuję. Są jakieś na to jakieś ew. patenty?
    Załączniki:
    • [stm32] Timer2 i DMA - jak przypisać wartości do TIM2->CCR dla trzech kanałów? Tabelka.JPG (127.31 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • Pomocny post
    #10 8582109
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Doczytałem głębiej i w sumie chyba faktycznie da się to zrobić. Wychodzi na to, że trzeba po prostu sprawdzić [; Trzeba tylko tak dobrać timer, aby jego (używane) kanały nie wypadały po kilka do jednego kanału DMA, bo wtedy się nie będzie dało.

    4\/3!!
  • #11 8582140
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Cytat:

    No to tylko taka różnica że za każdym razem będziesz musiał na nowo skonfigurować DMA


    Jeszcze raz-czy niezaznaczenie trybu kołowego powoduje reset ustawień dma po przesłaniu całego zadeklarowanego bloku danych?
  • #12 8582153
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Bruum napisał:
    Cytat:

    No to tylko taka różnica że za każdym razem będziesz musiał na nowo skonfigurować DMA


    Jeszcze raz-czy niezaznaczenie trybu kołowego powoduje reset ustawień dma po przesłaniu całego zadeklarowanego bloku danych?


    Trzeba na nowo ustawic ilość transferów i włączyć dany kanał

    Dodano po 15 [minuty]:

    Bruum napisał:

    Popatrzyłem jeszcze w RM i znalazłem tabelkę jak w załączniku-to chyba klucz do rozwiązania?


    Naucz używać się Alt+ PrtScrn kopiuje do schowka tylko aktualne okno i druga sprawa Reader ma takie narzędzie gotowe "Menu->Narzędzia->Zaznacz i powiększ-> Narzędzie zdjęcie" ;)

    Dodano po 6 [minuty]:

    Bruum napisał:
    Swoją drogą chcąc dma wykorzystać do paru rzeczy trzeba się nagimnastykować przez to wielokrotne przyporządkowanie HW_reqest-ów do różnych urządzeń? Jak na przykład kanał 7 gdzie od tim2 jest ch2 i 4? Szczęśliwie czterech kanałów timera nie potrzebuję. Są jakieś na to jakieś ew. patenty?


    No niestety patentów żadnych nie ma, albo przypisujesz tylko do jednego peryferiala i z reszty rezygnujesz albo z wykorzystaniem jakiegoś mutexu przerzucasz po peryferialach.
  • #13 8582316
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Cytat:

    Naucz używać się Alt+ PrtScrn kopiuje do schowka tylko aktualne okno i druga sprawa Reader ma takie narzędzie gotowe "Menu->Narzędzia->Zaznacz i powiększ-> Narzędzie zdjęcie"

    Człowiek uczy się całe życie z wyjątkiem lat szkolnych.

    Pytanie o praktykę warsztatową:
    jak to robicie, że bez pomyłek przepisujecie ciągi 1 i 0 na 0x..
    chodzi mi o praktyczne sposoby sprawdzające się przy nawet 32 bitach.
  • REKLAMA
  • #14 8582344
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ja na przykład nigdy nie używam ciągów 0/1 ani liczb hex, tylko odpowiednich definicji...

    np.
    ADC1->CR2 = ADC_CR2_JEXTSEL_JSWSTART | ADC_CR2_JEXTTRIG | ADC_CR2_CAL | ADC_CR2_ADON; // enable ADC, start calibration, enable external software trigger for Injected Group

    4\/3!!
  • #15 8582346
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Takich rzeczy się nie robi zazwyczaj, bo każdy bit jest zdefiniowany i oruje się nazwy bitów lub stosuje się bitbanding, ale jeśli trzeba już coś takiego zrobić to najlepiej pogrupować sobie na 4.

    0b10100010100011101100101100101000
    0b1010 0010 1000 1110 1100 1011 0010 1000
    0xA28ECB21
  • #17 8582360
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    michalko12 napisał:
    0b10100010100011101100101100101000
    0b1010 0010 1000 1110 1100 1011 0010 1000
    0xA28ECB21

    Jak widać też można się tak pomylić: 0xA28ECB28. Akurat STM odwalił kawał dobrej roboty robiąc takie definicje, łatwo i przyjemnie się taki kod czyta, spoglądając do Reference Manual.
  • #18 8582376
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Dzięki!
    Jak już Was męczę...

    Cytat:

    tylko odpowiednich definicji...


    zaczerpniętych literalnie z...

    Z grupowaniem-nie pomyślałem, dzięki.

    O co może chodzić teraz:

    Pierwsze próby konfiguracji i zonk:
    Cytat:

    Main.c(249): error: #136: struct "<unnamed>" has no field "CCR1"

    wpisuję
    Cytat:

    DMA1->CCR1=0x25b1;

    Gdy wpisuję jak w RM0008
    Cytat:

    DMA->CCR1=0x25b1;

    krzyczy
    Cytat:

    Main.c(249): error: #20: identifier "DMA" is undefined

    Keil...
    Dotąd wpisywałem nazwy z RM i było ok.
  • Pomocny post
    #19 8582392
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    Musisz dokładnie zajrzeć do "stm32f10x.h". Otworzyć go w okienku i CTRL+F i nazwa, lub okienko Outline jak masz i poszukać. Czasem są takie wyjątki w nazwie, ale większości wypadków tak nie jest (;
    typedef struct
    {
      __IO uint32_t CCR;
      __IO uint32_t CNDTR;
      __IO uint32_t CPAR;
      __IO uint32_t CMAR;
    } DMA_Channel_TypeDef;

    //...........
    #define DMA1_Channel1       ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE)
    #define DMA1_Channel2       ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE)
    //......

    DMA1_Channel1->CCR |= DMA_CCR1_EN;		//enable DMA
  • #20 8582407
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Wg mnie najwygodniej korzystać z Eclipse'owego Content Assist - wpisujemy kilka pierwszych liter - np. DMA - i naciskamy Ctrl + Spacja, a pojawi się lista pasujących podpowiedzi z których coś wybieramy - niech będzie DMA1_Channel1. Potem wpisujemy "->" i znów pojawia się lista elementów tej struktury, więc coś wybieramy. Po znaku '=' można znów skorzystać z Content Assist - wpisać kilka pierwszych liter i nacisnąć Ctrl + Spacja.

    4\/3!!
  • #21 8582421
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Dzięki Panowie za cierpliwość z poniedziałku.
    Jakiś czas temu Freddie oświecił mnie nt. stosowania nazw rejestrów a tu znowu:
    Cytat:

    Czasem są takie wyjątki w nazwie, ale w większości wypadków tak nie jest (;

    fajnie...
    Widziałem w pewnym poscie ostrzeżenia przed or-owaniem, więc pomyślałem, że pisząc całe wartości uniknę problemów.
  • #22 8582445
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Bruum napisał:
    Widziałem w pewnym poscie ostrzeżenia przed or-owaniem, więc pomyślałem, że pisząc całe wartości uniknę problemów.

    Pokaż linka, sprostujemy (; Przy bardziej zakręconym ORowaniu warto pamiętać o (zwykle zbędnych) nawiasach, żeby nie zastanawiać się niepotrzebnie nad priorytetami - np coś na styl:

    0x55 << 3 | 0x12340000

    jest równoznaczne temu

    (0x55 << 3) | 0x12340000.

    4\/3!!
  • #23 8582472
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    tymon_x napisał:
    michalko12 napisał:
    0b10100010100011101100101100101000
    0b1010 0010 1000 1110 1100 1011 0010 1000
    0xA28ECB21

    Jak widać też można się tak pomylić: 0xA28ECB28. Akurat STM odwalił kawał dobrej roboty robiąc takie definicje, łatwo i przyjemnie się taki kod czyta, spoglądając do Reference Manual.


    Że też chciało ci się to sprawdzać, myślałem 8 wpisałem 1, no ale fakt faktem w programie błędy są niewybaczalne.

    Freddie Chopin napisał:
    Tak BTW to GCC pozwala na zapis binarny liczb, więc przeliczanie jest zupełnie zbędne...

    int value = 0b01010101;


    No właśnie, przy 8 bitach to jeszcze fajnie wygląda ale przy 32 już jest porażka i tu jakieś grupowanie przydałby się w stylu:

    0b1010.0010.1000.1110.1100.1011.0010.1000
  • #24 8582486
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    michalko12 napisał:
    No właśnie, przy 8 bitach to jeszcze fajnie wygląda ale przy 32 już jest porażka i tu jakieś grupowanie przydałby się w stylu:

    0b1010.0010.1000.1110.1100.1011.0010.1000

    Może troszkę w bok wybiegnę, ale w językach HDL jest dostępne takie grupowanie:
    B"1010_0000_1000_1100"

    Może kiedyś (;
    michalko12 napisał:
    Że też chciało ci się to sprawdzać,...

    Akurat mi się takie rzeczy od razu rzucają w oczy, takie zboczenie (; Jak się patrzy na te ciągi 01 w symulacji w HDL, to można dostać takiego skrzywienia (;
  • #25 8582634
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    A to przejdzie?
    
    DMA1_Channel1->CPAR=&TIM2->CCR1;
    DMA1_Channel1->CMAR=&R; //	  uint16_t R[22];
    

    i czemu nie przechodzi?


    Drobna poprawka pomogła:
    
    DMA1_Channel1->CPAR=(uint32_t)&TIM2->CCR1;
     DMA1_Channel1->CMAR=(uint32_t)&R[0]; //	  uint16_t R[22];
    

    ma to szanse działać?
  • #26 8582969
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Nie ma szansy bo:

    TIM2_CH1 - DMA1-5
    TIM2_CH2 - DMA1-7
    TIM2_CH3 - DMA1-1
  • #27 8583038
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    Tak tak-to mam poprawione, ten 1 kanał to była próba.
    Ale formalnie? Czy przekazywanie adresów jest ok?

    
    DMA1_Channel5->CPAR=(uint32_t)&TIM2->CCR1;
    	 DMA1_Channel5->CMAR=(uint32_t)&R[0]; //	  
    


    Wejście CH2 będzie wykorzystywane do strobowania.
  • #28 8583241
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    jest ok
  • #29 8584310
    Bruum
    Poziom 23  
    Posty: 818
    Pomógł: 29
    Ocena: 54
    CUD! Poszło! Jeszcze raz dzięki, niech to wiekopomne wydarzenie będzie zwiastunem udanego tygodnia!

    Nie do końca jeszcze stabilne, niedopracowane wyzwalanie timera. Przed tygodniem o timerach i dma w stm32 wiedziałem, że są.

Podsumowanie tematu

✨ W dyskusji poruszono problem synchronizacji trzech przebiegów generowanych przez timer TIM2 w mikrokontrolerach STM32, z wykorzystaniem DMA do przypisywania wartości do rejestrów CCR dla trzech kanałów. Użytkownik chciał uzyskać zsynchronizowane impulsy, jednak napotkał trudności w konfiguracji DMA, ponieważ timer może wysyłać tylko jedno żądanie do DMA w danym momencie. Uczestnicy dyskusji zasugerowali, że każdy kanał DMA może być przypisany do odpowiedniego kanału timera, a także omówili konieczność odpowiedniej konfiguracji rejestrów TIM2 oraz DMA. Wskazano, że tryb kołowy nie jest obowiązkowy, a także poruszono kwestie związane z adresowaniem rejestrów i koniecznością ponownej konfiguracji DMA po zakończeniu transferu. Ostatecznie użytkownik uzyskał działające rozwiązanie, które wymagało poprawnej konfiguracji kanałów DMA i rejestrów timera.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA