Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.05.2016, 18:02   #11
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

там идет принцип:
Код:
void ThreadEntry(void *data)
{
    ((TThread*)data)->Execute();
}
TThread *thread=new TMyThread();
BeginThread(&ThreadEntry, thread);
по крайней мере так делает VCL.
да в принципе и логично
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 14.05.2016, 14:55   #12
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию

согласно статьи http://www.piclist.ru/S-COM-THREAD-R...HREAD-RUS.html, поток чтения такой

для надежности после

ReadFile(COMport, buffer, btr, &temp, &overlapped); //прочитать байты из порта в буфер программы

поставил

signal = WaitForSingleObject(overlapped.hEve nt, INFINITE);

так как операция чтения у нас асинхронная.


Код:
//---------------------------------------------------------------------------
#define BUFSIZE 255 //ёмкость буфера
unsigned char bufrd[BUFSIZE], bufwr[BUFSIZE]; //приёмный и передающий буферы
//---------------------------------------------------------------------------
HANDLE COMport; //дескриптор порта
//структура OVERLAPPED необходима для асинхронных операций, при этом для операции чтения и записи нужно объявить
разные структуры
//эти структуры необходимо объявить глобально, иначе программа не будет работать правильно
OVERLAPPED overlapped; //будем использовать для операций чтения (см. поток ReadThread)
OVERLAPPED overlappedwr; //будем использовать для операций записи (см. поток WriteThread)
//---------------------------------------------------------------------------
//главная функция потока, реализует приём байтов из COM-порта
{
COMSTAT comstat; //структура текущего состояния порта, в данной программе используется для определения
количества принятых в порт байтов
DWORD btr, temp, mask, signal; //переменная temp используется в качестве заглушки
overlapped.hEvent = CreateEvent(NULL, true, true, NULL); //создать сигнальный объект-событие для
асинхронных операций
SetCommMask(COMport, EV_RXCHAR); //установить маску на срабатывание по событию приёма байта в порт
while(условие) //пока поток не будет прерван, выполняем цикл
{
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); //прочитать байты из порта в буфер программы
}
}
}
}
CloseHandle(overlapped.hEvent); //перед выходом из потока закрыть объект-событие
}
//---------------------------------------------------------------------------
RAFA91 вне форума Ответить с цитированием
Старый 15.05.2016, 09:38   #13
Почтальон
Пользователь
 
Регистрация: 12.05.2016
Сообщений: 16
По умолчанию

RAFA91, спасибо большое за ссылку, полезная информация
Почтальон вне форума Ответить с цитированием
Старый 15.05.2016, 12:03   #14
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию

Вот накрутил класс для увязки с контроллером. Что не так ?????

С контроллера приходят посылки размером 100 байт.


Код:
void strcpy(char *buffer_write, const char *buff, int szBuff)
{
	int i;
	for (i=0; i<szBuff; i++) buffer_write[i] = buff[i];
	buffer_write[i] = '\0';
}

unsigned __stdcall ReadThread(void *);  //поток чтения
unsigned __stdcall WriteThread(void *); //поток записи

class ClassCOM
{
public:
	struct DataCom
{
	OVERLAPPED overlapped;
	HANDLE COMport;
	int  counter;
	char *buffer;
	bool flag;      //флаг чтения/записи
	HANDLE hEvent;
};
	ClassCOM();
	~ClassCOM();
	bool OpenCom(int port, int baud);	//открыть порт
	bool ReadCom(char* buff, int szBuff); //получить посылку
	bool WriteCom(const char* buff, int szBuff); //отправить посылку
	void CloseCom();
private:
	 HANDLE COMport;
	 HANDLE reader,writer; //дескрипторы потоков
	 bool state; //флаг открытия порта
	 char buffer_read[1000]; //буфер приема
	 char buffer_write[1000]; //буфер передачи
	 DataCom read;
	 DataCom write;
	 
