CnComm开发库是一位国产的大牛做的,封装得很不错,使用很简单。大牛的博客地址:点击打开链接 最新的库:点击打开链接
其实也没啥必要说怎么开发,因为里面有个很好的demo,其实就是完完全全是一个串口助手的源代码,但是是用VC6.0开发的,如果你用VS2010编译,你也可以编译出来,但是如果用VS2017编译,就一大堆错误了。这篇文章主要以最简单的方式去说一下怎么用,一般来说,串口通信都是需要关联一个窗口,这次我就不关联窗口,改为关联线程,也就是说在独立的线程里面去接收和发送信息。
在说之前要给大家介绍一个非常有用的串口辅助工具:Virtual Serial Port Driver(VSPD),一看英文就知道是个串口模拟工具,利用这个工具就可以不需要其它硬件去跟电脑通信,只需要电脑跟自己通信,至于怎么使用,不在本文章介绍了,找度娘帮忙吧~~~

第一步:新建一个SerialThread类,该类继承CWinThread
-
#pragma once
-
-
-
#define WM_COM_THREAD_START WM_USER + 8
-
// SerialThread
-
#include"CnComm.h"
-
class SerialThread : public CWinThread
-
{
-
DECLARE_DYNCREATE(SerialThread)
-
-
protected:
-
SerialThread(); // 动态创建所使用的受保护的构造函数
-
virtual ~SerialThread();
-
-
public:
-
virtual BOOL InitInstance();
-
virtual int ExitInstance();
-
-
void CloseSerialPort(); //关闭串口
-
void OpenSerialPort();//打开串口
-
void SendDatas(CString msg);//发送数据
-
-
afx_msg void OnReceive(WPARAM, LPARAM); //接收数据
-
private:
-
CnComm Com;
-
int Ascii2Hex(char* ascii, char* hex); //ascii转十六进制
-
int Hex2Ascii(char* hex, char* ascii); //十六进制转ascii
-
-
protected:
-
DECLARE_MESSAGE_MAP()
-
};
第二步当然是要定义各种函数:
-
// SerialThread.cpp : 实现文件
-
//
-
-
#include "stdafx.h"
-
#include "SerialDemo.h"
-
#include "SerialThread.h"
-
#include <iostream>
-
using namespace std;
-
-
// SerialThread
-
-
IMPLEMENT_DYNCREATE(SerialThread, CWinThread)
-
-
SerialThread::SerialThread()
-
{
-
}
-
-
SerialThread::~SerialThread()
-
{
-
}
-
-
BOOL SerialThread::InitInstance()
-
{
-
// TODO: 在此执行任意逐线程初始化
-
Com.SetNotifyThreadId(m_nThreadID);
-
Com.SetOption(Com.GetOption() | CnComm::EN_RX_BUFFER);
-
return TRUE;
-
}
-
-
int SerialThread::ExitInstance()
-
{
-
// TODO: 在此执行任意逐线程清理
-
HANDLE hp = m_hThread;
-
if (Com.IsOpen()) Com.Close();
-
if (hp)
-
{
-
if (WaitForSingleObject(hp, 1) != WAIT_OBJECT_0)
-
{
-
TerminateThread(hp, 0);
-
}
-
CloseHandle(hp);
-
}
-
-
return CWinThread::ExitInstance();
-
}
-
-
void SerialThread::CloseSerialPort()
-
{
-
Com.Close();
-
cout << "Close Successfully!" << endl;
-
}
-
-
void SerialThread::OpenSerialPort()
-
{
-
if (Com.IsOpen()) return;
-
bool open = Com.Open(8, _T("COM1"), 9600);
-
if (open)
-
{
-
cout << "Open Successfully!" << endl;
-
}
-
else
-
{
-
cout << "Open Failed!" << endl;
-
HANDLE hp = m_hThread;
-
if (hp)
-
{
-
if (WaitForSingleObject(hp, 1) != WAIT_OBJECT_0)
-
{
-
TerminateThread(hp, 0);
-
}
-
CloseHandle(hp);
-
}
-
}
-
}
-
-
void SerialThread::SendDatas(CString msg)
-
{
-
char* buffer = new char[msg.GetLength() * 2 + 1];
-
-
#ifdef UNICODE
-
int len = wcstombs(buffer, (LPCTSTR)msg, msg.GetLength());
-
buffer[len] = 0;
-
#else
-
strcpy(buffer, (LPCTSTR)msg);
-
int len = msg.GetLength();
-
#endif
-
-
//! 重叠模式下或者缓冲区模式下 可以不检查输出返回值,并直接输出
-
if (Com.IsOverlappedMode() || Com.IsTxBufferMode())
-
Com.Write(buffer);
-
else
-
{//! 阻塞非缓冲区模式 必须检查返回值,确保数据完全发送出
-
for (int i = 0; i < len; i++)
-
i += Com.Write(buffer + i, len - i);
-
}
-
-
delete[] buffer;
-
}
-
-
void SerialThread::OnReceive(WPARAM wParam, LPARAM lParam)
-
{
-
if (wParam == Com.GetPort())
-
{
-
do {
-
char buffer[1024];
-
int len = Com.Read(buffer, 1023);
-
buffer[len] = _T('\0');
-
cout << buffer << endl;
-
} while (Com.IsRxBufferMode() && Com.Input().SafeSize());
-
}
-
}
-
-
int SerialThread::Ascii2Hex(char* ascii, char* hex)
-
{
-
int i, len = strlen(ascii);
-
char chHex[] = "0123456789ABCDEF";
-
-
for (i = 0; i < len; i++)
-
{
-
hex[i * 3] = chHex[((BYTE)ascii[i]) >> 4];
-
hex[i * 3 + 1] = chHex[((BYTE)ascii[i]) & 0xf];
-
hex[i * 3 + 2] = ' ';
-
}
-
-
hex[len * 3] = '\0';
-
-
return len * 3;
-
}
-
-
int SerialThread::Hex2Ascii(char* hex, char* ascii)
-
{
-
int len = strlen(hex), tlen, i, cnt;
-
-
for (i = 0, cnt = 0, tlen = 0; i < len; i++)
-
{
-
char c = toupper(hex[i]);
-
-
if ((c >= '0'&& c <= '9') || (c >= 'A'&& c <= 'F'))
-
{
-
BYTE t = (c >= 'A') ? c - 'A' + 10 : c - '0';
-
-
if (cnt)
-
ascii[tlen++] += t, cnt = 0;
-
else
-
ascii[tlen] = t << 4, cnt = 1;
-
}
-
}
-
-
return tlen;
-
}
-
-
BEGIN_MESSAGE_MAP(SerialThread, CWinThread)
-
ON_THREAD_MESSAGE(ON_COM_RECEIVE, OnReceive) //消息映射
-
END_MESSAGE_MAP()
-
-
-
// SerialThread 消息处理程序
第三步:直接新建一个线程。
SerialThread*thread = (SerialThread*)AfxBeginThread(RUNTIME_CLASS(SerialThread));
把上面的直接copy到你的工程就可以用了~~~