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

STM32 - Konfiguracja modułu Bluetooth dla wysokiej częstotliwości próbkowania

25 Paź 2012 23:49 3564 24
  • Poziom 8  
    Witam,
    mam problem z poprawną konfiguracją modułu Bluetooth. Chodzi o to, że na przetwornik ADC wyzwalany timer1 podaje sygnał z GPIOB i chcę próbkować go wg ustawień timera z częstotliwością co najmniej 500Hz. Dane pobierane są z rejestru ADC przez DMA do zadeklarowanego wcześniej buforADC (unsigned short int buforADC[1]={0};).
    Teraz wg instrukcji z książki, żeby z największą prędkością przesyłać przez Bluetooth'a (19200) do buforTx (unsigned char buforTx[4]={0};) funkcją sprintf przepisuje dane z buforaADC (odpowiednio przeliczone) i wysyłam.
    Niestety na terminal przychodzi znacznie mniej danych niż mogę oczekiwać (gdzieś dla częstotliwości 100Hz jeszcze wynik był satysfakcjonujący).
    Nie bardzo wiem teraz gdzie tkwi problem, czy w przetworniku czy bluetooth jakoś nie nadąża i jak to zmienić.
    Myślałam żeby jakoś zmienić ilość danych np.
    ponieważ przetwornik jest 12bitowy na zapisanie całej liczby potrzeba w zaokrągleniu 2 bajtów i 2 bajty na znaki \r\n (stąd u mnie buforTx ma 4 elementy).
    Nie wiem tylko jak zrobić, by na terminalu wyświetlały się liczby, to znaczy żeby jednak buforTx był zestawem znaków (cyfr) odczytanych wartości sygnału.

    Mam nadzieję, że w miarę wyjaśniłam istotę mojego problemu. Dołączam jeszcze fragmenty kodu i proszę o wsparcie.

    Pozdrawiam

    USART:
    void USART_Config(void)
    {
    //konfigurowanie ukladu USART
    USART_InitTypeDef USART_InitStructure;

    USART_InitStructure.USART_BaudRate = 19200; //Predkosc transmisji w bps
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Dlugosc dlowa danych
    USART_InitStructure.USART_StopBits = USART_StopBits_1; //Bity stopu (1 bit)
    USART_InitStructure.USART_Parity = USART_Parity_No; //Bit parzystosci (wylaczony)
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Sprzetowa kontrola przeplywu wylaczona
    USART_InitStructure.USART_Mode = USART_Mode_Tx; //Tryb pracy (nadawnie)

    USART_Init(USART1, &USART_InitStructure);

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART1, ENABLE);
    }

    void ADC_Config(void)
    {
    //konfigurowanie przetwornika AC
    ADC_InitTypeDef ADC_InitStructure;

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //Jeden przetwornik, praca niezalezna
    ADC_InitStructure.ADC_ScanConvMode = DISABLE; //Pomiar dwoch kanalow, konieczne skanowanie kanalow
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //Pomiar w trybie ciaglym: wylaczone
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //Wyzwalanie zewnetrzne
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //Wyrownanie danych do prawej - 12 mlodszych bitow znaczacych
    ADC_InitStructure.ADC_NbrOfChannel = 1; //Liczba uzywanych kanalow =1
    ADC_Init(ADC1, &ADC_InitStructure); //Incjalizacja przetwornika

    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_1Cycles5);

    ADC_DMACmd(ADC1,ENABLE); //Wlaczenie DMA dla ADC1
    ADC_Cmd(ADC1, ENABLE); //Wlacz ADC1

    ADC_ResetCalibration(ADC1); //Reset rejestrow kalibracyjnych ADC1
    while(ADC_GetResetCalibrationStatus(ADC1)); //Odczekanie na wykonanie resetu
    ADC_StartCalibration(ADC1); //Kalibracja ADC1
    while(ADC_GetCalibrationStatus(ADC1)); //Odczekanie na zakonczenie kalibracji ADC1
    }

    void DMA_Config(void)
    {
    //konfigurowanie DMA

    #define ADC1_DR_Address 0x4001244C; //adres rejestru ADC1->DR

    DMA_InitTypeDef DMA_InitStructure;


    DMA_DeInit(DMA1_Channel1); //Usun ewentualna poprzednia konfiguracje DMA

    DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned long int)ADC1_DR_Address; //Adres docelowy transferu
    DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long int)&buforADC; //Adres poczatku bloku do przeslania
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //Kierunek transferu
    DMA_InitStructure.DMA_BufferSize = 1; //Liczba elementow do przeslania (dlugosc bufora)
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Wylaczenie automatycznego zwiekszania adresu po stronie ADC
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Wlaczenie automatycznego zwiekszania adresu po stronie pamieci (bufora)
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //Rozmiar pojedynczych przesylanych danych po stronie ADC (HalfWord = 16bit)
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //Rozmiar pojedynczych przesylanych danych po stronie pamieci (bufora)
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //Tryb dzialania kontrolera DMA - powtarzanie cykliczne
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //Priorytet DMA - wysoki
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Wylaczenie obslugi transferu z pamieci do pamieci
    DMA_Init(DMA1_Channel1, &DMA_InitStructure); //Zapis konfiguracji

    //Wlacz DMA, kanal 1
    DMA_Cmd(DMA1_Channel1, ENABLE);

    }

    void TIM_Config(void) {

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    //Konfiguracja licznika 1
    //Ustawienia taktowania i trybu pracy licznika 1
    TIM_TimeBaseStructure.TIM_Prescaler = 5600-1; //taktowanie licznka FCLK = 56MHz/5600 = 10kHz
    TIM_TimeBaseStructure.TIM_Period = 100; //okres przepelnienia licznika = 20000 taktow = 0,5Hz
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //dzielnik zegara dla ukladu generacji dead-time i filtra
    TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //licznik powtorzen
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //tryb pracy licznika
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //inicjalizacja licznika

    //Konfiguracja kanalu 1
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; //tryb pracy kanalu
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //wlaczenie generowania sygnalu na wyjsciu licznika
    TIM_OCInitStructure.TIM_Pulse =100; //40 taktow = 250Hz
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //polaryzacja wyjscia
    TIM_OC1Init(TIM1, &TIM_OCInitStructure); //Inicjalizacja kanalu 1 licznika TIM1

    //zapis ustawien
    //Wylaczenie rejestru preload - ewentualne zmiany konfiguracji uwzgledniane sa
    //od razu. Gdy preload jest wlaczony - zmiany wchodza w zycie dopiero przy
    //nastepnym update
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);


    //Wlaczenie przerwan od licznikow
    //wlaczenie przerwania od przepelnienia / aktualizacji wartości Period TIM1
    TIM_ITConfig(TIM1, TIM_IT_CC1 , ENABLE);

    //Wlaczenie timerow
    TIM_Cmd(TIM1, ENABLE);
    }

    Przerwanie od USART:

    extern unsigned char buforTx[];
    extern unsigned char bufTxIndex;

    void USART1_IRQHandler(void)
    {
    volatile unsigned long int i;

    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
    USART_SendData(USART1, buforTx[bufTxIndex++]);
    //for (i=0; i<5000; i++); //Odczekanie 10ms pomiedzy kolejnymi znakami komendy

    if ((buforTx[bufTxIndex-2] == '\r')&&(buforTx[bufTxIndex-1] == '\n')) //Jesli wysylany zostal ostatni znak (CR)
    {
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //Wylacz przerwanie = koniec transmisji
    GPIO_SetBits(GPIOB, GPIO_Pin_1);
    bufTxIndex = 0;
    }
    }
    }
  • Poziom 12  
    Witaj Kasiu.
    Miałaś tyle różnych przerwań USARTA do wydoru, a wybrałaś przerwanie USART_IT_RXNE, które informuje o tym, że rejestr odbiornika nie jest pusty. Nie do końca rozumiem dlaczego. Tak sobie myślę, że jak wysyłasz znaki USART-em, to lepiej byłoby wiedzieć, że znak został wysłany i można wysyłać kolejny. To chyba przerwanie USART_IT_TXE. Do "tłumaczenia" liczby na ciąg znaków najlepiej nadaje się sprintf, bo pozwala od razu określić format liczby. Wystarczy napisać np. sprintf(buforTx, "%3.6f", Twoja_przeliczona_wartosc_ADC) i od razu w buforze będziesz miała dobry ciąg. Jeżeli chcesz dołożyć jeszcze "coś" czyli \r \n to możesz użyć funkcji strncpy(buforTx, "\r", 2). Tylko Twój buforTx musiałby mieć więcej niż 4 znaki :)
  • Poziom 8  
    Witaj,
    dzięki za szybką odpowiedź. Pojawiła się jednak pewna rozbieżność ponieważ, ja właśnie używam przerwania USART_IT_TXE, o którym wspominałeś. Ponadto też używam funkcji sprintf, ale wiem, że podobno ona jest bardzo pamięcio żerna, w związku z tym zastanawiałam się, czy to może ona wpływa na zmniejszenie szybkości wysyłania przez bluetooth'a.
    Myślałam bardziej o funkcjach, które pozwoliłyby mi zapisać dane z buforADC w postaci tylko dwóch bajtów czy przepisać jakoś dane odczytując kolejne bity i ewentualnie na koniec dopisać do tego znaki \r\n.
    Chodzi o to, żeby ustalić czy osiągnięcie wysyłania z częstotliwością 500Hz lub większą jest w ogóle możliwe.
  • Poziom 12  
    Witaj
    Żeby nie było, że się czepiam to w konfiguracji USARTA masz wpisane USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    Najlepsza droga do sprawdzenia, czy to działa to eksperyment :) Wpisałem Twój programik do STM32F103. Nie skorzystałem z przerwań, bo do eksperymentu to niepotrzebne. Miałem zwykłą pętlę while (1), a sprawdzanie USARTA do wysłania kolejnego znku miałem ustawione tak
    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
    {}
    i wysyłałem kolejny znak.
    W ciągu minuty z ustawioną przez Ciebie prędkością 19200 bodów USART wysłał do PC w ciągu minuty 8820 "buforów" 8 bajtowych (4 bajty miał licznik przetłumaczony funkcją sprintf z formatem "%4d" potem dołożyłem 4 bajty funkcją strncpy "\r\n").
    Daje to mniej więcej 70560 znaków na minutę, czyli 1176 znaków/sek. Ale licząc wysłane "bufory" 8 bajtowe tylko 147 buf/s.
    I więcej nie będzie raczej ;/ a przypuszczam, że ograniczenie 19200 bodów narzuca moduł Bluetooth. Sytuacja zmienia się radykalnie przy prędkości 115200 bodów. Wtedy zdązyłabyś wysłąć USARTEM te 500 pomiarów na sekundę. Uważam, że ograniczeniem nie jest ani przetwornik, ani timer. Po prostu USART przy takiej szybkości nie wyrabia więcej. Nawet teoretycznie licząc wychodzi podobnie, bez żadnych eksperymentów. Funkcja USART_SendData(USART_TypeDef* USARTx, uint16_t Data) wysyła 16 bitowe dane. Wysyłając znak z bufora wysyłasz więc 16 bitów. Licząc to co otrzymałem od tyłu dostaniesz 1176 znaków/s * 16 bitów = 18816.
  • Specjalista - Mikrokontrolery
    Mechanik PSC napisał:
    potem dołożyłem 4 bajty funkcją strncpy "\r\n")

    Jesteś pewny?

    Mechanik PSC napisał:
    Funkcja USART_SendData(USART_TypeDef* USARTx, uint16_t Data) wysyła 16 bitowe dane. Wysyłając znak z bufora wysyłasz więc 16 bitów.

    Na pewno nie. To że przyjmuje parametr o wielkości 16 bitów o niczym nie świadczy. Sprawdź dobrze.

    4\/3!!
  • Poziom 38  
    Mechanik PSC napisał:
    1176 znaków/sek (...) I więcej nie będzie raczej ;/ a przypuszczam, że ograniczenie 19200 bodów narzuca moduł Bluetooth. Sytuacja zmienia się radykalnie przy prędkości 115200 bodów. Wtedy zdązyłabyś wysłąć USARTEM te 500 pomiarów na sekundę. Uważam, że ograniczeniem nie jest ani przetwornik, ani timer. Po prostu USART przy takiej szybkości nie wyrabia więcej. Nawet teoretycznie licząc wychodzi podobnie, bez żadnych eksperymentów. Funkcja USART_SendData(USART_TypeDef* USARTx, uint16_t Data) wysyła 16 bitowe dane. Wysyłając znak z bufora wysyłasz więc 16 bitów. Licząc to co otrzymałem od tyłu dostaniesz 1176 znaków/s * 16 bitów = 18816.


    Zamiast robić cudowne "eksperymenty" to kolega może weźmie kartkę i długopis i najpierw sobie policzy ile bajtów może wysłać przy baud = 19200.

    Poza tym moduł BT jest konfigurowalny i spokojnie można mu ten baud zwiększyć. Pozatym sprintf jest trochę wolny i ograniczony, w Keilu pewnie działa, ale w gcc nie do końca. Większy sens ma wysyłanie wartości ADC w postaci surowej niż przerabianie tego na stringa.

    Mechanik PSC napisał:
    Funkcja USART_SendData(USART_TypeDef* USARTx, uint16_t Data) wysyła 16 bitowe dane. Wysyłając znak z bufora wysyłasz więc 16 bitów.


    Z każdym dniem co raz bardziej uwielbiam te biblioteki :D

    kasia.p napisał:

    Niestety na terminal przychodzi znacznie mniej danych niż mogę oczekiwać


    Być może terminal nie nadąża z wyświetlaniem ?
  • Poziom 12  
    Szanowni Panowie.
    We wszystkim oczywiście macie rację. Chciałoby się nawet powiedzieć jedyną rację, właściwą rację i świętą rację, po czym dodać "nieszczęścia chodzą parami", bo na tym cudownym forum trudno znaleść post Pana Freddiego nie poparty natychmiast postem Pana gaskoina. Ja się nie wstydzę przyznać, że się nie znam na mikrokontrolerach, ale zauważcie że ani post Pana Freddiego, ani Pana gaskoina nie odpowiedział na pytanie zadane w temacie. Panie Freddie. Rejestr USART_TDR przyjmuje 9 bitów danych więc pewnie dlatego funkcja send jako parametr ma daną 16 bitową a nie 8. Funkcja strncat rzeczywiście nie dokłada z ciągu "\r\n" 4 bajtów, a jedynie 2, o czym się dowiedziałem dopiero debugując program. Dalej, nie wiem na czym polega ograniczenie funkcji sprintf, bo u mnie działa dobrze. Co do wypowiedzi Pana gaskoina, że terminal PC lub grafika nie nadąża wyświetlać odebranych znaków nie będę się wypowiadał, podobnie jak do tematu stosowania lub nie standardowych bibliotek. Powiem tylko, że kilkaset tysięcy ludzi pisze programy w Delphi, które nie dość, że są obciążone ogromnym balastem bibliotek, to są wolniejsze od programów napisanych w C. Dlaczego to robią i dlaczego na forach piszących o "C" nie tępią ludzi używających Delphi? przecież Delphi produkuje 10-krotnie większy kod wynikowy, na dodatek wolniejszy. Z bibliotekami standardowymi jest podobnie, ale wytykanie komuś że je stosuje jest po prostu nie na miejscu. Panie gaskoin proponuję zacząć pisać programy na PC w kodzie maszynowym a na forum nie bić piany, tylko napisać wprost "ile znaków da się wysłać na terminal w ciągu sekundy przy prędkości transmisji 19200 bodów". I byłoby po temacie.
    Pozdrowienia i szacun dla obydwu Panów :)
  • Specjalista - Mikrokontrolery
    Mechanik PSC napisał:
    "nieszczęścia chodzą parami", bo na tym cudownym forum trudno znaleść post Pana Freddiego nie poparty natychmiast postem Pana gaskoina. Ja się nie wstydzę przyznać, że się nie znam na mikrokontrolerach, ale zauważcie że ani post Pana Freddiego, ani Pana gaskoina nie odpowiedział na pytanie zadane w temacie.

    Jeśli uważasz, że mój post na to zasługuje, zawsze możesz go zgłosić moderatorom.

    Mechanik PSC napisał:
    Panie Freddie

    Darujmy sobie te oficjalne formy - nawet w złośliwościach.

    Mechanik PSC napisał:
    Rejestr USART_TDR przyjmuje 9 bitów danych więc pewnie dlatego funkcja send jako parametr ma daną 16 bitową a nie 8

    Czy ja gdzieś napisałem inaczej? Czy może nie powinienem sprostować Twojej informacji, jakoby ta funkcja wysyłała 2 bajty na raz? No chyba że dalej przy tym się upierasz...

    Mechanik PSC napisał:
    Dalej, nie wiem na czym polega ograniczenie funkcji sprintf, bo u mnie działa dobrze

    Na niczym, poza tym że zajmuje bardzo dużo pamięci. Jeśli używasz toolchaina z biblioteką newlib, to zawsze lepszym pomysłem jest korzystać z funkcji typu iprintf(), siprintf(), fiprintf() itd. - literka "i" oznacza że nie obsługują one zmiennego przecinka, wymagania pamięciowe są drastycznie mniejsze.

    Mechanik PSC napisał:
    Co do wypowiedzi Pana gaskoina, że terminal PC lub grafika nie nadąża wyświetlać odebranych znaków nie będę się wypowiadał

    Ponownie pokazując jak bardzo się znasz na sprawie - jest to znany problem Windowsa, że jak zarzucisz UART długim CIĄGIEM danych, to w pewnym momencie zaczyna się przytykać. Nie wiem czy efekt nastąpi przy niskiej prędkości typu 19200, ale przy 115200 nie trzeba wcale zbyt dużo danych, żeby zaczęła się czkawka. Tylko niektóre terminale potrafią obejść ten problem, niestety jeden z najpopularniejszych - br@y terminal - tego nie potrafi.

    Mechanik PSC napisał:
    Powiem tylko, że kilkaset tysięcy ludzi pisze programy w Delphi, które nie dość, że są obciążone ogromnym balastem bibliotek, to są wolniejsze od programów napisanych w C

    Jest takie przysłowie o muchach i jedzeniu...

    Mechanik PSC napisał:
    Z bibliotekami standardowymi jest podobnie, ale wytykanie komuś że je stosuje jest po prostu nie na miejscu. Panie gaskoin proponuję zacząć pisać programy na PC w kodzie maszynowym a na forum nie bić piany

    Nikt nie ma tutaj nic do bibliotek OGÓLNIE, tylko do tego pseudo-kodu stworzonego przez ST. Widzisz różnicę?

    4\/3!!
  • Poziom 15  
    Mechanik PSC napisał:
    Powiem tylko, że kilkaset tysięcy ludzi pisze programy w Delphi, które nie dość, że są obciążone ogromnym balastem bibliotek, to są wolniejsze od programów napisanych w C. Dlaczego to robią i dlaczego na forach piszących o "C" nie tępią ludzi używających Delphi? przecież Delphi produkuje 10-krotnie większy kod wynikowy, na dodatek wolniejszy.

    To kompletny off-topic, ale czy mógłbyś podać źródło tej rewelacyjnej tezy? Najlepiej jakiś program w Delphi i C, robiący to samo na podstawie tego samego algorytmu - żeby ten Delphiowy był 10 razy większy i na dodatek wolniejszy.

    Pozdrowienia,
    m.ki
  • Poziom 19  
    " jest to znany problem Windowsa, że jak zarzucisz UART długim CIĄGIEM danych, to w pewnym momencie zaczyna się przytykać. "
    Nie to, żebym się czepiał ale gdzie mogę o tym przeczytać?
  • Specjalista - Mikrokontrolery
    Proponuję wypraktykować (;

    Może inaczej - "jest to znany problem 99% terminali pod Windowsa", nie wnikałem czy jest to wina Windowsa, terminali, jakiejś systemowej biblioteki czy może sterowników ale fakt jest jaki jest - na różnych komputerach, na różnych programach, na różnych wersjach Windowsa, na różnych typach portu (prawdziwy/wirtualny USB) zjawisko występowało i występuje - przy szybkiej, DŁUGIEJ i ciągłej transmisji - rzędu kilkanaście kB danych - w pewnym momencie transmisja zaczyna się "rwać", tzn na chwilę się zatrzymuje, a potem idzie dalej, tyle że po drodze gubiąc całkiem sporą porcję danych. Gdy bardzo mi to przeszkadzało, to udało mi się odnaleźć program który nie miał tego problemu, nie pamiętam już nazwy, ale coś o zaawansowanym monitorowaniu portów. Program tylko pisał do pliku, bez wyświetlania danych na ekranie, ale nie gubił niczego. Wg informacji na jego stronce program ten miał jakieś swoje metody tak aby obsługiwać sprzęt bardziej bezpośrednio - nie poprzez Windowsowe sterowniki.

    Napisz sobie programik na mikrokontroler, który np wysyła kolejne liczby i oddziela je spacją:
    1 2 3 4 5 6 7 8 9 10 11 12 ...
    i napisz go tak, żeby dane szły maksymalnie szybko i bez przerw. Zobaczysz sam, że w końcu ciągłość się "zgubi" i dane "przeskoczą" o kilkaset pozycji.

    4\/3!!
  • Poziom 19  
    "Program tylko pisał do pliku, bez wyświetlania danych na ekranie, ale nie gubił niczego."
    Myślę, że to jest wyjaśnienie. Windows może ustawić bufor portu na dużą wartość i po zebraniu danych zapisywać je w tablicy a dopiero stamtąd do pliku. Sam używam prędkości 57600 i działa bez zastrzeżeń. Co do postu Kasi to prędkość 19200 jest jak na możliwości BlueTooth i komputera jest śmiesznie mała. Może te dane najpierw trzeba obejrzeć na Hyperterminalu? To pomaga.
  • Poziom 38  
    Szanowny Panie Mechaniku. Ja tylko prostuję nieprawidłowości jakie Pan tutaj na forum wypisuje. Jednym z punktów regulaminu tego forum jest niewprowadzanie w błąd co Pan właśnie robi. Więc proszę nie zarzucać mi nieodpowiadania na pytania, kiedy samemu się pociska pierdoły.

    UART to 8 (no max 9) bit i żadna cudowna biblioteka tego nie ominie. Z tego co Pan napisał wynika, że dzięki cudownemu 16_t uart posyła 16 bit...

    UART ma stałą prędkość, jeśli ciągle karmimy go danymi to wyśle ni mniej ni więcej tylko 1960 bajtów (19600 / (8 + 1 + 1)), skąd więc ta magiczna liczba, którą Pan podał ? Tu nie chodzi o pisanie na PC w kodzie maszynowym bo jestem od tego daleki, ale Pan wykazuje się brakiem znajomości podstaw :)

    A co do terminala - zanim zacznie się z kogoś kpić, to może warto sprawdzić o co chodzi ? FC już wyjaśnił, ale dodam bardzo uproszczone wyjaśnienie, że strumień odbioru na PC ma domyślnie pewną ustaloną długość. W międzyczasie jak program wyświetla coś na ekranie, bufor się zapełnia i nim obsługa grafiki wróci sobie po dane z bufora, ten mógł zacząć się nadpisywać. Jest to typowa bolączka programów terminalowych (a nie problem windowsa). Nawet baud 9600 jest w stanie zacisnąć niektóre terminale (oczywiście przy ciągłym wysyle danych a nie przy wysłaniu jednego znaku co dwa lata).

    PS.
    Freddie Chopin napisał:
    Jest takie przysłowie o muchach i jedzeniu...


    Masz ciekawe nawyki żywieniowe :)


    Jak pisałem wyżej można baud kontrolować w BT. Trzeba zajrzeć do dokumentacji po komendę AT (bo jej nie pamiętam), którą można skonfigurować baud. 115200 jest możliwy do osiągnięcia, o ile nie więcej. Floata lepiej sobie posłać "na raty", raz część po lewej stronie przecinka, raz tę po prawej. Z resztą już o tym pisałem, ale w końcu nie odpowiadam na pytania :) (przynajmniej wg tych co mają jakieś filtry w oczach)
  • Poziom 35  
    >kasia.p
    Policzmy: dla 115200bd, można przesłać 11520 bajtów na sekunde. Jeśli chcesz popchnąć ramkę z danymi 500 razy na sekundę, to 11520/500=23. Czyli możesz wysłać paczkę danych o wielkości 23 bajty 500 razy na sekundę. Ograniczmy się do łopatologii, zakładając:
    - enkodowanie base16, czyli potrzebujesz 3 bajty do popchnięcia 12 bitowej danej, plus
    - delimiter poczatku i konca
    = 5 bajtow danych, i to w takim formacie, aby było łatwo dekodować i jeszcze łatwiej synchronizować strumień
    ...wnioskujmy, że potrzebna przepustowość dla 5 bajtowej ramki to: 500x5=2500B/s.
    Smutne 2.5kB/s... To jest tzw. nic, i po stronie samego STM32, jak i po stronie komputera.

    Wykorzystuj DMA zamiast bawić się w przerwania...
    Kod: C
    Zaloguj się, aby zobaczyć kod


    No i inity...
    Kod: C
    Zaloguj się, aby zobaczyć kod


    Sam moduł przekonfigurujesz na 115200bd wysylajac do niego ciag znaków: ATL5[cr]
    Więc korzystając z powyższych funkcji:
    Kod: C
    Zaloguj się, aby zobaczyć kod


    Pamietaj, że moduł w trybie slave, dopóki do niego nie połączy się jakiś master (np. komp) będzie wszelkie znaki odebrane interpretował jako komendy.
    Slave po nawiązaniu połączenia (czyli jeśli inny moduł BT będąc masterem wyszuka moduł i połączy się z nim) zacznie mieć 'przezroczystego' UARTa.
  • Poziom 8  
    Witajcie, dziękuję za wszystkie posty. Większość okazała się bardzo pomocna.
    Swoją modyfikację chciałam zacząć od najprostszej zmiany, tj. zmiany konfiguracji modułu bluetooth poprzez komendy AT. Najpierw jednak chciałam przetestować odbiór danych z terminala.
    Znalazłam program i nieco go zmodyfikowałam, którego celem jest odebranie wpisanej danej w terminalu "n" lub "f", która ma odpowiednio włączyć lub wyłączyć diodę LED1. W programie działa reset układu i odebranie komunikatu z przycisku o włączeniu działania programu (patrz kod). Następnie wpisuję "n$0d" - tak jak opisano w temacie na forum (https://www.elektroda.pl/rtvforum/topic2377663.html#11302202), błyśnie czerwona lampka na bluetooth'ie (co sugerowałoby, że odebrał daną), ale niestety dioda się nie zapala. Nie wiem gdzie może tkwić błąd, bo poprzednio wysyłanie (mimo że z mniejszą niż bym chciała prędkością) ale działało. Obawiam się wobec tego jak zareaguje na komendy AT i też czy w ogóle w ten sposób jestem w stanie nad nim panować (tj. zmieniać mu ustawienia).
    Dołączam kod poniżej:
    Kod: C
    Zaloguj się, aby zobaczyć kod


    przerwania:
    Kod: C
    Zaloguj się, aby zobaczyć kod
  • Poziom 35  
    W tym temacie co podałaś to też dużo mądrego napisali... Skoro dalej nie działa, może faktycznie zasugeruj się tym, co napisałem w #14, zaczynając od natychmiastowego olania SPL... Inity 'po ludzku' juz nie raz byly podawane w różnych wątkach, wystarczy poszukać. Albo mogę podesłać... whatever.

    Strasznie chaotycznie piszesz ;] Nie załapałem kto odbiera co i w jakich okolicznościach ;]

    Czy używasz debuggera?
  • Poziom 8  
    Witaj,
    na początku tylko powiem, że jednak cały czas pracuję na bibliotece, bo po prostu jest dla mnie bardziej zrozumiała; nie jestem specem od mikrokontrolerów, ale cały czas się uczę :) jeśli już faktycznie ona całkiem nie będzie działać, to będę próbować "po Twojemu". Wydaje mi się, że program, który ma dla mnie sprawdzić wysyłanie nie powinien być jakoś bardzo trudny, więc dziwię się, że to nie chce zadziałać. Powiem jeszcze raz o co ma chodzić w kodzie dla tego testującego wysyłanie programu:
    1. po wykonaniu funkcji konfiguracyjnych wyłącza diody
    2. robię reset bluetooth'a na linii nRes
    3. włączam diodkę 2
    4. czekam na przycisk
    5. wyłączam diodkę 2
    i teraz czekam na przerwanie

    void USART1_IRQHandler(void)
    {

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
    buforRx[bufRxIndex++] = USART_ReceiveData(USART1);

    if(buforRx[bufRxIndex-1] == 0x0D)
    {
    odebranoDane = TRUE;
    bufRxIndex = 0;
    }
    }
    }
    które ma zgłaszać, że wpisałam coś ("n" lub "f") na terminalu.
    I jak odbierze tę daną, ma zmienić odebranoDane na TRUE,po czym wraca do maina, gdzie jeśli to "n" to włącza diodkę 1, a jeśli "f" to ją wyłącza.
    Korzystam z zestawu uruchomieniowego ZL31ARM firmy Kamami i do niego przyłączona jest płytka z bluetoothem, a przy kompie mam adaptor który mi zapewnia kontakt na drodze terminal na lapku ->mikrokontroler z bluetoothem

    Mam nadzieję, że teraz jest jaśniej ;)
  • Poziom 35  
    Mam rozumieć ze pomiedzy krokami 2 a 3 wysyłasz konfigurację do BTka zeby zmienił predkosc na 115200, a nastepnie przekonfigurowujesz UART na 115200?...;]

    Czy zupełnie nigdzie nie zmieniasz prędkości BTka?... Jesli nie zmieniasz nigdzie tych predkosci, to na test każ w przerwaniu RXNE xorować diodke, sprawdz czy co znak wyslany z kompa zmienia ona swoj stan.
    Jesli tak, to wtedy spróbuj:

    0. [inicjalizuj UART na 19200]
    1. nRES=0
    2. delay 500ms
    3. nRES=1
    4. delay 500ms
    5. wyslij polecenie ATL5[cr]
    6. delay 50ms
    7. zmien predkosc uarta na 115200
    8. zapal diodke
    9. czekaj na przycisk
    10. zgas diodke
    11. [itd]

    i wtedy sprawdz czy co znak wyslany z kompa nadal xoruje się diodka z przerwania RXNE...

    Dodatkowo, czekanie na przycisk. Nie ma debounce'a, wiec to może bardzo różnie chodzić... Jeśli już preferujesz kod niskiej jakości rodem stąd (nie bierz tego do siebie ;) ), to debounce blokujący można zrobić tak:
    Kod: C
    Zaloguj się, aby zobaczyć kod


    Druga sprawa, to bufor RX. Patent rozpoznawnia delimitera (tutaj 0xD) w przerwaniu jest średni. Bardzo średni...
    To powinno być rozpoznawane interpretowane w pętli głównej, a nie w przerwaniu. Pomysl co sie stanie jesli po 0xD odbierzesz jeszcze jeden znak - pieknie nadpisuje sie index 0 bufora tym znakiem, a poprzednia wartość poszła 'do tam'. To wygeneruje Ci błędy parsowanej z bufora treści, a co gorsza, nie rozpoznasz ich nawet, bo nie wysyłasz żadnej sumy kontrolnej...
    Pomysl nad uzyciem bufora kołowego (aka kolejka, aka FIFO), a dane interpretować tylko w pętli głównej...
  • Poziom 8  
    Witajcie,
    udało mi się zrobić prosty program, gdzie wpisując w terminalu 1 włączam diodę LED1, 3 - wyłączam ją, 2 - włączam diodę LED2 i 4 wyłączam ją. Zatem wydaje się, że moduł Bluetooth odbiera znaki, które wpisuję mu z terminala. Jednak kiedy wpisuję ATL5 (mignięcie czerwonej diodki sugeruje odebranie danych) oraz kiedy w konfiguracji USARTa zmieniam prędkość oraz zmieniam ją na terminalu mój główny program nie zwiększa częstotliwości wysyłania danych (sprawdzałam dla 100Hz) i ponadto nie reaguje też na zwykłą częstotliwość 1Hz. W związku z tym myślę, że moduł Bluetooth nie odebrał mojego ATL5 jako komendy tylko jako zwykły ciąg znaków.
    Zatem moje główne pytanie w tej chwili brzmi jak skonfigurować moduł Bluetooth używając terminala, aby zwiększyć jego prędkość? Oraz czy mogę to zrobić bez użycia dodatkowych kabli typu FTDI to znaczy zrobić to bezprzewodowo, mając podłączony do lapka adapter bluetooth odbierający z anteny mojego Modułu Bluetooth.
    Dołączam kody:
    Prosty program włączający/wyłączający diody (tylko poglądowo)
    Kod: C
    Zaloguj się, aby zobaczyć kod

    Teraz w moim głównym programie, o którym mówiłam na samym początku:
    Kod: C
    Zaloguj się, aby zobaczyć kod


    Przypomnę, że korzystam z modułu bluetooth BTM222.
  • Poziom 35  
    Wysyłasz znak [cr] na końcu tego ATL5? Poza tym, rozkaz musisz wysłać do modułu zanim jeszcze podłączysz się do niego z lapka...
    - jeśli moduł nie będzie połączony z innym BT-kiem (np. z lapka), to wszystko co do niego wyślesz, będzie chciał interpretować jako rozkazy
    - jeśli moduł będzie połączony z innym B-Tkiem, to UART będzie "przezroczysty" pomiędzy tymi dwoma BT-kami...

    Dodatkowo, jeśli modem jest w trybie komend (czyli 'nie połączony') to na każdy prawidłowy rozkaz odpowie on ciągiem znaków [cr][lf]OK[cr][lf] lub [cr][lf]ERROR[cr][lf]...

    Moduł sam z siebie nie zapamiętuje tych ustawień. Nie prościej wysłać z procka rozkaz bezpośrednio po resecie?... Po co dodatkowy kabel szeregowy 'typu FTDI'...

    Skoro moduł nie zapamiętuje ustawień (i nawet nie ma rozkazu żeby go do tego zmusić) to musisz go konfigurować za każdym razem po resecie... i żaden kabel 'typu FTDI' nie pomoże...
  • Poziom 8  
    Próbowałam wysłać komendę z terminala, ale nie mogę tego zrobić przed połączeniem się z komputerem... już nie wiem co robię źle.
    Krok po kroku:
    1.Włączam adaptor bluetooth do lapka;
    2. Włączam zasilanie modułu bluetooth - trzy razy mryga zielona i czerwona lampka, potem miga tylko zielona ok 1Hz co sugerowałoby urządzenie w trybie master zgodnie z opisem w dokumentacji - http://www.meraprojekt.com.pl/files/MP-BTM222-5V.pdf
    3. Łączę się przez usługę port szeregowy za pomocą bluesoleil
    4. Włączam connect w terminalu (bez tego nie mogę nic wysyłać).
    Dopiero teraz mogę coś przesyłać, ale jak widać interpretacja nie jest dobra.
    Jak można się połączyć z modułem z lapka, żeby z nim "rozmawiać" tj. wysyłać komendę AT? i dostawać odpowiedzi np. na jaką prędkość jest obecnie skonfigurowany,bo jak próbuję wysłać jakąś komendę to nic na ekranie w terminalu Receive się nie pojawia?


    Ok, ale zapisanie komendy do bufora Tx i wysłanie nie powoduje mrygnięcia czerwonej lampki, tylko na terminalu pojawia się "ATL?" czyli to co wysłałam
    Kod: C
    Zaloguj się, aby zobaczyć kod


    Kod: C
    Zaloguj się, aby zobaczyć kod
  • Poziom 35  
    Zupełnie źle i nie tak!

    Trzeci raz tłumaczę: po resecie modułu BTM222 wyslij do niego z mikrokontrolera przez UART rozkaz ATL5[cr]. Dopiero wtedy łącz się przez usługę port szeregowy z bluesoleil'a...

    To co teraz robisz, to próba _zdalnego_ przekonfigurowania modułu- tego się nie da zrobić...
  • Poziom 38  
    kasia.p napisał:

    Jak można się połączyć z modułem z lapka, żeby z nim "rozmawiać" tj. wysyłać komendę AT? i dostawać odpowiedzi np. na jaką prędkość jest obecnie skonfigurowany,bo jak próbuję wysłać jakąś komendę to nic na ekranie w terminalu Receive się nie pojawia?


    Musisz rozróżnić dwie rzeczy - połączenie z modułem i połączenie przez BT. Zauważ, że do modułu masz podłączonego UARTa. Zanim wejdziesz w tryb komunikacji (zanim się z kimkolwiek sparujesz) moduł działa w trybie konfiguracji. Wtedy po UARCie wysyłasz mu tę komendę (ale tylko raz w życiu, bo konfiguracja zapisywana jest w eepromie modułu). Zauważ, że po połączeniu się przez BT idą surowe dane, więc jak wyślesz ATS345314 to nie skonfigurujesz modułu tylko wyślesz do uC te znaki.
  • Poziom 8  
    Witam wszystkich,
    oficjalnie chciałabym zakomunikować, że się udało!
    Otóż jedyną skuteczną metodą okazała się przejściówka USART-USB. Po podłączeniu jej do lapka i ustawieniu parametrów w terminalu udało się nawiązać połączenie. Moduł BT został przestawiony na maksymalną prędkość i dzięki temu wysyła dane do terminala z częstotliwością co najmniej 1000Hz :) Struktury głównego programu nie zmieniałam (tj. zostawiłam funkcję sprintf). Dziękuję wszystkim za pomoc i cenne rady :) Temat można uznać za zamknięty.
  • Specjalista - Mikrokontrolery
    Jeśli tylko nie konwertujesz liczb zmiennoprzecinkowych, to zawsze lepiej skorzystać z siprintf() (zakładając, że mowa o GCC, newlib itd.)

    4\/3!!