	 HANDLE hEvent_read; // решение критических зон для чтения
	 HANDLE hEvent_write; // решение критических зон для записи

};

ClassCOM :: ClassCOM()
{
	COMport = NULL;
	reader = NULL;
	writer = NULL;
	state = false;     //флаг открытия порта
	
	hEvent_read =  NULL;
	hEvent_write =  NULL;
}

ClassCOM :: ~ClassCOM()
{
	if(writer)
	{
		TerminateThread(writer,0);
		CloseHandle(write.overlapped.hEvent);	//нужно закрыть объект-событие
		CloseHandle(writer);
		writer = NULL;
	}
	if(reader)
	{
		TerminateThread(reader,0);
		CloseHandle(read.overlapped.hEvent);	//нужно закрыть объект-событие
		CloseHandle(reader);
		reader = NULL;
	}
	if (hEvent_write)
	{
		CloseHandle(hEvent_write);
		hEvent_write = NULL;
	}
	if (hEvent_read)
	{
		CloseHandle(hEvent_read);
		hEvent_read = NULL;
	}
	if (COMport)
	{
		CloseHandle(COMport);
		COMport = NULL;
	}
	state = false;      //сбросить флаг открытия порта
}

bool ClassCOM :: OpenCom(int port, int baud) //открыть порт
{
	if (state) return true;

	char COM_string[20];
	sprintf(COM_string,"COM%d", port);

	COMport = CreateFile(COM_string,GENERIC_READ | GENERIC_WRITE, 0,
		      NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	
	if(COMport == INVALID_HANDLE_VALUE) return false;

	DCB dcb;

	GetCommState(COMport, &dcb);

	dcb.DCBlength = sizeof(DCB);
	dcb.BaudRate = baud; 
	dcb.fBinary = TRUE;
	dcb.fOutxCtsFlow = FALSE;
	dcb.fOutxDsrFlow = FALSE; 
	dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; 
	dcb.fDsrSensitivity = FALSE; 
	dcb.fNull = FALSE; 
	dcb.fRtsControl = RTS_CONTROL_DISABLE; 
	dcb.fAbortOnError = FALSE; 
	dcb.ByteSize = 8; 
	dcb.Parity = NOPARITY; 
	dcb.StopBits = ONESTOPBIT ; 

	SetCommState(COMport, &dcb);

	COMMTIMEOUTS timeouts;

	 timeouts.ReadIntervalTimeout = 0;	 	
	 timeouts.ReadTotalTimeoutMultiplier = 0;	
	 timeouts.ReadTotalTimeoutConstant = 0;   
	 timeouts.WriteTotalTimeoutMultiplier = 0;    
	 timeouts.WriteTotalTimeoutConstant = 0;  

	 SetCommTimeouts(COMport, &timeouts);

	 SetupComm(COMport, 1000, 1000);

	 PurgeComm(COMport, PURGE_RXCLEAR); 

	 //*************************************************

	hEvent_read = CreateEvent(NULL, false, true, NULL); // автосброс
	hEvent_write = CreateEvent(NULL, false, true, NULL); // автосброс

	//*************************************************

	ZeroMemory(&read,sizeof(read));

	 read.overlapped.hEvent = CreateEvent(NULL, true, true, NULL); // создать сигнальный объект-событие
							  // для асинхронных операций
	 read.COMport = COMport;
	 read.counter = 0;
	 read.buffer = buffer_read;
	 read.flag = false; 
	 read.hEvent = hEvent_read; 

	  //*************************************************

	  ZeroMemory(&write,sizeof(write));

	 write.overlapped.hEvent = CreateEvent(NULL, true, true, NULL); // создать сигнальный объект-событие
							  // для асинхронных операций
	 write.COMport = COMport;
	 write.counter = 0;
	 write.buffer = buffer_write;
	 write.flag = false; 
	 write.hEvent = hEvent_write; 

	 //создаем потоки чтения/записи
	 
	 reader = (HANDLE)_beginthreadex(NULL, 0, ReadThread, &read, 0, NULL); //поток чтения
	 writer = (HANDLE)_beginthreadex(NULL, 0, WriteThread, &write, 0, NULL); //поток записи

	 if (!reader || !writer) return false;
	 
	 state = true;  //установить флаг открытия порта
  
   return true;
  }  

void ClassCOM :: CloseCom()
{
	if(writer)
	{
		TerminateThread(writer,0);
		CloseHandle(write.overlapped.hEvent);	//нужно закрыть объект-событие
		CloseHandle(writer);
		writer = NULL;
	}
	if(reader)
	{
		TerminateThread(reader,0);
		CloseHandle(read.overlapped.hEvent);	//нужно закрыть объект-событие
		CloseHandle(reader);
		reader = NULL;
	}
	if (hEvent_write)
	{
		CloseHandle(hEvent_write);
		hEvent_write = NULL;
	}
	if (hEvent_read)
	{
		CloseHandle(hEvent_read);
		hEvent_read = NULL;
	}
	if (COMport)
	{
		CloseHandle(COMport);
		COMport = NULL;
	}
	state = false;     //сбросить флаг открытия порта
}

bool ClassCOM :: WriteCom(const char* buff, int szBuff)
{
	if (!state)  return false;

	WaitForSingleObject(hEvent_write, INFINITE); //начало критического участка

	  bool flag_write = write.flag;

	  if (!flag_write && buff && (szBuff > 0))
	  {
		  strcpy(buffer_write,buff,szBuff);
		  
		  write.flag = true;      //установить флаг записи
		  write.counter = szBuff; //установить байты записи
		  
		  SetEvent(hEvent_write); //конец критического участка
		  return true;
	  }
	  else
	  {
		  SetEvent(hEvent_write); //конец критического участка
		  return false;
	  }
}


bool ClassCOM :: ReadCom(char* buff, int szBuff)
{
	if (!state)  return false;
	
	WaitForSingleObject(hEvent_read, INFINITE); //начало критического участка

	bool flag_read = read.flag;
	

	 if (flag_read && (szBuff > 0) && (szBuff <= 100))
	 {
		 strcpy(buff,buffer_read,szBuff);
		 
		 read.flag = false; //сбросить флаг чтения
		 
		 SetEvent(hEvent_read); //конец критического участка
		 return true;
	 
	 }
	  else
	  {
		  SetEvent(hEvent_read); //конец критического участка
		  return false;
	  }
}

Последний раз редактировалось RAFA91; 15.05.2016 в 12:05.
RAFA91 вне форума Ответить с цитированием
Старый 15.05.2016, 12:04   #15
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию

Код:
unsigned __stdcall ReadThread(void *lpParam)
{
	ClassCOM::DataCom &data = *(ClassCOM::DataCom *)lpParam; //получить ссылку на структуру DataCom

	OVERLAPPED &overlapped = data.overlapped;
	HANDLE COMport = data.COMport;
	char *buffer_read = data.buffer; 
	HANDLE hEvent = data.hEvent;

	int counter = 0;

	COMSTAT comstat;		
	DWORD btr, temp, mask, signal;	
	
	SetCommMask(COMport, EV_RXCHAR);  //установить маску        
	
	while(1)				    
	{
		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 >= 100) 
					{
						ReadFile(COMport, buffer_read, btr, &temp, &overlapped);     //прочитать байты из порта в буфер программы
						
						signal = WaitForSingleObject(overlapped.hEvent, INFINITE);
								
						if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlapped, &temp, true)))
						{
							WaitForSingleObject(hEvent, INFINITE); //начало критического участка
									
							data.flag = true; //установить флаг чтения
									
							SetEvent(hEvent); //конец критического участка
						}
					}
					
				}
		}
	}
}


