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

wyciagniecie jednago bajta z LONG lub DOUBLE

Gostek 01 Lip 2010 15:38 1884 20
  • #1 8251012
    Gostek
    Poziom 17  
    Witam,

    Problem jest raczej laicki , ale mnie dzis zmeczyl:

    Mam zmienna LONG ( w ktorej jest 32bitowy adres ) i chce wyciagnac tylko najmlodsze 8 bitow, czyli n.p.

    uint32_t adres;
    uint8_t bajt;

    bajt = adres; // jesli adres jest typu uint16_t, to nie ma problemu,ale z uint32_t nie dziala...
  • #3 8251064
    Gostek
    Poziom 17  
    No wlasnie dlatego rwe wlosy z glowy.

    jesli adres = 0x00000002
    to bajt ma wartosc 0x00 :/


    nawet jesli za bajt podstawie PORTA z ledami, to widze ( nie widze ) nic
  • #5 8251103
    Gostek
    Poziom 17  
    proc9 napisał:
    To może coś w tym stylu:

    uint32_t adres;
    uint8_t bajt;
    
    bajt = adres & 0xFF;


    To powinno działać.
    Pozdrawiam


    Juz sprawdzalem - nie dziala :o
  • #6 8251112
    proc9
    Poziom 14  
    Nie wiem jaki to dokładnie kod, ale skoro to nie działa to możliwe że kompilator za bardzo zoptymalizował tą część. Warto spróbować zadeklarować te zmienne jako "volatile".
  • #7 8251139
    Gostek
    Poziom 17  
    To tez nie pomaga, optymalizacje tez zmienialm - nic...
    avr-gcc

    Ratujcie moje wlosy...
  • #8 8251279
    m.bartczak
    Poziom 16  
    Nie mam kompilatora pod ręką, ale może coś takiego:

    
    bajt = ((uint8_t*)(&adres))[0]; ?
    


    Update: Zmieniłem 3 na 0, bo z tego co pamiętam 8 bitowy AVR to Little Endian...
  • #9 8251362
    nenpa8lo
    Poziom 17  
    Jeżeli do 'adres' przypisujesz sztywne 0x2 to może być błąd kompilatora, już kiedyś się spotkałem z bykiem IAR gdzie 1<<16 robiło mi na 32bit zmiennej unsigned liczbę ujemną ( o zgrozo ).
    Możliwe także, że optymalizacja poszła w ruch. A najlepiej to pokaż większy kawałek kodu bo to co pokazujesz musi działać, więc błąd jest gdzieś indziej.

    Dodano po 1 [minuty]:

    Czy uint32_t sam zdefiniowałeś, jeżeli tak to pokaż define.
  • #10 8251697
    markosik20
    Poziom 33  
    nenpa8lo napisał:
    Jeżeli do 'adres' przypisujesz sztywne 0x2 to może być błąd kompilatora, już kiedyś się spotkałem z bykiem IAR gdzie 1<<16 robiło mi na 32bit zmiennej unsigned liczbę ujemną ( o zgrozo ).


    No nie przesadzajmy...w takim podstawowym przypisaniu błąd? W jaki sposób autor sprawdza wartość tego bajtu? Jeżeli nic dalej nie jest "robione" z tą zmienną to włączona optymalizacja może po prostu zignorować to przypisanie.
  • #11 8252226
    rpal
    Poziom 27  
    kolego sposobów jest bez liku ale moim zdaniem najprostszy to zastosowanie unii dla przykładu
    
    union {
    	unsigned long int duza_liczba;
    	unsigned char bajty[4];
    } wyciagnij;
    

    masz już zadeklarowaną tablicę wewnątrz unii i gdzie tak sama liczba typu long int jak i 4 elementy jej tablicy zajmują ten sam obszar pamięci z tą różnicą że można się do nich odwoływac na różne sposoby. Jeśli użyjesz następującego odwołania wewnątrz programu
    
    wyciagnij.bajty[1]=1;
    

    to liczba long int przyjmie wartosc 256 i podobnie będzie na innych elementach tablic oraz "szprzężonej" z nią liczby long int. Jest też odwrotnie bo jeśli przywołasz coś takiego
    wyciagnij.duza_liczba = 257;
    

    to element tablicy wyciagnij.bajty[0] oraz wyciagnij.bajty[1] przyjmą wartosc 1 i w ten sposob najprosciej możesz wyłuskiwac poszczególne bajty składające się na daną liczbę (w tym przypadku 4 bajty) bez żadnych przesunięć bitów czy operacji logiczny. Proste i przyjemne. Zapuść symulator i zobaczysz jakie cuda się dzieją na poszczególnych bitach twojej dużej liczby kiedy to zmieniasz elementy tablicy :)
  • #12 8252267
    Gostek
    Poziom 17  
    markosik20 napisał:
    nenpa8lo napisał:
    Jeżeli do 'adres' przypisujesz sztywne 0x2 to może być błąd kompilatora, już kiedyś się spotkałem z bykiem IAR gdzie 1<<16 robiło mi na 32bit zmiennej unsigned liczbę ujemną ( o zgrozo ).


    No nie przesadzajmy...w takim podstawowym przypisaniu błąd? W jaki sposób autor sprawdza wartość tego bajtu? Jeżeli nic dalej nie jest "robione" z tą zmienną to włączona optymalizacja może po prostu zignorować to przypisanie.


    Oto kawalek:
    
    //********************************************************************************
    //* Name    : ReadData                                                           
    //* Purpose : Read Data from S1D13781 memory           							 
    //* IN		:
    //* 	adr		/ UINT32 / 
    //*
    //* OUT		:
    //*		data 	/ UINR16 /
    //******************************************************************************** 
    uint16_t S1D13781_ReadData( uint32_t adr)
    {
    	UCHAR data;	
    
    
    
    	
    	CTRL_PORT ClrBit ( PC );
    	CTRL_PORT ClrBit ( CS );
    
    
    	S1D13781_WriteByte( adr );					// first byte of address
    	S1D13781_WriteByte( 0x08 );					// second byte of address
    	S1D13781_WriteByte( 0x06 );					// third byte of address
    
    	CTRL_PORT SetBit ( PC );
    
    	data = S1D13781_ReadByte();
    
    	CTRL_PORT SetBit ( CS );
    
    	return data;
    }
    

    narazie reszta adresu jest ustawiona na sztywno, ale docelowo ma byc rozbita.
    Zreszta, tak jak napisalem wyzej, nawet kiedy skieruje to prosto na port, to tez nic tam nie wychodzi.
    sam nic nie deklarowalem, ale nawet z [unsigned long int] jest to samo.
    0x02 przypisywalem na sztywno ( w ramach testu )

    Dodano po 8 [minuty]:

    rpal napisał:
    kolego sposobów jest bez liku ale moim zdaniem najprostszy to zastosowanie unii dla przykładu
    
    union {
    	unsigned long int duza_liczba;
    	unsigned char bajty[4];
    } wyciagnij;
    

    masz już zadeklarowaną tablicę wewnątrz unii i gdzie tak sama liczba typu long int jak i 4 elementy jej tablicy zajmują ten sam obszar pamięci z tą różnicą że można się do nich odwoływac na różne sposoby. Jeśli użyjesz następującego odwołania wewnątrz programu
    
    wyciagnij.bajty[1]=1;
    

    to liczba long int przyjmie wartosc 256 i podobnie będzie na innych elementach tablic oraz "szprzężonej" z nią liczby long int. Jest też odwrotnie bo jeśli przywołasz coś takiego
    wyciagnij.duza_liczba = 257;
    

    to element tablicy wyciagnij.bajty[0] oraz wyciagnij.bajty[1] przyjmą wartosc 1 i w ten sposob najprosciej możesz wyłuskiwac poszczególne bajty składające się na daną liczbę (w tym przypadku 4 bajty) bez żadnych przesunięć bitów czy operacji logiczny. Proste i przyjemne. Zapuść symulator i zobaczysz jakie cuda się dzieją na poszczególnych bitach twojej dużej liczby kiedy to zmieniasz elementy tablicy :)


    :D to wyglada zachecajaco. Ze tez o tym nie pomyslalem :D I chyba mozna zaoszczedzic duzo cykli ( zamiast shitftowania ). Sprawdze to jutro rano w pracy.
  • #13 8252308
    rpal
    Poziom 27  
    w czym jest zatem problem przekazujesz swój adres do funkcji , w niej deklarujesz unię i przypisujesz liczbie long ten adres, kolejne S1D13781_WriteByte() używa jako argumentu po kolei wartości tablicy z unii, adres możesz sobei już brac choćby z księżyca bo wiadomo że będzie poprawnie przekazany? Po wyjściu z fukcji zwlaniane są zasoby pamięci i po kłopocie.
  • #14 8252345
    Gostek
    Poziom 17  
    rpal napisał:
    w czym jest zatem problem przekazujesz swój adres do funkcji , w niej deklarujesz unię i przypisujesz liczbie long ten adres, kolejne S1D13781_WriteByte() używa jako argumentu po kolei wartości tablicy z unii, adres możesz sobei już brac choćby z księżyca bo wiadomo że będzie poprawnie przekazany? Po wyjściu z fukcji zwlaniane są zasoby pamięci i po kłopocie.


    Teraz to juz nie widze zadnego problemu :) A rano to zmontuje.
  • #16 8252372
    Freddie Chopin
    Specjalista - Mikrokontrolery
    To nie ma żadnego znaczenia którym sposobem to zrobisz - kompilator na 99% zrobi z tego identyczny kod assemblera. Dla testów jednak sprawdzałbym wyciąganie bajtów z liczby typu 0x01020304, wtedy będziesz widział czy cokolwiek się dzieje.

    4\/3!!
  • #17 8252390
    Gostek
    Poziom 17  
    markosik20 napisał:
    A funkcję wywołujesz jak?

    S1D13781_ReadData(0x00000002) ? 


    wywolywalem i tak
    S1D13781_ReadData(0x00000002);
    i tak
    S1D13781_ReadData(0x02);


    brak roznicy.

    Dodano po 6 [minuty]:

    Freddie Chopin napisał:
    To nie ma żadnego znaczenia którym sposobem to zrobisz - kompilator na 99% zrobi z tego identyczny kod assemblera. Dla testów jednak sprawdzałbym wyciąganie bajtów z liczby typu 0x01020304, wtedy będziesz widział czy cokolwiek się dzieje.

    4\/3!!


    A z tego 0xAABBCCDD, wyciagalo mi chyba BB, ale tylko jak AA mialo jakas wartosc... jakas magia, albo klatwa chyba.
    ( ale teraz juz dokladnie nie pamietam, tez rano moge sprawdzic ).

    Piszesz, ze kompilator zrobi taki sam kod jak bede wyciagal bajty z unii albo bede je shiftowal ? Przy shifcie jest chyba wykonywane mnozenie, wiec pochlania to wiecej cykli. A moze sie myle..
  • #18 8252442
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Ale jaki shift? Przecież kompilator po to został wymyślony, żeby kod optymalizować. Przy braku optymalizacji może faktycznie wynik będzie różny, ale jeśli ją włączysz, to na 99% będzie identyczny. Jeśli chcesz wyciągnąć jakiś bajt (cały, a nie np bajt przesunięty o 3 bity), to procesor musi przecież zrobić dokładnie to samo jakkolwiek byś tego nie napisał.

    4\/3!!
  • #19 8253303
    Gostek
    Poziom 17  
    No, a wiec tak. Jesli wszystko co bylo napisane na gorze jes umieszczone w pliku glownym /main/ to dziala jak nalezy.
    Jesli :
    uint16_t S1D13781_ReadData( uint32_t adr)
    { .....


    Jest umieszczone w innym pliku, to niedziala....( nie dzialalo )

    Problem juz rozwiazany, a mianowicie nie wpisalem deklaracji
    uint16_t S1D13781_ReadData( uint32_t adr)
    w naglowku....

    Wszystko dziala tak jak wszyscy pisali ze ma dzialac, ze mnie dupa, ze zapomnialem o tym z roztargnienia chyba...
  • #21 8253355
    Gostek
    Poziom 17  
    Prawie zgadles. Unikam warningow jak ognia, ale tym razem problem mnie tak zaslepil , ze na nic wiecej juz nie patrzylem .


    Pozatym czasami sa warningi typu "unused variable" , ktore swiadomie ignorujesz, bo np tyczasowo cos w kodzie skasowales. Niestety czasami mozna zapomniec o innych :)
REKLAMA