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

[WinAPI] WinAPI: Jak wykryć nowe znaki w buforze portu szeregowego?

achilles 17 Lis 2004 15:44 2742 11
REKLAMA
  • #1 992477
    achilles
    Poziom 15  
    Posty: 212
    Ocena: 6
    Czy jest jakiś komunikat w windowsie, który tworzony jest w przypadku wystąpienia takiego zdarzenia jak pojawienie się danego znaku w buforze wejśćiowym portu szeregowego?
    Jeśli nie ma takiego komunikatu to czy jedynym rozwiązniem jest utworzenie jakiegoś Timera, który cyklicznie co jakiś czas będzie sprawdzał, czy nic nowego nie pojawiło się w buforze, czy może sa inne, jakieś bardziej optymalne rozwiązania?
    Jeśli ktoś coś wie to dzięki za radę.
    Pozdrawiam.
    HEJ.

    Zamykam. - arnoldziq
  • REKLAMA
  • #2 992555
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 41
    Ja to robie tak: uruchamiam nowy watek (funkcja CreateThread()) w ktorym w petli caly czas czytam z com-a a w orginalnym watku robie reszte rzeczy (obsluga okien itp.).Po otrzymaniu danych mozesz wyslac do okna jakis komunikat za pomoca SendMessage() i tam obsluzyc to zdarzenie.Jest jeszcze kilka innych metod na postepowanie z czytaniem z portu szeregowego np:poprzez ustawienie w funkcji CreateFile flagi FILE_FLAG_OVERLAPPED ktora powoduje ze uchwyt pliku nabiera wlasciowsci asynchronicznych (nie blokujacych) i wowczas mozna umiescic funkcje ReadFile w glownej petli programu czekajac na odpowiednia ilosc bajtow.Sa jeszcze dostepne zdarzenia przyjscia pierwszego bajtu itp. (ustawiane za pomoca funkcji SetCommMask()) ale nie sa one wysylane jako komunikaty okna i i tak trzeba je sprawdzac za pomoca funkcji WaitCommEvent wiec maly z niej pozytek.Twoj pomysl tez jest do zrealizowania tzn. za pomoca SetTimer mozna utworzyc sobie timer i nastawic go na zadany czas i pollingowac stan portu wywolujac funkcje ClearCommError().Wydaje mi sie jednak ze ten sposob jest najgorszy ze wszystkich.
  • #3 999393
    ZlyDotyk
    Poziom 19  
    Posty: 169
    Pomógł: 40
    Ocena: 1
    mozna jeszcze uzyc SetCommTimeouts, i sprawdzac czy niema nic w glownej petli programu;]
    pozdrawiam
  • REKLAMA
  • #4 1008476
    achilles
    Poziom 15  
    Posty: 212
    Ocena: 6
    Właśnie poczytałem sobie coś o wątkach w windowsie. Zrobiłem to tak jak napisałeś na samym początku, tzn stworzyłęm sobie wątek w którym sprawdzam i odbieram jak cos mi przyjdzie do portu i działa to ok. Napisałem sobie na szybko aplikacje, która w wyniku otrzymiania odpowiednie rozkazu z mojego programu zaczyna wysyłać mi jakieś przykładowe badziewia. Mój program odbiera jest bezbłędnie. ALe ejst jeden szkopół. Mój program po stworzeniu nowego wątku odczytującego coma mocna obciąża procesor, ponad 90%.
    Wątek odpowiedzialny za czytanie portu zrobiłem w ten sposób, że cały czas program biega sobie w pętli i sprawdza warunek (czy mój ptogram chce odbierać dane), jeśli chce to wskakuje mi do wewnętrznej pętli odczytującej port jeśli coś w nim jest do odczytania. Wydaje mi się że jest to wporządku napisane, kierowałem sie troche książką Petzolda.
    Czy to normalne, że mój program tak obciąża procka i jak zrobić, aby go nie obciążał aż w tak dużym stopniu?
  • REKLAMA
  • #5 1008645
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 41
    Tak, zapomnialem dodac ze wazna jest rowniez synchronizacja watkow za pomoca mutex-ow czyli dochodza do tego rowniez funkcje CreateMutex,OpenMutex,ReleaseMutex no i czasem przydaja sie funkcje SuspendThread i ResumeThread.
  • REKLAMA
  • #6 1008860
    Akane
    Poziom 27  
    Posty: 638
    Pomógł: 144
    Ocena: 33
    achilles napisał:
    Mój program po stworzeniu nowego wątku odczytującego coma mocna obciąża procesor, ponad 90%.


    Nie musisz uruchamiać nowego wątku. Otwórz jakieś okienko i uruchom w nim timer np 100ms, a w zdarzeniu timera zrób ReadFile - to wcale nie obciąża procesora
    Timeout COMa ustaw na max 90% interwału timera okna

    Jest taką funkcja w SDK : WaitCommEvent ale ona nie powraca until coś się nie stanie

    W załączniku jest programik (sample w IBasic pro) odczytujący dane z coma - odczytuje w kółko i nie obciąża procesora
    Załączniki:
    • commread[1].iba.zip (1.93 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #7 1009522
    achilles
    Poziom 15  
    Posty: 212
    Ocena: 6
    Jak dla mnie najlepszym rozwiązaniem jest jednak zastosowanie wątku, zależy mi na tym aby znaki były odbierane przez mój program wmiarę szybko. Jak zastosuje funkcje zawieszające i resumujące wątek to nawet to nie źle działa. Obciążam procka tylko przy odbieraniu danych co jest dla mnie w miarę satysfakcjonujące.
    Ale mam inny problem. Odebrane dane wrzucam sobie do bufora. Stworzyłem sobie taką tablice znaków, którą potem wyświetlam za pomoca kontrolki edycji. Zależy mi jednak nad tym, aby po napotkaniu charakterystycznego znaku przejść do następnej linii. Próbowałem poprostu podmieniać znak kodem entera '/r' ale niestety to nie chce działać. Czy ma ktoś pomysł jak "zmusić" kontrolke edycji do przechodzenia w pewnych momentach do następnej linii?
  • #8 1009551
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 41
    Przede wszystkim musisz a kontrolke zrobic typu multiline i wowczas znak entera powinien przechodzic na druga linie.Poza tym jesli chcesz przejsc na poczatek linijki nizej to musisz chyba dac \n\r aby przeskoczyl na nastepna linie i dopiero wrocil karetke.
  • #9 1009554
    Akane
    Poziom 27  
    Posty: 638
    Pomógł: 144
    Ocena: 33
    Dodaj jej(mu) styl ES_MULTILINE (0x4) a będzie wieloliniowa, ewentualnie dodaj ES_AUTOVSCROLL (0x40) żeby zmieśliło się więcej znaków niż widać, no i WS_VSCROLL (0x200000) żeby dało się łatwo przewijać :)
  • #10 1009611
    achilles
    Poziom 15  
    Posty: 212
    Ocena: 6
    Te wszystkie style mam, tylko jak do bufora wrzuce '\r' to on to traktuje jako niezdefiniowany znak i pokazuje jako pusty kwadracik. Z '\n' też próbowałem i było tak samo.
  • #11 1009654
    Akane
    Poziom 27  
    Posty: 638
    Pomógł: 144
    Ocena: 33
    Nie wiem co to za język (\r) ale \n to powiny być 2 znaki: 13 i 10 - wyślij te 2 znaki a na 100% przejdzie do nowej linii
  • #12 1009698
    achilles
    Poziom 15  
    Posty: 212
    Ocena: 6
    Zadziałało, dzięki.