unsigned __stdcall WriteThread(void *lpParam)
{
	ClassCOM::DataCom &data = *(ClassCOM::DataCom *)lpParam; //получить ссылку на структуру DataCom
	
	DWORD temp, signal;	
	bool flag_write; //флаг записи
	int counter;
	
	OVERLAPPED &overlapped = data.overlapped;
	HANDLE COMport = data.COMport;

	char *buffer_write = data.buffer;

	HANDLE hEvent = data.hEvent;
	
	while(1)
	{
		WaitForSingleObject(hEvent, INFINITE); //начало критического участка
		
		flag_write = data.flag;
		counter = data.counter;  //к-во байт записи
		
		SetEvent(hEvent); //конец критического участка
		
		if (flag_write)
		{
			WriteFile(COMport, buffer_write, counter, &temp, &overlapped); //записать байты из буфера программы в порт
			
			signal = WaitForSingleObject(overlapped.hEvent, INFINITE);
			
			if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlapped, &temp, true)))
			{
				WaitForSingleObject(hEvent, INFINITE); //начало критического участка
				
				data.flag = false; //сбросить флаг записи
				
				SetEvent(hEvent); //конец критического участка
			}
		}
	}
}
RAFA91 вне форума Ответить с цитированием
Старый 16.05.2016, 15:54   #16
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию

