sscanf() - co robię źle?

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Polish to

Threaded View
Co prawda pytanie dotyczy programowania, ale chodzi o programowanie AVR,  
więc chyba mieści się w tematyce tej grupy. ;)

Mianowicie kontynuuję temat analizy odpowiedzi na komendy AT przy  
komunikacji między Atmegą8 a modułem GSM. Do tej pory stosowałem mało  
eleganckiego i mało rozwiązania nie wymagającego angażowania stdio.h.  
Teraz jednak potrzebuję możliwości odczytania wartości liczbowych  
zwracanych przez niektóre polecenia (AT+CPAS, AT+CSQ) i zapisania ich do  
zmiennej liczbowej.

W przypadku polecenia AT+CPAS mój moduł GSM zawsze odpowiada w  
następujący sposób:

"+CPAS: 00x\r\n" (x to liczba z zakresu 0-5)

W odpowiedniej funkcji przepisuję znaki pojawiające się w buforze  
(circular buffer) do tabeli. Gdy pojawi się znak \r dopisuję za nim  
jeszcze zero, a potem przystępuję do wydzielenia wartości liczbowej:

sscanf(tablica, "+CPAS: %d\r", &zmienna_int);

następnie funkcja zwraca wartość zapisaną w zmiennej.

Robię coś nie tak? A może %d nie przyjmie liczby poprzedzonej zerami? Z  
drugiej strony próbowałem także zapisu "+CPAS: 00%d\r" i także nic nie  
dało...


Jak powinno wyglądać pobranie wartości zwracanych przez "AT+CSQ"?
Format wygląda następująco: "+CSQ: xxx, xxx\r\n"
Rozumiem, że sscanf(tablica, "+CSQ: %d, %d\r", zmienna1, zmienna2)  
również nie zadziała?

Re: sscanf() - co robię źle?
Dnia Sat, 23 Feb 2013 13:02:00 +0100, Atlantis napisał(a):
Quoted text here. Click to load it

Zawsze mozesz wrocic - lepiej korzystac ze zgrabnego i dzialajacego
rozwiazania, niz angazowac kobyle ktora robi za duzo i niepewnie.

Quoted text here. Click to load it

Ja bym sie juz w to \r nie bawil.

Quoted text here. Click to load it

Wyglada na to ze poprawnie wszystko.
http://www.cplusplus.com/reference/cstdio/scanf/
Ale sprawdz jeszcze raz czy _wszystko_ jest poprawnie, no i co zwraca  
sscanf ?  
tablica jest tablica znakow, zmienna_int zmienna int itp ?  

Quoted text here. Click to load it

Jeszcze mozesz sprobowac %s i zobaczyc gdzie przerywa analize ...
hm, tego \r w formacie nie jestem pewien, moze usun ?

Quoted text here. Click to load it

ale powinno.

J.

Re: sscanf() - co robię źle?
On 2013-02-23 13:02, Atlantis wrote:
[...]
Quoted text here. Click to load it
To w końcu funkcja zwraca to co chcesz czy nie? Dawno już nie zaglądałem
do wnętrzności stdio, ale jakaś taka dziwna myśl chodzi mi po głowie że
funkcje z rodziny scanf "pod spodem" korzystają z dynamicznej alokacji
pamięci i w związku z tym musisz dostarczyć taki alokator. Jeśli tego
nie zrobisz to jest używany jakiś "place holder".

W każdym razie poniższy programik skompilowany gcc 4.7.2 pod WinXP/MinGW
działa zgodnie z oczekiwaniami.

/******************* Utnij tutaj *******************/
/* Kompilacja: gcc -O3 -s -o ssctest ssctest.c */

#include <stdio.h>

const char *tablica1 = "+CPAS: 002\r";
const char *tablica2 = "+CSQ: 123, 010\r";

int main ( int argc, char *argv[] )
{
    int i, j, k;

    sscanf (tablica1, "+CPAS: %d\r", &i);
    printf ("Odczytana licba: %d\n", i);

    sscanf (tablica2, "+CSQ: %d, %d\r", &j, &k);
    printf ("Odczytane licby: %d, %d\n", j, k);

    return 0;
}
/******************* Utnij tutaj *******************/


Re: sscanf() - co robię źle?

Quoted text here. Click to load it

avr-libc ma normalnego malloca, żaden placeholder.

--  
"Project Manager to człowiek, który myśli, że jak weźmie  
dziewięć kobiet, to urodzą dziecko w miesiąc."

