Skocz do zawartości

Problem z czasem zapisu na kartę SD STM32 F746


bartchez

Pomocna odpowiedź

Witam,
od dłuższego czasu próbuję napisać program który odczytywał by wartości z ADC (częstotliwość min 1K na kanał, z jak największej liczby kanałów) i zapisywał czas uzyskania i wartość na karcie w postaci pliku txt. Wszystko było by ok gdyby nie przerwa podczas przepełnienia bufora karty i konieczność odczekania 2[ms] na zapis bufora na karcie.

Wygląda to miej więcej tak, że przed 10[ms] wszystko jest ok po czym następuje przerwa 2[ms] i znowu jest ok. Chciałbym zapisywać na karcie ok 5 min.

Czy ktoś ma pomysł jak rozwiązać ten problem ?

Dodam że dopiero zaczynam moją przygodę z tego typu układami (STM32) prosił bym o pomoc jak dla całkowicie zielonej osoby.

#include "mbed.h"
#include "TS_DISCO_F746NG.h"
#include "LCD_DISCO_F746NG.h"
#include "SDFileSystem.h"
#include <stdio.h>

DigitalOut myled(LED1);
InterruptIn user(USER_BUTTON);
LCD_DISCO_F746NG lcd;
TS_DISCO_F746NG Ts;
TS_StateTypeDef TS_State;
Timer timer;

SDFileSystem sd("sd");
FILE *fp;


AnalogIn ANALOG_0(A0);
AnalogIn ANALOG_1(A1);
AnalogIn ANALOG_2(A2);
AnalogIn ANALOG_3(A3);
AnalogIn ANALOG_4(A4);
AnalogIn ANALOG_5(A5);

uint16_t x, y;
uint8_t text[30];
uint8_t status;

uint8_t pomiar_start=0;

uint32_t time_us=0;
char buffer_time [10];
char buffer_0 [10];
char buffer_1 [10];
char buffer_2 [10];
char buffer_3 [10];
char buffer_4 [10];
char buffer_5 [10];

uint8_t ANALOG_0_ON=0;
uint8_t ANALOG_1_ON=0;
uint8_t ANALOG_2_ON=0;
uint8_t ANALOG_3_ON=0;
uint8_t ANALOG_4_ON=0;
uint8_t ANALOG_5_ON=0;

void display_analog_on(void);
void pomiar_on_of(void);
void pomiar_pokaz(void);
void pomiar_zapis(void);
void check_SD(void);


int main()
{
   lcd.Clear(LCD_COLOR_BLUE);
   lcd.SetBackColor(LCD_COLOR_BLUE);
   user.fall(&pomiar_on_of);

   lcd.SetTextColor(LCD_COLOR_RED);
   lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"ANALOG_0", CENTER_MODE);
   lcd.DisplayStringAt(0, LINE(2), (uint8_t *)"ANALOG_1", CENTER_MODE);
   lcd.DisplayStringAt(0, LINE(4), (uint8_t *)"ANALOG_2", CENTER_MODE);
   lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"ANALOG_3", CENTER_MODE);
   lcd.DisplayStringAt(0, LINE(8), (uint8_t *)"ANALOG_4", CENTER_MODE);
   lcd.DisplayStringAt(0, LINE(10), (uint8_t *)"ANALOG_5", CENTER_MODE);

   sd.mount();
   check_SD();

   while(1) {
       display_analog_on();
       if(pomiar_start == 1) {
           //pomiar_pokaz();
           pomiar_zapis();


       }
   }//koniec while(1)
}//koniec main


void check_SD(void)
{

   fp = fopen("/sd/emg.txt", "w");
   if (fp == NULL) {
       lcd.SetTextColor(LCD_COLOR_RED);
       lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"SD_ERROR", LEFT_MODE);
   } else {
       lcd.SetTextColor(LCD_COLOR_GREEN);
       lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"SD_OK", LEFT_MODE);
   }
   //fclose(fp);
}// koniec check_SD();


void pomiar_on_of(void)
{
   pomiar_start=!pomiar_start;
}//koniec pomiar()

void pomiar_pokaz(void)
{
   timer.start();
   time_us=timer.read_us();
   sprintf((char*)text, "time=%d [ms]", time_us);
   lcd.DisplayStringAt(0, LINE(7), (uint8_t *)&text, CENTER_MODE);

   sprintf((char*)text, "ADC_0=%d [ms]", ANALOG_0.read_u16());
   lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text, LEFT_MODE);
   sprintf((char*)text, "ADC_1=%d [ms]", ANALOG_1.read_u16());
   lcd.DisplayStringAt(0, LINE(2), (uint8_t *)&text, LEFT_MODE);
   sprintf((char*)text, "ADC_2=%d [ms]", ANALOG_2.read_u16());
   lcd.DisplayStringAt(0, LINE(3), (uint8_t *)&text, LEFT_MODE);
   sprintf((char*)text, "ADC_3=%d [ms]", ANALOG_3.read_u16());
   lcd.DisplayStringAt(0, LINE(4), (uint8_t *)&text, LEFT_MODE);
   sprintf((char*)text, "ADC_4=%d [ms]", ANALOG_4.read_u16());
   lcd.DisplayStringAt(0, LINE(5), (uint8_t *)&text, LEFT_MODE);
   sprintf((char*)text, "ADC_5=%d [ms]", ANALOG_5.read_u16());
   lcd.DisplayStringAt(0, LINE(6), (uint8_t *)&text, LEFT_MODE);

}


void pomiar_zapis(void)
{
   timer.start();
   while (time_us<=1000000) {

       timer.reset();

       //fp = fopen("/sd/emg.txt", "w");



       time_us=timer.read_us();

       sprintf(buffer_time, "%d", time_us);
       fprintf(fp, buffer_time);
       fprintf(fp,";");

       if (ANALOG_0_ON == 1) {
           sprintf(buffer_0, "%d", ANALOG_0.read_u16());
           fprintf(fp, buffer_0);
           fprintf(fp,";");
       } else {
           fprintf(fp, "0;");
       }
       if (ANALOG_1_ON == 1) {
           sprintf(buffer_1, "%d", ANALOG_1.read_u16());
           fprintf(fp, buffer_1);
           fprintf(fp,";");
       } else {
           fprintf(fp, "0;");
       }
       if (ANALOG_2_ON == 1) {
           sprintf(buffer_2, "%d", ANALOG_2.read_u16());
           fprintf(fp, buffer_2);
           fprintf(fp,";");
       } else {
           fprintf(fp, "0;");
       }
       if (ANALOG_3_ON == 1) {
           sprintf(buffer_3, "%d", ANALOG_3.read_u16());
           fprintf(fp, buffer_3);
           fprintf(fp,";");
       } else {
           fprintf(fp, "0;");
       }
       if (ANALOG_4_ON == 1) {
           sprintf(buffer_4, "%d", ANALOG_4.read_u16());
           fprintf(fp, buffer_4);
           fprintf(fp,";");
       } else {
           fprintf(fp, "0;");
       }
       if (ANALOG_5_ON == 1) {
           sprintf(buffer_5, "%d", ANALOG_5.read_u16());
           fprintf(fp, buffer_5);
       } else {
           fprintf(fp, "0");
       }
       fprintf(fp, ";\r\n");







       wait_us(500);
   }

   fclose(fp);
   pomiar_start=0;
   lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"DONE", RIGHT_MODE);


}//koniec pomiar_zapis();


