rs232 linux win32 cz8


K U R S
Programowanie portu szeregowego
w systemach operacyjnych Linux
i Windows, część 8
Umiejętność programowej obsługi interfejsu RS232 od strony sum kontrolnych (jak choćby CRC,
czy kod Reeda Solomona), jednak
komputera PC jest dziś istotnym elementem elektronicznego
w niniejszym, prostym przykładzie
rzemiosła. W niniejszym kursie piszemy jak w praktyce
suma arytmetyczna jest wystarcza-
oprogramować port szeregowy w środowiskach Linux i Windows.
jąca.
Odpowiedzią na ramkę zapyta-
Wiele miejsca poświęcamy pisaniu przenośnych aplikacji GUI,
nia jest ramka odpowiedzi, której
które korzystają z interfejsu szeregowego i zachowują się tak samo
format jest następujący:
w systemach Windows jak i Linux. Wszystkie omawiane zagadnienia
0x56 ByteH ByteL CKS
poparte są szczegółowo opisanymi praktycznymi przykładami.
Pierwszy bajt to kod ASCII zna-
ku  V , symbolizującego napięcie
W poprzednich częściach kursu ASCII znaku zapytania  ?  łatwo elektryczne (Volt). Jest to nagłówek
poznaliśmy, jak stworzyć przenośną odgadnąć, że symbolizuje on py- ramki. Następne dwa bajty są wy-
aplikację wykorzystującą interfejs tanie. Ostatni bajt jest sumą kon- nikiem konwersji analogowo cyfro-
RS232 z użyciem pakietu Qt firmy trolną i pozwala odbiornikowi do- wej i, ze względu na rozdzielczość
Trolltech. Poniżej zostanie zapre- konać kontroli poprawności ramki. przetwornika mikrokontrolera ATme-
zentowany nieco bardziej złożony Jego wartość jest dopełnieniem do ga8, istotnych jest 10 ich najmniej
przykład. Jest nim woltomierz od- dwóch sumy arytmetycznej pozosta- znaczących bitów. Bajt CKS jest
czytywany przez łącze RS232. łych bajtów ramki zapytania, dzięki oczywiście sumą kontrolną, oblicza-
czemu najmniej znaczący bajt sumy ną tak samo jak w przypadku ramki
Woltomierz  część sprzętowa arytmetycznej wszystkich bajtów po- zapytania. Pozwala on odbiornikowi
Do budowy woltomierza wyko- prawnej ramki jest równy zero: (PC) stwierdzić, czy ramka jest po-
rzystano ten sam zestaw testowy, 41+3F+80=100 (HEX) prawna, czy nie.
który posłużył do testów poprzednio Jak widać, za-
opisanych aplikacji  został on opi- proponowano for-
sany w części 2. kursu. Oprogramo- mat ramki nieco na
wanie części sprzętowej woltomierza wyrost w stosunku
stworzono wykorzystując kompilator do funkcji jaką peł-
AVR GCC, ten sam, który wykorzy- ni. Przesyłany jest
stano przy implementacji opisanej jeden rodzaj infor-
wcześniej aplikacji testowej. Działanie macji, co sprawia,
oprogramowania mikrokontrolera pole- że suma kontrolna
ga na skonfigurowaniu modułu UART ma zawsze tę samą
i przetwornika A/C, a następnie na wartość. Pokazuje
oczekiwaniu na odpowiednie ramki on jednak podsta-
zapytania. W odpowiedzi na poprawną wowe cechy, jakie
ramkę przesyłana jest informacja o na- powinna mieć po-
pięciu panującym na wejściu ADC0 prawna ramka zapy-
przetwornika. Jak widać, układ PC tania: nagłówek słu-
 mikrokontroler jest typowym ukła- żący synchronizacji,