Re: sscanf() - co robię źle?
Quoted text here. Click to load it

Tak, używasz sscanf().
Napisz normalny interpreter składni na jakiejś maszynie stanów. Będ
zie
mniejszy, elastyczniejszy i bardziej niezawodny.
Poza tym będzie można przetwarzać dane bez zbędnych buforów.

Re: sscanf() - co robię źle?
On 2013-02-23 16:53, shg wrote:
Quoted text here. Click to load it

Mozna zawsze isc po bandzie ;-)

int getStatusFromResponse(const char* response)
{
    return response[9] - '0';
}

Pozdrawiam

Marek




Re: sscanf() - co robię źle?
W dniu 2013-02-23 20:55, Marek Borowski pisze:

Quoted text here. Click to load it

To się sprawdzi tylko wówczas, gdy wartość jest jednocyfrowa, jak w  
przypadku +CPAS. Sprawa się komplikuje w sytuacji, gdy trzeba odebrać  
coś większego, jak np. poziom sygnału z +CSQ.

#include <stdio.h> istotnie powoduje zauważalny wzrost rozmiaru hex'a,  
ale tragedii nie ma. Jeszcze sporo brakuje do całkowitego zapchania  
flasha Atmegi8.

BTW problem rozwiązany. Okazało się, że moduł wysyłał dodatkową linijkę  
\r\n przed głównym komunikatem - coś, czego nie było w przykładach z  
dokumentacji. Szukałem przyczyny wszędzie, ale na to nie wpadłem. :)

Re: sscanf() - co robię źle?
Dnia Sat, 23 Feb 2013 22:07:25 +0100, Atlantis napisał(a):
Quoted text here. Click to load it

A po co ci ten poziom ? Moze wystarczy sama druga cyfra :-)

Podobna konwersja dla 2-3 cyfr jest trywialna, jest jeszcze atoi().

Quoted text here. Click to load it

Owszem, ale patrzac na to co sscanf potrafi ... za duzo. Niepotrzebne
obciazenie :-)

J.

Re: sscanf() - co robię źle?
W dniu 2013-02-24 12:12, J.F. pisze:

Quoted text here. Click to load it

Po chwili zastanowienia przyznaję rację. Uparłem się na stdio.h ze  
względów "dydaktycznych" sądząc, że funkcje w nim zawarte i tak mi się  
przydadzą (myślę o dodaniu obsługi odbieranych SMS-ów via morse code w  
słuchawce ;P).

Po chwili zastanowienia wróciłem jednak do starej koncepcji. Liczę  
napływające znaki, i w odpowiedniej chwili zwracam znak-'0' w przypadku  
+CPAS oraz 10*(znak1-'0')+(znak2-'0') w przypadku CSQ. Sprawdzanie czy  
wcześniejsze znaki pasują odpuściłem sobie.

Re: sscanf() - co robię źle?
Quoted text here. Click to load it

To błąd, bo tak się rodzą potem problemy przy zmianie sprzętu.  


Re: sscanf() - co robię źle?
W dniu 2013-02-24 14:27, Pszemol pisze:

Quoted text here. Click to load it

Funkcje i tak piszę z myślą o ściśle określonym module.
Jeśli zajdzie konieczność jego zmiany (na co się nie zanosi) i tak będę  
musiał przejrzeć całość kodu odpowiedzialnego za komunikację.

Re: sscanf() - co robię źle?

Quoted text here. Click to load it

Nie do końca o to chodzi.

Ukrywanie błędów nigdy nie kończy się dobrze. Miałeś dobry przykład -  
coś nie przyszło tak, jak zakładałeś, a ty szukałeś błędu zupełnie gdzie  
indziej. Dobry program to taki program, który sprawdza takie niepewne  
rzeczy. Im mniej ślepych założeń odnośnie wejściowych danych, tym lepiej  
(a jak się spodziewasz, że takie będą, to daj asserta lub jego swój  
odpowiednik).

--  
"Project Manager to człowiek, który myśli, że jak weźmie  
dziewięć kobiet, to urodzą dziecko w miesiąc."

Re: sscanf() - co robię źle?

Quoted text here. Click to load it

Wymyślanie koła na nowo to niestety cecha początkujących programistów  
i amatorów. Syndrom NIH.

Ja jestem jak najbardziej za sscanf. O ile nie ma przeciwwskazań, typu  
brak miejsca we flashu, to ma to same zalety - głównie taką, że błąd w  
sscanf jest raczej mało prawdopodobny. Dostajesz coś, co działa.