Вот еще не поточная версия класса. Поточный вариант сильно жрет процессор.

Код:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <process.h>
#include "WRITE.h"

using namespace std;

void strcpy(char *buffer_write, const char *buff, int szBuff)
{
	int i;
	for (i=0; i<szBuff; i++) buffer_write[i] = buff[i];
	buffer_write[i] = '\0';
}

class ClassCOM
{
public:
	ClassCOM();
	~ClassCOM();
	bool OpenCom(int port, int baud);	//открыть порт
	bool ReadCom(char* buff, int szBuff); //получить посылку
	bool WriteCom(const char* buff, int szBuff); //отправить посылку
	void CloseCom();
private:
	 HANDLE COMport;
	 
	 bool state; //флаг открытия порта
	 char buffer_read[1000]; //буфер приема
	 char buffer_write[1000]; //буфер передачи
	 OVERLAPPED read;
	 OVERLAPPED write;
	
	 HANDLE hEvent_read; // 
	 HANDLE hEvent_write; // 

};

ClassCOM :: ClassCOM()
{
	COMport = NULL;
	state = false;     //флаг открытия порта
	hEvent_read =  NULL;
	hEvent_write =  NULL;
}

ClassCOM :: ~ClassCOM()
{
	if (hEvent_write)
	{
		CloseHandle(hEvent_write);
		hEvent_write = NULL;
	}
	if (hEvent_read)
	{
		CloseHandle(hEvent_read);
		hEvent_read = NULL;
	}
	if (COMport)
	{
		CloseHandle(COMport);
		COMport = NULL;
	}
	state = false;      //сбросить флаг открытия порта
}

