Elektroda.pl
Elektroda.pl
X
Elektroda.pl
IT SerwisIT Serwis
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY

wojlej 28 Lut 2013 16:49 24903 125
  • #91
    wojlej
    Poziom 17  
    Cytat:
    Najpierw włączyć transmisję, a potem ustawić jej szybkość? - jakaś totalna bzdura.


    Też mi się tak wydaje, bo powinno się najpierw ustawić parametry a potem włączyć, jak zresztą w przypadku innych peryferiów. Ale piszą tak:

    Code:
    Procedure:
    
    1. Enable the USART by writing the UE bit in USART_CR1 register to 1.
    2. Program the M bit in USART_CR1 to define the word length.
    3. Program the number of stop bits in USART_CR2.
    4. Select DMA enable (DMAT) in USART_CR3 if Multi buffer Communication is to take
    place. Configure the DMA register as explained in multibuffer communication.
    5. Select the desired baud rate using the USART_BRR register.
    6. Set the TE bit in USART_CR1 to send an idle frame as first transmission.
    7. Write the data to send in the USART_DR register (this clears the TXE bit). Repeat this
    for each data to be transmitted in case of single buffer.
    8. After writing the last data into the USART_DR register, wait until TC=1. This indicates
    that the transmission of the last frame is complete. This is required for instance when
    the USART is disabled or enters the Halt mode to avoid corrupting the last
    transmission.
  • IT SerwisIT Serwis
  • #92
    Freddie Chopin
    Specjalista - Mikrokontrolery
    No ale tu generalnie i tak najpierw ustawiasz, a potem włączasz, bo dopiero po pełnej konfiguracji ustawiasz TE (Transmitter Enable), wiec wychodzi na jedno. Ale ja to i tak zawsze robiłem odwrotnie niż tutaj piszą (czyli najpierw BRR, potem cokolwiek w CRx) i działa [;

    4\/3!!
  • #93
    wojlej
    Poziom 17  
    No więc kod wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Proszę jeszcze o kontrolę tego Baudrate, czy poprawnie to wyliczyłem i ma to prawo ruszyć?
  • IT SerwisIT Serwis
  • #94
    Freddie Chopin
    Specjalista - Mikrokontrolery
    No ale nie możesz po prostu... sprawdzić? Jak chcesz cały program napisać tutaj hipotetycznie, to masz 99,666% szansy że nic nie zadziała - to się pisze po kawałku i sprawdza, a nie wrzuca na forum. Na forum zaś wrzuca się kawałki z którymi masz KONKRETNY problem.

    Co do baudrate, to wzór z manuala to jakaś parodia, wystarczy częstotliwość magistrali podzielić przez oczekiwany baudrate (z zaokrąglaniem, czyli najpierw do licznika dodajesz połowę dzielnika) i masz wartość do wpisania do BRR - te całe cyrki z jakimiś mantysami, dzielnikami i tym podobnymi bzdurami chyba są tam tylko po to, żeby ludzi zapędzić do używania SPLa, no bo "to takie skomplikowane!!!!111".

    Swoją drogą możesz po prostu ustawić baudarate 1.5M i też będzie dobrze, na PC i tak możesz zwykle ustawić dowolny...

    4\/3!!
  • #95
    wojlej
    Poziom 17  
    Cytat:
    No ale nie możesz po prostu... sprawdzić?


    No właśnie na razie nie, Z tego względu, że nie mam jeszcze fizycznie układu (pomiarowego) - czekam na wzmacniacze itp. Po napisaniu programu chcę ewentualnie podłączyć 4 potencjometry pod każdy kanał i wtedy sprawdzić.

    Po drugie myślę, że taki temat może być pomocny dla ludzi którzy też chcą się nauczyć operacji na rejestrach bez użycia bibliotek, bo to faktycznie nietrudne, aczkolwiek może sprawić problemy, jak widać w powyższych postach. Taki temat może być bardzo pomocny z tego względu, że podobnych na elektrodzie nie ma, bo jak przeglądałem tematy to było tylko wspomniane, że po co używać bibliotek skoro można coś tam ustawić wpisując 2 wartości do rejestrów. Wszystko fajnie, ale jak? Jak ktoś prześledzi ten temat od początku to będzie wiedział, a przecież po to jest forum.

    Więc spokojnie, kodu jeszcze nie wrzucam do uC tylko kompiluje sprawdzając błędy. Niedługo wrzucę.

    I np mam problem z tym NVICEM bo BlueDraco napisał tak:
    Cytat:
    NVIC_EnableIRQ(EINT3_IRQn); - standaardowo


    No ale skąd wziąśc to EINT3_IRQn. Szukam po tym manualu i nie ma. W pliku coś tam h. są tylko rejestry ISER itp. Nie mam pojęcia jak włączyć to przerwanie zakończenia DMA z ADC, żeby tam pozmieniać konfigurację i zmienić bufory.
  • #96
    Freddie Chopin
    Specjalista - Mikrokontrolery
    wojlej napisał:
    W pliku coś tam h.

    No i to właśnie jest w tym pliku cośtam-h - np. stm32f1x.h

    4\/3!!
  • #97
    BlueDraco
    Specjalista - Mikrokontrolery
    Litości...

    1. Pokazałem Ci, jak się włącza dowolne przerwania w dowolnym Cortexie,a nie jak masz włączyć przerwanie, o którym marzysz, bo nawet nie wiem, o którym marzysz. Lista nazw przerwań znajduje się w sławnym pliku cośtam.h.

    2. Ja jestem za leniwy naliczenie wartości ładowanych do BRR i timerów, dlatego każę to robić kompilatorowi. Tobie radzę to samo. W przypadku BRR należy upewnić się, czy uzyskasz dobrą wartość częstotliwości transmisji - błąd musi być mniejszy od 2%.

    Wzór na BRR podaję co chwila - dla STM32F jest to (FCLK + BAUD / 2) / BAUD. Trzeba to wyrażenie po prostu napisać po prawej stronie podstawienia BRR.
  • #98
    wojlej
    Poziom 17  
    Wpisałem coś takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Odblokowanie przerwania od kanału 1 DMA1 bo w konfiguracji DMA kanał 1 miałem:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    TCIE włączenie przerwania od zakończenia transferu. Wydaje mi się, że tak powinno być.

    Teraz w przerwaniu mam zamianę buforów:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Najpierw zeruje flagę przerwania i neguje swoją flagę typu bool która mówi o tym jaki bufor gdzie ma zostać wpisany.

    Potem wpisuje bufory odpowiednio do rejestrów w zależności od zmiennej bool i na końcu włączam DMA. Czy powinno tu być coś jeszcze?
  • #99
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Dokumentacja twierdzi, że przed modyfikacją ustawień DMA rejestr CCR powinien być wyzerowany (czy tam jeden bit w nim).

    4\/3!!
  • #100
    BlueDraco
    Specjalista - Mikrokontrolery
    Ja tylko zacytuję mówj post w tym wątku z 18 lutego:

    "Do zaprogramowania tego przyda Ci się taka instrukcja:

    akt_bufor ^= bufor1 ^ bufor2;

    W ten sposób obsługa przerwania nie musi zawierać rozejścia na przypadek z buforem 1 i buforem 2 - zawsze wykonuje tę samą liniową sekwencję instrukcji."
  • #101
    wojlej
    Poziom 17  
    Cytat:
    akt_bufor ^= bufor1 ^ bufor2;


    Tak, pamiętam.
    Zastosowanie XOR Swap, ale nie za bardzo potrafię to zastosować :).

    Cytat:
    Dokumentacja twierdzi, że przed modyfikacją ustawień DMA rejestr CCR powinien być wyzerowany (czy tam jeden bit w nim).


    Poszukam :). A czy na pewno to przerwanie będzie się wykonywać? Jest poprawny wpis w NVIC?
  • #102
    BlueDraco
    Specjalista - Mikrokontrolery
    Nie wiem, co zrobołeś z NVIC - nie zauważyłem kodu.
    Obsługa przerwania DMA to będzie coś takiego:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • #103
    wojlej
    Poziom 17  
    Zmieniłem obsługę przerwania aczkolwiek nie do końca rozumiem to podsatwienie:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    I tam zmieniłem na (uint32_t) bufor1 bo kompilator wywalał błąd.

    Podłączyłem układ do do komputera odpaliłem i spodziewałem się uzyskiwania w terminalu albo samych zer albo losowych wartości, niestety nie ma nic. Postawiłem kilka breakpointów i chciałem zobaczyć konfiguracje poszczególnych peryferii i sprawa wygląda tak:

    Najpierw wykonuje się RCC_Config(); (napisałem to z obsługą bibliotek, niedługo to zmienię).
    [STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY

    Wygląda w porządku, procesor taktowany 24MHz, Timer 24MHz, ADC 12MHz.

    Następnie wykonuje się GPIO_Config(); który również jest z użyciem bibliotek:
    [STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY
    Tutaj jest problem, bo RX i TX są skonfigurowane poprawnie (PA9 i PA10) ale porty PA1... PA4 (wejścia ADC - nie widać na screenie) są jako floating input, ale z tym jakoś sobie poradzę. Pod te wejścia oczywiście nic nie jest podłączone.

    Następnie wykonuje się konfiguracja DMA:

    DMA kanał 1 i 4
    [STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY [STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY

    Wygląda w porządku, Dalej program wchodzi do ADC_Config(); i się zatrzymuje w tym miejscu:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czeka i czeka. Nie może z tego wyjść. Albo nie może wykonać kalibracji albo coś źle z tym poleceniem.

    Proszę o pomoc, pozdrawiam.

    Dodano po 19 [minuty]:

    zmieniłem na coś takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Dodałem wykrzyknik bo przecież czekam na pojawienie się zanegowanej wartości. Nie wiem czy poprawnie rozumuje więc proszę mnie poprawić. Po uruchomieniu w terminalu otrzymuje 4 wartości o wartości 00. Czyli poprawnie, ale otrzymuje je tylko raz, Procesor nie nadaje cały czas. Tak jak nie wchodziłby do przerwania. Niżej kod proszę o zwrócenie mi uwagi na błędy:

    Konfiguracja:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I funkcja obsługi przerwania:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • #104
    Freddie Chopin
    Specjalista - Mikrokontrolery
    wojlej napisał:
    Dodałem wykrzyknik bo przecież czekam na pojawienie się zanegowanej wartości. Nie wiem czy poprawnie rozumuje więc proszę mnie poprawić.

    Niepoprawnie, bo operator "!" jest operatorem LOGICZNYM, a nie BITOWYM. Innymi słowy ten operator działa tak:
    cokolwiek-byle-nie-zero -> 0
    0 -> 1

    4\/3!!
  • #105
    wojlej
    Poziom 17  
    W takim razie program cały czas czeka w tym miejscu, a konfiguracja ADC1 do tego momentu wygląda tak:
    [STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY

    Jak widać RSTCAL = 1 co oznacza
    Code:
    1: Initialize calibration register.

    Co jest nie tak?
  • #106
    BlueDraco
    Specjalista - Mikrokontrolery
    No to doczytaj w manualu, jak dokładnie wygląda kalibracja w tym mikrokontrolerze, którego używasz. Mój przykład działa na STM32F051.
  • #107
    wojlej
    Poziom 17  
    W manualu jest napisane:

    Code:
    Calibration is started by setting the CAL bit in the ADC_CR2 register. Once calibration is over, the CAL bit is reset by hardware and normal conversion can be performed. It is recommended to calibrate the ADC once at power-on. The calibration codes are stored in the ADC_DR as soon as the calibration phase ends.


    Najważniejsze z tego to, że "Zalecane jest kalibrować przetwornik raz na włączenie zasilania" no to wydaje się logiczne.

    Następnie
    Code:
    1 It is recommended to perform a calibration after each power-up.

    "Zalecane jest aby przeprowadzić kalibracje po każdym włączeniu zasilania" No zgadzam się ;)

    I ostatnie:
    Code:
    Before starting a calibration the ADC must have been in power-off state (ADON bit = ‘0’) for at least two ADC clock cycles.


    Rozumiem to tak:
    "Przed rozpoczęciem kalibracji ADC musi być wyłączony przez co najmniej 2 takty zegara"
    Ja to wszystko rozumiem tak, że ADC należy konfigurować po włączeniu zasilania, ale przed kalibracją musi być wyłączony. Więc algorytm powinien w skrócie wyglądać tak:
    1. ADON wyłączony przez co najmniej 2 takty
    2. ADON włączony
    3. Reset kalibracji i kalibracja
    czyli po włączeniu ADON a nie przed tak jak koledzy mówili szybciej. Przy takim ustawieniu program się wykonuje a konfiguracja końcowa ADC wygląda tak:
    [STM32][USART][DMA] - Nadawanie przez USART z wykorzystaniem DMA STM32DISCOVERY

    a Kod konfiguracji ADC tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Niestety nadal otrzymuje tylko 4 bajty o wartości 0. Może przerwanie w ogóle się nie wykonuje? Można to jakoś sprawdzić?

    Kod w NVIC:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • #108
    BlueDraco
    Specjalista - Mikrokontrolery
    Popatrz na mój kod - kalibracja odbywa się prz ADON = 0, zgodnie z tym, co napisano w manualu. Jak Ty go czytasz, że kiedy piszą, że ADC ma być wyłączony, to Tobie wychodzi, że trzeba go włączyć?

    Bardzo dziwnie też wymyśliłeś tę konfigurację. Po wyzwoleniu masz JEDEN raz przeskanować wszystkie mierzone kanały, bez przerw między nimi, czyli raczej bez bitów z DISC w nazwie.
  • #109
    wojlej
    Poziom 17  
    Cytat:
    Popatrz na mój kod - kalibracja odbywa się prz ADON = 0, zgodnie z tym, co napisano w manualu. Jak Ty go czytasz, że kiedy piszą, że ADC ma być wyłączony, to Tobie wychodzi, że trzeba go włączyć?


    Masz rację, ale dla F05X. Specjalnie ściągnąłem manuala i jest napisane tam wyraźnie:

    Code:
    The calibration is initiated by software by setting bit ADCAL=1. [b]Calibration can only be initiated when the ADC is disabled (when ADEN=0).[/b] ADCAL bit stays at 1 during all the calibration sequence. It is then cleared by hardware as soon the calibration completes. After this, the calibration factor can be read from the ADC_DR register (from bits 6 to 0)...
    
    ... Software Procedure:
    ● Ensure that ADEN=0
    ● Set ADCAL=1
    ● Wait until ADCAL=0
    ● The calibration factor can be read from bits 6:0 of ADC_DR register


    Tutaj wyraźnie jest napisane, że ma być przy wyłączonym ADC.
    Jeżeli chodzi o F1 to powiedz mi w takim razie dlatego to nie działa? Dopiero przy włączonym ADON rusza.
    Kolejna sprawa to to, że we wszystkich materiałach jakie znalazłem, książkach i kodach na różnych stronach kalibracja odbywa się na samym końcu po włączeniu ADON. Bo manual piszę, że przed Kalibracją musi być wyłączony a nie w trakcie. Więc zaraz po włączeniu musi się odbyć kalibracja.

    Wracając do kodu, zauważyłem, że program nie wchodzi w przerwanie od zakończenia transferu z DMA. Zapaliłem na samym początku przerwania diodę (potem już nie gasiłem) więc powinna się zapalić po wejściu i świecić już zawsze. No i dioda się nie zapala. Więc program nie wchodzi w obsługę przerwania. Dlaczego?
  • #110
    BlueDraco
    Specjalista - Mikrokontrolery
    Pokaż cały kod związany z DMA i przerwaniami. Włączyłeś to przerwanie?
  • #111
    wojlej
    Poziom 17  
    NVIC:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Konfiguracja DMA:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Druga sprawa, to może ADC nie jest wyzwalane przez Timer bo konfiguracja timera wygląda tylko tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    No i obsługa przerwania:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • #112
    BlueDraco
    Specjalista - Mikrokontrolery
    Tak na początek - rejestr danych USART ma 8 bitów, nie 16. Zaprogramuj transfer DMA 8 bajtów, a nie czterech słów. Liczby transmitowanych elementów nie musisz podawać kompilatorowi szesnastkowo. :)

    O ile pamiętam, wyzwalanie ADC przez timer włącza się w dwóch miejscach - i w timerze i w ADC,
  • #113
    wojlej
    Poziom 17  
    Więc, doszedłem do tego, że mam źle skonfigurowany Timer. Jak wrzuciłem kod z użyciem bibliotek to ruszyło, zaczął przesyłać w nieskończoność jakieś losowe wartości. Po pierwsze w NVICu muszę odblokować przerwanie od Timera:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Po drugie muszę umieścić w przerwaniu od timera, zerowanie flagi od przepełnienia i włączenie triggera dla kolejnego pomiaru z ADC chyba w ten sposób (bez bibliotek więc proszę o sprawdzenie)
    Kod: c
    Zaloguj się, aby zobaczyć kod


    No i muszę odpowiednio skonfigurować kanał Timera bo konfiguracjha z użyciem bibliotek wygląda tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Teraz muszę to przerobić na kod bez bibliotek. Po wpisaniu tego koduu dioda zielona sie włącza co oznacza że układ wchodzi w przerwanie DMA od zakończenia transferu z ADC.

    Cytat:
    Tak na początek - rejestr danych USART ma 8 bitów, nie 16. Zaprogramuj transfer DMA 8 bajtów, a nie czterech słów. Liczby transmitowanych elementów nie musisz podawać kompilatorowi szesnastkowo.


    No właśnie zauważyłem, że jak wstawie w 1 miejsce bufora2 0xFFFF to przesyła mi tylko FF.

    Cytat:
    Zaprogramuj transfer DMA 8 bajtów, a nie czterech słów.


    No właśnie, ale jak wpisuje
    Kod: c
    Zaloguj się, aby zobaczyć kod

    To nic to nie daje, wyzerowałem też w DMA1_Channel4->CCR bit DMA_CCR4_PSIZE_0 co powoduje że rozmiar po stronie bufora USART to 8 bitów. Ale to też nic nie daje.
  • #114
    BlueDraco
    Specjalista - Mikrokontrolery
    Nie musisz odblokowywać ani obsługiwać przerwań timera. Jeśli raz włączysz wyzwalanie ADC, będzie ono włączone (raczej - co prawda STM32F1 są strasznie skopane, ale chyba nie aż tak).

    Nie ruszaj w ogóle rejestrów timera, których nie potrzebujesz. na oko potrzebujesz czterech dostępów - preskaler, okres, włączenie wyzwalania ADC i wystartowanie z autoreload.

    Z ADC odbierasz 4 słowa. Do USART wysyłasz 8 bajtów. Trzeba odpowiednio zaprogramować i rozmiary danych i liczbę transferów. Rozmiary źródła i przeznaczenia mają być te same w danym kanale DMA.
  • #115
    wojlej
    Poziom 17  
    Cytat:
    Nie musisz odblokowywać ani obsługiwać przerwań timera. Jeśli raz włączysz wyzwalanie ADC, będzie ono włączone (raczej - co prawda STM32F1 są strasznie skopane, ale chyba nie aż tak).

    No ale jak widać nie działa, nawet nie wchodził w przerwanie więc nie wiem już jak to powinno być poustawiane.

    DMA już chyba wysyła dobrze:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Śle mi te dane w nieskończoność i terminal mi się zawiesza więc chciałem przerwać powiedzmy po 10 transmisjach. Utworzyłem sobie zmienną uint16_t licznik = 0;
    i po każdym wejściu do obsługi przerwania ją zwiększam o jeden. Na końcu obsługi przerwania jeśli jest większa od 10 to wyłączam Timer. Ale to mi nie działa bo dostaje coś takiego:
    Code:
    00 00 00 00 00 00 00 00 46 05 6E 07 BC 07 C9 07 08 08 AF 07 03 08 AF 07


    3 x 8 bajtów. Zwiększanie warunku nic nie daje. Dlaczego?

    Kod obsługi przerwania:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Kolejne moje pytanie to czemu takie dziwne wartości? Nawet jak podłącze wejścia do masy to przecież powinienem otrzymywać same 0 a tak nie jest. Ale nigdzie nie konfigurowałem napięcia referencyjnego. Skąd ARM je bierze?

    Dodano po 1 [godziny] 45 [minuty]:

    Panowie, kombinuje i już nie mam siły. Proszę o jakąś wskazówkę bo nie mam pojęcia czemu tak jest. Uruchomiłem przerwanie Timera od Uploada Timera ale to też nic nie daje. Bez przerwania tak jak mówi BlueDraco program w ogóle nie wchodzi w przerwanie zakończenia transmisji z ADC.

    Niżej kod:
    Program główny:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Funkcja konfiguracyjna Board:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I funkcja obsługi przerwania Timera:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Funkcja obsługi przerwania z DMA
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Proszę o wszelkie sugestie.
  • #116
    BlueDraco
    Specjalista - Mikrokontrolery
    Co to niby ma być?
    USART1->BRR = (24+(0.9216/2))/0.9216;

    Policz to po ludzku:
    FCLK w Hz, szybkość transmisji w b/s

    Popatrz, jak zaprogramowałeś DMA - po 8 transferów, miały być 4 po 16 bitów z ADC do pamięci i 8 po 8 bitów z pamięci do USART.

    Dobry zwyczaj: nie ustawiaj bitów, których nie potrzebujesz ustawiać - w tym przypadku np.priorytetów DMA. Kod będzie krótszy i czytelniejszy, a jak widać cały czas wpadasz na czytaniu kodu - tracisz kontrolę nad tym, co napisałeś.

    Założę się na ślepo (a STM32F1 nie znam), że to nie jest potrzebne:
    ADC1->CR2 |= ADC_CR2_EXTTRIG;

    Czy uruchomiłeś wcześniej USART na DMA bez ADC - np. wysyłanie ciągu znaków z pamięci?

    Spróbuj zaprogramować timer na dużo dłuższy okres, np. 1 sekundę - będzie łatwiej zobaczyć na terminalu, o co chodzi.

    Czy ADC po kalibracji nie wymaga włączenia do konwersji? - bit ADEN czy coś takiego.

    W konfiguracji timera nie masz włączania wyzwalania ADC.
    Gdzie w konfiguracji ADC włączyłeś wyzwalanie od timera?
  • #117
    wojlej
    Poziom 17  
    Cytat:
    Co to niby ma być?
    USART1->BRR = (24+(0.9216/2))/0.9216;


    Zmieniłem na:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Ale to i tak nic nie zmienia. W trybie debugowania jak włączę podgląd parametrów USART to pokazuje BAUD = 923076 czyli jest odchyłka, ale BD mam w terminalu na 923076.

    Cytat:
    Popatrz, jak zaprogramowałeś DMA - po 8 transferów, miały być 4 po 16 bitów z ADC do pamięci i 8 po 8 bitów z pamięci do USART.

    Poprawione, usunąłem również priorytety:
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Cytat:
    Założę się na ślepo (a STM32F1 nie znam), że to nie jest potrzebne:
    ADC1->CR2 |= ADC_CR2_EXTTRIG;


    No więc sprawa wygląda tak. We wstępnej konfiguracji w Board_config(); nie jest potrzebne załadowanie bitu ADC_CR2_SWSTART. Natomiast jeśli nie ustawie bitu ADC_CR2_EXTTRIG w konfiguracji Board i w przerwaniu od Timera to program nie wchodzi w przerwanie zakończenia transferu z DMA.
    Manual piszę, że:
    Code:
    EXTTRIG: External trigger conversion mode for regular channels
    
    This bit is set and cleared by software to enable/disable the external trigger used to start conversion of a regular channel group.
    0: Conversion on external event disabled
    1: Conversion on external event enabled


    Czyli wydaje się, że ten bit powinien być ustawiony tylko raz ale jeżeli nie jest on ustawiony w przerwaniu od Timera to nie działa. Zauważyłem, że on działa tylko raz, Kiedy program przechodzi przez Board_Config(); przez instrukcję EXTTRIG to ustaia bit EXTTRIG, ale jak występuje przerwanie z Timera, i kolejny raz przechodzi przez EXTTRIG to ustawia flagę STRT w rejestrze SR (Start konwersji). Potem ta flaga się nie zeruje, ale ustawia się tylko w tym momencie.


    Cytat:
    Czy uruchomiłeś wcześniej USART na DMA bez ADC - np. wysyłanie ciągu znaków z pamięci?


    Tak, kilka stron wcześniej :D.

    Cytat:
    Spróbuj zaprogramować timer na dużo dłuższy okres, np. 1 sekundę - będzie łatwiej zobaczyć na terminalu, o co chodzi.


    Dziwna sprawa, zaprogramowałem Timer w ten sposób:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Teoretycznie powinien zliczać co 1s, więc co 1s wykonuje przerwanie. Ale dane przychodzą mi do terminala co około 4s. Nie mam pojęcia czemu.

    Cytat:
    Czy ADC po kalibracji nie wymaga włączenia do konwersji? - bit ADEN czy coś takiego.


    Manual nic nie wspomina o tym. Występuje tylko bit ADON -> ADC ON/OFF i SWSTART - Start konwersji ale tylko wtedy jeśli:
    Code:
    It starts a conversion of a group of regular channels if SWSTART is selected as trigger event by the EXTSEL[2:0] bits.


    Cytat:
    Gdzie w konfiguracji ADC włączyłeś wyzwalanie od timera?


    Ustawienie bitów EXTSEL w 000:
    Code:
    EXTSEL[2:0]: External event select for regular group
    
    These bits select the external event used to trigger the start of conversion of a regular group:
    000: Timer 1 CC1 event



    Cytat:
    W konfiguracji timera nie masz włączania wyzwalania ADC.

    No nie mam, ale w jego przerwaniu mam włączenie triggera. Inaczej nie wiem jak to ustawić, nie mogę znaleźć żadnego rejestru Timera do wyzwalania zewnętrznych układów

    Dodano po 3 [godziny] 47 [minuty]:

    Bawię się z tym i bawię...

    Zrobiłem tak:
    Aby sprawdzić kod zrobiłem tak:
    1 - Zmieniam stan diody LED1 w każdym wejściu do obsługi przerwania Timera
    2 - Zmieniam stan diody LED2 w każdym wejściu do obsługi przerwania zakończenia transferu z ADC

    Dioda numer 1 miga co 1s, co oznacza, że Timer jest skonfigurowany poprawnie, ale dioda numer 2 zmienia swój stan co 4 przerwania od Timera. Czy to wynika z tego, że skanuje 4 kanały? Jeżeli tak to prawie jestem w domu. Bo nie mogę się doczytać czy Timer wyzwala pomiar z jednego kanału czy ze wszystkich skanowanych?
  • #118
    BlueDraco
    Specjalista - Mikrokontrolery
    Timer wyzwala taki pomiar, jaki zaprogramowałeś w ADC. Jeśli zaprogramowałeś kolejny pomiar czterech kanałów bez discontinuous mode, to ADC zmierzy 4 kanały. Problem ze sprzętowym startowaniem polega na tym, że wybrałeś zdarzenie CC1, a nie reload/update. Sprawdź, czy da się wyzwalać ADC innym zdarzeniem timera, a jeśli się nie da - zaprogramuj blok Capture1 timera na dowolną wartość, np. na połowę okresu. Wtedy będziesz mógł wyłączyć przerwanie timera i wyzwalać ADC sprzętowo.
  • #119
    wojlej
    Poziom 17  
    Cytat:
    Timer wyzwala taki pomiar, jaki zaprogramowałeś w ADC. Jeśli zaprogramowałeś kolejny pomiar czterech kanałów bez discontinuous mode, to ADC zmierzy 4 kanały.


    Właśnie nie mogę zrozumieć różnic pomiędzy trybami discontinous i scan. Rozumiem, że SCAN skanuje dowolną ilość kanałów, dodatkowo można skanować z innym czasem próbkowania, ale czym się różni discontinous? Przecież on też skanuje dowolną liczbę kanałów. Nie mogę tu zrozumieć tego manuala więc prosiłbym o wytłumaczenie.

    Zmieniłem konfiguracje przetwornika na coś takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dziwnie są opisane te rejestry SQR w manualu więc nie mam pojęcia czy jest to poprawnie zaprogramowane. Rozumiem je tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Długość sekwencji kanałów regularnych? Jakiej sekwencji? Ustawiłem wartość na 3 czyli 4 konwersje. Chodzi o 4 kanały?

    Cytat:
    ADC1->SQR3 = (ADC_SQR3_SQ1_0 | ADC_SQR3_SQ2_1 | ADC_SQR3_SQ3_0 | ADC_SQR3_SQ3_1 | ADC_SQR3_SQ4_2);

    Kolejność skanowania? Ustawiłem tak:
    Pierwszy kanał numer 1;
    Drugi kanał numer 2;
    Trzeci kanał nr 3;
    Czwarty kanał numer 4;

    Poprawnie myślę?
    Przy takiej konfiguracji Przerwanie zakończenia transferu jest wywoływane nie co 4 przepełnienia Timera tylko za każdym razem. Czyli teoretycznie poprawnie. Tylko, że nadal dostaje randomowe wartości w terminalu. O ile pierwsze dane które przychodzą to zera, bo jest wysyłany pusty bufor2 to kolejne mają już losowe wartości.

    Cytat:
    Problem ze sprzętowym startowaniem polega na tym, że wybrałeś zdarzenie CC1, a nie reload/update. Sprawdź, czy da się wyzwalać ADC innym zdarzeniem timera


    Zmieniłem na zdarzenie Update. Ale nic to nie zmienia, cały czas potrzebna jest obsługa przerwania od Timera.

    Cytat:
    zaprogramuj blok Capture1 timera na dowolną wartość, np. na połowę okresu. Wtedy będziesz mógł wyłączyć przerwanie timera i wyzwalać ADC sprzętowo.


    Spróbuje choć średnio rozumiem o co Ci chodzi, więc jak byś mógł wytłumaczyć jaśniej to będę wdzięczny.

    Chciałem podziękować za wszelakie wskazówki bo widzę, że Freddie chyba się poddał ze względu na mój "opór" ;), ale podziękowania i dla niego.
  • #120
    m.ki
    Poziom 15  
    wojlej napisał:
    Właśnie nie mogę zrozumieć różnic pomiędzy trybami discontinous i scan.

    SCAN robi pomiar wszystkich kanałów podanych w SQRx. Liczba pomiarów jest określona przez ADC_SQR1_L - ja to zazwyczaj zapisuję tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    a nie bawię się w symbole.
    DISCONTINUOUS robi pomiar podzbioru kanałów określonych dla SCAN - liczba dla tego trybu jest określona w ADC_CR1_DISCNUM. Jeśli tam wpiszesz 2, to za pierwszym wyzwoleniem zmierzy pierwszy i drugi kanał określony w SQRx, za drugim trzeci i czwarty, za trzecim z powrotem pierwszy i drugi itd.

    Pozdrowienia,
    m.ki