Обращение к com порту |
Ответить | Страница <123> |
Автор | |
Новичок Присоединился: 23 Январь 2010 Online Status: Offline Публикации: 27 |
Опубликовано: 15 Июль 2010 10:02 |
#include <vcl.h>
#pragma hdrstop #include <io.h> #include <fcntl.h> #include <sys\stat.h> #include "Unit1.h" #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; #define BUFSIZE 255 //ёмкость буфера unsigned char bufrd[BUFSIZE], bufwr[BUFSIZE]; //--------------------------------------------------------------------------- HANDLE COMport; /OVERLAPPED overlapped; OVERLAPPED overlappedwr; //--------------------------------------------------------------------------- int handle; //--------------------------------------------------------------------------- bool fl=0; unsigned long counter; //--------------------------------------------------------------------------- void COMOpen(void); void COMClose(void); //============================================================================= //.............................. объявления потоков ........................... //============================================================================= //--------------------------------------------------------------------------- //поток для чтения последовательности байтов из COM-порта в буфер class ReadThread : public TThread { private: void __fastcall Printing(); //вывод принятых байтов на экран и в файл protected: void __fastcall Execute(); //основная функция потока public: __fastcall ReadThread(bool CreateSuspended); //конструктор потока }; //--------------------------------------------------------------------------- //поток для записи последовательности байтов из буфера в COM-порт class WriteThread : public TThread { private: void __fastcall Printing(); //вывод состояния на экран protected: void __fastcall Execute(); //основная функция потока public: __fastcall WriteThread(bool CreateSuspended); //конструктор потока }; /*---------------------------Поток чтения с порта-----------------------------*/ ReadThread *reader; //--------------------------------------------------------------------------- __fastcall ReadThread::ReadThread(bool CreateSuspended) : TThread(CreateSuspended) {} void __fastcall ReadThread::Execute() { COMSTAT comstat; DWORD btr, temp, mask, signal; overlapped.hEvent = CreateEvent(NULL, true, true, NULL); SetCommMask(COMport, EV_RXCHAR); while(!Terminated) //пока поток не будет прерван, выполняем цикл { WaitCommEvent(COMport, &mask, &overlapped); signal = WaitForSingleObject(overlapped.hEvent, INFINITE); if(signal == WAIT_OBJECT_0) { if(GetOverlappedResult(COMport, &overlapped, &temp, true)) if((mask & EV_RXCHAR)!=0) { ClearCommError(COMport, &temp, &comstat); btr = comstat.cbInQue; if(btr) { ReadFile(COMport, bufrd, btr, &temp, &overlapped); counter+=btr; Synchronize(Printing); } } } } CloseHandle(overlapped.hEvent); /*перед выходом из потока закрыть объект-событие*/ } //--------------------------------------------------------------------------- void __fastcall ReadThread::Printing() { Form1->Memo1->Lines->Add((char*)bufrd); //выводим принятую строку в Memo /* Form1->StatusBar1->Panels->Items[2]->Text = "Всего принято " + IntToStr(counter) + " байт"; //выводим счётчик в строке состояния*/ if(Form1->CheckBox3->Checked == true) //если включен режим вывода в файл { write(handle, bufrd, strlen(bufrd)); //записать в файл данные из приёмного буфера } memset(bufrd, 0, BUFSIZE); } WriteThread *writer; /*--------------------------поток записи данных в порт-------------------------*/ __fastcall WriteThread::WriteThread(bool CreateSuspended) : TThread(CreateSuspended) {} //--------------------------------------------------------------------------- void __fastcall WriteThread::Execute() { DWORD temp, signal; overlappedwr.hEvent = CreateEvent(NULL, true, true, NULL); //создать событие WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr); //записать байты в порт signal = WaitForSingleObject(overlappedwr.hEvent, INFINITE); if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlappedwr, &temp, true))) fl = true; else fl = false; Synchronize(Printing); CloseHandle(overlappedwr.hEvent); //перед выходом из потока закрыть объект-событие } //--------------------------------------------------------------------------- //вывод состояния передачи данных на экран void __fastcall WriteThread::Printing() { if(!fl) //проверяем состояние флажка { Form1->StatusBar1->Panels->Items[0]->Text = "Ошибка передачи"; return; } Form1->StatusBar1->Panels->Items[0]->Text = "Передача прошла успешно"; } /////////////////////////////////////////////////////////////////////////////// /// форма /// /////////////////////////////////////////////////////////////////////////////// __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { //инициализация элементов формы при запуске программы Form1->Label5->Enabled = false; Form1->Label6->Enabled = false; Form1->Button1->Enabled = false; Form1->CheckBox1->Enabled = false; Form1->CheckBox2->Enabled = false; } //--------------------------------------------------------------------------- //обработчик нажатия на кнопку "Открыть порт" void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { if(SpeedButton1->Down) { COMOpen(); Form1->ComboBox1->Enabled = false; Form1->ComboBox2->Enabled = false; Form1->Button1->Enabled = true; Form1->CheckBox1->Enabled = true; Form1->CheckBox2->Enabled = true; Form1->SpeedButton1->Caption = "Закрыть порт"; counter = 0; Form1->CheckBox1Click(Sender); Form1->CheckBox2Click(Sender); } else { COMClose(); Form1->SpeedButton1->Caption = "Открыть порт"; Form1->StatusBar1->Panels->Items[0]->Text = ""; //очистить первую колонку строки состояния Form1->ComboBox1->Enabled = true; Form1->ComboBox2->Enabled = true; Form1->Button1->Enabled = false; Form1->CheckBox1->Enabled = false; Form1->CheckBox2->Enabled = false; } } //--------------------------------------------------------------------------- //обработчик закрытия формы void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { if(reader)reader->Terminate(); //завершить поток чтения из порта, проверка if(reader) обязательна, иначе возникают ошибки if(writer)writer->Terminate(); //завершить поток записи в порт, проверка if(writer) обязательна, иначе возникают ошибки if(COMport)CloseHandle(COMport); //закрыть порт if(handle)close(handle); //закрыть файл, в который велась запись принимаемых данных } //--------------------------------------------------------------------------- //галочка "Сохранить в файл" void __fastcall TForm1::CheckBox3Click(TObject *Sender) { if(Form1->CheckBox3->Checked) //если галочка включена { //активировать соответствующие элементы на форме Form1->Label5->Enabled = true; Form1->Label6->Enabled = true; //вывести индикатор записи в файл в строке состояния Form1->StatusBar1->Panels->Items[1]->Text = "Вывод в файл!"; } else //если галочка выключена { //отключить соответствующие элементы на форме Form1->Label5->Enabled = false; Form1->Label6->Enabled = false; //убрать индикатор записи в файл из строки состояния Form1->StatusBar1->Panels->Items[1]->Text = ""; } } //--------------------------------------------------------------------------- //кнопка "Передать" void __fastcall TForm1::Button1Click(TObject *Sender) { memset(bufwr,0,BUFSIZE); //очистить программный передающий буфер, чтобы данные не накладывались друг на друга PurgeComm(COMport, PURGE_TXCLEAR); //очистить передающий буфер порта strcpy(bufwr,Form1->Edit1->Text.c_str()); //занести в программный передающий буфер строку из Edit1 writer = new WriteThread(false); //создать и активировать поток записи данных в порт writer->FreeOnTerminate = true; //установить это свойство, чтобы поток автоматически уничтожался после завершения } //--------------------------------------------------------------------------- //кнопка "Очистить поле" void __fastcall TForm1::Button3Click(TObject *Sender) { Form1->Memo1->Clear(); //очистить Memo1 } //--------------------------------------------------------------------------- //галочка "DTR" void __fastcall TForm1::CheckBox1Click(TObject *Sender) { //если установлена - установить линию DTR в единицу, иначе - в ноль if(Form1->CheckBox1->Checked) EscapeCommFunction(COMport, SETDTR); else EscapeCommFunction(COMport, CLRDTR); } //--------------------------------------------------------------------------- //галочка "RTS" void __fastcall TForm1::CheckBox2Click(TObject *Sender) { //если установлена - установить линию RTS в единицу, иначе - в ноль if(Form1->CheckBox2->Checked) EscapeCommFunction(COMport, SETRTS); else EscapeCommFunction(COMport, CLRRTS); } //--------------------------------------------------------------------------- //============================================================================= //........................... реализации функций .............................. //============================================================================= //--------------------------------------------------------------------------- //функция открытия и инициализации порта void COMOpen() { String portname; //имя порта (например, "COM1", "COM2" и т.д.) DCB dcb; //структура для общей инициализации порта DCB COMMTIMEOUTS timeouts; //структура для установки таймаутов portname = Form1->ComboBox1->Text; //получить имя выбранного порта if(COMport == INVALID_HANDLE_VALUE) //если ошибка открытия порта { Form1->SpeedButton1->Down = false; //отжать кнопку Form1->StatusBar1->Panels->Items[0]->Text = "Не удалось открыть порт"; //вывести сообщение в строке состояния return; } //инициализация порта dcb.DCBlength = sizeof(DCB); //в первое поле структуры DCB необходимо занести её длину, она будет использоваться функциями настройки порта для контроля корректности структуры //считать структуру DCB из порта if(!GetCommState(COMport, &dcb)) //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния { COMClose(); Form1->StatusBar1->Panels->Items[0]->Text = "Не удалось считать DCB"; return; } //инициализация структуры DCB dcb.BaudRate = StrToInt(Form1->ComboBox2->Text); //задаём скорость передачи 115200 бод dcb.fBinary = TRUE; //включаем двоичный режим обмена dcb.fOutxCtsFlow = FALSE; //выключаем режим слежения за сигналом CTS dcb.fOutxDsrFlow = FALSE; //выключаем режим слежения за сигналом DSR dcb.fDtrControl = DTR_CONTROL_DISABLE; //отключаем использование линии DTR dcb.fDsrSensitivity = FALSE; //отключаем восприимчивость драйвера к состоянию линии DSR dcb.fNull = FALSE; //разрешить приём нулевых байтов dcb.fRtsControl = RTS_CONTROL_DISABLE; //отключаем использование линии RTS dcb.fAbortOnError = FALSE; //отключаем остановку всех операций чтения/записи при ошибке dcb.ByteSize = 8; //задаём 8 бит в байте dcb.Parity = 0; //отключаем проверку чётности dcb.StopBits = 0; //задаём один стоп-бит //загрузить структуру DCB в порт if(!SetCommState(COMport, &dcb)) //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния { COMClose(); Form1->StatusBar1->Panels->Items[0]->Text = "Не удалось установить DCB"; return; } //установить таймауты timeouts.ReadIntervalTimeout = 0; //таймаут между двумя символами timeouts.ReadTotalTimeoutMultiplier = 0; //общий таймаут операции чтения timeouts.ReadTotalTimeoutConstant = 0; //константа для общего таймаута операции чтения timeouts.WriteTotalTimeoutMultiplier = 0; //общий таймаут операции записи timeouts.WriteTotalTimeoutConstant = 0; //константа для общего таймаута операции записи //записать структуру таймаутов в порт if(!SetCommTimeouts(COMport, &timeouts)) //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния { COMClose(); Form1->StatusBar1->Panels->Items[0]->Text = "Не удалось установить тайм-ауты"; return; } //установить размеры очередей приёма и передачи SetupComm(COMport,2000,2000); //создать или открыть существующий файл для записи принимаемых данных handle = open("test.txt", O_CREAT | O_APPEND | O_BINARY | O_WRONLY, S_IREAD | S_IWRITE); if(handle==-1) //если произошла ошибка открытия файла { Form1->StatusBar1->Panels->Items[1]->Text = "Ошибка открытия файла"; //вывести сообщение об этом в командной строке Form1->Label6->Hide(); //спрятать надпись с именем файла Form1->CheckBox3->Checked = false; //сбросить и отключить галочку Form1->CheckBox3->Enabled = false; } else { Form1->StatusBar1->Panels->Items[0]->Text = "Файл открыт успешно"; } //иначе вывести в строке состояния сообщение об успешном открытии файла PurgeComm(COMport, PURGE_RXCLEAR); //очистить принимающий буфер порта reader = new ReadThread(false); //создать и запустить поток чтения байтов reader->FreeOnTerminate = true; //установить это свойство потока, чтобы он автоматически уничтожался после завершения } //--------------------------------------------------------------------------- //функция закрытия порта void COMClose() { if(writer)writer->Terminate(); //если поток записи работает, завершить его; if(reader)reader->Terminate(); //если поток чтения работает, завершить его; CloseHandle(COMport); //закрыть порт COMport=0; //обнулить переменную для дескриптора порта close(handle); //закрыть файл для записи принимаемых данных handle=0; //обнулить переменную для дескриптора файла } //--------------------------------------------------------------------------- |
|
Профили участников
Послать частное письмо
Поиск публикаций участников
Посетить домашнюю страницу участника
Добавить в список приятелей
Новичок Присоединился: 19 Июль 2005 Категория: Ukraine Online Status: Offline Публикации: 39 |
|
На первый взгляд в функции COMOpen() нет вызова CreateFile(....), но это видимо так скопировано просто. Скажи, а что происходит через 2 часа работы программы?
|
|
Новичок Присоединился: 23 Январь 2010 Online Status: Offline Публикации: 27 |
|
Компьютер зависает или датчик сигнал перестает передовать
|
|
Профили участников
Послать частное письмо
Поиск публикаций участников
Посетить домашнюю страницу участника
Добавить в список приятелей
Новичок Присоединился: 19 Июль 2005 Категория: Ukraine Online Status: Offline Публикации: 39 |
|
Сделай так: |
|
Новичок Присоединился: 23 Январь 2010 Online Status: Offline Публикации: 27 |
|
Я проще некаких объяснений к доступу не нашел. Вообще мне потом надо все это дело зациклить. и чтобы работало хотябы 12 часов!
|
|
Профили участников
Послать частное письмо
Поиск публикаций участников
Посетить домашнюю страницу участника
Добавить в список приятелей
Новичок Присоединился: 19 Июль 2005 Категория: Ukraine Online Status: Offline Публикации: 39 |
|
Хочешь я выложу программку в 10 раз проще, не виснущую, когда-то сделал для "общения" с не помню каким датчиком. Можно отправлять посылки и читать ответы в 16-ричном виде. |
|
Новичок Присоединился: 23 Январь 2010 Online Status: Offline Публикации: 27 |
|
Буду очень благодарен. Можешь даже скинуть ее на почту: carmogedon@mail.ru.
|
|
Профили участников
Послать частное письмо
Поиск публикаций участников
Посетить домашнюю страницу участника
Добавить в список приятелей
Новичок Присоединился: 19 Июль 2005 Категория: Ukraine Online Status: Offline Публикации: 39 |
|
Да я уже выложил тут http://casey.at.ua/load/com_port_read_write/1-1-0-1 . Может кому еще будет интересно.
|
|
Новичок Присоединился: 28 Декабрь 2009 Online Status: Offline Публикации: 18 |
|
2 часа - это много. А что происходит через 2 часа? Может дисковая память закончилась.
Можно перезапускать программу каждые 2 часа. А вообще, присылайте код. Нужно смотреть. У меня такие программы работают месяцами. (охлаждение промышленной физ. установки) |
|
Новичок Присоединился: 23 Январь 2010 Online Status: Offline Публикации: 27 |
|
Сбрось пожалуйста свой код посмотреть, а то я сделать не могу а сроки уже поджимают
|
|
Ответить | Страница <123> |
Переход на форум | Права доступа на форуме Вы не можете публиковать новые темы в этом форуме Вы не можете отвечать на сообщения в этом форуме Вы не можете удалять Ваши сообщения на этом форуме Вы не можете редактировать Ваши сообщения на этом форуме Вы не можете создавать голосования на этом форуме Вы не можете выражать своё мнение в голосованиях на этом форуме |