Опубликован: 24.04.2009 | Доступ: свободный | Студентов: 1180 / 358 | Оценка: 4.39 / 4.28 | Длительность: 18:45:00
Специальности: Программист
Лекция 8:

Программирование приложений в CE

Пример программы SerialIO, использующей вызовы В/В файлов ОС

Пример программы C++ читает последовательный ввод данных с COM2:, выводит каждый символ в консольном окне eBox, и отправляет его назад на вывод на COM2:.

Программа использует базовые функции API В/В файлов CE, такие как CreateFile, ReadFile, WriteFile, и CloseHandle для передачи данных в/из последовательного порта. В функции ModifyCommSettings используются вызовы API GetCommStatus и SetCommStatus для получения, модификации, и затем задания для порта COM скорости в бодах, числа битов данных, и вариантов квитирования. Вызов API SetCommTimeouts используется для задания задержек для операций последовательного чтения и записи. Его можно использовать для определения, что операция чтения должна подождать ввода символа или вернуть управление немедленно.

Вызов API WaitCommEvent используется для блокирования процесса, пока не появится входящий символ. Это более эффективно в терминах времени процессора и питания, чем постоянное циклическое повторение. SetCommEvent используется для определения, какой тип коммуникационного события будет запускать WaitCommEvent. Обычно основной процесс не будет блокироваться, и для чтения и записи последовательного порта будет использоваться поток. Так как основной процесс в этом примере только посылает данные назад, то поток не требуется.

Для просмотра последовательных данных последовательный null-модемный кабель соединяется из COM2: на eBox с неиспользуемым портом COM на настольном ПК системы разработки. Выполняя HyperTerminal или другую программу эмулятора терминала, соединитесь с портом COMx: на скорости 9600 бод, с 8 битами данных, без контроля четности, с 1 стоп битом, и без задания управления потоком.

Когда выполняется программа, она печатает заголовок, а затем каждый символ, введенный на клавиатуре настольного ПК посылается в устройство eBox, которое считывает символы, выводит их в консольном окне, и посылает символы назад. Так как они посылаются назад, они также выводятся в эмуляторе терминала. Ввод Ctrl-C в эмуляторе терминала заставляет eBox выйти из программы, а вызов CloseHandle освобождает порт COM для использования в других приложениях.

HyperTerminal выполняющийся в системе разработки и взаимодействующий с COM-портом eBox

Рис. 8.1. HyperTerminal выполняющийся в системе разработки и взаимодействующий с COM-портом eBox
// SerialIO.cpp : Определяет точку входа для консольного приложения.
//
// Пример программы В/В файла через последовательный порт 
//
// FOR DEMO: Соедините Ebox COM2: с ПК с помощью null-модемного кабеля 
// Выполните HyperTerminal на скорости 9600 бод, с 8 битами данных, 1 стоп 
// битом, без четности и без управления потоком 

#include "stdafx.h"
BOOL ModifyCommSettings (HANDLE hComPort);
HANDLE hSerial;

int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
	DWORD cBytes_out, cBytes_in;
	DWORD dwMask;
	char cBuffer_out[] = "\f\n    Hello Serial World! \n\r Type something and watch it echo back
    \n\r Ctrl C to exit   \n\r";
	TCHAR cBuffer_in[80];
// Выводит сообщение на консоль 
	printf("\nOpening COM2: Serial Port - Type ctrl C on other device to exit\n\r");
// Откройте последовательный порт COM2: для чтения и записи 
// Примечание: COM1: обычно задается для отправки отладочной информации 
// В этом случае COM2: становится COM1: в ОС
	hSerial = CreateFile(_T("COM1:"), GENERIC_READ | GENERIC_WRITE, 0, NULL,
		OPEN_EXISTING, 0, NULL);
// Проверка ошибок открытия файла 
	if (hSerial == INVALID_HANDLE_VALUE){
		printf("file open errors\n");
		Sleep(4000);
		return 0;
	}
// Модифицируйте настройки порта Com (т.е., Baud Rate, #bits, parity и т.д.)
	if(!ModifyCommSettings (hSerial)){
		printf("com port settings errors\n");
		Sleep(4000);
		return 0;
	}

  // Запишите заголовок в последовательный порт.
	if (!WriteFile(hSerial, cBuffer_out, strlen(cBuffer_out), &cBytes_out, NULL)) {
		printf("file write errors\n");
		Sleep(4000);
		return 0;
	}
// Задаем маску коммуникационного события для WaitCommEvent для rxchar (получить символ) в буфер 
	SetCommMask(hSerial, EV_RXCHAR | EV_ERR);

	cBuffer_in[0] = 0;
// Считать символы, скопировать в консольное окно и Echo
// Цикл, пока не будет нажато ctrl C 
	while (cBuffer_in[0] != 0x03){
// Ожидаем символ в буфере ввода - события являются более эффективными, чем 
// цикл 
		WaitCommEvent(hSerial, &dwMask, 0);
		cBytes_in = 1;
// Цикл на тот случай, если более одного символа находится в буфере ввода 
// UART 
		while (cBytes_in != 0){
// Эхо-считывание всех последовательных данных и вывод 
		  if (ReadFile(hSerial, cBuffer_in, 64, &cBytes_in, NULL)){
			if (cBytes_in == 0) break;
// Вывод эхо-считанных данных 
			printf("%s",cBuffer_in, cBytes_in);
// Эхо-Отправка символов отправителю 
			if (!WriteFile(hSerial, cBuffer_in, cBytes_in, &cBytes_out, NULL)){
				printf("\rfile write errors\n");
				Sleep(4000);
				return 0;
				}
		  }
		}
	}
	// Закрытие файла 
	CloseHandle(hSerial);
    return 1;
}
// Функция для задания параметров порта COM 
BOOL   ModifyCommSettings (HANDLE hComPort)
{
      COMMTIMEOUTS ctos;
	DCB PortDCB;
// Инициализация члена DCBlength. 
	PortDCB.DCBlength = sizeof (DCB); 
// Получение информации DCB о настройках по умолчанию последовательного порта
	GetCommState (hSerial, &PortDCB);
// Изменение настроек обычной структуры DCB для модификации настроек 
// последовательного порта.
PortDCB.BaudRate = 9600;              // Current baud 
PortDCB.fBinary = TRUE;               // Binary mode; no EOF check 
PortDCB.fParity = TRUE;               // Enable parity checking 
PortDCB.fOutxCtsFlow = FALSE;         // No CTS output flow control 
PortDCB.fOutxDsrFlow = FALSE;         // No DSR output flow control 
PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type 
PortDCB.fDsrSensitivity = FALSE;      // DSR sensitivity 
PortDCB.fTXContinueOnXoff = TRUE;     // XOFF continues Tx 
PortDCB.fOutX = FALSE;                // No XON/XOFF out flow control 
PortDCB.fInX = FALSE;                 // No XON/XOFF in flow control 
PortDCB.fErrorChar = FALSE;           // Disable error replacement 
PortDCB.fNull = FALSE;                // Disable null stripping 
PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control 
PortDCB.fAbortOnError = FALSE;        // Do not abort reads/writes on error
PortDCB.ByteSize = 8;                 // Number of bits/byte, 4-8 
PortDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space 
PortDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2 
// Конфигурирование настроек порта согласно новым спецификациям 
// структуры DCB.
	if (!SetCommState (hSerial, &PortDCB)){
	    printf("Unable to configure the serial port"); 
		Sleep(4000);
		return false;
		}
	// Set read time outs
	ctos.ReadIntervalTimeout = MAXDWORD;
	ctos.ReadTotalTimeoutMultiplier = MAXDWORD;
	ctos.ReadTotalTimeoutConstant = 1;
	ctos.WriteTotalTimeoutMultiplier = 0;
	ctos.WriteTotalTimeoutConstant = 0;
	if(!SetCommTimeouts(hSerial, &ctos)){
	    printf("Unable to configure the serial port"); 
		Sleep(4000);
		return false;
	}
	return true;
	}
8.2.