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

Eclipse- deklaracja zmiennych globalnych i zewnetrznych

ninja_zlomiarz 28 Gru 2011 22:16 3108 27
  • #1 28 Gru 2011 22:16
    ninja_zlomiarz
    Poziom 9  

    Hej,
    mam taki ciężki do przejścia dla mnie problem.

    Piszę program w którym wykorzystuję przerwanie od timera i nie mogę sobie poradzić z deklaracją zmiennych. Mam dwa pliki main.c i stm32f10x_it.c.

    W pliku main deklaruję zmienne globalne:

    Code:
    #include "stm32f10x.h"
    
    #include "fatfs/src/ff.h"
    #include "fatfs/src/diskio.h"
    #include <stdio.h>

    void RCC_Conf(void);
    void NVIC_Conf(void);
    void SysTick_Conf(void);
    void GPIO_Conf(void);

    FATFS g_sFatFs;
    DIR g_sDirObject;
    FILINFO g_sFileInfo;
    FIL g_sFileObject;

    WORD zapisanych_bajtow;

    uint16_t ADC1Val = 0;

    FRESULT fresult;
    FIL plik;
    FILINFO plikInfo ;
    DIR Dir;
    FILINFO *p;

    int main(void)
    {
          RCC_Conf();
         SysTick_Conf();
         NVIC_Conf();
       GPIO_Conf();

         GPIO_SetBits(GPIOC, GPIO_Pin_12);

        fresult = f_mount(0, &g_sFatFs);

       // Tworzenie pliku na karcie
       fresult = f_open (&plik,"plik.txt", FA_CREATE_ALWAYS | FA_WRITE);



    a w pliku stm32f10x_it.c. chciałbym je wykorzystać w przerwaniu
    Code:

    void TIM1_CC_IRQHandler(void)
    {
       extern FRESULT fresult;
       extern FIL plik;
       extern FILINFO plikInfo ;
       extern DIR Dir;
       extern FILINFO *p;
         if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
         {
           TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
          ADC_ExternalTrigConvCmd(ADC1, ENABLE);
          fresult = f_write(&plik, "zawatosc pliku", 15, &zapisanych_bajtow);
         }
    }


    to dodałem przed nazwami plików extern żeby sobie szukał program tego w innym pliku ale wyskakują błędy:

    Code:

    Description   Resource   Path   Location   Type
    unknown type name 'DIR'   
    unknown type name 'FIL'   
    unknown type name 'FILINFO'   
    unknown type name 'FILINFO'   
    unknown type name 'FRESULT'   



    wie ktoś może w czym leży problem?

    0 27
  • Arrow Multisolution Day
  • Pomocny post
    #2 28 Gru 2011 22:23
    tadzik85
    Poziom 38  

    Przecież kompilator sam wywala ci błąd nieznany typ. Brak dołączonej deklaracji typu.

    0
  • Pomocny post
    #3 28 Gru 2011 22:24
    michalko12
    Specjalista - Mikrokontrolery

    Gdzie masz zadeklarowane typy z którymi masz problem.
    Plik stm32f10x_it.c musi znać te typy (DIR,FIL...). Dołącz do pliku stm32f10x_it.c nagłówek z deklaracjami tych typów.

    0
  • #4 29 Gru 2011 00:13
    ninja_zlomiarz
    Poziom 9  

    dzięki działa, a mam teraz jeszcze inne pytanie odnośnie deklaracji i odwoływania się do zmiennych.

    W pliku main.c mam stworzoną zmienną globalną :

    Code:

    uint16_t ADC1Val = 0;

    chciałbym jej wartość wykorzystać w funkcji ale w innym pliku.

    więc w tym pliku wpisuję:

    Code:

    extern uint16_t ADC1Val


    i jeżeli chcę się odwołać do jej wartości w funkcji to wystarczy że napiszę takie coś?

    Code:
    fresult = f_write(&plik, ADC1Val, 6, &zapisanych_bajtow);


    tylko że funkcja oczekuje wartości char i nie wiem jak to rozwiązać

    0
  • Arrow Multisolution Day
  • Pomocny post
    #5 29 Gru 2011 01:46
    stanleysts
    Poziom 27  

    konwersja - polecam zajrzec do tablic ascii, i z tego co pamietam to drugi argument to wskaznik na dane ktore maja byc zapisane i jest on typu void

    0
  • #6 29 Gru 2011 11:18
    ninja_zlomiarz
    Poziom 9  

    próbowałem zrobić jakoś tak:

    Code:

       extern uint16_t ADC1Val;
       unsigned char tab[20];
       sprintf(tab,"%d",ADC1Val);
       write_text(tab);


    ale pojawiają mi się takie błędy:

    Eclipse- deklaracja zmiennych globalnych i zewnetrznych

    hmm nie wiem co mogę, może brakuje mi jakiejś biblioteki? albo pliki nagłówkowego?

    0
  • Pomocny post
    #7 29 Gru 2011 12:04
    michalko12
    Specjalista - Mikrokontrolery

    Gdzie masz funkcję write_text(); ?
    Tworzysz w ogóle jakieś pliki nagłówkowe?


    extern możesz też zastosować do tej funkcji

    Kod: c
    Zaloguj się, aby zobaczyć kod



    lub nawet nie musisz wystarczy, że w tym pliku zadeklarujesz ją i tez będzie działać.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    a co do sprintfa to rzutowanie potrzebne

    Kod: c
    Zaloguj się, aby zobaczyć kod


    i jeszcze jedno...
    Potrzebujesz pliku syscalls.c który współgra ze skryptem linkera
    a o tym poczytaj na stronie Freddiego http://www.freddiechopin.info/

    0
  • #8 29 Gru 2011 15:27
    ninja_zlomiarz
    Poziom 9  

    sorry trochę źle się określiłem co do mojego problemu.

    Problem wygląda tak że zczytuję dane z przetwornika ADC i dane zczytywane są w momencie przerwania od timera co 5s.
    Typ danych zczytywanych z ADC to w programie main zmienna globalna:

    Code:

    uint16_t ADC1Val;


    Teraz kiedy funkcja wchodzi do przerwania to chciałbym zapisać wartość tej zmiennej na kartę SD do tego służy funkcja f_write

    Definicja funkcji f_write:
    Code:

    FRESULT f_write (FIL*, const void*, WORD, WORD*);    /* Write data to a file */


    Funkcja f_write oczekuje na wartość cont void*


    np. mogę wpisać takie coś i taki kod działa, wpisuje do pliku ciąg znaków "zawartosc pliku":
    Code:
    fresult = f_write(&plik, "zawartość pliku", 15, &zapisanych_bajtow)




    i muszę teraz zamiast "zawartość pliku" jakoś wartość ADC1Val wstawić, próbowałem dla przykładu kombinować z charem tzn zrobiłem takie coś:

    Code:

    char c[2];
    c[0]='a';
    c[1]='b';
    c[2]='c';

    fresult = f_write(&plik, c, 3, &zapisanych_bajtow)


    ale takie coś mimo że się kompiluje to przy debugowaniu program wchodzi w pętlę HardFault

    0
  • #9 31 Gru 2011 01:24
    kriss68
    Poziom 20  

    Michalko12 podał Ci gotowe rozwiązanie, sprintifem zamieniasz wartość konwersji na tekst a potem tablice do której zapisywał sprintif przekazujesz do f_write i tyle. To co podałeś nie dziala bo tablica c ma dwa elementy a Ty operujesz na trzech.

    0
  • #10 31 Gru 2011 02:15
    ninja_zlomiarz
    Poziom 9  

    kriss68 napisał:
    Michalko12 podał Ci gotowe rozwiązanie, sprintifem zamieniasz wartość konwersji na tekst a potem tablice do której zapisywał sprintif przekazujesz do f_write i tyle. To co podałeś nie dziala bo tablica c ma dwa elementy a Ty operujesz na trzech.



    1. dziękuję za zainteresowanie :)

    2. niestety nie w tym leży problem, tu jest oczywiście błąd powinno być c[3] tak też robiłem tylko tu źle skopiowałem

    Tak wielkie podziękowania dla Michalko12 dzięki niemu działa mi sprintf tylko że właśnie nawet go nie wykorzystywałem skoro najprostsza tablica mi nie działa, najdziwniejsze jest to że jak wpiszę normalnie tekst w cudzysłowach to działa a jak podam zmienną tablicową to wchodzi w tą pętlę HardFault

    jedynie jak odwołam się bezpośrednio przez referencję do zmiennej ADC1Val czyli wykonam kod:

    Code:
    fresult = f_write(&plik, &ADC1Val, sizeof(uint16_t), &zapisanych_bajtow);
    


    to coś zapisuje do pliku tylko nie są to liczby a jakieś dziwne symbole

    próbowałem ustawić tablicę c jako zmienną globalną ale również nie działa tzn kompiluje się ale wchodzi w pętlę HardFault

    jest tu jakiś dobry człowiek który mi udzieli odpowiedzi ? :) stawiam piwo w Krakowie ! za dobrą odpowiedź :)

    0
  • #11 31 Gru 2011 09:08
    Freddie Chopin
    Specjalista - Mikrokontrolery

    ninja_zlomiarz napisał:
    to coś zapisuje do pliku tylko nie są to liczby a jakieś dziwne symbole

    Bo zapisujesz BINARNĄ wartość, więc raczej ciężko oczekiwać, żeby ładnie wyglądała przedstawiona w postaci znaków odpowiadających tym wartościom, które akurat się trafiły.

    Skoro masz debugger, to w czym problem, żeby sobie podejrzeć w którym miejscu się wysypuje?

    A zamiast sprintf() polecam itoa() (np na mojej stronce do pobrania) - wielokrotnie mniejsze, wielokrotnie szybsze, nie wymaga 10000x innych rzeczy. Jeśli komuś nie potrzebne liczby zmiennoprzecinkowe to jak znalazł. Jest też do ściągnięcia uproszczony printf/sprintf() - obsługuje tylko liczby całkowite, znaki i stringi.

    4\/3!!

    0
  • #12 31 Gru 2011 12:46
    ninja_zlomiarz
    Poziom 9  

    Freddie Chopin napisał:

    Skoro masz debugger, to w czym problem, żeby sobie podejrzeć w którym miejscu się wysypuje?

    A zamiast sprintf() polecam itoa() (np na mojej stronce do pobrania) - wielokrotnie mniejsze, wielokrotnie szybsze, nie wymaga 10000x innych rzeczy. Jeśli komuś nie potrzebne liczby zmiennoprzecinkowe to jak znalazł. Jest też do ściągnięcia uproszczony printf/sprintf() - obsługuje tylko liczby całkowite, znaki i stringi.

    4\/3!!


    dzięki funkcje o których wspomniałeś już zassałem wcześniej i na pewno będą bardzo pomocne tylko jak rozwiążę zagadkę dlaczego mi się to wysypuje. Napisałem możliwie najprostszą funkcję dla przerwania czyli:

    Code:
    void TIM1_CC_IRQHandler(void)
    
    {

       extern FRESULT fresult;
       extern FIL plik;
       extern FILINFO plikInfo ;
       extern DIR Dir;
       extern FILINFO *p;
       extern WORD zapisanych_bajtow;

       char c[] = {'a','b','c'};

         if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
         {
          ADC_ExternalTrigConvCmd(ADC1, ENABLE);
          GPIO_WriteBit(GPIOC, GPIO_Pin_12,
                      (BitAction) ((1 - GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_12))));

          fresult = f_write(&plik, c, sizeof(c), &zapisanych_bajtow);
          //czyszczenie flagi
           TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);

         }
    }



    i wysypuje się podczas debugowania już w startupie bo nawet nie mogę programu włączyć.

    Taki komunikat wyświetlił mi debugger:

    Eclipse- deklaracja zmiennych globalnych i zewnetrznych


    czyli praktycznie niewiele, nie wiem co jeszcze mogę zrobić :/

    0
  • #13 31 Gru 2011 13:01
    Freddie Chopin
    Specjalista - Mikrokontrolery

    No ale czemu nie spróbować najpierw zapisu z innego miejsca niż przerwanie? A jak Ci się wysypuje przed wejściem do main(), to raczej problem jest zupełnie gdzie indziej...

    4\/3!!

    0
  • #14 31 Gru 2011 15:31
    ninja_zlomiarz
    Poziom 9  

    Freddie Chopin napisał:
    No ale czemu nie spróbować najpierw zapisu z innego miejsca niż przerwanie? A jak Ci się wysypuje przed wejściem do main(), to raczej problem jest zupełnie gdzie indziej...

    4\/3!!


    no nie wiem dlaczego tego wcześniej nie zrobiłem ... rzeczywiście masz racje problem leży gdzie indziej jeżeli w pliku main zadeklaruję tablicę i w pliku main następuje zapis to wszystko jest ok, problem zaczyna się kiedy chcę zapis przeprowadzić w przerwaniu.

    Jeżeli w przerwaniu zapisuje zwykły ciąg znaków w cudzysłowach do funkcji f_write to jest ok, ale jeżeli w przerwaniu deklaruję tablicę i chce ją zapisać do funkcji f_write to już mu się nie podoba. Może jest coś nie tak z deklaracją? Istnieje w Eclipsie możliwość podglądnięcia zmiennych lokalnych? bo globalnych to wiem że wystarczy dodać zmienną globalną i się już ją widzi.

    i czy istnieje taka możliwość że w przerwaniu od timera nie mogę robić takich rzeczy? i dlatego wpada w Hard Faulta?

    0
  • Pomocny post
    #15 31 Gru 2011 15:45
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Żeby widzieć zmienne lokalne trzeba być po pierwsze w danej funkcji, a pozatym dobrze ustawić optymalizację na 0 i wyłączyć usuwanie niepotrzebnego kodu i zmiennych.

    4\/3!!

    0
  • Pomocny post
    #16 01 Sty 2012 19:25
    kriss68
    Poziom 20  

    Nie łatwiejsze i optymalniejsze będzie użycie f_printf z FatFs'a? Wystarczy włączyć jego obsługę w configu(_FS_READONLY == 0 _USE_STRFUNC == 1). I odpalasz to tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod
    W tym przerwaniu co podałeś to jakieś dziwne rzeczy robisz też :)

    0
  • #17 01 Sty 2012 19:54
    ninja_zlomiarz
    Poziom 9  

    kriss68 napisał:
    Nie łatwiejsze i optymalniejsze będzie użycie f_printf z FatFs'a? Wystarczy włączyć jego obsługę w configu(_FS_READONLY == 0 _USE_STRFUNC == 1). I odpalasz to tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    W tym przerwaniu co podałeś to jakieś dziwne rzeczy robisz też :)



    kriss68 dziękuję za radę, nie znałem tej funkcji, a odnośnie przerwania co konkretnie wydaje się dziwne? mówisz o zmiennych zewnętrznych?

    0
  • Pomocny post
    #18 01 Sty 2012 23:14
    kriss68
    Poziom 20  

    Chodzi mi o wyzwalanie konwersji ADC w przerwaniu - można do tego użyć timera bez przerwań ;) No i te wszystkie externy można by przenieść nad funkcję obsługi przerwania.

    0
  • #19 02 Sty 2012 12:36
    ninja_zlomiarz
    Poziom 9  

    dobra uporałem się z jednym problemem, trzeba było ustawić tablicę c globalną. Już tak robiłem ale miałem jeszcze inny błąd. Chyba chodzi o ustawienia stosów w linkerze?

    Czyli teraz moje przerwanie wygląda tak:

    Code:
    void TIM1_CC_IRQHandler(void)
    
    {

         if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
        {

          ADC_ExternalTrigConvCmd(ADC1, ENABLE);

                    fresult = f_write(&plik, c, 5, &zapisanych_bajtow);

                   TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);

         }
    }


    i działa jeżeli tablica c jest zmienną globalna i jest stała,

    tylko że ja potrzebuję do tablicy c wpisywać wartość z przetwornika analogowego która jest zmienna, do zamiany wartości z przetwornika na ciąg znaków zastosowałem funkcję itoa ze stronki freddiego w programie głównym main:

    Code:
        while(1)
    
         {
          ADC1Val = ADC_GetConversionValue(ADC1) * 0.807;
          itoa( ADC1Val, c, 10 );
          }
         }



    no i teraz chcę żeby zapis na kartę następował cyklicznie czyli w tym przerwaniu od timera, tylko że jak tak zrobię to program wpada w HardFaulta

    jeżeli zapis na kartę następuje w pętli programu głównego czyli:

    Code:
         while(1)
    
         {
          ADC1Val = ADC_GetConversionValue(ADC1) * 0.807;
          itoa( ADC1Val, c, 10 );
                    fresult = f_write(&plik, c, 5, &zapisanych_bajtow);
          }
         }


    to wszystko jest wporządku,


    ma ktoś pomysł ja to rozwiązać? muszę zmienić jkieś ustawienia w skrypcie Linkera? skrypt Linkera mam ze strnki freddiego

    0
  • Pomocny post
    #20 02 Sty 2012 15:00
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Ustaw rozmiar stosu na przerwań - domyślnie w przykładzie jest 0, bo nie ma tam przerwań.

    4\/3!!

    0
  • #21 02 Sty 2012 15:47
    ninja_zlomiarz
    Poziom 9  

    Freddie Chopin napisał:
    Ustaw rozmiar stosu na przerwań - domyślnie w przykładzie jest 0, bo nie ma tam przerwań.

    4\/3!!



    dzięki teraz śmiga ale w sumie i tak to inaczej rozwiązałem ustawiam flagę w przerwaniu i sprawdzam w mainie ifem,

    mam jeszcze jeden mały problemik z funkcją itoa, moja funkcja wygląda tak:

    Code:
         while(1)
    
         {
          ADC1Val = ADC_GetConversionValue(ADC1);
          if(data_ready)
          {
          itoa(ADC1Val, c, 10);
          fresult = f_write(&plik, c, 5, &zapisanych_bajtow);
          data_ready = 0;
          }
         }


    i teraz nie wiem dlaczego, ale jak debuguje krok po kroku to
    funkcja itoa prawidłowo odczytuje wartość ze zmiennej ADC1Val a jak
    puszcze 'play' i zatrzymam w jakimś miejscu to tablica c ma inną
    wartość niż aktualna wartość ADC1Val, wiecie co mogę na to poradzić?
    jakieś opóźnienie trzeba wstawić?

    0
  • Pomocny post
    #22 02 Sty 2012 16:50
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Wartość z ADC odczytujesz ciągle, a powinieneś ją odczytywać tak samo wewnątrz if'a. Do tego zależnie od tego w którym miejscu się zatrzymasz, może być już po nowym odczycie, ale przed nową konwersją - wtedy masz w zmiennej nową wartość, w tablicy starego stringa.

    4\/3!!

    0
  • #23 02 Sty 2012 19:10
    ninja_zlomiarz
    Poziom 9  

    Freddie Chopin napisał:
    Wartość z ADC odczytujesz ciągle, a powinieneś ją odczytywać tak samo wewnątrz if'a. Do tego zależnie od tego w którym miejscu się zatrzymasz, może być już po nowym odczycie, ale przed nową konwersją - wtedy masz w zmiennej nową wartość, w tablicy starego stringa.

    4\/3!!



    dobra wszystko działa, rzeczywiście namieszałem z tymi timerami

    mam ostatnie głupie pytanie :) obiecuję :)


    jak ustawić ten stos dla przerwań bo patrze na ten skrypt linkera i nie mam pojęcia co mógłbym zmienić?

    z góry dziękuję za odpowiedź :)

    0
  • Pomocny post
    #24 02 Sty 2012 21:15
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Code:
    /*
    
    +=============================================================================+
    | stacks sizes
    +=============================================================================+
    */

    /* Handler mode (core exceptions / interrupts) can use only main stack */
    /* Thread mode can use main stack (default) or process stack - selected in CONTROL special register */

    __main_stack_size = 0;
    __process_stack_size = 1024;


    Rozmiar w bajtach oczywiście.

    4\/3!!

    0
  • #25 03 Sty 2012 21:37
    ninja_zlomiarz
    Poziom 9  

    dzięki Freddie Chopin to już się wyjaśniło dlaczego tego nie widziałem: już to miałem ustawione na 1024. Problem miałem gdzie indziej i już go w sumie rozwiązałem.

    Mam jeszcze takie pytanie odnośnie sprawdzenia ile czasu zajmuje przerwanie. Mam takie przerwanie wyzwalane TIM1:

    Code:
    void TIM1_UP_IRQHandler(void)
    
    {
          // Start przetwarzania przetwornika ADC
          ADC_SoftwareStartConvCmd(ADC1, ENABLE);
          ADC1Val = (ADC_GetConversionValue(ADC1));
          itoa(ADC1Val, c, 10);
          //znaki końca linii
          //c[5]='\t';
          c[5]='\r';
          c[6]='\n';
          //zapis stringa do pliku
          fresult = f_write(&plik, c, 7, &zapisanych_bajtow);
          //zapis danych z bufora
          fresult=f_sync(&plik);
    TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
    ile_czasu=(TIM_GetCounter(TIM1));
    }



    no i ile czasu zajmuje przerwanie sprawdzam tak że na końcu przerwania pobieram sobie aktualną wartość licznika TIM1 (tak mi się wydaje) do zmiennej ile_czasu dobrze myślę? co myślicie o takim sprawdzeniu ile czasu zajmuje przerwanie? Da się to jakoś optymalniej zrobić?

    Robię to w celu obliczenia czy mikrokontroler wyrobi z zapisywaniem danych na kartę przy próbkowaniu około 166 MHz.

    0
  • #26 03 Sty 2012 22:38
    Freddie Chopin
    Specjalista - Mikrokontrolery
  • #27 03 Sty 2012 23:08
    ninja_zlomiarz
    Poziom 9  

    Freddie Chopin napisał:

    Przerwanie czy odczyt ile ono trwa?
    4\/3!!



    a sorki trochę się nie sprecyzowałem, chodzi mi oczywiście o odczyt, no jak teraz na to patrze to głupio to jest zrobione, bo ja to sprawdzałem przez ustawienie breakpointa po zmiennej ile czas i sprawdzałem ile aktualnie wynosi wartość tej zmiennej (czyli countera licznika). W sumie robiłem to też przez debugger więc pewnie to też spowolniło proces.

    Jak to najelpiej zrobić? Może poprzez wysyłanie informacji przez UART? i czy wogóle robić to tym GetCounter czy jest jakiś sprytniejszy sposób?

    0
  • #28 04 Sty 2012 08:33
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Tak jak robisz jest OK - szybciej już nie będzie. Miej tylko świadomość, że jak układ zostaje zatrzymany przez debugger (stoi na breakpoincie), to liczniki nadal się kręcą - da się to przestawić w którymś rejestrze.

    4\/3!!

    0