Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[MSP430/IAR] Jak odczytać stan linii / rejestru ?

smokFAFI 13 Sty 2012 18:50 1886 8
  • #1 13 Sty 2012 18:50
    smokFAFI
    Poziom 7  

    Witam :)
    Mam pewien problem, który dotyczy odczytania aktualnego stanu linii danych / rejestru. Korzystam z MSP430 (msp430f149) i środowiska IAR.

    Zakładając, że dioda led jest podpięta pod P2.1 piszę następujący kod:

    Code:

    P2DIR |= BIT1; // ustawiam odpowiedni kierunek aby móc ustawić diode
    P2OUT &= ~BIT1; // 0 czyli w zapala diode

    //teraz sprawdzam stan rejestru, dioda pali się a więc powinno być 0 na linii
    // WYSLIJ_NA_LCD to POPRAWNA (!!!) funkcja która wysyła znak na ekran lcd, jest na 100% poprawna!

    if(P2OUT&BIT1 == 0) WYSLIJ_NA_LCD('0');
    if(P2OUT&BIT1 == 1) WYSLIJ_NA_LCD('1');


    Jeżeli zamiast powyższych dwóch instrukcji warunkowych if napiszę to:
    Code:

    if(P2OUT&BIT1 == 0) WYSLIJ_NA_LCD('0');
    else if(P2OUT&BIT1 == 1) WYSLIJ_NA_LCD('1');
    else WYSLIJ_NA_LCD('?');

    to zawsze wypisuje mi znak zapytania, czyli wykonuje else, hmm ? :)

    Program kończy działanie i nie wyświetla nic na ekran, dlaczego ?

    Kombinowałem oczywiście z P2DIR i P2OUT chyba na wszystkie kombinacje ale wg. mnie to co napisałem powyżej jest poprawne dlatego wybrałem ten fragment kodu.

    Czytałem, że pomiędzy sprawdzeniami rejestrów musi być przerwa a więc dałem pętle odliczającą, ale nie przyniosło to pożądanych efektów.

    Dioda działa poprawnie. Ten sam problem z czytaniem stanu linii mam min. z czujnikiem DS18B20, bo pomimo ustawienia linii danych na poziom 0 lub 1 nie mogę odczytać jego stanu chwilę potem.

    Proszę o pomoc.
    Pozdrawiam.

    0 8
  • Pomocny post
    #2 13 Sty 2012 19:54
    94075
    Użytkownik usunął konto  
  • #3 14 Sty 2012 14:50
    smokFAFI
    Poziom 7  

    albertb napisał:
    Nie masz problemu z czytaniem portu.
    Masz problem ze znajomością C / działań logicznych

    P2OUT & BIT1 nigdy nie będzie miało wartości 1
    Natomiast trochę inna sprawa z DS1820.
    Tam musisz przestawiać linię na wejście ze względu na zasadę działania.
    To dobrze opisują noty aplikacyjne

    Albert


    Czy mógłbyś rozwinąć swoją myśl ? Odczytując dla czujnika stan przestawiam rejestr DIR ale nie przynosi to żadnego rezultatu, napiszę jak to robię i proszę Cię o poprawę gdzie robię błąd.

    Linia danych dla DS18B20 w moim przypadku to P1.7 i robię to w ten sposób:

    Code:

    P1DIR |= BIT7; // teraz mogę ustawić linie na stan wysoki
    P1OUT |= BIT7; // zmieniam stan linii na wysoki

    P1DIT &= ~BIT7; // dzięki temu mam możliwość odczytu
    if(P1IN&BIT7==0) WYSLIJ_NA_LCD('0');
    if(P1IN&BIT7==1) WYSLIJ_NA_LCD('1');
    else WYSLIJ_NA_LCD('?');



    W powyższym kodzie pominąłem fakt zastosowania oczekiwania dla poszczególnych operacji tj. reset, czytanie, zapisywanie dla ds18b20, bo jedyne co chce na razie osiągnąć to odczytać wartość stanu linii i nie istotne czy mi przeskoczy na 0 czy 1.

    Dlaczego nie mogę w powyższy sposób uzyskać stanu linii ?

    0
  • Pomocny post
    #4 14 Sty 2012 14:53
    BoskiDialer
    Poziom 34  

    Priorytety operatorów: kod "P1IN&BIT7==0" jest interpretowany jako "P1IN & (BIT7==0)" co może być bez sensu.

    -- edit:
    "P1IN&BIT7==0" jest bez sensu, gdyż będzie interpretowane jako "P1IN & (BIT7==0)", BIT7 jest najprawdopodobniej równe 0x80, równość nie jest spełniona a więc instrukcja jest równoważna "P1IN & 0", co zawsze jest fałszywe (równe 0).

    "P1IN&BIT7==1" jest bez sensu podobnie jak poprzednie, ale dodatkowo występuje porównanie do jedynki, co jest niebezpieczne - albo powinno się użyć sprawdzenia nierówności do zera, albo równości do BIT7 (preferuję test (P1IN & BIT7) != 0)

    0
  • #5 14 Sty 2012 23:16
    smokFAFI
    Poziom 7  

    BoskiDialer napisał:
    Priorytety operatorów: kod "P1IN&BIT7==0" jest interpretowany jako "P1IN & (BIT7==0)" co może być bez sensu.

    -- edit:
    "P1IN&BIT7==0" jest bez sensu, gdyż będzie interpretowane jako "P1IN & (BIT7==0)", BIT7 jest najprawdopodobniej równe 0x80, równość nie jest spełniona a więc instrukcja jest równoważna "P1IN & 0", co zawsze jest fałszywe (równe 0).

    "P1IN&BIT7==1" jest bez sensu podobnie jak poprzednie, ale dodatkowo występuje porównanie do jedynki, co jest niebezpieczne - albo powinno się użyć sprawdzenia nierówności do zera, albo równości do BIT7 (preferuję test (P1IN & BIT7) != 0)


    Czyli ten, poprawiony kod powinien działać poprawnie, tak ?

    Code:
    P1DIR |= BIT7; // teraz mogę ustawić linie na stan wysoki
    
    P1OUT |= BIT7; // zmieniam stan linii na wysoki

    P1DIT &= ~BIT7; // dzięki temu mam możliwość odczytu
    if((P1IN&BIT7)==0) WYSLIJ_NA_LCD('0');
    if((P1IN&BIT7)!=0) WYSLIJ_NA_LCD('1');
    else WYSLIJ_NA_LCD('?');


    Zawsze uzyskam w ten sposób odpowiedni stan linii danych ?

    A czy jesteś w stanie krótko napisać dlaczego porównanie stanu do jedynki jest niebezpieczne, z czego to wynika ? Skoro mamy dwa stany (0,1) to jaka jest różnica do którego porównamy i czy to będzie równość lub nierówność do 0 lub 1 ?

    Dzięki za pomoc, pozdrawiam.

    0
  • Pomocny post
    #6 14 Sty 2012 23:53
    BoskiDialer
    Poziom 34  

    Jeśli BIT7 jest równe 0x80, to zauważ, że wyrażenie (P1IN & BIT7) może przyjmować dwie wartości: 0x00 lub 0x80. Stąd przyrównanie do jedynki jest niepoprawne, nigdy taka wartość nie wystąpi. Niebezpieczeństwo wynika z tego, że jeśli maska będzie równa 0x01, to kod będzie działać, co nie przekłada się na inne wartości maski (np właśnie na 0x80).

    0
  • #7 15 Sty 2012 01:03
    smokFAFI
    Poziom 7  

    BoskiDialer napisał:
    Jeśli BIT7 jest równe 0x80, to zauważ, że wyrażenie (P1IN & BIT7) może przyjmować dwie wartości: 0x00 lub 0x80. Stąd przyrównanie do jedynki jest niepoprawne, nigdy taka wartość nie wystąpi. Niebezpieczeństwo wynika z tego, że jeśli maska będzie równa 0x01, to kod będzie działać, co nie przekłada się na inne wartości maski (np właśnie na 0x80).


    Rozumiem, czyli jeżeli linia przyjmuje wartość inną niż 0 to jest w stanie wysokim, a jeżeli w stanie niskim to przyjmuje standardowo 0 i poniższy kod jest poprawny, tak ?

    Code:
    P1DIR |= BIT7; // teraz mogę ustawić linie na stan wysoki
    
    P1OUT |= BIT7; // zmieniam stan linii na wysoki

    P1DIT &= ~BIT7; // dzięki temu mam możliwość odczytu
    if((P1IN&BIT7)==0) WYSLIJ_NA_LCD('0');
    else if((P1IN&BIT7)!=0) WYSLIJ_NA_LCD('1');
    else WYSLIJ_NA_LCD('?');

    0
  • Pomocny post
    #8 15 Sty 2012 09:15
    BoskiDialer
    Poziom 34  

    Jeśli trzeba sprawdzić wartość konkretnego bitu, to żeby nie mnożyć kodu przesuwając testowany bit do prawej, nakłada się tylko maskę na wartość, bit zostawia się w miejscu gdzie był. Konsekwencją nieprzesuwania jest to, że bit mający wartość równą 1 powoduje, że całe wyrażenie (zawierające testowany bit oraz inne bity, które nas nie interesują) może mieć wartość różną od jedynki (gdy testowany bit nie jest LSB).
    To tłumaczy czemu lepiej jest używać testu równości/nierówności względem zera w każdym przypadku - kod jest niezależny od położenia testowanego bitu.

    0
  • #9 15 Sty 2012 12:56
    smokFAFI
    Poziom 7  

    BoskiDialer napisał:
    Jeśli trzeba sprawdzić wartość konkretnego bitu, to żeby nie mnożyć kodu przesuwając testowany bit do prawej, nakłada się tylko maskę na wartość, bit zostawia się w miejscu gdzie był. Konsekwencją nieprzesuwania jest to, że bit mający wartość równą 1 powoduje, że całe wyrażenie (zawierające testowany bit oraz inne bity, które nas nie interesują) może mieć wartość różną od jedynki (gdy testowany bit nie jest LSB).
    To tłumaczy czemu lepiej jest używać testu równości/nierówności względem zera w każdym przypadku - kod jest niezależny od położenia testowanego bitu.


    Dzięki za wytłumaczenie :D

    0