#include <vcl.h>#pragma hdrstop #include "Unit1.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma link "CSPIN"#pragma resource "*.dfm"#include <iostream>TForm1 *Form1; DWORD nBytesRead, rb;unsigned char Ibuffer[6000];unsigned char buf_r[128];char Data[6000];using namespace std;bool NbRead = false;BOOL fSuccess;char BufferSendCom[128];unsigned int nBytesToRead = 6000; //--------------------------------------------------------------------------- void hexdumpstrRead ( char src[], size_t size){ Form1->Memo2->Clear(); static const char hex[] = "0123456789abcdef"; char *result = (char *)malloc((size > 0)? size*3: 1), *p = result; if (result) { while (size-- > 0) { *p++ = hex[(*src >> 4) & 0x0f]; *p++ = hex[*src++ & 0x0f]; *p++ = ' '; } p[(p > result)? -1: 0] = 0; } Form1->Memo2->Lines->Add(result);}//--------------------------------------------------------------------------- void hexdumpstrWrite ( char src[], size_t size){ Form1->Memo1->Clear(); static const char hex[] = "0123456789abcdef"; char *result = (char *)malloc((size > 0)? size*3: 1), *p = result; if (result) { while (size-- > 0) { *p++ = hex[(*src >> 4) & 0x0f]; *p++ = hex[*src++ & 0x0f]; *p++ = ' '; } p[(p > result)? -1: 0] = 0; } Form1->Memo1->Lines->Add(result);} //---------------------------------------------------------------------------// Com DWORD WINAPI Input_thread( LPVOID lpParam ){ int i, j, n, NbByteRead; char Buffer[10]; AnsiString S,S1,S2,S3,St; while(1) { fSuccess = ReadFile( Form1->hSerial, &Ibuffer, Form1->buf_rez, &nBytesRead, NULL ); if(fSuccess && nBytesRead) { fSuccess = 0; for (i = 0; i < nBytesRead; i++) { if(Ibuffer[i] == 0xa1 && Ibuffer[i + 1] == 0xa2) { NbByteRead = (Ibuffer[i + 2] << 8) | Ibuffer[i + 3]; // sprintf(Buffer," Lenght \n %x", NbByteRead); Form1->Label6->Caption = Buffer; for (j = 0; j < nBytesRead; j++) { Data[j] = Ibuffer[j]; Ibuffer[j] = 0; } hexdumpstrRead(Data, nBytesRead); } } Form1->BufferSendCom[0] = 0x55; Form1->BufferSendCom[1] = 0x80; Form1->BufferSendCom[2] = 0x00; for(i = 0; i < sizeof(BufferSendCom); i++) { TransmitCommChar(Form1->hSerial, Form1->BufferSendCom[i]); } hexdumpstrWrite(Form1->BufferSendCom,128); // Задержка ::Sleep(1); } } return 0; }
void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift){ if(Key == 13) { buf_rez = Edit1->Text.ToInt();}}
fSuccess = ReadFile( Form1->hSerial, &Ibuffer, Form1->buf_rez, &nBytesRead, NULL );
#include <vcl.h>#pragma hdrstop #include "Unit1.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma resource "*.dfm"TForm1 *Form1; #define BUFSIZE 1000 //ёмкость буфера //---------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}//---------------------------------------------------------------------------// Глобальные переменные //---------------------------------------------------------------------------AnsiString portname;HANDLE COMport;DWORD WINAPI ReadThread(LPVOID);DWORD WINAPI WriteThread(LPVOID); //дескриптор потока чтения из портаHANDLE reader;//дескриптор потока записи в портHANDLE writer;//приёмный и передающий буферыunsigned char bufrd[BUFSIZE], bufwr[BUFSIZE]; //структура OVERLAPPED необходима для асинхронных операций, при этом для операции чтения и записи нужно объявить разные структуры//эти структуры необходимо объявить глобально, иначе программа не будет работать правильноOVERLAPPED overlapped; //будем использовать для операций чтения (см. поток ReadThread)OVERLAPPED overlappedwr; //будем использовать для операций записи (см. поток WriteThread)int handle; //дескриптор для работы с файлом с помощью библиотеки <io.h>// bool fl=0; //флаг, указывающий на успешность операций записи (1 - успешно, 0 - не успешно)DWORD bc;DCB *dcb;// счетчик приемовunsigned long counterRX; //--------------------------------------------------------------------------- // Функции //---------------------------------------------------------------------------// Вывод принятых байтов на экран void ReadPrinting(DWORD btr){ String stroka, temp_str; for(UINT32 i=0; i<btr ; i++) stroka = stroka + IntToHex(bufrd[i], 2) + ' '; // Перенос буфера в строку. Form1->Memo1->Lines->Add(stroka); // Вывод. Form1->Label1->Caption = "Всего принято: " + IntToStr(counterRX); memset(bufrd, 0, BUFSIZE); // Очистить буфер (чтобы данные не накладывались друг на друга).} //---------------------------------------------------------------------------// Поток чтения ReadThead //главная функция потока, реализует приём байтов из COM-портаDWORD WINAPI ReadThread(LPVOID){ COMSTAT comstat; // структура текущего состояния порта, в данной программе используется для определения количества принятых в порт байтов DWORD btr, temp, mask, signal; // переменная temp используется в качестве заглушки overlapped.hEvent = CreateEvent(NULL, true, true, NULL); // создать сигнальный объект-событие для асинхронных операций SetCommMask(COMport, EV_RXCHAR); // установить маску на срабатывание по событию приёма байта в порт while(1) //while(!flag) // пока поток не будет прерван, выполняем цикл { WaitCommEvent(COMport, &mask, &overlapped); //ожидать события приёма байта (это и есть перекрываемая операция) signal = WaitForSingleObject(overlapped.hEvent, INFINITE); //приостановить поток до прихода байта if(signal == WAIT_OBJECT_0) //если событие прихода байта произошло { if(GetOverlappedResult(COMport, &overlapped, &temp, true)) //проверяем, успешно ли завершилась перекрываемая операция WaitCommEvent if((mask & EV_RXCHAR)!=0) //если произошло именно событие прихода байта { ClearCommError(COMport, &temp, &comstat); // нужно заполнить структуру COMSTAT btr = comstat.cbInQue; // и получить из неё количество принятых байтов if(btr) // если действительно есть байты для чтения { ReadFile(COMport, bufrd, btr, &temp, &overlapped); // прочитать байты из порта в буфер программы counterRX+=btr; // увеличиваем счётчик байтов ReadPrinting(btr); // вызываем функцию для вывода данных на экран и в файл } } } }//CloseHandle(overlapped.hEvent);//flag2=1;} //---------------------------------------------------------------------------// Поток записи WriteThread //главная функция потока, выполняет передачу байтов из буфера в COM-портDWORD WINAPI WriteThread(LPVOID){ DWORD temp, signal; //temp - переменная-заглушка overlappedwr.hEvent = CreateEvent(NULL, true, true, NULL); //создать событие while(1) { //записать байты в порт (перекрываемая операция!) WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr); //приостановить поток, пока не завершится перекрываемая операция WriteFile signal = WaitForSingleObject(overlappedwr.hEvent, INFINITE); //если операция завершилась успешно if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlappedwr, &temp, true))) { //вывести сообщение об этом в строке состояния Form1->Panel2->Caption = "Передача прошла успешно"; } //иначе вывести в строке состояния сообщение об ошибке else {Form1->Panel2->Caption = "Ошибка передачи";} SuspendThread(writer); }} //---------------------------------------------------------------------------// установки Com порта void __fastcall TForm1::Button1Click(TObject *Sender){ Form1->Panel1->Caption = ""; DCB dcb; COMMTIMEOUTS timeouts; // Открытие порта// portname += "\\\\."; // com_port.c_str()// portname += ComboBox1->Text; //portname = ChoiceCOM->Text; portname = Form1->ComboBox1->Text; COMport=CreateFile(portname.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); //здесь: // - portname.c_str() - имя порта в качестве имени файла, // c_str() преобразует строку типа String в строку в виде массива типа char, иначе функция не примет // - GENERIC_READ | GENERIC_WRITE - доступ к порту на чтение/записть // - 0 - порт не может быть общедоступным (shared) // - NULL - дескриптор порта не наследуется, используется дескриптор безопасности по умолчанию // - OPEN_EXISTING - порт должен открываться как уже существующий файл // - FILE_FLAG_OVERLAPPED - этот флаг указывает на использование асинхронных операций // - NULL - указатель на файл шаблона не используется при работе с портами if(COMport==INVALID_HANDLE_VALUE) { Panel1->Font->Color = clRed; Panel1->Caption = " Не удалось открыть последовательный порт " + AnsiString(portname.c_str()) + "."; return; } else { Panel1->Font->Color = clGreen; Panel1->Caption = " Открыт порт " + AnsiString(portname.c_str()); return; } // Инициализация порта //dcb=(DCB*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DCB)); // Выделение области памяти для DCB из кучи и заполнение этой области нулями. dcb.DCBlength=sizeof(DCB); if(!GetCommState(COMport, &dcb)) // Эта функция заполняет DCB информацией о текущем состоянии устройства, точнее о его настройках. { // Если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния.// HeapFree(GetProcessHeap(),0,dcb); // Освобождение памяти из кучи. CloseHandle(COMport); Panel1->Font->Color = clRed; Panel1->Caption = "Не удалось считать 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)) {// Если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния.// HeapFree(GetProcessHeap(),0,dcb); // Освобождение памяти из кучи. CloseHandle(COMport); Panel1->Font->Color = clRed; Panel1->Caption = "Не удалось установить DCB."; return; } // Установка таймаутов. timeouts.ReadIntervalTimeout = 0; // таймаут между двумя символами timeouts.ReadTotalTimeoutMultiplier = 0; // общий таймаут операции чтения timeouts.ReadTotalTimeoutConstant = 0; // константа для общего таймаута операции чтения timeouts.WriteTotalTimeoutMultiplier = 0; // общий таймаут операции записи timeouts.WriteTotalTimeoutConstant = 0; // константа для общего таймаута операции записи // Загрузить структуру таймаутов в порт. if(!SetCommTimeouts(COMport, &timeouts)) {// Если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния. CloseHandle(COMport); Panel1->Font->Color = clRed; Panel1->Caption = "Не удалось установить тайм-ауты."; return; } // Установить размеры очередей приёма и передачи SetupComm(COMport,2000,2000); PurgeComm(COMport,PURGE_RXCLEAR); // Очистка буферов порта. Button1->Enabled = false; Button2->Enabled = true; // Создание потоков на WINAPI: // Cоздаём поток чтения, который сразу начнёт выполняться (предпоследний параметр = 0). reader = CreateThread(NULL, 0, ReadThread, NULL, 0, NULL); // Cоздаём поток записи в остановленном состоянии (предпоследний параметр = CREATE_SUSPENDED). writer = CreateThread(NULL, 0, WriteThread, NULL, CREATE_SUSPENDED, NULL); counterRX = 0;}//---------------------------------------------------------------------------// завершение по закрытию формы void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action){ if(writer) { TerminateThread(writer,0); CloseHandle(overlappedwr.hEvent); //нужно закрыть объект-событие CloseHandle(writer); } //завершить поток чтения из порта, проверка if(reader) обязательна, иначе возникают ошибки //if(reader) reader->Terminate(); //завершить поток записи в порт, проверка if(writer) обязательна, иначе возникают ошибки// if(writer)writer->Terminate(); if(COMport) CloseHandle(COMport); //закрыть порт// if(handle) close(handle); //закрыть файл, в который велась запись принимаемых данных if(reader) { TerminateThread(reader,0); CloseHandle(overlappedwr.hEvent); //нужно закрыть объект-событие CloseHandle(reader); } }//---------------------------------------------------------------------------// передача данных void __fastcall TForm1::Button2Click(TObject *Sender){ memset(bufwr,0,BUFSIZE); //очистить программный передающий буфер, //чтобы данные не накладывались друг на друга PurgeComm(COMport, PURGE_TXCLEAR); //очистить передающий буфер порта strcpy(bufwr,Form1->Edit1->Text.c_str()); //занести в программный передающий буфер строку из Edit1 ResumeThread(writer); //активировать поток записи данных в порт}//---------------------------------------------------------------------------