dem Master  Slave. W celu wymia- dane, suma kontro- Rys. 15. Test części sprzętowej woltomierza
ny danych pomiędzy mikrokontrole- lna, a w przypadku
rem a komputerem PC ustalono prosty ramek o zmiennych List. 25. Konfiguracja przetwornika A/C mikrokontrolera
//*******************************
protokół komunikacyjny. Format ramki długościach  prze-
// ADC Init
//*******************************
zapytania (Query Frame) wysyłanej syłana powinna być
void Init_ADC(void)
przez komputer jest następujący: długość ramki lub
{
//ADC channel 0, internal vref=2.56V
0x41 0x3F 0x80 liczba bajtów da-
ADMUX=0xC0;
Pierwszy bajt jest umownie wy- nych, ewentualnie
//single conversion
branym bajtem nagłówkowym ramki bajt terminujący
ADCSR=0x97;
(QF_HEADER). Określa on początek (określający koniec
//start first dummy conversion -
ramki i służy do synchronizacji od- pakietu danych).
//- here ADC is adjusting himself
ADCSR|=0x40;
biornika (w tym przypadku mikro- W profesjonalnych
while((ADCSR & 0x40)!=0);
kontrolera) z nadajnikiem (w tym systemach stosuje
Waitms(10);
przypadku komputerem PC). Dru- się znacznie lepsze
}
gi bajt (QF_COMMAND) to kod sposoby obliczania
Elektronika Praktyczna 7/2007
89
K U R S
List. 27. Pętla główna programu mikrokontrolera
List. 26. Konfiguracja USART i funkcje
while(1)
obsługi łącza RS232
{
//*******************************
//Waiting for query frame header - QF_HEADER
// RS232 Init
UCSRA&=~(1<//*******************************
while((UCSRA&(1<void Init_UART(void)
{
QFrame[0]=UDR;
//enable transmitter
UCSRB|=(1< if(QFrame[0]==QF_HEADER)
{
//enable receiver
//Waiting for rest 2 bytes of query frame with timeout
UCSRB|=(1< unsigned char byte_counter;
unsigned int timeout_counter;
//normal speed
UCSRA&=~(1< timeout_counter=0;
for(byte_counter=1;byte_counter<3;byte_counter++)
//19200 baud, err=0.0%
{
UBRRH=0;
//Waiting for 1 byte
UBRRL=5;
UCSRA&=~(1< UCSRB&=~(1< while((UCSRA&(1< if(++timeout_counter>=TIMEOUT)
//8bit, no parity, one stop bit
break;
UCSRC=(1<}
QFrame[byte_counter]=UDR;
//*******************************
//If timeout occured - break for loop
// RS232 Send one byte
if(timeout_counter>=TIMEOUT)
//*******************************
break;
void SendByte(unsigned char byte)
{
}
UCSRA|=(1< UDR=byte;
//If timeout did not occured - check checksum and
while((UCSRA&(1< //if OK then check query and send response
}
if(timeout_counter {
//*******************************
//Checking checksum
// RS232 Send string
unsigned char summa=0;
//*******************************
for(byte_counter=0;byte_counter<3;byte_counter++)
void SendString(char *pString)
summa+=QFrame[byte_counter];
{
char a;
if((summa & 0xFF)==0)
unsigned char i=0;
{
while(a=PRG_RDB(&pString[i++]))
unsigned char adc_valL,adc_valH;
SendByte(a);
}
//Checking query command
if(QFrame[1]==QF_COMMAND)
{
//Measuring voltage
Przykładowy test części sprzę- RED_ON;
ADCSR|=0x40; //start conversion
towej z użyciem terminala RS232
while((ADCSR & 0x40)!=0);
Docklight przedstawiono na rys. 15. adc_valL=ADCL; //read LSB first
adc_valH=(ADCH & 0x03); //read MSB (2 bits)
Widoczne są trzy testy. Pierwszy
został dokonany w chwili, gdy na- //Sending response
SendByte( V );
pięcie na wejściu ADC0 wynosiło
SendByte(adc_valH);
SendByte(adc_valL);
zero, drugi  gdy było ono maksy-
SendByte(0x100- V -adc_valH-adc_valL);
malne. Trzeci test przeprowadzono
Waitms(10);
dla dowolnej wartości pośredniej
RED_OFF;
(w tym przypadku równej 1,48 V, }
}
przy napięciu referencyjnym, odpo-
}
}
wiadającym pełnej skali, równym
}
2,56 V). We wszystkich przypad-
kach najmniej znaczący bajt sumy
arytmetycznej wszystkich bajtów USART pracuje z ramką 8N1 przy transmisji dwóch bajtów. Jeśli w tym
ramki jest równy 0 (np. 56+02+4E- szybkości 19200 b/s. czasie nie odebrano 2 bajtów, ram-
+5A=100). Pętlę główną oprogramowania ka jest ignorowana i program prze-
Na list. 25 przedstawiono kon- mikrokontrolera przedstawiono na chodzi do oczekiwania na bajt na-
figurację przetwornika analogowo- list. 27. Na początku procesor ocze- główkowy. Jeśli odebrano, to spraw-
 cyfrowego mikrokontrolera. Został kuje na bajt nagłówkowy ramki dzana jest wartość drugiego bajtu
on skonfigurowany do pracy z we- zapytania. Oczekiwanie to nie jest ramki (QF_COMMAND). Jeśli jego
wnętrznym napięciem odniesienia objęte żadnym czasem przetermi- wartość jest poprawna, to następ-
o wartości nominalnej 2,56 V i do nowania. Odebranie bajtu innego nie jest obliczana suma arytmetycz-
pracy w trybie pojedynczych kon- niż QF_HEADER (o wartości 0x41) na wszystkich bajtów ramki i, jeśli
wersji. Pierwsza konwersja, jaka jest powoduje jego zignorowanie i kon- jest ona poprawna, mikrokontroler
wywoływana w funkcji z list. 25, tynuowanie oczekiwania. Jeśli ode- dokonuje konwersji analogowo cy-
ma na celu ustawienie przetwor- brano właściwy bajt nagłówkowy, frowej. Odczytana z przetwornika
nika  konwersja ta trwa znacznie mikrokontroler przechodzi do pętli, wartość napięcia (w formie dwóch
dłużej niż pózniejsze przetwarzanie. w której oczekuje na pozostałe dwa bajtów) jest wysyłana do kompute-
Na list. 26 przedstawiono konfigu- bajty ramki zapytania. Oczekiwanie ra PC w formie ramki odpowiedzi
rację oraz funkcje obsługi interfej- to jest objęte odpowiednim czasem opisanej wyżej. Na czas konwersji
su RS232 (wysyłanie jednego baj- przeterminowania (timeout), wyno- i transmisji tej ramki oraz przez ok.
tu i wysyłanie łańcucha znaków). szącym około 4 krotnemu czasowi 10 następnych milisekund, zapalana
Elektronika Praktyczna 7/2007
90
K U R S
List. 29. Deklaracja klasy wątku SamplingThread
nej (2,56 V) wynosi
#ifndef SamplingThreadH
0,36 V, co oczywi- #define SamplingThreadH
ście znacznie prze-
#include  CommInterface.h
kracza rozdzielczość
#include
niniejszego wolto-
#include
#include
mierza.
Ko d a p l i k a c j i
class SamplingThread : public QThread
{
woltomierza składa
Q_OBJECT
Rys. 16. Aplikacja woltomierza działa- się z trzech klas:
public:
jąca w systemie Windows  CCommInterface
QMutex mutex;
 SamplingThread CCommInterface Comm;
SamplingThread(QObject *parent = 0);
 VoltmeterWFrm
~SamplingThread();
void Suspend();
Pierwsza z nich
void Resume();
j e s t n a m d o b r z e
signals:
znana z poprzednich
void NewDataReceived(ulong data, QString status);
części kursu. Klasa
protected:
VoltmeterWFrm jest
void run();
klasą głównej (i je-
private:
dynej) formy apli-
bool abort;
bool suspend;
Rys. 17. Aplikacja woltomierza działa- kacji. Została ona
QWaitCondition condition;
jąca w systemie Linux stworzona podob-
void CheckResponse(void);
};
nie do klasy formy
jest dioda czerwona D1 sygnalizu- aplikacji testowej
#endif
jąc aktywność woltomierza. Example2W, opisanej
w poprzednich czę-
Woltomierz  program na ściach kursu. Podobnie jak wtedy, void UpdateResult(ulong data,
komputer PC tak i w tym przypadku, do budowy QString status);
Woltomierz działający w systemie interfejsu graficznego wykorzystano Funkcji tej przekazywana jest
Windows przedstawiono na rys. 16, program Qt Designer. Deklarację kla- wartość napięcia (10 najmniej zna-
zaś na rys. 17 pokazano widok sy VoltmeterWFrm przedstawiono na czących bitów argumentu data) oraz
okna programu pracującego w sys- list. 28. Jak widać, jednym z jej pól napis, jaki pojawić się ma w polu
temie Linux. Aplikacja VoltmeterW jest obiekt stSampling klasy Sam- stanu. Slot jest wywoływany wtedy,
posiada pole wyniku (pokazujące plingThread. Klasa ta implementuje gdy wątek próbkujący wyemituje
napięcie wejściowe z rozdzielczością wątek odpytujący część sprzętową. następujący sygnał:
0,01 V), pole stanu (zawierające Zastosowanie w tym celu osobnego void NewDataReceived(ulong
informację o poprawności otrzyma- wątku, zamiast np. licznika klasy data, QString status);
nej odpowiedzi lub jej braku), pole QTimer, ma ogromne zalety. Two- Sygnał ten jest zadeklarowany
pozwalające zatrzymać i wznowić rząc nowy wątek otrzymujemy moż- w klasie wątku (list. 29). Oczywiście
odświeżanie wyniku oraz pole tek- liwość przeprowadzania przeróżnych slot jest wywoływany z tymi samy-
stowe, służące do kalibracji wolto- operacji, które wykonają się w tle mi argumentami, co sygnał z nim
mierza. Kalibracja może okazać się głównego wątku, dzięki czemu nie połączony. Połączenie wymienionych
konieczna, ze względu na spory będą one niepotrzebnie zabierać slotów i sygnałów jest dokonywane
rozrzut napięć wewnętrznego zródła jego czasu. Wątek SamplingThread w konstruktorze klasy VoltmeterW-
napięcia odniesienia mikrokontrolera zajmuje się odpytywaniem sprzętu Frm (list. 30). Implementację slotu
ATmega8. Zgodnie z dokumentacja (działa jako typowy Worker Thread) UpdateResult() przedstawiono na
mikrokontrolera, wewnętrzne napię- i analizowaniem odpowiedzi, a do list. 31. Jak widać, jego działanie
cie odniesienie może zawierać się wątku głównego przesyła gotowe polega na pobraniu wartości napię-
w przedziale 2,3...2,7 V. Maksymal- efekty tej analizy, które są w tym cia kalibrującego (odpowiadającego
na odchyłka od wartości nominal- wątku jedynie wizualizowane. napięciu pełnej skali) i przetworze-
Plik nagłówkowy kla- niu 10 bitowej liczby odczytanej
List. 28. Deklaracja klasy VoltmeterWFrm
sy wątku przedstawiono z przetwornika A/C na liczbę ułam-
#include  ui_VoltmeterWFrm.h
na list. 29. Obiekt interfej- kową oraz jej wyświetlenie w po-
#include  SamplingThread.h
su szeregowego jest polem lu wyniku. Informacja z argumentu
class VoltmeterWFrm : public QDialog
tej właśnie klasy. Port jest status trafia do pola stanu. Wartość
{
Q_OBJECT
otwierany w konstruktorze napięcia jest zakodowana w 10 bito-
public: klasy VoltmeterWFrm, w któ- wej zmiennej data (zakres wartości
VoltmeterWFrm(QDialog *parent = 0);
rym wątek jest uruchamiany 0...1023).
~VoltmeterWFrm();
(list. 30). Do komunikacji Ważnymi polami klasy Sampling-
private slots:
pomiędzy wątkiem próbku- Thread są pola abort i suspend, oba
void UpdateResult(ulong data, QString
status);
jącym a wątkiem głównym typu bool (list. 29). Nadanie war-
void ClickedCheckBoxSampling(int state);
wykorzystano mechanizm sy- tości true polu abort powoduje za-
private:
gnałów i slotów. Klasa Volt- kończenie działania wątku, zaś polu
SamplingThread stSampling;
Ui::frmVoltmeterW ui; meterWFrm posiada następu- suspend  zawieszenie jego działa-
};
jący slot: nia. Do realizacji zawieszania służy
Elektronika Praktyczna 7/2007
91
K U R S
fragmentu aplikacji testowej, opisa-
List. 30. Konstruktor klasy VoltmeterWFrm
nej w poprzednich częściach kursu.
VoltmeterWFrm::VoltmeterWFrm(QDialog *parent)
: QDialog(parent)
Funkcja sprawdza czy nie wystąpi-
{
ui.setupUi(this); ły błędy i czy odpowiedz w ogóle
nadeszła. W przypadku braku od-
//Set palette (text color) for result display and status label
QPalette pal=ui.lbResult->palette();
powiedzi lub błędu emituje ona
pal.setColor(QPalette::Foreground,QColor(tr( lightgreen )));
sygnał NewDataReceived(), podając
ui.lbResult->setPalette(pal);
jako argument data wartość 0, a ja-
pal=ui.lbStatus->palette();
ko status stosowną informację. Jeśli
pal.setColor(QPalette::Foreground,QColor(tr( white )));
ui.lbStatus->setPalette(pal);
nadeszła poprawna odpowiedz, emi-
//Set text codec for tr() function towany jest sygnał zawierający 10-
QTextCodec::setCodecForTr(QTextCodec::codecForName( ISO8859-2 ));
 bitową informację o napięciu oraz
//Connect signals and slots
stan  OK .
connect(&stSampling, SIGNAL(NewDataReceived(ulong, QString)),
Wróćmy na chwilę do funkcji
this, SLOT(UpdateResult(ulong, QString)));
connect(ui.cbSampling, SIGNAL(stateChanged(int)),
run(). Niektóre jej fragmenty są uję-
this, SLOT(ClickedCheckBoxSampling(int)));
te w następującą klamrę:
//Initial information
mutex.lock();
UpdateResult(0, No response );
...
//Open port
mutex.unlock();
string port= COM1 ;
if(stSampling.Comm.Open(port,19200)==false)
Pole klasy SamplingThread o na-
{
zwie mutex (obiekt klasy QMutex)
QString portname=port.c_str();
QMessageBox::critical(this,tr( Error ),tr( Port  )+portname+
to semafor binarny wzajemnego wy-
tr( opening error. Application will terminate. ));
kluczania (MUTual EXclusion). Jego
this->reject();
}
działanie polega na tym, że unie-
//Start the thread możliwia on dwóm (lub więcej)
if (!stSampling.isRunning())
wątkom na jednoczesne operowanie
stSampling.start(QThread::TimeCriticalPriority);
}
na współdzielonych zasobach. Gdy-
by nie został zastosowany, to je-
den wątek mógłby zmienić warun-
ki pracy drugiego wątku w sposób
List. 31. Odświeżanie wartości napięcia i stanu
dla niego zupełnie nieprzewidywal-
void VoltmeterWFrm::UpdateResult(ulong data, QString status)
ny. Byłoby tak dlatego, że system
{
//Format result
operacyjny może przełączyć wątki
double fUmax=ui.leCalibration->text().toDouble();
na przykład w chwili, gdy jeden
if((fUmax<0) || (fUmax>5))
fUmax=0;
z nich (wątek A) jest w trakcie wy-
double fResult=(fUmax*data)/1024; konywania pewnego ciągu instruk-
cji na pewnych danych. Dostęp do
//Dislpay result and status
ui.lbResult->setText(QString::number(fResult, f ,2)+ V );
tych danych ma także drugi wątek
ui.lbStatus->setText(status);
(wątek B). Wątek B może zmienić
}
wartości zmiennych, które są wy-
nikami operacji wykonanych przed
pole condition klasy QWa- przełączeniem przez wątek A. Po
List. 32. Funkcja run() wątku SamplingThread
void SamplingThread::run()
itCondition (szczegóły opi- ponownym przekazaniu sterowania
{
sane zostaną dalej). wątkowi A próbuje on skorzystać
forever
{
Na list. 32 przedsta- z tych zmiennych, ale ich warto-
//Repeat sampling every 200ms (150+50)
wiono funkcję run() wątku ści są już inne niż te, których się
msleep(150);
próbkującego. Do tej wła- spodziewa. Powoduje to oczywiście
//Send query frame
mutex.lock(); śnie funkcji przekazywane nieprzewidywalne zachowanie się
unsigned char QueryFrame[3];
jest sterowanie po urucho- programu. Gdy mutex jest opusz-
QueryFrame[0]=0x41; // A
QueryFrame[1]=0x3F; // ?
mieniu wątku za pomocą czony (lock), to wątek próbujący
QueryFrame[2]=0x80; //checksum
metody start(). Działanie dostać się do chronionej przez
Comm.Write(QueryFrame,3);
mutex.unlock();
tej funkcji polega na cy- niego sekcji krytycznej zostaje za-
klicznym wysyłaniu za- wieszony. Gdy wątek, który opu-
//Break Time
msleep(50);
pytania, odczekaniu czasu ścił semafor, podniesie go (unlock),
//Check response break time (ok. 50 ms), wątek zawieszony wznawia swoje
mutex.lock();
analizie odpowiedzi za działanie i wchodzi do sekcji kry-
this->CheckResponse();
mutex.unlock();
pomocą funkcji CheckRe- tycznej opuszczając jednocześnie
sponse() oraz sprawdzeniu semafor. Operacje sprawdzenia sta-
if(abort)
return;
warunków zakończenia nu semafora i jego opuszczenia (je-
i zawieszenia wątku. Im- śli to możliwe) są operacjami ato-
mutex.lock();
if(suspend)
plementację funkcji Chec- mowymi.
condition.wait(&mutex);
mutex.unlock(); kResponse() przedstawiono W przypadku aplikacji wolto-
}
na list. 33. Jej działanie mierza, konkurencyjnymi wątkami
}
jest podobne do działania są: główny wątek aplikacji i wątek
Elektronika Praktyczna 7/2007
92
K U R S
List. 34. Funkcje zawieszenia i wzno-
List. 33. Funkcja analizująca odpowiedz części sprzętowej
void SamplingThread::CheckResponse(void)
wienia wątku próbkującego
{
void SamplingThread::Suspend()
unsigned long Errors,InQue,BytesRead;
{
unsigned char *Input;
suspend=true;
}
Comm.CheckCommInput(&Errors,&InQue);
if(Errors!=0)
void SamplingThread::Resume()
{
{
emit NewDataReceived(0, UART error );
mutex.lock();
}
suspend=false;
else
condition.wakeOne();
{
mutex.unlock();
if(InQue==0)
}
{
emit NewDataReceived(0, No response );
}
else nam na ciągłości wykonywanych
{
operacji. Zasada ta dotyczy zarów-
Input=new unsigned char[InQue];
if(Comm.Read(Input,&BytesRead,InQue)==false)
no implementacji klasy Sampling-
{
Thread, jak i klasy VoltmeterWFrm,
emit NewDataReceived(0, Read error );
delete [] Input;
znajdującej się w przestrzeni wątku
return;
głównego.
}
Jeśli pole abort ma wartość true,
//Checking response
if((Input[0]!= V ) || (BytesRead!=4)) funkcja run() kończy swoje działa-
{
nie, a co za tym idzie, kończy je
emit NewDataReceived(0, Response error );
delete [] Input;
także wątek próbkujący. Jeśli pole
return;
suspend ma wartość true, to wątek
}
jest zawieszany na zmiennej warun-
//Checking checksum
kowej condition. Wywołanie funkcji
unsigned char summa=0;
for(unsigned long j=0;jcondition.wait(&mutex);
summa+=Input[j];
powoduje nie tylko zawieszenie
//Checksum OK
działania wątku, ale także niejaw-
if((summa & 0xFF)==0)
{
ne podniesienie (unlock) semafora
//Show result
mutex. Dzięki temu wątek główny
emit NewDataReceived(256*Input[1]+Input[2], OK );
}
ma dostęp do zmiennej condition
else
i może wznowić działanie wątku
emit NewDataReceived(0, Checksum error );
próbkującego, gdy tylko  zechce .
delete [] Input;
} Jednocześnie zapewniona jest spój-
}
ność operacji sprawdzenia stanu
}
zmiennej suspend i zawieszenia
wątku. Na list. 34 pokazano funk-
S a m p l i n g T h - cje zapewniające dostęp do pola
List. 35. Slot ClickedCheckBoxSampling()
void VoltmeterWFrm::ClickedCheckBoxSampling(int state)
read. Główny suspend. Funkcje te wykorzystano
{
wątek aplika- w slocie obsługi zdarzenia polega-
if(0==state)
stSampling.Suspend();
cji ma bezpo- jącego na zmianie stanu pola typu
else
średni dostęp QCheckBox, pozwalającego zatrzy-
stSampling.Resume();
}
do publicznych mać i wznowić odświeżanie wyni-
p ó l i m e t o d ku (list. 35).
List. 36. Konstruktor i destruktor klasy wątku SamplingThre- w ą t k u S a m - Na list. 36 przedstawiono kon-
ad p l i n g T h r e a d , struktor i destruktor klasy wątku
SamplingThread::SamplingThread(QObject *parent)
a c o z a t y m SamplingThread. Destruktor powo-
: QThread(parent)
{
i d z i e  p o - duje ustawienie znacznika abort
abort = false;
średni dostęp oraz obudzenie wątku, który może
suspend=false;
}
do składowych być zawieszony na warunku con-
p r y w a t n y c h . dition. Dzięki wywołaniu funkcji
SamplingThread::~SamplingThread()
{
Należy pamię- wait(), istnieje pewność, że de-
mutex.lock();
abort=true; tać, że wywo- struktor zakończy swoje działa-
suspend=false;
łanie np. kon- nie dopiero po zakończeniu pracy
condition.wakeOne();
mutex.unlock();
struktora czy funkcji run(). Port szeregowy jest
destruktora kla- zamykany w destruktorze klasy
//Wait until thread ends run()
wait();
sy SamplingTh- VoltmeterWFrm (list. 37). Aby nie
}
read odbywa odbyło się to w trakcie korzysta-
się w przestrzeni wątku głównego nia z portu przez wątek próbkują-
List. 37. Destruktor klasy Voltme-
(bo to właśnie on wywołuje kon- cy, operacja zamykania portu ujęta
terWFr
struktor i destruktor). Z tego po- jest w klamrę mutex.lock()...mutex.
VoltmeterWFrm::~VoltmeterWFrm()
{
wodu, klamrą mutex.lock()...mutex. unlock().
stSampling.mutex.lock();
unlock() należy objąć wszystkie te Arkadiusz Antoniak, EP
stSampling.Comm.Close();
stSampling.mutex.unlock();
odwołania do składowych klasy arkadiusz.antoniak@ep.com.pl
}
SamplingThread, w których zależy www.antoniak.ep.com.pl
Elektronika Praktyczna 7/2007
93


Wyszukiwarka

Podobne podstrony:
rs232 linux win32 cz2
rs232 linux win32 cz6
rs232 linux win32 cz1
rs232 linux win32 cz7
rs232 linux win32 cz3
rs232 linux win32 cz4
rs232 linux win32 cz5
STM32 Butterfly RS232
Linux 2000 DVB T Experiments
linux kobiety
compilar linux
Linux IPCHAINS HOWTO Appendix Differences between ipchains and ipfwadm
systemy operacyjne cw linux apache mysql
Linux materialy
Linux System Plików
Asembler linux
Nauka słówek i memoryzacja na Puppy Linux

więcej podobnych podstron