robię źle?

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?

Reply to
Atlantis
Loading thread data ...

Dnia Sat, 23 Feb 2013 13:02:00 +0100, Atlantis napisał(a):

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

Ja bym sie juz w to \r nie bawil.

Wyglada na to ze poprawnie wszystko.

formatting link
sprawdz jeszcze raz czy _wszystko_ jest poprawnie, no i co zwraca sscanf ? tablica jest tablica znakow, zmienna_int zmienna int itp ?

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

ale powinno.

J.

Reply to
J.F.

On 2013-02-23 13:02, Atlantis wrote: [...]

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\0"; const char *tablica2 = "+CSQ: 123, 010\r\0";

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 *******************/

Reply to
JDX

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

Reply to
shg

Mozna zawsze isc po bandzie ;-)

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

Pozdrawiam

Marek

Reply to
Marek Borowski

W dniu 2013-02-23 20:55, Marek Borowski pisze:

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. :)

Reply to
Atlantis

Dnia Sat, 23 Feb 2013 22:07:25 +0100, Atlantis napisał(a):

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

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

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

J.

Reply to
J.F.

W dniu 2013-02-24 12:12, J.F. pisze:

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.
Reply to
Atlantis

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

Reply to
Pszemol

W dniu 2013-02-24 14:27, Pszemol pisze:

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ę.

Reply to
Atlantis

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).

Reply to
Adam Wysocki

avr-libc ma normalnego malloca, żaden placeholder.

Reply to
Adam Wysocki

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.

Reply to
Adam Wysocki

W dniu 2013-02-25 12:00 Adam Wysocki napisał(a):

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.

Reply to
Adam Dybkowski

Całkiem niezgodnie z Netykietą, ale nie mogłem się powstrzymać... Użytkownik "Adam Wysocki" snipped-for-privacy@somewhere.invalid napisał w wiadomości news: snipped-for-privacy@news.chmurka.net...

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...

Reply to
Anerys

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).

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.

Reply to
Adam Wysocki

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.