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

Odczyt adresu IP z EEPROM AT24C32 na Atmega328 w języku C

jaros85 05 Maj 2012 19:44 2415 10
  • #1 10864059
    jaros85
    Poziom 20  
    Witam wszystkich.
    Mam taki problem do EEPROM-u zapisałem następujące dane:
    adres IP (192.168.0.250), maskę podsieci, bramę, DNS oraz adres MAC (zapis szesnastkowy liter z kodu ASCII) w sposób dziesiętny czyli każda komórka zawiera kolejną wartość pod adresem 0x00 jest 192 pod 0x01 jest 168 pod 0x02 jest 0 pod 0x03 jest 250 i tak dalej.

    Sprawa się komplikuje kiedy chcę odczytać np cały adres IP i zapisać go do tablicy.

    Biblioteka
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Funkcja wywoływana
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Główny kod
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Po wysłaniu tych danych tablic przez RS232 w terminalu widać same śmieci.
    Jeżeli odczytam tylko jedną komórkę pamięci i wyślę ją przez RS232 wartości liczbowe wyświetlają się prawidłowo zamiast adresu MAC wyświetlają się litery z kodu ASCII ale właśnie takie miało być założenie.

    Chciałbym aby po odczycie danych z EEPROM-u dane w każdej z tablic zapisane były następująco:
    uint8_t MAC[6] = {0x4A,0x61,0x72,0x65,0x6B,0x53};
    uint8_t IP[4] = {192,168,0,250};
    itp.

    Jeżeli takie tablice jak wyżej wyślę przez RS232 ich zawartość wyświetlana jest prawidłowo ale moja procedura odczytu z EEPROM-u nie działa i te wartości nie są wyświetlane.

    Gdzie popełniłem błąd wiem że gdzieś w procedurze zapisu do tablicy ale sam kod kompiluje się prawidłowo.
  • #2 10865394
    y0yster
    Poziom 19  
    Jak sam napisałeś nie masz problemu z odczytem jednego bajtu. Problem może być właśnie tutaj. Urządzenia pracujące z wykorzystaniem magistrali I2C wymagają odpowiedniej sekwencji potwierdzeń i ich braku przy odczycie większej ilości bajtów.

    Niektóre urządzenie w ogóle nie zwracają uwagi na ACK, czy NACK. Wysyłają dane jedna po drugiej.
  • #3 10865444
    jaros85
    Poziom 20  
    Sam odczyt sekwencyjny działa i działa rozpoznawanie sygnałów AKC i NACK wysyłanych przez EEPROM.
    Jeżeli napiszę program który sekwencyjnie odczytuje bajt po bajcie i każdy z tych bajtów wysyłany jest oddzielnie przez RS232 to wszystko działa prawidłowo. Gorzej jest jeżeli zaczynam te dane zapisywać do tablicy.

    Czy taka instrukcja jest prawidłowa :?:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wydaje mi się że w tym miejscu może być problem chociaż jak mówiłem kompiluje się prawidłowo.
  • #4 10865458
    y0yster
    Poziom 19  
    jaros85 napisał:

    Czy taka instrukcja jest prawidłowa :?:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Zwracanie wartości jest tutaj nadmiarowe i nie potrzebne, ponieważ masz to już w tej tablicy.

    Masz:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Spróbuj tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Problem jest tutaj taki, że pierwsza deklaracja przekazuje dane do funkcji przez wartość, czyli kopiuje dane. Także wszystko co zostanie wykonane w ciele funkcji nie będzie widziane na zewnątrz. Natomiast druga deklaracja przekazuje adres, a nie kopiuje dane.
  • #5 10886246
    jaros85
    Poziom 20  
    Ostatnio byłem zajęty i nie miałem kiedy sprawdzić tego algorytmu.

    Niestety po zmianie kompilator wysypuje sporo błędów:
    warning: passing argument 3 of 'odczyt_stronicowy' from incompatible pointer type
    dla instrukcji
    odczyt_stronicowy(0, 6, MAC);
    
    warning: assignment makes pointer from integer without a cast 
    dla linijek
    odczyt[i]=READ_TWI(1);
    i
    odczyt[i+1]=READ_TWI(0);


    Chyba też z tym wskaźnikiem już kombinowałem i jest nie ciekawie ale jakoś chyba można to zrobić :?:
  • Pomocny post
    #6 10888941
    y0yster
    Poziom 19  
    jaros85 napisał:

    warning: passing argument 3 of 'odczyt_stronicowy' from incompatible pointer type
    dla instrukcji
    odczyt_stronicowy(0, 6, MAC);



    Musisz wywołać funkcję w ten sposób:

    
    odczyt_stronicowy(0, 6, &(MAC[0]));
    


    Jeśli chodzi o :

    jaros85 napisał:

    
    warning: assignment makes pointer from integer without a cast 
    dla linijek
    odczyt[i]=READ_TWI(1);
    i
    odczyt[i+1]=READ_TWI(0);



    możesz wywołać to w ten sposób:

    
    *(odczyt + i) = READ_TWI(1);
    


    Jeśli chodzi o ostrzeżenie, które wyrzuca kompilator to, aby go się pozbyć musisz odpowiednio rzutować typy, a nie pozostawiać kompilatorowi "pewnej dowolności" w rzutowaniu.
  • #7 10914058
    jaros85
    Poziom 20  
    Wielkie dzięki za pomoc udało się teraz odczytuje całą tablicę prawidłowo :D .

    Mam tylko problem z interpretacją znaków w terminalu ale teraz już sobie chyba z tym poradzę.
  • #9 10914788
    jaros85
    Poziom 20  
    Jeżeli chodzi o konwersie bin na dec i wysłanie tego przez rs232 to chyba nie powinienem mieć problemów.
    Nie wiem jak ugryźć adres MAC. Jak go wysyłam przez rs232 to w oknie terminala wyświetlają mi się litery z tego kodu a ja nie chcę liter tylko chcę wyświetlić ich wartość szesnastkową z kodu ASCII.
    Czyli jak w tablicy mam zapis [4A,61,72,65,6B,53] i wyślę to bezpośrednio to otrzymam tekst JarekS a ja właśnie chcę te wartości szesnastkowe uzyskać.

    Mam jeszcze drugi problem dotyczący komunikacji 1-Wire. Ten sam procesor taktowany zegarem 20MHz i jeżeli skompiluje kod w AVR Studio to komunikacja działa a jak skompiluje w Eclipse to już nie działa. Ten sam procesor w ustawieniach jest, ta sama wartość zegara ustawiona i nic nie chodzi :?:

    Wynik pomiaru wysyłam przez rs232.
    Używam Ecilpsa ponieważ kod głóny jest w nim napisany i sporo by czasu zajęło przerobienie tego żeby można było kompilować pod AVRStudio.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #10 10915559
    y0yster
    Poziom 19  
    Co do wysyłana szesnastkowych wartości przez RS'a.

    Możesz użyć funkcji sprintf();

    Wyglądało by to następująco:

    sprintf ( Bufor, "%X:%X:%X:%X:%X:%X", MAC[0], MAC[1] .......);

    Bufor powinien mieć wielkość 6*3 bajtów. Zostanie w nim zapisana np. tak postać:

    "0C:2A:......"

    Aby wykorzystać tą procedurę musisz dołączyć stdio.h. Tu pojawiają się pewne schody. Po dołączeniu w/w nagłówka zajętość pamięci w małym mikrokontrolerze podskoczy o około 2kB. Pewną alternatywą jest samodzielne napisanie funkcji, która będzie realizować to co chcesz, a jest to zamiana liczby na jej szesnastkowy odpowiednik zapisany jako tekst.

    Jeśli chodzi o kompilację w Eclipsie, a AVR Studio mogą być dwie przyczyny jakie w tym momencie nasuwają mi się na myśl.

    Pierwsza to ustawienie kompilatora. Zapewne używasz Win-AVR. Zobacz, czy czasem nie masz włączonej optymalizacji na innym poziomie niż w AVR Studio.

    Druga sprawa jest następująca. Transmisja One-Wire opiera się na opóźnieniach. Napisałeś, że uC jest taktowany z prędkością 20MHz. Jeśli wykorzystujesz funkcje z biblioteki delay.h jak _delay_us() to pamiętaj, że wartość jaką przekazujesz przez argument nie może być większa niż stała. Stała ta jest uzależniona od częstotliwości. Dokładniej jest to opisane właśnie w w/w pliku. Jednakże bezpośrednio może to Ciebie nie dotyczyć. Taka rada na przyszłość.

    Pozdrawiam.
  • #11 10923938
    jaros85
    Poziom 20  
    Jeszcze raz dziękuję za pomoc udało mi się uruchomić magistralę 1-wire rzeczywiście problem leżał w optymalizacji kodu przez kompilator.
    Zmieniłem w Eclipse z (-00 czyli brak optymalizacji) na (-0s optymalizację rozmiaru) i zadziałało. Sam bym nigdy nie pomyślał że stopień optymalizacji może aż tak drastycznie wpływać na działanie kodu.

    Co do reszty bibliotekę stdio.h już mam dodaną bo coś z niej potrzebowałem więc zobaczymy co uda mi się zrobić z tą funkcją sprontf(). Ostatnio mam mało czasu ale postaram się coś wymyślić i pochwalę się kodem :D

    Jeszcze raz dzięki y0yster za pomoc.
REKLAMA