void display_analog_on(void)
{
   Ts.GetState(&TS_State);

   if (TS_State.touchDetected) {
       x = TS_State.touchX[0];
       y = TS_State.touchY[0];
       //sprintf((char*)text, "x=%d y=%d    ", x, y);
       //lcd.DisplayStringAt(0, LINE(10), (uint8_t *)&text, LEFT_MODE);


       if (x >= 160 && x<=320 && y >= 1 && y <= 40) {
           ANALOG_0_ON = !ANALOG_0_ON;
           if (ANALOG_0_ON == 0) {
               lcd.SetTextColor(LCD_COLOR_RED);
               lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"ANALOG_0", CENTER_MODE);
           }
           if (ANALOG_0_ON == 1) {
               lcd.SetTextColor(LCD_COLOR_GREEN);
               lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"ANALOG_0", CENTER_MODE);
           }
       }
       if (x >= 160 && x<=320 && y >= 41 && y <= 80) {
           ANALOG_1_ON = !ANALOG_1_ON;
           if (ANALOG_1_ON == 0) {
               lcd.SetTextColor(LCD_COLOR_RED);
               lcd.DisplayStringAt(0, LINE(2), (uint8_t *)"ANALOG_1", CENTER_MODE);
           }
           if (ANALOG_1_ON == 1) {
               lcd.SetTextColor(LCD_COLOR_GREEN);
               lcd.DisplayStringAt(0, LINE(2), (uint8_t *)"ANALOG_1", CENTER_MODE);
           }
       }
       if (x >= 160 && x<=320 && y >= 81 && y <= 120) {
           ANALOG_2_ON = !ANALOG_2_ON;
           if (ANALOG_2_ON == 0) {
               lcd.SetTextColor(LCD_COLOR_RED);
               lcd.DisplayStringAt(0, LINE(4), (uint8_t *)"ANALOG_2", CENTER_MODE);
           }
           if (ANALOG_2_ON == 1) {
               lcd.SetTextColor(LCD_COLOR_GREEN);
               lcd.DisplayStringAt(0, LINE(4), (uint8_t *)"ANALOG_2", CENTER_MODE);
           }
       }
       if (x >= 160 && x<=320 && y >= 121 && y <= 180) {
           ANALOG_3_ON = !ANALOG_3_ON;
           if (ANALOG_3_ON == 0) {
               lcd.SetTextColor(LCD_COLOR_RED);
               lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"ANALOG_3", CENTER_MODE);
           }
           if (ANALOG_3_ON == 1) {
               lcd.SetTextColor(LCD_COLOR_GREEN);
               lcd.DisplayStringAt(0, LINE(6), (uint8_t *)"ANALOG_3", CENTER_MODE);
           }
       }
       if (x >= 160 && x<=320 && y >= 181 && y <= 220) {
           ANALOG_4_ON = !ANALOG_4_ON;
           if (ANALOG_4_ON == 0) {
               lcd.SetTextColor(LCD_COLOR_RED);
               lcd.DisplayStringAt(0, LINE(8), (uint8_t *)"ANALOG_4", CENTER_MODE);
           }
           if (ANALOG_4_ON == 1) {
               lcd.SetTextColor(LCD_COLOR_GREEN);
               lcd.DisplayStringAt(0, LINE(8), (uint8_t *)"ANALOG_4", CENTER_MODE);
           }
       }
       if (x >= 160 && x<=320 && y >= 221 && y <= 272) {
           ANALOG_5_ON = !ANALOG_5_ON;
           if (ANALOG_5_ON == 0) {
               lcd.SetTextColor(LCD_COLOR_RED);
               lcd.DisplayStringAt(0, LINE(10), (uint8_t *)"ANALOG_5", CENTER_MODE);
           }
           if (ANALOG_5_ON == 1) {
               lcd.SetTextColor(LCD_COLOR_GREEN);
               lcd.DisplayStringAt(0, LINE(10), (uint8_t *)"ANALOG_5", CENTER_MODE);
           }
       }
       wait_ms(300);
   }

} //koniec display_analog_on();

Program działa następująco

Włączam mikro(sprawdzenie obecności karty) po czym na ekranie wybieram ADC których chcę odczytywać wartości, następnie przycisk i 10 s. Wyświetla się napis"DONE" po zakończeniu zapisu wyciągam kartę wrzucam w czytnik i uzyskuję czasy pomiędzy danymi próbkami"

565

556

556

556

555

556

556

556

555

556

556

556

18187(to miejsce problemu z którym nie mogę sobie poradzić)

557

555

556

556

556

557

557

556

556

556

5287

Link do komentarza
Share on other sites

Spotkałem się gdzieś z podobnym problemem. Winna może być karta SD i to w jaki sposób buforuje sobie dane do zapisu.

Jakiej karty teraz używasz? Testowałeś inne karty?

Link do komentarza
Share on other sites

O ile zużycie pamięci to nie problem to buforuj sobie dane i zapisuj jakieś większe paczki.

Czyli np. możesz mieć bufor 1000 danych po 2 bajty = 2000 bajtów pamięci * 2 i najpierw czytasz 1000 próbek do bufora 1, potem zmieniasz ustawienia dma na bufor 2, a bufor 1 zapisujesz w całości na kartę... jak bufor 2 dojdzie do końca zmieniasz dma na bufor 1, a bufor 2 zapisujesz w całości na kartę i tak cały czas. Wielkość bufora zależy od szybkości karty ( w tym przypadku przy 1000 próbek na sekundę zapis 2kB na kartę może trwać do sekundy... albo możesz zapisywać dane z 10 adc przez 100ms )..

PS. używanie sprintf/fprintf jest wolne - zamiast tego napisz własną funkcję zmieniającą wartość pomiaru na odpowiedni tekst.

Link do komentarza
Share on other sites

Kartę mam SanDisk (10), wiem że podczas zapisu na karcie przy przepełnieniu jej bufora(512) karta wchodzi tak jakby w trym zapisu bufora w pamięci przez co występuje ta przerwa. Próbowałem buforować więcej danych do 100 próbek mieściłem się jeszcze w zadanym 1k na kanał.

Nie bardzo rozumiem jeszcze jak używać tego dma,(wiem na czym to polega, czytałem artykuł o tym) jak wygląda kod do użycia tego "systemu".

używanie sprintf/fprintf jest wolne- możliwe, ale dla mnie wystarczająco gdyby nie ta przerwa 2ms dało radę uzyskać ok 10k na kanał (przynajmniej tak mi się wydaje).

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.