Podsumowanie tematu

✨ Dyskusja dotyczy wykrywania nowych znaków pojawiających się w buforze portu szeregowego w systemie Windows za pomocą WinAPI. Wskazano, że nie istnieje standardowy komunikat okienny informujący o pojawieniu się znaku w buforze, jednak można zastosować różne metody odczytu danych z portu. Jednym z rozwiązań jest uruchomienie osobnego wątku (CreateThread), który w pętli odczytuje dane z portu i po otrzymaniu danych wysyła komunikat do okna (SendMessage). Alternatywnie można użyć asynchronicznego odczytu z flagą FILE_FLAG_OVERLAPPED oraz funkcji WaitCommEvent i SetCommMask do wykrywania zdarzeń, choć te nie generują komunikatów okiennych i wymagają aktywnego oczekiwania. Zastosowanie timera (SetTimer) z cyklicznym wywołaniem ReadFile również jest możliwe i nie obciąża znacznie procesora, pod warunkiem odpowiedniego ustawienia timeoutów portu (SetCommTimeouts). Wątki mogą jednak powodować wysokie obciążenie CPU, jeśli implementacja polega na ciągłym pollingowaniu bez synchronizacji. Synchronizacja wątków za pomocą mutexów (CreateMutex, OpenMutex, ReleaseMutex) jest zalecana. W kwestii wyświetlania odebranych danych w kontrolce edycji, aby wymusić przejście do nowej linii po określonym znaku, należy użyć kontrolki z stylem ES_MULTILINE oraz wstawiać sekwencję znaków CR+LF (13 i 10), czyli "rn". Sam znak 'r' lub 'n' nie jest wystarczający i może być wyświetlany jako nieczytelny symbol. Takie podejście zapewnia poprawne formatowanie tekstu w kontrolce wieloliniowej.
Wygenerowane przez model językowy.
REKLAMA