--  
"Project Manager to człowiek, który myśli, że jak weźmie  
dziewięć kobiet, to urodzą dziecko w miesiąc."

Re: sscanf() - co robię źle?
W dniu 2013-02-25 12:00 Adam Wysocki napisał(a):

Quoted text here. Click to load it

Oj coś masz podejście zbyt wysokopoziomowe jak do tego zastosowania.  
Znam takich - najczęściej speców od Javy i wszystkich możliwych  
frameworków. Program wynikowy puchnie w takich przypadkach o cały worek  
różnistych bibliotek a czas kompilacji sięga zenitu - tylko po to aby  
kilka linii mniej napisać własnego kodu (niemały czas potrzebny na  
obczajenie każdego nowego frameworka pomijam).

Wg mnie zrobienie automatu analizującego znaki odczytywane z modułu GSM  
(i to "karmionego" znak po znaku) jest najlepszym z zaproponowanych  
rozwiązań. Oczywiście jeżeli zrobi się to z głową i odpowiednio obsłuży  
sytuacje nadzwyczajne (asynchronicznie przychodzące komunikaty na inny  
temat gdy się spodziewamy danej odpowiedzi modułu). Przy okazji  
włączyłbym także echo w module GSM (ATE1) dla pewności czy każda komenda  
została poprawnie przesłana.

Natomiast jeżeli dla uproszczenia chcemy jednak zbierać całe linie  
znaków i dopiero potem je analizować - to w takim przypadku przydadzą  
się raczej funkcje strstr, memchr i atoi/atol a nie moloch sscanf.

--  
Adam Dybkowski
               http://dybkowski.net/

We've slightly trimmed the long signature. Click to see the full one.
Re: sscanf() - co robię źle?

Quoted text here. Click to load it

Bez przesady, funkcje biblioteki standardowej nie są aż takim bloatem.  
Użycie sscanf dodaje 2kB do wynikowej binarki.

[gof@raid /tmp]$ cat test1.c
#include <stdio.h>

int main()
{
        int i;
        sscanf("test", "%d", &i);
}
[gof@raid /tmp]$ avr-gcc -mmcu=atmega8 -Os -o test1.elf test1.c
[gof@raid /tmp]$ avr-objcopy -j .text -j .data -O binary test1.elf test1.bin
[gof@raid /tmp]$ ls -l test1.bin
-rwxr-xr-x 1 gof gof 1950 02-27 10:07 test1.bin
[gof@raid /tmp]$  

Jak nie ma miejsca, to jasne że robi się różne sztuczki. Ale nie warto na  
siłę dokładać sobie pracy i tworzyć sytuacji, które mogą generować błędy,  
gdy nie ma takiej potrzeby. Co innego jakiś mały attiny z trzypoziomowym  
stosem, w którym rzeźbi się w assemblerze (chociaż w C też się da, jeżeli  
napisze się własny crt, wtedy C to bardziej zestaw makr dla assemblera),  
a co innego atmega, na którą z powodzeniem można pisać w C++ (avr-g++  
dobrze sobie radzi z optymalizacją, nie ma wprawdzie wyjątków, ale jest  
to co dla mnie najważniejsze - obiektowość i RAII).

Quoted text here. Click to load it

Ja też znam. To ekstrema. Trzeba znaleźć złoty środek. stdio to nie jest  
wg mnie aż taki bloat, żeby pisać własne automaty. To tylko odczytanie  
inta z linii.

Jak kończą się zasoby (pamięć albo limit czasu wykonania), to wiadomo,  
że przedkłada się je nad wygodę pisania i łatwość debugowania i wymyśla  
własne koło, skrojone pod konkretne rozwiązanie.

--  
"Project Manager to człowiek, który myśli, że jak weźmie  
dziewięć kobiet, to urodzą dziecko w miesiąc."

OT: (P,NMSP) Re: sscanf() - co robię źle?
Całkiem niezgodnie z Netykietą, ale nie mogłem się powstrzymać...
Quoted text here. Click to load it

Gorzej, gdy z tego wyjdzie 49 miesięcy, znając pomysły niektórych "szpecuff"  
(absolutnie nie mam na myśli nikogo z naszej grupy), to zagrożenie jest  
całkiem realne...

--  
Pod żadnym pozorem nie zezwalam na wysyłanie mi jakichkolwiek reklam,
ogłoszeń, mailingów, itd., ani nawet zapytań o możliwość ich wysyłki.
We've slightly trimmed the long signature. Click to see the full one.

Site Timeline