Как очистить буфер com-порта?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Alsou93
Сообщения: 3
Зарегистрирован: 04 мар 2014, 02:47

В этой программе я считываю данные с lpt-порта и в зависимости от полученных значений, посылаю данные в com-порт, куда подключен микроконтроллер. Проблема в том, что в процессе работы программы com-порт лишь принимает первые данные, а остальные игнорирует, т.е микроконтроллер только один раз замыкает реле, а размыкать он их не размыкает. И теперь я не знаю как очистить буфер com-порта, для того чтобы можно было отправлять новые команды com-порту. Испробовала несколько функций( они в комментариях к программе), но все безуспешно, может я как то их не так использую?

Код: Выделить всё

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <ctime>   
#include <stdio.h>
#include <conio.h>
#include "h.h"
#define _WIN32_WINNT 0x0500
#include <fstream>
using namespace std;
 
HANDLE hSerial;
 
int VklRele() //включаю 
 
{ 
    LPCTSTR sPortName = L"COM3";  
 
    hSerial = ::CreateFile(sPortName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if(hSerial==INVALID_HANDLE_VALUE)
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
            cout << "serial port does not exist.\n";
        }
        cout << "some other error occurred.\n";
    }
     
    
      if(hSerial!= NULL) //здесь как бы пытаюсь очистить буфер, но безуспешно
      CloseHandle(hSerial);
 
    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams))
    {
        cout << "getting state error\n";
    }
    dcbSerialParams.BaudRate=CBR_9600;
    dcbSerialParams.ByteSize=8;
    dcbSerialParams.StopBits=ONESTOPBIT;
    dcbSerialParams.Parity=NOPARITY;
    if(!SetCommState(hSerial, &dcbSerialParams))
    {
        cout << "error setting serial port state\n";
    }
    char data[] = "$KE,REL,1,1\r\n";
    DWORD dwSize = sizeof(data);
    DWORD dwBytesWritten;
    LPOVERLAPPED ov;
    
 
    BOOL iRet = WriteFile (hSerial,data,dwSize,&dwBytesWritten ,NULL);
 
    cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
 
    
    //PurgeComm(hSerial, PURGE_TXCLEAR);//  эту команду пробовала использовать
        //PurgeComm(hSerial, PURGE_RXCLEAR);//  здесь пробовала параметр сменить
    //FlushFileBuffers(hSerial);// и эта тоже не работает...
    return 0;
    
}
 
int ViklRele()// выключаю
{ 
    LPCTSTR sPortName = L"COM3";  
 
    hSerial = ::CreateFile(sPortName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if(hSerial==INVALID_HANDLE_VALUE)
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
            cout << "serial port does not exist.\n";
        }
        cout << "some other error occurred.\n";
    }
 
    
      if(hSerial!= NULL)
      CloseHandle(hSerial);
 
    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams))
    {
        cout << "getting state error\n";
    }
    dcbSerialParams.BaudRate=CBR_9600;
    dcbSerialParams.ByteSize=8;
    dcbSerialParams.StopBits=ONESTOPBIT;
    dcbSerialParams.Parity=NOPARITY;
    if(!SetCommState(hSerial, &dcbSerialParams))
    {
        cout << "error setting serial port state\n";
    }
    char data[] = "$KE,REL,1,0\r\n";
    DWORD dwSize = sizeof(data);
    DWORD dwBytesWritten;
    LPOVERLAPPED ov;
    
    BOOL iRet = WriteFile (hSerial,data,dwSize,&dwBytesWritten ,NULL);
 
    cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
 
    //PurgeComm(hSerial, PURGE_TXCLEAR);// вообщем те же самые попытки, что и в функции VklRele()
        //PurgeComm(hSerial, PURGE_RXCLEAR);//  
    //FlushFileBuffers(hSerial);//
 
    return 0;
    
}
//здесь я делаю таймер, чтобы использовать в main
 
void how2timer(int ms) { 
    int CLOCKS_PER_MSEC = CLOCKS_PER_SEC / 1000;   
    clock_t end_time = clock() + ms * CLOCKS_PER_MSEC ; 
    while (clock() < end_time) {} 
    cout << "5 seconds passed!!!\n";  
}
 
int _tmain(int argc, _TCHAR* argv[])
{ 
     while(1){
  
  cout<<"Read data from DATA register.\n"<<endl;    
 
  int data;
  data = Inp32(888); //считываю с lpt порта
  cout<<"10: "<<data<<endl;
 
  char number[20];
  itoa(data,number,2); //считываю с lpt порта
  cout<<" 2: "<<number<<endl;
    
  //здесь сравниваю значения, полученные с lpt порта
    
    if(number[0]=='1' && number[1]=='1' && number[2]=='1' && number[3]=='1' && number[4]=='1' && number[5]=='1' && number[6]=='1' && number[7]=='1')
    {
        VklRele();// если замкнулся нужный контакт, то включаю реле, т.е.какое-нибудь устройство
        how2timer(5000);//жду 5 секунд
        ViklRele();//устройство должно выключиться
    }
    
    
  }
  return 0;
 }
