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

[C] Sterowanie silnikami krokowymi przez Atmega32 z portu LPT - odczyt stanów

skyline11 20 Kwi 2013 14:05 2316 13
  • #1 12220103
    skyline11
    Poziom 11  
    Problem wygląda następująco: korzystam z 4 linii danych portu LPT. Według mojego założenia, atmega powinna rozpoznawać następujące stany:

    0001
    0010
    0011
    0100
    0101
    0110
    0111
    1000

    i na ich podstawie (w czasie ich wystąpienia) realizować pewne zadania (w moim przypadku jest to sterowanie silnikami krokowymi). Aby sprawdzić stan najpierw do zmiennych zapisuję stan portu w danym momencie, a potem sprawdzając wartości zmiennych realizuję pewne zadania. Wygląda to mniej więcej tak:

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


    Jeżeli z portu lpt atmega odczyta np. taki stan :0001 to wszystko jest ok, ale jeżeli zostaje odczytany stan 0011 to silnik, który powinien się kręcić po odczytaniu przez atmegę stanu 0011 pracuje poprawnie, ale czasami występują drgania czy pojedyńcze skoki silnika, który powinien pracować przy stanie 0001. Jest jakaś możliwość pozbycia się tego błędu w inny sposób, niż zwiększenia linii danych?
  • #2 12220486
    domansolarpower
    Poziom 13  
    A sprawdź jak zachowa się sterowanie nie stanami wysokimi a stanami niskimi. Podciągnij piny atmegi wewnętrznie. Jakim napięciem zasilasz procka? Ile silników chcesz sterować z 1 atmegi? Z tego co się orientuje to prawie wszystkie (albo nawet wszystkie) sterowniki silników krokowych to 1uC-1 silnik. A sterowanie jest na przerwaniach i zboczu (zazwyczaj opadającym).
  • Pomocny post
    #3 12220747
    BlueDraco
    Specjalista - Mikrokontrolery
    Zacznij od tego:

    polecenie = PINA & 0xf;

    A potem

    switch (polecenie)
    {
    case 1:
    // wykonanie
    break;
    itd.
    }
  • #4 12222305
    Brutus_gsm
    Poziom 25  
    Kolego, znasz taką składnię jak "if... else"? Bo robienie dwóch pętli for i w jednej sprawdzanie, czy bit jest ustawiony, a w drugiej, czy wyzerowany jest co najmniej dziwne.

    Odczytuj sobie cały port jednym poleceniem, a następnie przemnóż logicznie przez 0x0F, tak jak kolega wyżej zasugerował. Oczywiście podłączasz D0 do np. PA0, żeby wagi bitów były takie same. Wtedy zmienna będzie miała wartość odczytaną z LPT. Potem zamiast IF'ów stosujesz instrukcję switch. Pamiętaj jednak, że wykonując takie operacje w pętli nieskończonej powtarzają się one co kilka milisekund (uogólnienie, wszystko zależy od taktowania procesora), więc może to działać nie do końca tak jak chcesz. Szczególnie niespodziewanych zmianach stanów na LPT.

    Zresztą nie podałeś kilku ważnych rzeczy: schematu podłączenia, ani reszty programu, która może być też ważna. Uzupełnij swój post, proszę.
  • #5 12222368
    skyline11
    Poziom 11  
    W jakim celu mam pomnożyć wszystko przez 0xF ??
  • Pomocny post
    #6 12222410
    McMonster
    Poziom 32  
    Wspomniane "pomnóż logicznie przez 0xF" znaczy tyle co "wykonaj operację bitowego AND z 0xF". Wartość 0xF to ustawione cztery najmłodsze bity, jej efektem będzie to, że na tych bitach z odczytanej wartości nic się nie zmieni, a pozostałe zawsze będą zerami.
  • #7 12222720
    Brutus_gsm
    Poziom 25  
    0x0F, (nie 0xF) - dzięki temu masz pewność, że cztery najstarsze bity zostaną wyzerowane. A to oznacza, że zmienna po tej operacji będzie przyjmować wartości od 0 do 15 i będzie odwzorowywać stan tych czterech odczytywanych linii LPT. Wtedy możesz posługiwać się już liczbami w systemie dziesiętnym, np. w instrukcji switch.
  • Pomocny post
    #8 12222799
    dondu
    Moderator na urlopie...
    Taka drobna uwaga, by skyline11 nie doszedł do złych wniosków:

    Brutus_gsm napisał:
    0x0F, (nie 0xF)

    To dokładnie to samo, choć oczywiście warto jest podawać liczbę jednobajtową za pomocą dwóch cyfr, czyli 0x0F.
    Możesz także podać tę liczbę w kodzie dwójkowym, co ułatwi zrozumienie operacji podanej przez BlueDraco:

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

    Więcej: http://mikrokontrolery.blogspot.com/2011/02/kurs-jezyka-c-operator-bitowy-and.html
  • Pomocny post
    #9 12223324
    BlueDraco
    Specjalista - Mikrokontrolery
    Brutus: 0xf to to samo, co 0x0f, 0x000f, 0x0000000f itd. Nie wypisuj bzdur, bo wprowadzasz ludzi w błąd. Procesor wszystkie liczby zapisuje wyłącznie w postaci binarnej i jest mu wszystko jedno, jakiego zapisu stałych używa programista - dziesiętnego, szesnastkowego, ósemkowego, binarnego czy znakowego. Nawet w jednej instrukcji switch możesz dla poszczególnych case użyć różnych zapisów stałych (może nie ma to sensu, ale jest całkowicie poprawne).
  • Pomocny post
    #10 12223405
    Brutus_gsm
    Poziom 25  
    BlueDraco - chyba nie do końca zrozumiałeś o co mi chodziło. Z tą tożsamością 0xF i 0x0F się zgodzę, faktycznie mój błąd. Uważam jednak, że ośmiobitowe liczby warto podawać używając dwóch znaków (w systemie szesnastkowym), a szesnastobitowe, analogicznie - czterech.

    Wiem o tym, że programista może sobie używać systemu zapisu jaki mu się żywnie podoba. Chodziło mi o to, że autor tematu będzie mógł używać zapisu dziesiętnego w instrukcji case (który jest dla ludzi chyba bardziej intuicyjny), gdyż będzie pewien, że cztery najstarsze bity są wyzerowane i w sytuacji, gdy np. wszystkie odczytane wyjścia LPT będą w stanie wysokim, zmienna będzie miała wartość na pewno 15, a nie np. 31 czy 47.

    Oczywiście można to rozwiązać na tysiąc sposobów, nie przeczę. Chciałem tylko podpowiedzieć autorowi tematu, że zamiast takiej instrukcji:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    będzie mógł po prostu użyć:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

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


    Oczywiście ile osób, tyle pomysłów.Może faktycznie za bardzo zamotałem, a może i wcale nie pomogłem, ale nigdy mi nie chodziło o to, żeby przekonywać kogoś, że zmienna zapisana dziesiętnie różni się od tej zapisanej szesnastkowo ;)W zasadzie, to starałem się wyjaśnić kod, który ty podałeś w drugim poście - może nie do końca mi to wyszło ;)
  • #11 12223976
    skyline11
    Poziom 11  
    Tak myślałem, że należy cały port zapisać do jednej zmiennej, tylko nie byłem pewny czy po zapisaniu do zmiennej liczby binarnej mogę korzystać z niej jako dziesiętna. Jeszcze pytanko z tym mnożeniem, jeżeli po pomnożeniu wartość liczby się nie zmieni, to po co ją w ogóle mnożymy? :D
  • Pomocny post
    #12 12224081
    pawel_mr
    Poziom 15  
    skyline11 napisał:
    Tak myślałem, że należy cały port zapisać do jednej zmiennej, tylko nie byłem pewny czy po zapisaniu do zmiennej liczby binarnej mogę korzystać z niej jako dziesiętna. Jeszcze pytanko z tym mnożeniem, jeżeli po pomnożeniu wartość liczby się nie zmieni, to po co ją w ogóle mnożymy? :D

    Chyba nie do końca dokładnie przeczytałeś posty wyżej. McMonster napisał Ci, że:
    Cytat:
    Wspomniane "pomnóż logicznie przez 0xF" znaczy tyle co "wykonaj operację bitowego AND z 0xF". Wartość 0xF to ustawione cztery najmłodsze bity, jej efektem będzie to, że na tych bitach z odczytanej wartości nic się nie zmieni, a pozostałe zawsze będą zerami.

    Czyli nie zmienią się cztery najmłodsze bity, reszta jest zerowana, żeby nie wprowadzać ewentualnego błędu, gdyby te starsze bity na porcie były wykorzystywane do innych celów. Oczywiście to czy mnożyć czy nie zależy od tego jak później będziesz badał zmienną (czy poszczególne bity czy całą jej wartość).
  • Pomocny post
    #13 12224201
    BlueDraco
    Specjalista - Mikrokontrolery
    Na szczęście procesor nie wie, co to jest liczba dziesiętna, więc nie ma rozterek z tym związanych - czytaj wyżej.
  • #14 12229481
    skyline11
    Poziom 11  
    Działa, zamykam.
REKLAMA