bool ClassCOM :: OpenCom(int port, int baud) //открыть порт
{
	if (state) return true;

	char COM_string[20];
	sprintf(COM_string,"COM%d", port);

	COMport = CreateFile(COM_string,GENERIC_READ | GENERIC_WRITE, 0,
		      NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	
	if(COMport == INVALID_HANDLE_VALUE) return false;

	DCB dcb;

	GetCommState(COMport, &dcb);

	dcb.DCBlength = sizeof(DCB); //Длина структуры, в байтах.
	dcb.BaudRate = baud; //Скорость передачи данных
	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; //Число переданных и принятых битов, в байтах.
	dcb.Parity = NOPARITY; //Без проверки четности
	dcb.StopBits = ONESTOPBIT; //1 стоповый бит 

	SetCommState(COMport, &dcb);

	COMMTIMEOUTS timeouts;

	 timeouts.ReadIntervalTimeout = 0;	 	
	 timeouts.ReadTotalTimeoutMultiplier = 0;	
	 timeouts.ReadTotalTimeoutConstant = 0;   
	 timeouts.WriteTotalTimeoutMultiplier = 0;    
	 timeouts.WriteTotalTimeoutConstant = 0;  

	 SetCommTimeouts(COMport, &timeouts);

	 SetupComm(COMport, 1000, 1000);

	 PurgeComm(COMport, PURGE_RXCLEAR); 

	 //*************************************************

	hEvent_read = CreateEvent(NULL, true, true, NULL); // ручной сброс
	hEvent_write = CreateEvent(NULL, true, true, NULL); // ручной сброс

	//*************************************************

	ZeroMemory(&read,sizeof(read));

	 read.hEvent = hEvent_read; // создать сигнальный объект-событие
							    // для асинхронных операций
	 
	  //*************************************************

	  ZeroMemory(&write,sizeof(write));

	 write.hEvent = hEvent_write; // создать сигнальный объект-событие
							  // для асинхронных операций
	 
	 state = true;  //установить флаг открытия порта
  
   return true;
  }  

void ClassCOM :: CloseCom()
{
	if (hEvent_write)
	{
		CloseHandle(hEvent_write);
		hEvent_write = NULL;
	}
	if (hEvent_read)
	{
		CloseHandle(hEvent_read);
		hEvent_read = NULL;
	}
	if (COMport)
	{
		CloseHandle(COMport);
		COMport = NULL;
	}
	state = false;     //сбросить флаг открытия порта
}

bool ClassCOM :: WriteCom(const char* buff, int szBuff)
{
	if (!state)  return false;
	
	DWORD signal,temp;
	
	signal = WaitForSingleObject(hEvent_write, 0);

	if((signal == WAIT_OBJECT_0)) 
	{
		 if (buff && (szBuff > 0))
		 {
			 strcpy(buffer_write,buff,szBuff);
			 
			 WriteFile(COMport, buffer_write, szBuff, &temp, &write);

			 return true;
		 }
		 else  return false;
	}
	else return false;
}


bool ClassCOM :: ReadCom(char* buff, int szBuff)
{
	if (!state)  return false;

	DWORD signal,temp,btr;

	COMSTAT comstat;

	ClearCommError(COMport, &temp, &comstat);	
	
	btr = comstat.cbInQue;  

	if (buff && (szBuff > 0) && (szBuff <= btr))
	{
		ReadFile(COMport, buffer_read, szBuff, &temp, &read); 

		WaitForSingleObject(hEvent_read, INFINITE);

		strcpy(buff,buffer_read,szBuff);

		return true;
	}
	else  return false;
}



int main()
{
	ClassCOM COM;
	if (COM.OpenCom(1, CBR_110)) cout<<"OK 1"<<endl;
	cout<<strlen(write)<<endl;
	system("pause");
	if (COM.WriteCom(write, strlen(write))) cout<<"OK 2"<<endl;
	system("pause");
	while (!COM.ReadCom(read, strlen(write))) {cout<<"OK 3"<<endl;}
	system("pause");
	cout<<read<<endl;
	system("pause");
	cout<<strlen(read)<<endl;
	system("pause");
	cout<<"**********************************"<<endl;
	system("pause");
	if (COM.WriteCom(write, strlen(write))) cout<<"OK 2"<<endl;
	//system("pause");
	while (!COM.ReadCom(read, strlen(write))) {cout<<"OK 3"<<endl;}
	system("pause");
	cout<<read<<endl;
	system("pause");
	cout<<strlen(read)<<endl;
	system("pause");
	return 0;
}
RAFA91 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Разработка приложений для работы с базами данных JuliaO Помощь студентам 2 04.11.2015 23:14
Разработка ПО для работы с сетевыми устройствами M_Pavel Фриланс 2 04.03.2013 11:54
программа для работы с СОМ-портом cambit Visual C++ 1 16.02.2012 17:57
программа для работы с COM портом BARNEY Фриланс 2 03.02.2012 16:00
Разработка приложения для работы с MSQL базами Tvv7-7-7 Общие вопросы Delphi 11 31.12.2010 15:24