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

[atmega64][c]Buforowanie danych transmisji UART nie działa.

namlooc 29 Paź 2010 00:58 2856 10
REKLAMA
  • #1 8676547
    namlooc
    Poziom 15  
    Witam!

    Staram sie komunikowac z modemem GSM. Chce opracowac metode rozłanczania osoby dzwoniącej niezaleznie od chwili w której dzwoni.

    Zalozenie jest takie iż w sposób ciągły:
    - wysyłam "AT" i sprawdzam czy jest "OK"
    - w miedzyczasie sprawdzam czy nie pojawilo sie RING, jezeli pojawilo wydaje komende "ATH0"
    *opcja echo jest off

    Wszystko działa tylko moje bufory nie zerują się.

    volatile char wynikGSM[50];
    volatile char bufor[50];
    volatile int ilosc_znakow=0;
    int ilosc;
    .
    .
    .
    .
    ISR(USART1_RX_vect) // przerwanie wywolywane naplywem znaków
    {
    char temp;
    temp=UDR1;           
    wynikGSM[ilosc_znakow]=temp; 
    ++ilosc_znakow;
    }
    
    int szukaj(char *wzorzec) // szukanie okreslonego wzorca, jezeli nie ma zwraca 0, jezeli jest zwraca wartosc rózna od zera
    {
    char *pozycja;
    pozycja=strstr((char*)bufor,wzorzec);
    return *pozycja;
    }
    .
    .
    .
    .
    int main (void)
    {
    usart_init();
    usart_debug();
    
    while(1)
    {
    
    sei()
    
    wyslij("AT\r");
    delayms(1000); 
     
     
    strcpy((char*)bufor,(char*)wynikGSM);     // przepisujemy do bufor,aby przeanalizowac
    wynikGSM[0]=0;                            // zerujemy aby mogly naplywac nowe dane
    int ilosc;
    ilosc=ilosc_znakow;
    ilosc_znakow=0;				// zeruje aby dane naplywaly od poczatku do wynikGSM
    
    wyslij2((char*)bufor); //wysylam zawartosc przeszukiwanego nizej bufora na drugiego uarta, taki debug robie dla siebie
    
    char x[5];                 // wyswietla ilość znaków zapisanych w buforze
    itoa(ilosc,x,10);         //
    wyslij2(" ");              //
    wyslij2(x);                //
    wyslij2("||");             //
    
    
    int wynik;
    wynik=szukaj("RING"); // jezeli ktoś dzwoni, szukam ring i rozlanczam go podajac komende ATH0;
    if(wynik==0) {wyswietl("nie ma ring");delayms(2000);}
    else{wyswietl("znalazlem, rozlanczam :)");delayms(2000);wyslij("ATH0\r");delayms(1000);}
    wynik=0;
    
    }



    Puki nikt do mnie nie dzwoni zawartosc zmiennej bufor w kolejnych obiagach petli wyglada następująco:
    
    ..ok..6||
    ..ok..6||
    ..ok..6||
    itd.

    W momencie gdy ktos do mnie zadzwoni wszystko wyglada jak by sie wogole nie zerowaly bufory:
    
    ..OK.. 6||    
    ..RING....RING....OK.. 22||        
    ..RING....OK....OK.... 20||        
    ..OK....OK......OK.... 12||
    ..OK....OK......OK.... 6||
    

    Wniosek: Poprawna ilosc znakow jest tylko w dwoch pierwszych wersach 6 oraz 22, pozniej kiedy zeruje bufory bo ringa juz nie ma bo rozlaczylem..on dalej pamieta koncowki..

    Pytanie: jak zerowac tablice volatile char zapisująca sie w przerwaniu w sposob inny niz bufor[0]=0; poniewaz to nie działa.




    inventco.eu - temat poprawiłem. Regulamin p.11.1.
  • REKLAMA
  • #2 8676972
    psine.pl

    Poziom 30  
    Sugeruję byś wpisywał do tablicy bufor wartość "null" (pustą).
    Najlepiej zrób sobie pętlę liczącą 0-49 i w tej pętli wpisuj puste znaki do zmiennej bufor.
    U mnie zawsze tak działa :-)
    Wpisywałem znaki końca ciągu i różne takie i nic. Dopiero wpisywanie odpowiedniej ilości pustych znaków w tabelę ją "kasuje" dokumentnie.
    Może ktoś ma inny patent ale ten wiem, że działa na 100%.

    Pozdrawiam
    Marek
  • REKLAMA
  • #3 8679566
    namlooc
    Poziom 15  
    inventco.eu napisał:

    Najlepiej zrób sobie pętlę liczącą 0-49 i w tej pętli wpisuj puste znaki do zmiennej bufor.


    zamiast niedzialajacego

    dalem:
    void czysc_wynikGSM(void)
    {
    int y,j;
    y=strlen((char*)wynikGSM);
    for(j=0;j<y;j++)
    {
    wynikGSM[j]=0;
    }
    
    i działa :)

    Tylko ze ile by mnie nie uczyli C, zawsze kazdy twierdzil ze ustawiene 0 na pierwszej pozycji zeruje cala tablice. Ciekawe do ktorego momentu mieli racje..
  • REKLAMA
  • #4 8679582
    gaskoin
    Poziom 38  
    wynikGSM jako nazwa jest adresem na pierwszy element w tablicy a nie pierwszym jej elementem.
  • #5 8679747
    Freddie Chopin
    Specjalista - Mikrokontrolery
    namlooc napisał:
    Tylko ze ile by mnie nie uczyli C, zawsze kazdy twierdzil ze ustawiene 0 na pierwszej pozycji zeruje cala tablice. Ciekawe do ktorego momentu mieli racje..

    Ciekawe kto takie bzdury wypisuje... Podejrzewam jednak, że "oni" mieli rację, tylko Ty źle zrozumiałeś...

    4\/3!!
  • #6 8681043
    namlooc
    Poziom 15  
    Freddie Chopin napisał:
    tylko Ty źle zrozumiałeś...
    4\/3!!


    To dlaczego w moim wypadku tablica sie nie zeruje ?

    
    wynikGSM[0]=0; ani wynikGSM=0;
    
    nie dziala w moim kodzie...
  • #7 8682610
    nsvinc
    Poziom 35  
    wynikGSM[0]=0 musi dzialac. Wpisujesz zero pod zerowy (pierwszy) element tablicy, w efekcie czego masz zero w zerowym (pierwszym) elemencie tablicy.

    wynikGSM=0 nie ma prawa dzialac, bo wynikGSM faktycznie jest wskaznikiem, ale const. A zapisanie czegos do consta to jak mieszanie stwardnialego gipsu :]

    Dlaczego
    Freddie Chopin napisał:
    Podejrzewam jednak, że "oni" mieli rację, tylko Ty źle zrozumiałeś...
    ?

    Ano dlatego, ze gdy wpisujesz zero pod wskaznik nie-const ktory wskazuje na pierwszy element tablicy to szlag trafia tablice. Dane zostaja w pamieci, ale ty, gubiac (nadpisujac zerem) wskaznik, nie wiesz juz gdzie te dane sa. W najgorszym wypadku wycieknie pamiec (a gorzej, gdy sprobujesz cos zapisac pod ten niezywy wskaznik, to wywalisz soft), w najlepszym zdazyles sie juz pozbyc wczesniej niepotrzebnych danych i uwalenie wskaznika to zadna strata (no i to wolno robic).

    To co sie robi w tym kodzie to koszmar. Wszystko powinno poginac na buforach kolowych, powinien istniec regularny parser tego co przylazi (czyli komend(y) AT), i to taki, ktory obsluguje zawijanie sie na krancu bufora. Wtedy nie bedzie opcji zeby cokolwiek z poprzedniego obrotu zostalo do nastepnego obrotu petli, nigdy nie zgubisz danych nawet jak bedzie ich bardzo duzo przylazic.
  • #8 8685994
    Freddie Chopin
    Specjalista - Mikrokontrolery
    namlooc napisał:
    To dlaczego w moim wypadku tablica sie nie zeruje ?

    Zerujesz pierwszy element i on na pewno jest wyzerowany. Tablica "się" na pewno od tego nie wyzeruje cała, bo niby dlaczego?

    Cytat:
    wynikGSM[0]=0;

    Zeruje pierwszy element - wszystko ok.

    Cytat:
    wynikGSM=0;

    Jeśli "wynikGSM" zadeklarowane jest jako tablica (typ wynikGSM[rozmiar];), to operacja taka (zmiana wartości z niejawnym modyfikatorem const) jest niedozwolona w języku C, więc nie ma to prawa działać.

    4\/3!!
  • REKLAMA
  • #9 8691413
    namlooc
    Poziom 15  
    nsvinc napisał:
    Wszystko powinno poginac na buforach kolowych, powinien istniec regularny parser tego co przylazi


    ok, bufor cykliczny wydaje sie byc ciekawszym rozwiazaniem :) Zrobie dwa wskazniki jeden do odczytu drugi do zapisu.
    *Wskaznik do zapisu pokazuje nam gdzie zapisac kolejny znak, po czym jest inkrementowany.
    *Wskaznik odczytu ustawiony na znaku ktory aktualnie odczytalismy,po czym takze jest inkrementowany.

    ..no i baze regul dodam:
    - wskazik odczytu nie moze byc wiekszy niz wskaznik zapisu
    - wskaznik odczytu nie moze przegonic wskaznik zapisu
    - wskaznik odczytu nie moze sie ociagac, wzgledem wskaznika zapisu itd.
    Bufor bedzie mial okreslona wielkosc np. 100 znakow, po przekroczeniu 100znakow wskaznik zapisu przeskoczy na poczatek czyli 0, podobnie wskaznik odczytu bedzie gonil za wskasnikiem zapisu kołowo.


    Komendy oraz odpowiedzi ktorych moge sie spodziewac sa takie:
    AT\r --> 'OK' lub 'ERROR' 
    AT+CREG=1 --> 'OK' lub 'ERROR' 
    AT+CSNS=4\r--> OK lub ERROR 
    AT+CSTT=\"INTERNET\",\"INTERNET\",\"INTERNET\"\r--> 'OK' lub 'ERROR' 
    AT+CIICR\r-->'OK' lub 'ERROR'
    AT+CIFSR\r-->'OK' lub 'ERROR' oraz 'ADRES ip'
    AT+CIPSTART=\"TCP\",\"89.77.235.11\",\"15156\"\r-->'OK' oraz 'CONNECT OK' lub 'ERROR' oraz 'CONNECT FAIL'
    AT+CIPSEND\n\r <tekst zakonczony 0x1A>--> 'OK' oraz 'SEND OK' lub 'ERROR' oraz 'SEND FAIL'
    AT+CIPCLOSE\r--> 'CLOSE OK' lub 'ERROR'
    AT+CIPSHUT\r--> 'SHUT OK' lub 'ERROR'


    Bufor cykliczny bedzie zawierał np. taki ciągi znaków:
    AT....OK....AT+CREG=1....OK....AT+CSNS=4....OK....AT+CSTT=\"INTERNET\",\"INTERNET\",\"INTERNET\"....OK..AT+CIICR....OK....AT+CIFSR....OK....98.231.123.23....AT+CIPSTART=\"TCP\",\"89.77.235.11\",\"15156\"....OK....CONNECT OK....AT+CIPSEND....HELLO WORLD 0x1A....OK....SEND OK....AT+CIPCLOSE....CLOSE OK....AT+CIPSHUT....SHUT OK....

    *mam wlaczone echo
    *póki co wszystko wyglada ladnie (zapytanie-->odpowiedz)

    W kazdym wypadku musze sprawdzic odpowiedz na kazde zapytanie i zareagowac odpowiednio:
    - wydawac komendy dalej
    - przerwac dalsze wydawanie
    - wydac komende nadprogramowa (ATH0)

    Odpowiedzi mam przewidziane np. OK lub nieprzewidziane typu RING. Przewidziane wystepuja po zapytaniu, nieprzewidziane bez zapytania.
    Gdy pojawi sie:
    - RING musze kogos rozlaczyc ATH0 (nieprzewidane)
    - gdy '+CREG: 2' oraz '+CREG: 0' czyli brak zasiegu musze przerwac dalsze komendy i np. zapisywac informacje w pamieci SD (nieprzewidziane)
    - gdy ERROR na jakakolwiek komende musze przerywac dalsze instrukcje i rozpoczynac jeszcze raz (przewidywalne)
    itd.
    - gdy OK musze wydawac komendy dalej (przewidziane)

    Jak podejsc do parsowania takich danych w C ? Jakimi metodami robic to ?
  • #11 8694356
    namlooc
    Poziom 15  
    Freddie Chopin napisał:
    namlooc napisał:
    - wskazik odczytu nie moze byc wiekszy niz wskaznik zapisu

    Jak najbardziej może.

    4\/3!!
    zgadza sie, chodzilo mi ze nie moze przegonic go..wkoncu bufor jest kolowy..


    Czy analizatory skladni takie jak Lex i Yac to dobra droga do napisania parsera GSM ?
REKLAMA