Аватара пользователя
somewhere
Сообщения: 1858
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

У вас инициализация порта происходит два раза - и во включении и в выключении. Необходимо исправить программу так, чтобы инициализация происходила единожды при запуске, а вкл/выкл - это всего лишь поток данных, отсылаемых в порт. Уверен, что тогда все заработает. Здесь, имхо, причина в том, что после второго инита скорее всего получаем Invalid Handle, т.к. порт уже открыт и команду выключения мы посылаем инвалиду)
It's a long way to the top if you wanna rock'n'roll
Alsou93
Сообщения: 3
Зарегистрирован: 04 мар 2014, 02:47

somewhere, спасибо за совет, переделала так, что инициализация порта происходит в main, а включение и выключение осуществляется в других отдельных функциях. Теперь другая проблема, как показывает консольное окно приложения, com-порт принимает команды, но микроконтроллер по-прежнему только один раз замыкает реле, а остальное все игнорирует. Отсюдова доводы, что посылаемые команды в буфере не обновляются, попыталась использовать функцию UpdateData(true) но компилятор выдает ошибки. Какую функцию нужно использовать чтобы обновить записи в буфере com-порта?

Код: Выделить всё

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <ctime>   
#include <stdio.h>
#include <conio.h>
#include "h.h"
#define _WIN32_WINNT 0x0500
#include <fstream>
using namespace std;

HANDLE hSerial;

 int VklRele()
{ 	
	//UpdateData(true);// хочу обновить значения в буфере com-порта, но эта функция здесь не работает
	PurgeComm(hSerial, PURGE_TXCLEAR);
	char data[] = "$KE,REL,1,1\r\n";
	DWORD dwSize = sizeof(data);
	DWORD dwBytesWritten;
	LPOVERLAPPED ov;


	BOOL iRet = WriteFile (hSerial,data,dwSize,&dwBytesWritten ,NULL);
	cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
	return 0;
}

int ViklRele()
{ 
	//UpdateData(true);
	PurgeComm(hSerial, PURGE_TXCLEAR);
	char data[] = "$KE,REL,1,0\r\n";
	DWORD dwSize = sizeof(data);
	DWORD dwBytesWritten;
	LPOVERLAPPED ov;
	BOOL iRet = WriteFile (hSerial,data,dwSize,&dwBytesWritten ,NULL);
	cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
	return 0;
	
}

void how2timer(int ms) {
    int CLOCKS_PER_MSEC = CLOCKS_PER_SEC / 1000;  
    clock_t end_time = clock() + ms * CLOCKS_PER_MSEC ;  
    while (clock() < end_time) {}  
    cout << "5 seconds passed!!!\n";  
}

int _tmain(int argc, _TCHAR* argv[])
{ 
	 LPCTSTR sPortName = L"COM3";  

	hSerial = ::CreateFile(sPortName,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	if(hSerial==INVALID_HANDLE_VALUE)
	{
		if(GetLastError()==ERROR_FILE_NOT_FOUND)
		{
			cout << "serial port does not exist.\n";
		}
		cout << "some other error occurred.\n";
	}
	
	DCB dcbSerialParams = {0};
	dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
	if (!GetCommState(hSerial, &dcbSerialParams))
	{
		cout << "getting state error\n";
	}
	dcbSerialParams.BaudRate=CBR_9600;
	dcbSerialParams.ByteSize=8;
	dcbSerialParams.StopBits=ONESTOPBIT;
	dcbSerialParams.Parity=NOPARITY;
	if(!SetCommState(hSerial, &dcbSerialParams))
	{
		cout << "error setting serial port state\n";
	}

	while(1){
  
  cout<<"Read data from DATA register.\n"<<endl;	

  int data;
  data = Inp32(888);
  cout<<"10: "<<data<<endl;

  char number[20];
  itoa(data,number,2);
  cout<<" 2: "<<number<<endl;
    
   FILE * fo;
   fo=fopen("fajl6.txt","wt");
    fprintf(fo,"%s\n",number);
    fclose(fo);
	

	if(number[0]=='1' && number[1]=='1' && number[2]=='1' && number[3]=='1' && number[4]=='1' && number[5]=='1' && number[6]=='1' && number[7]=='1')
	{
		VklRele();
		how2timer(5000);
		ViklRele();
	}

	how2timer(5000);  // 5 секунд
  }
  return 0;
}
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Alsou93, зачем плодить темы? Я удалил дубликат.

По поводу проблемы - она элементарна, как и предыдущая. Каждому CreateFile должен соответствовать CloseFile. Подозреваю, что имеенно он и произведёт флашинг (запись временного буфера в устройство), в случае COM-порта. Если есть желание, чтобы данные записывались в порт без буфферизации, то следует выставить флаг FILE_FLAG_NO_BUFFERING при открытии файла.

И вообще, я бы рекомендовал почитать документацию по тем функциям, которые используются, а то как-то непрофессионально получается (о том, как проверяются флажки в числе - конвертация числа в строку и последующее сравнение символов - я вообще молчу).

Документация:
CreateFile
File Buffering
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить