Member 12669621 Ответов: 3

Чтение из последовательного порта с помощью языка C в visual studio


привет, ребята. Я делаю некоторый com - порт ввода-вывода в C с помощью visual studio. Я успешно написал запрос в порт. Теперь проблема заключается в том, чтобы прочитать то, что было отправлено. Он получает данные, но это просто жаргон, вероятно, мои типы данных. может кто-нибудь, пожалуйста, помочь с этим. мой код здесь

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#define    BUFFERLENGTH 256
int main(int argc, char *argv[])
{
	HANDLE hComm;
	DWORD MORO;
	char   *pcCommPort = "COM8";
	BOOL Write_Status;
	DCB dcbSerialParams;					// Initializing DCB structure
	COMMTIMEOUTS timeouts = { 0 };
	BOOL  Read_Status;                      // Status of the various operations 
	DWORD dwEventMask;						// Event mask to trigger
	char  TempChar = "";                        // Temperory Character
	char  *SerialBuffer[BUFFERLENGTH+1];               // Buffer Containing Rxed Data
	DWORD NoBytesRead;                     // Bytes read by ReadFile()
	int i = 0;

	
	printf("\n\n +==========================================+");
	printf("\n |  Serial Transmission (Win32 API)         |");
	printf("\n +==========================================+\n");

	hComm = CreateFileA(pcCommPort,
		GENERIC_READ | GENERIC_WRITE,
		0,    // must be opened with exclusive-access
		NULL, // no security attributes
		OPEN_EXISTING, // must use OPEN_EXISTING
		0,    // not overlapped I/O
		NULL  // hTemplate must be NULL for comm devices
	);

	if (hComm == INVALID_HANDLE_VALUE)
	{
		
		if (GetLastError() == ERROR_FILE_NOT_FOUND)
		{
			puts("cannot open port!");
			return;
		}

		puts("invalid handle value!");
		return;
	}
	else
	  printf("opening serial port successful");

	dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

	Write_Status = GetCommState(hComm, &dcbSerialParams);     //retreives  the current settings

	if (Write_Status == FALSE) {
		printf("\n   Error! in GetCommState()");
		CloseHandle(hComm);
		return 1;
	}


	dcbSerialParams.BaudRate = CBR_57600;      // Setting BaudRate = 9600
	dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8
											  //dcbSerialParams.
	dcbSerialParams.StopBits = ONESTOPBIT;    // Setting StopBits = 1
	dcbSerialParams.Parity = ODDPARITY;      // Setting Parity = None

	Write_Status = SetCommState(hComm, &dcbSerialParams);  //Configuring the port according to settings in DCB

	if (Write_Status == FALSE)
	{
		printf("\n   Error! in Setting DCB Structure");
		CloseHandle(hComm);
		return 1;
	}
	else
	{
		printf("\n   Setting DCB Structure Successful\n");
		printf("\n       Baudrate = %d", dcbSerialParams.BaudRate);
		printf("\n       ByteSize = %d", dcbSerialParams.ByteSize);
		printf("\n       StopBits = %d", dcbSerialParams.StopBits);
		printf("\n       Parity   = %d", dcbSerialParams.Parity);
	}

	// Set COM port timeout settings
	timeouts.ReadIntervalTimeout = 50;
	timeouts.ReadTotalTimeoutConstant = 50;
	timeouts.ReadTotalTimeoutMultiplier = 10;
	timeouts.WriteTotalTimeoutConstant = 50;
	timeouts.WriteTotalTimeoutMultiplier = 10;
	if (SetCommTimeouts(hComm, &timeouts) == 0)
	{
		printf("Error setting timeouts\n");
		CloseHandle(hComm);
		return 1;
	}


	/*----------------------------- Writing a Character to Serial Port----------------------------------------*/
	char lp[] = "RDGFIELD? \r\n";		// lpBuffer should be  char or byte array, otherwise write wil fail

	DWORD  NumWritten;
	DWORD  dNoOFBytestoWrite;              // No of bytes to write into the port
	DWORD  dNoOfBytesWritten = 0;          // No of bytes written to the port

	dNoOFBytestoWrite = sizeof(lp); // Calculating the no of bytes to write into the port


	if (!WriteFile(hComm, lp, dNoOFBytestoWrite,
		&dNoOfBytesWritten, NULL))
	{
		printf("Error writing text to %s\n", pcCommPort);
	}
	else
	{
			printf("\n %d bytes written to %s\n",
			dNoOfBytesWritten, pcCommPort);
	}

	if (Write_Status == TRUE)
		printf("\n\n    %s - Written to %s", lp, pcCommPort);
	else
		printf("\n\n   Error %d in Writing to Serial Port", GetLastError());

	/*------------------------------------ Setting Receive Mask ----------------------------------------------*/

	Read_Status = SetCommMask(hComm, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception

	if (Read_Status == FALSE)
		printf("\n\n    Error! in Setting CommMask");
	else
		printf("\n\n    Setting CommMask successfull");


	/*------------------------------------ Setting WaitComm() Event   ----------------------------------------*/

	printf("\n\n    Waiting for Data Reception");

	Read_Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received

	 /*-------------------------- Program will Wait here till a Character is received ------------------------*/

	if (Read_Status == FALSE)
	{
		printf("\n    Error! in Setting WaitCommEvent()");
	}
	else //If  WaitCommEvent()==True Read the RXed data using ReadFile();
	{
		printf("\n\n    Characters Received \t");

		
		
		do
		{
			//Read_Status = ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);
			if (!ReadFile(hComm, SerialBuffer, BUFFERLENGTH, &NoBytesRead, NULL))
			{
				printf("wrong character");
			}
			SerialBuffer[i] = TempChar;
			printf("%c", SerialBuffer[i]);
			i++;
		} while (NoBytesRead > 0);



		/*------------Printing the RXed String to Console----------------------*/

		printf("\n\n    ");
		int j = 0;
		for (j = 0; j < i - 1; j++)		// j < i-1 to remove the dupliated last character
			printf("%c",SerialBuffer[j]);

	}


	CloseHandle(hComm);//Closing the Serial Port
	printf("\n ==========================================\n");


	return 0;
}


Что я уже пробовал:

Я попытался изменить свои типы данных, так как то, что возвращается, - это вопросительные знаки, когда я использую char и только 6363(все время), когда я использую int

3 Ответов

Рейтинг:
2

OriginalGriff

63-это знак вопроса: смотрите таблицу ASCII.
http://www.asciitable.com/index/asciifull.gif[^]
Таким образом, это не ваш тип данных: скорее всего, у вас неправильно настроен порт, чтобы соответствовать тому, что находится на другом конце, и в результате он повторяет обратные вопросительные знаки как символы "я не понимаю" - или то, что он отправляет обратно, не распознается Windows как допустимые символы, поэтому он заменяется по прибытии.
Быстрое сканирование вашего кода предполагает, что вы устанавливаете его до 57 600 БОД и комментируете это как 9 600 бод - один из них неверен! (И, вероятно, паритет тоже)
Я бы посоветовал вам использовать что - то вроде Hyperterminal для проверки ваших коммуникаций и убедиться, что у вас есть точно правильные настройки порта, прежде чем прыгать в код-в противном случае вы пытаетесь отладить все одновременно, не имея ни малейшего представления о том, что работает до сих пор.
Когда он будет работать через hyperterminal, вручную отправьте "известную" команду на устройство и зафиксируйте его ответ. Затем настройте свой код так, чтобы он делал то же самое, отправлял ту же команду и внимательно изучал ответ, прежде чем переходить к более сложным действиям.


Member 12669621

спасибо. Да, я определенно правильно настроил настройки порта, 9600-это неправильный комментарий. Я пишу строки на устройство, чтобы изменить его настройки, и оно работает, так что теперь, когда я пишу на него код для отправки обратно данных, проблема заключается именно в этом. так что попробуем гипертерминал

OriginalGriff

Никогда не оставляйте неправильных комментариев! Они длятся дольше, чем проклятый код...:смех:

Member 12669621

лол, это правда,моя беда. к сожалению насчет путаницы. Но да, я уверен, что все это настроено правильно, так что просто нужно прочитать цифры его отправки, и я ожидаю значений типа - 0.015

Рейтинг:
2

CPallini

Цитата:
делать
{
//Read_Status = слотом ReadFile(hComm, &ампер;TempChar, оператор sizeof(TempChar), &ампер;NoBytesRead, нуль);
if (!ReadFile(hComm, SerialBuffer, BUFFERLENGTH, &NoBytesRead, NULL))
{
printf("неправильный символ");
}
SerialBuffer[i] = TempChar;
printf("%c", SerialBuffer[i]);
я++;
} while (NoBytesRead > 0);



/*------------Печать строки RXed на консоль----------------------*/

printf("\n\n ");
int j = 0;
Для (от j = 0; J И Л; Я - 1; с J++) // J И Л; Я-1, чтобы удалить последний символ dupliated
printf("%c",SerialBuffer[j]);


Я бы заменил это на (обработку ошибок, оставленную в качестве упражнения...)
if (ReadFile(hComm, SerialBuffer, BUFFERLENGTH, &NoBytesRead, NULL))
{
  for (int i=0; i<nobytesread;>    printf("%c", SerialBuffer[i]);
}


Member 12669621

я попробую это сделать и дам вам знать, большое спасибо

Member 12669621

это все равно не работает. Я ожидаю, что ответ от устройства будет в таком формате - 0.013

CPallini

Каков же выход, вместо этого?

Member 12669621

все еще ставя вопросительные знаки

Member 12669621

Я отлаживал его и обнаружил, что он выдает ошибки при попытке прочитать строку в буфер символов
так что проблема именно в этих строках

Read_Status = слотом ReadFile(hComm, &ампер;TempChar, оператор sizeof(TempChar), &ампер;NoBytesRead, нуль);
SerialBuffer[i] = TempChar;

Рейтинг:
0

Member 14853185

Источником ошибки была звезда '*' , предшествующая определению SerialBuffer.
Правильное определение буфера:

char  SerialBuffer[BUFFERLENGTH+1];
...
ReadFile(hComm, SerialBuffer, BUFFERLENGTH, &NoBytesRead, NULL)


Richard MacCutchan

Хорошо заметен, хотя и опоздал почти на четыре года.