rs232_linux-win32_cz6.pdf

(799 KB) Pobierz
rs232_linux-win32_cz6.indd
KURS
Programowanie portu szeregowego
w systemach operacyjnych Linux
i Windows, część 6
Umiejętność programowej obsługi interfejsu RS232 od strony
komputera PC jest dziś istotnym elementem elektronicznego
rzemiosła. W niniejszym kursie piszemy jak w praktyce
oprogramować port szeregowy w środowiskach Linux i Windows.
Wiele miejsca poświęcamy pisaniu przenośnych aplikacji GUI,
które korzystają z interfejsu szeregowego i zachowują się tak samo
w systemach Windows jak i Linux. Wszystkie omawiane zagadnienia
poparte są szczegółowo opisanymi praktycznymi przykładami.
RS232 i włączany jest licznik timer-
BreakTime . Na czas trwania ocze-
kiwania ( break time ) przycisk Send
jest wyłączany. Aplikacja jest wy-
posażona w kontrolkę, która „świeci
się” na jasno niebiesko (kolor cyan )
podczas trwania czasu break time .
Po upływie tego czasu aplikacja
sprawdza, jaka (i czy w ogóle) od-
powiedź nadeszła. Zadanie to jest
realizowane w slocie obsługującym
przepełnienie licznika timerBreakTi-
me , pokazanym na list. 23 . Po wy-
łączeniu kontrolki i zatrzymaniu licz-
nika, program sprawdza za pomocą
Wykorzystanie łącza RS232
w aplikacji testowej
Funkcje obsługi interfejsu RS232
dostarczane są za pomocą klasy
CCommInterface . Plik nagłówkowy
tej kasy jest włączany do pliku na-
główkowego głównej formy aplikacji
(list. 19). Klasa tej formy posiada
pole będące wskaźnikiem do obiek-
tu interfejsu komunikacyjnego:
CCommInterface *pComm;
Obiekt tego interfejsu tworzony
jest dynamicznie w konstruktorze
klasy Example2WFrm wraz z obiek-
tem licznika odmierzającego czas
break time (list. 21).
Jak wspomniano, działanie apli-
kacji polega na wysłaniu zapytania
i prezentacji odpowiedzi. Zapytanie
jest wysyłane w chwili kliknięcia
przycisku Send, zaś odpowiedź, bę-
dąca ciągiem bajtów, prezentowana
jest w formie szesnastkowej i ASCII
za pomocą obiektu klasy QTableWid-
get. Klasa ta implementuje tabelkę
(siatkę) mogącą zawierać dowolne
widgety. Odpowiedź jest sprawdza-
na po upłynięciu czasu break time
liczonego od chwili wysłania zapy-
tania. Czas ten jest ustalany przez
użytkownika aplikacji i odmierzany
za pomocą licznika timerBreakTime
typu QTimer .
Ciało slotu obsługującego klik-
nięcie przycisku Send przedstawio-
no na list. 22 . W pierwszej kolejno-
ści dokonywane jest otwarcie por-
tu COM1 dla szybkości transmisji
19200 bodów. Niepowodzenie skut-
kuje wyświetleniem odpowiedniego
komunikatu i zamknięciem aplikacji.
Jeśli port został poprawnie otwar-
ty, to z pól tekstowych odczyty-
wane jest zapytanie oraz wartość
czasu break time wyrażonego w mi-
lisekundach. Następnie czyszczone
jest pole odpowiedzi, po czym za-
pytanie jest wysyłane przez łącze
List. 22. Wysyłanie jednobajtowego zapytania
void Example2WFrm::clickedSendQuery()
{
//Open port
string port=”COM1”;
if(pComm->Open(port,19200)==false)
{
QString portname=port.c_str();
QMessageBox::critical(this,tr(„Error”),tr(„Port „)+portname+tr(„ opening
error. Application will terminate.”));
this->reject();
}
//Read query
bool ok;
unsigned char qry=ui.leQuery->text().toInt(&ok,16);
if(false==ok)
{
QMessageBox::critical(this,tr(„Error”),tr(„Invalid query value.”));
pComm->Close();
return;
}
//Update displayed query value
ui.leQuery->setText(QString::number(qry,16));
//Read break time
int btime=ui.leBreakTime->text().toInt(&ok);
if((false==ok) || (btime<0))
{
QMessageBox::critical(this,tr(„Error”),tr(„Invalid break time value.”));
pComm->Close();
return;
}
//Clear response window
ui.twResponse->clear();
ui.twResponse->setRowCount(2);
ui.twResponse->setColumnCount(1);
ui.leStatus->setText(tr(„”));
//Send query
ui.pbtnSendQuery->setEnabled(false);
if(pComm->Write(&qry,1)!=1)
{
QMessageBox::critical(this,tr(„Error”),tr(„Write error.”));
pComm->Close();
return;
}
QPalette pal;
pal.setColor(QPalette::Base,QColor(tr(„cyan”)));
ui.leLamp->setPalette(pal);
this->timerBreakTime->start(btime);
}
Elektronika Praktyczna 7/2007
89
66534854.007.png
KURS
List. 23. Odbiór odpowiedzi
void Example2WFrm::timerBreakTimeOverflow()
{
QPalette pal;
pal.setColor(QPalette::Base,QColor(tr(„black”)));
ui.leLamp->setPalette(pal);
this->timerBreakTime->stop();
//Read response
unsigned long Errors,InQue,BytesRead;
unsigned char *Input;
pComm->CheckCommInput(&Errors,&InQue);
if(Errors!=0)
ui.leStatus->setText(tr(„*** ERROR „)+QString::number(Errors)+tr(„
***”));
else
{
if(InQue==0)
ui.leStatus->setText(tr(„*** NO RESPONSE ***”));
else
{
ui.leStatus->setText(tr(„*** OK ***”));
//Read response
Input=new unsigned char[InQue];
if(false==pComm->Read(Input,&BytesRead,InQue))
{
QMessageBox::critical(this,tr(„Error”),tr(„Read error.”));
delete [] Input;
pComm->Close();
ui.pbtnSendQuery->setEnabled(true);
return;
}
//Show response
ui.twResponse->setColumnCount(BytesRead);
for(unsigned long j=0;j<BytesRead;j++)
{
QTableWidgetItem *hexItem = new QTableWidgetItem(QString::
number(Input[j],16));
QTableWidgetItem *charItem = new QTableWidgetItem(QString((char)
(Input[j])));
ui.twResponse->setItem(0, j, hexItem);
ui.twResponse->setItem(1, j, charItem);
}
delete [] Input;
}
}
pComm->Close();
ui.pbtnSendQuery->setEnabled(true);
}
Unicode – są one implementowane
przez typ QChar.
Drugie z wymienionych poleceń
powoduje stworzenie trzech plików:
Makefile, Makefile.Debug i Makefile.
Release , które oczywiście umożli-
wiają tworzenie wersji Debug i Re-
lease aplikacji. Kompilacji wersji
Debug dokonujemy wpisując:
mingw32–make –f Makefile.Debug
zaś wersji Release, wpisując:
mingw32–make –f Makefile. Re-
lease
Uruchomienie aplikacji może
odbyć się bez podania parametrów
wywołania (co odpowiada kliknię-
ciu myszy na pliku Example2W.
exe ), lub przykładowo z podaniem
stylu w jakim program ma zostać
uruchomiony. Dostępne są następu-
jące style (użytkownik może także
definiować własne):
– Windows (domyślny w systemie
Windows)
– WindowsXP
– Motif
– CDE
– Macintosh
– Plastique (domyślny w systemie
Linux)
Uruchomienie aplikacji z uży-
ciem danego stylu odbywa się po
podaniu jego nazwy z opcją –style .
Przykładowo, aplikację Example2W
w stylu Plastique uruchamiamy za
pomocą polecenia:
Example2W.exe –style=plastique
funkcji CheckCommInput() ile bajtów
oczekuje w buforze wejściowym oraz
czy nie wystąpiły błędy transmisji
na poziomie kontrolera UART i syste-
mu operacyjnego. W przypadku błędu
wyświetlany jest odpowiedni komu-
nikat. Brak odpowiedzi (zero bajtów
w buforze) jest sygnalizowany poprzez
wyświetlenie komunikatu „*** NO
RESPONSE ***”. Jeśli zaś odpowiedź
nadeszła, wyświetlany jest komunikat
„*** OK ***”, a odpowiedź jest od-
czytywana z bufora wejściowego za
pomocą funkcji Read() . Odczytany
ciąg bajtów trafia do tabelki prezen-
tującej odpowiedź (w tym przypadku
każdy z jej elementów przechowuje
obiekt klasy QString ). Na koniec port
szeregowy jest zamykany, a przycisk
Send ponownie włączany.
podstawie plików źródłowych za
pomocą wspomnianego już progra-
mu narzędziowego qmake.exe . Bę-
dąc w katalogu projektu wpisujemy
w linii poleceń:
qmake – project
a następnie:
qmake
Pierwsze z wymienionych po-
leceń spowoduje stworzenie pliku
Example2W.pro , który pokazano na
list. 24 . Plik ten stanowi informa-
cję, które pliki (zarówno źródłowe,
jak i pliki *.ui ) należy brać pod
uwagę przy tworzenia plików Make-
file , a także dodatkowe opcje. Linia:
DEFINES –= UNICODE
została dodana ręcznie po to,
aby biblioteka Qt traktowała znaki
char jako znaki ASCII, a nie jak
znaki zapisane w Unicode ( Wide
Char ). Jest to potrzebne, bo pro-
totypy funkcji WinAPI wymagają
typu ASCII. Mimo to, biblioteka Qt
w pełni wspiera Unicode i możliwe
jest używanie 16–bitowych znaków
Integracja biblioteki Qt
z edytorem Code Blocks
O ile możliwa jest praca z pli-
kami źródłowymi projektu za po-
mocą zwykłego notatnika, to oczy-
wiście wygodnie jest nimi opero-
wać za pomocą dowolnego edytora
przeznaczonego dla programistów,
wyposażonego co najmniej w moż-
liwość kolorowania składni. Edytor
Code Blocks , oprócz tej podstawo-
wej cechy, posiada między innymi
wzorzec projektu Qt, dzięki któ-
remu tworzenie własnego projek-
tu wykorzystującego tę bibliotekę
jest wyjątkowo łatwe. Posiada on
także możliwość współpracy z de-
buggerem GDB, będącym częścią
środowiska MinGW, co znakomicie
ułatwia (a niekiedy wręcz warun-
kuje) proces tworzenia aplikacji.
Ponadto, integracja z GDB jest do-
konywana automatycznie, a progra-
mista otrzymuje wygodne środowi-
sko pracy z możliwością zastawia-
nia pułapek breakpoint z poziomu
Kompilacja i uruchomienie
programu z linii poleceń
Przed kompilacją projektu, nale-
ży przygotować odpowiednie pliki
Makefile . Pliki te są tworzone na
90
Elektronika Praktyczna 7/2007
66534854.008.png
KURS
wej apli-
kacji. Wła-
ściwe pliki
projektu
m o ż n a
stworzyć
ręcznie. Po
stworzeniu
projektu
należy od-
powiednio
skonfigu-
rować śro-
dowisko,
wybierając
opcję Pro-
ject–>Bu-
ild options .
D z i ę k i
użyciu wzorca projektu Qt,
w sekcji konsolidatora są
już wymienione potrzebne
biblioteki ( rys. 8 ). Bardzo
ważne jest właściwe poda-
nie ścieżek do plików na-
główkowych biblioteki Qt.
Jest to o tyle istotne, że
– przynajmniej w wersji 1.0
edytora – domyślne ścieżki
są błędne i nie pasują do
wersji 4.0.1 biblioteki. Być
może jest to relikt pozo-
stały z wersji 3.x. Przykład
właściwie podanych ścieżek
przedstawiono na rys. 9 .
Można dodać ścieżki do-
stępu do pozostałych pod-
katalogów katalogu \inclu-
de , ale można też pozosta-
wić jedynie dwie pierwsze
ścieżki i włączając pliki na-
główkowe podawać, oprócz
samej nazwy pliku, ścieżkę
dostępu do niego, odniesio-
ną do jednego z katalogów
wymienionych w zakładce
Directories/Compiler . Drugie
rozwiązanie jest bezpiecz-
niejsze i takie też zostało
wybrane.
Podobnie jak w przypad-
ku nazw bibliotek, ścieżka
do katalogu je zawierające-
go powinna być poprawnie
ustalona, co jest zapew-
nione dzięki wykorzysta-
niu wzorca projektu Qt
( rys. 10 ). Ustawienia opcji
kompilatora ( rys. 11 ) zależą
od tego, co chcemy otrzy-
mać w wyniku kompilacji
oraz jak proces kompilacji
ma przebiegać. Jedną z naj-
bardziej użytecznych opcji
Rys. 9. Opcje projektu – pliki nagłówkowe
Rys. 6. Środowisko Code Blocks podczas pracy z aplika-
cją Example2W
interfejsu graficznego, podglądu
zmiennych i różnymi rodzajami
pracy krokowej. Ogólny widok
edytora Code Blocks podczas pra-
cy nad niniejszą aplikacją przed-
stawiono na rys. 6.
Podczas tworzenia nowego pro-
jektu ( Project–>New project... ) pro-
ponuję, zgodnie z rys. 7 , zaznaczyć
opcję „ Do not create any files ”.
Dzięki temu unika się tworzenia
niepotrzebnych plików przykłado-
Rys. 10. Opcje projektu – biblioteki
Rys. 11. Opcje projektu – kompilator
Rys. 7. Nowy projekt Code Clocks
Rys. 8. Opcje projektu – konsolidator
jest –g . Jej zaznaczenie spowoduje
stworzenie wersji Debug , odznacze-
nie – wersji Release .
Przed przystąpieniem do kompi-
lacji projektu za pomocą IDE Code
Blocks należy za pomocą programu
narzędziowego moc.exe stworzyć,
na podstawie pliku nagłówkowego
formy Example2WFrm.h , specjalny
plik moc_Example2WFrm.cpp . Plik
ten powinien być umieszczony
w katalogu projektu i dodany do
projektu w środowisku Code Blocks .
Utworzenia pliku moc_Example2W-
Frm.cpp dokujemy wydając nastę-
pujące polecenie:
Elektronika Praktyczna 7/2007
91
66534854.009.png 66534854.010.png 66534854.001.png 66534854.002.png 66534854.003.png 66534854.004.png
KURS
Rys. 12. Aplikacja testowa działająca
w systemie Windows (styl Windows)
List. 24. Plik Example2W.pro
######################################################################
# Automatically generated by qmake (2.00a) Cz 18. maj 23:36:02 2006
######################################################################
TEMPLATE = app
TARGET +=
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += CommInterface.h Example2WFrm.h
FORMS += Example2WFrm.ui
SOURCES += CommInterface.cpp main.cpp Example2WFrm.cpp
DEFINES -= UNICODE
moc –o moc_Example2WFrm.cpp
Example2WFrm.h
Działanie takie nie było po-
trzebne podczas kompilacji progra-
mu w linii poleceń, gdyż program
qmake sam umieszczał w plikach
Makefile stosowne wywołania pro-
gramu moc. Program ten zajmuje
się obsługą rozszerzeń języka C++
właściwych dla biblioteki Qt, m.in.
mechanizmu sygnałów i slotów. Po-
winien on być używany dla każde-
go pliku nagłówkowego zawierające-
go deklarację klasy, która zawiera
w sobie wywołanie makra Q_OB-
JECT . Pliki wygenerowane przez
program moc muszą być skompilo-
wane i skonsolidowane razem z in-
nymi plikami projektu.
Po wygenerowaniu pliku moc_
Example2WFrm.cpp można skompi-
lować i uruchomić aplikację (F9).
Jeśli zaznaczono opcję –g , to pro-
gram jest gotowy do uruchomienia
w trybie debuggowania – wystarczy
ustawić pułapki w wybranych miej-
scach programu i wcisnąć F8. Apli-
kację testową działającą w systemie
Windows przedstawiono na rys. 12 .
Arkadiusz Antoniak, EP
arkadiusz.antoniak@ep.com.pl
www.antoniak.ep.com.pl
180x128
1/2
180x23
92
Elektronika Praktyczna 7/2007
66534854.005.png 66534854.006.png
Zgłoś jeśli naruszono regulamin