快捷搜索:

Windows CE下串口通信

网上已经有CE下串口通信的文章了。我之以是颁发同样内容的文章是由于我的文章是一系列的,不会由于别人写过我就不写了。别的我对串口通信有着自己的不雅点。

现在大年夜多半的条记本电脑都没有外置串口,这不稀罕,由于有更快更稳定的接口代替了串口。不过基于 Windows CE 的设备仍旧保留着串口,而且今朝看来串口的职位地方暂时不会动摇。今朝盛行的基于CE的设备很多都具有像导航、打电话等功能,而GPS、GSM/GPRS模块都是外置串口的终端设备,你想不用串口都不可。

上面我说了我有着自己的不雅点,我的不雅点便是不要把串口通信封装成类。我不明白为什么有些人总要把串口封装成类呢。把一个事物封装成类,那这个事物就必然是不易改变的,假如每次编写都要改动,那封装成类就一点意义都没有了。设想假如MFC类总要改变的话,那我们用MFC编的法度榜样也要改动同样次数了。假如编写超级终端一类的法度榜样倒是可以将串口封装成类,由于超级终端尽管输入敕令和显示输出数据,纰谬输出数据进行处置惩罚,那读串口的函数就可以不停应用而不必变动。但事实上串口通信大年夜多半用来与终端设备进行通信,必要对终端设备返回的数据进行处置惩罚。而返回的数据在什么光阴返回、数据量的大年夜小不是确定的,非要封装成类难度很大年夜。

正如CE的赞助文档所说,串口通信是最简单的通信之一。稍麻烦的是在读数据方面。

一、打开串口    hSerial = CreateFile(L"COM1:",

GENERIC_READ | GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

0,

NULL);

if(m_hSerial == NULL)

{

///L"串口打开掉败";

return;

}

///设置设置设备摆设摆设串口

DCB PortDCB;

PortDCB.DCBlength = sizeof(DCB);

// 默认串口参数

GetCommState(hSerial, &PortDCB);

PortDCB.BaudRate = 115200; // baud

PortDCB.ByteSize = 8;   // Number of bits/byte, 4-8

PortDCB.Parity = NOPARITY;

PortDCB.StopBits = ONESTOPBIT;

if (! SetCommState(hSerial, &PortDCB))

{

///L"设置设置设备摆设摆设串口掉败";

return;

}

////设置设置设备摆设摆设超时价

COMMTIMEOUTS CommTimeouts;

GetCommTimeouts(m_hSerial, &CommTimeouts);

CommTimeouts.ReadIntervalTimeout = MAXDWORD;

CommTimeouts.ReadTotalTimeoutMultiplier = 10;

CommTimeouts.ReadTotalTimeoutConstant = 10;

CommTimeouts.WriteTotalTimeoutMultiplier = 50;

CommTimeouts.WriteTotalTimeoutConstant = 100;

if (!SetCommTimeouts(hSerial, &CommTimeouts))

{

///L"不能设置超时参数";

return;

}           CE的串口驱动不支稳重叠,这个大年夜家都知道的。这样的话收和发就要分开。要接管串口数据就必须创建一个线程专门用于接管数据。串口的设置设置设备摆设摆设不必要设置很多参数,默认的设置设置设备摆设摆设大年夜部分是不必要改动的。一样平常篡改便是波特率、位数、奇偶校检等几项。超时价是必要篡改的。ReadIntervalTimeout是指两个字符传送之间的超韶光阴。一次写操作的超韶光阴即是WriteTotalTimeoutMultiplier 乘以 要发送的字符数 加上WriteTotalTimeoutConstant。 单位是毫秒。读操作的超时和写类似。以是设置超时是一个关键。设置太小可能损掉数据。

二、关闭串口

关闭串口用关闭句柄函数。if(hSerial != NULL)

{

CloseHandle(hSerial);

hSerial = NULL;

}三、向串口发送数据WriteFile (hSerial,      // 句柄

&Byte,       // 数据缓冲区地址

nByte,       // 数据大年夜小

&dwNumBytes,    // 返回发送出去的字节数

NULL        // 不支稳重叠

);  向串口发送数据一样平常都邑成功。必要留意的是假如终端设备必要必然处置惩罚光阴或者称反映光阴的话,那么两个写操作之间必然要留意光阴距离不能太小。详细的光阴由终端设备的反映光阴懈弛冲区大年夜小有关。

四、读取串口数据

串口麻烦就麻烦在读取数据上。除了斟酌及时的读取数据外,还要办理接管到的数据的处置惩罚事情。假如在读取串口数据的线程中安置数据处置惩罚事情,那么可能会损掉数据(终端设备发送数据然则没收到),也有可能不会损掉(终端设备发送的数据的光阴、大年夜小都是确定的)。假如肯定接管的数据在处置惩罚事情停止后终端设备才发送数据,那么完全可以将数据处置惩罚事情放在读取串口的线程中。对付及时的读取数据,下面供给了一种办理法子:奸淫 假设接管的都是字符 奸淫

UINT ReadThread(LPVOID pParam) ?////接管串口数据线程

{

HANDLE  hPort = *(HANDLE*)pParam;

BYTE  Byte;

int  iCounter = 0;

DWORD  dwBytes;

char  ReceiveBuf[1000]; ///缓冲区的大年夜小

SetCommMask (hPort, EV_RXCHAR);  ///只接管字符

while (hPort != INVALID_HANDLE_VALUE)

{

DWORD dwCommStatus;

WaitCommEvent(hPort, &dwCommStatus, 0);

SetCommMask (hPort, EV_RXCHAR); ///从新设置要等待的旌旗灯号

//// 接管数据

do

{

ReadFile(hPort, &Byte, 1, &dwBytes, 0);

if(dwBytes == 1)

{

ReceiveBuf[iCounter++] = Byte;

if(iCounter == 1000)

{

///L"接管缓冲区已满";

return -1;

}

}

} while (dwBytes == 1);

if(iCounter == 0) ?////没接到数据

{

continue;

}

//////保存数据

char* pTmp = new char[iCounter + 1];

if(pTmp == NULL)

{

///L"内存不够,接管串口数据线程关闭";

return -1;

}

memcpy(pTmp, ReceiveBuf, iCounter);

pTmp[iCounter] = NULL;  ////字符串结尾

////////创建新线程处置惩罚数据

////在ProcessData函数中处置惩罚数据。别忘了delete[] pTmp;

AfxBeginThread(ProcessData, pTmp);

iCounter = 0;     ////清空计数器

} ///////end while

return 0;

}

您可能还会对下面的文章感兴趣: