#include "pch.h"
#include "stdafx.h"
#include "commassist.h"
#include "commassistDlg.h"
#include "comm.h"
char ConvertHexChar(char ch);
HANDLE hCom; //串口句柄
CString strcomname; //串口名,如"COM1"
bool ComIsOK; //串口打开状态标识,为真表示已打开,否则未打开
//============自动寻找串口函数================================= //
//函数功能:通过扫描注册表来找出当前所有物理串口
//输入参数:无
//返回类型:无
//说 明:若搜索成功,则每搜到一个串口便发送消息通知主对话框,并将串口号以WPARAM传递
void FindComm()
{
//枚举当前系统中的串口
LONG result = 0;
HKEY key = NULL;
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, //需要打开的主键的名称
"HARDWARE\\DEVICEMAP\\SERIALCOMM",
//需要打开的子键的名称,设备串口
0, //保留,必须设置为0
KEY_READ, //安全访问标记,也就是权限
&key); //得到的将要打开键的句柄,当不再需要句柄,
//必须调用 RegCloseKey 关闭它
if( result )
{
AfxMessageBox("无法获取串口,请确认是否安装并连接串口!");
return;
}
TCHAR portname[250]; //串口名
TCHAR data[250];
DWORD portnamelen = 0; //串口名长度
DWORD datalen = 0;
int index = 0;
while(1) //找完COM后跳出
{
portnamelen = 255;
datalen = 255;
result = RegEnumValue(key,
//Long,一个已打开项的句柄,或者指定一个标准项名
index++,
//Long,欲获取值的索引。注意第一个值的索引编号为零
portname,
//String,用于装载位于指定索引处值名的一个缓冲区
&portnamelen,
//Long,用于装载lpValueName缓冲区长度的一个变量。
//一旦返回,它会设为实际载入缓冲区的字符数量
NULL,
//Long,未用;设为零
NULL,
//Long,用于装载值的类型代码的变量
(LPBYTE)data, //Byte,用于装载值数据的一个缓冲区
&datalen); //Long,用于装载lpData缓冲区长度的一个变量。
//一旦返回,它会设为实际载入缓冲区的字符数量
if( result )
break;
//发送消息,WM_USER+1为自定义消息,即找到串口的,并将串口号"COMx"通过WPARA M参数传送给主对话框窗口
//::AfxGetMainWnd()->m_hWnd,获得主对话框句柄
//(WPARAM)(LPCTSTR)data,类型转换
::SendMessage(::AfxGetMainWnd()->m_hWnd,WM_FOUNDCOMM,(WPARAM)(LPCTSTR)data,0);
}
RegCloseKey(key); //调用 RegCloseKey 关闭打开键的句柄
}
//==========串口打开函数===========================
//功 能:打开串口,将已打开的串口句柄赋值给hCom,给出串口打开状态ComIsOK,完成串口状态 设置
//输入参数:波特率,数据位,停止位,校验位
//返回类型:无
void OpenComm(int nBaud, int nData, int nStop, int nCal) {
hCom = CreateFile(strcomname, //串口号
GENERIC_READ | GENERIC_WRITE, //允许读或写
0, //独占方式
NULL,
OPEN_EXISTING, //打开而不是创建
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,//重叠方式,用于异步通信
NULL );
if (hCom == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("打开COM失败,串口不存在或已被占用!"));
ComIsOK = false; return;
}
ComIsOK = true;
SetCommMask(hCom, EV_TXEMPTY | EV_RXCHAR); //设置事件掩码,暂时没用上
SetupComm(hCom,1024,1024); //设置输入缓冲区和输出缓冲区的大小都是1024
COMMTIMEOUTS TimeOuts; //设定读超时
TimeOuts.ReadIntervalTimeout = MAXDWORD;
TimeOuts.ReadTotalTimeoutConstant = 0;
TimeOuts.ReadTotalTimeoutMultiplier = 0; //设定写超时
TimeOuts.WriteTotalTimeoutConstant = 500;
TimeOuts.WriteTotalTimeoutMultiplier = 100;
if(SetCommTimeouts(hCom,&TimeOuts) == false)
{
CloseHandle(hCom);
ComIsOK = false; return;
} //串口属性配置
DCB dcb;
GetCommState(hCom,&dcb);
dcb.BaudRate=nBaud; //dcb.BaudRate=9600; //波特率为9600
dcb.ByteSize=nData; //dcb.ByteSize=8; //每个字节为8位
dcb.StopBits=nStop; //dcb.StopBits=ONESTOPBIT; //1位停止位
dcb.Parity=nCal; //dcb.Parity=NOPARITY; //无奇偶检验位
SetCommState(hCom, &dcb);
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
if (SetCommState(hCom, &dcb) == false)
{
CloseHandle(hCom);
ComIsOK = false;
return;
}
return;
}
//==========串口关闭控制函数=====================
void CloseComm()
{
CloseHandle(hCom);
hCom = NULL;
ComIsOK = false;
}
//==========串口监听线程函数======================
UINT ThreadFunc(LPVOID pParam)
{
// CCommassistDlg* pdlg = (CCommassistDlg*)pParam; //定义指针指向主对话框
COMSTAT ComStat;
DWORD dwErrorFlags;
while(ComIsOK)
{
DWORD dwBytesRead = 100;
ClearCommError(hCom,&dwErrorFlags,&ComStat);
dwBytesRead = min(dwBytesRead,(DWORD)ComStat.cbInQue);
if(!dwBytesRead)
{
Sleep(10);//continue;//使用continue时,打开串口后CPU占用率非常高
} else ::SendMessage(::AfxGetMainWnd()->m_hWnd,WM_READCOMM,1,0); //发送消息,已读到
}
return 0;
}
//=================字符串转16进制显示==========
//字符串转16进制显示的函数
//传入参数Data为字符串
//Blank_allow为空格允许标志,为真则代表允许加入空格
//函数返回为CString的结果sResult
CString DisplayCString2Hex(CString Data, bool Blank_allow)
{
CString sResult;
CString sTemp;
int Data_Length;
Data_Length = Data.GetLength();
if (Data_Length == 0)
return "";
char *pchar = new char[Data_Length+1]; //用了new分配内存空间,要记得释放
strncpy_s(pchar, Data_Length+1,Data,Data_Length);//此处使用strncpy_s(char * str2, int size2, char * str1, int size1);
//这里多了一个长度,就是被复制的str2的长度,我们可以用sizeof(str2)来表示这个长度
for(int i=0; i
sTemp.Format("%02X",pchar[i]);
if(Blank_allow)
{
if(i == Data_Length -1)
sResult = sResult + sTemp; //去掉最后一个空格
else
sResult = sResult + sTemp+" ";
}
else sResult = sResult + sTemp;
}
delete pchar; //释放内存空间
return sResult;
}
char ConvertHexChar(char ch)
{
//将一个字符转换为相应的十六进制
if ((ch >= '0') && (ch <= '9'))
return ch - 48;//0x30;
else if ((ch >= 'A') && (ch <= 'F'))
return ch - 'A' + 10;
else if ((ch >= 'a') && (ch <= 'f'))
return ch - 'a' + 10;
else return (-1);
}
//=================16进制转字符串======================
//16进制转字符串,输入16进制的字符串,输出转换为16进制码
//传入参数str为字符串,判断输入是否按照16进制格式输入
int ConvertHexC2String(CString str, CByteArray& senddata)
{
//先判断输入字符串是否2个字符一组
int str_Length,iLength;
int hexdata, l_data;
char hstr,lstr;
char cTemp; str_Length = str.GetLength();
iLength = 0;
senddata.SetSize(str_Length/2); //预先设置数组长度,不设置时,允许有错
char *ppchar = new char[str_Length+1];
strncpy_s(ppchar, str_Length+1,str,str_Length);
for(int i=0; i
cTemp = ppchar[i];
if(cTemp == ' ')
{
//iLength--;
i++;
continue; //如检测到空格则跳过,继续下一次循环
}
else
{
hstr = ppchar[i]; //取出字符作为16进制高位
i++;
lstr = ppchar[i]; //取出下一个字符作为16进制低位
if(lstr == ' ') //若取出的低位为空格,则不符合16进制2个一组的格式,终止循环
{
AfxMessageBox("请按照16进制每2个字符一组的方式输入", MB_ICONERROR); break;
}
else
{
hexdata = ConvertHexChar(hstr); //高位转换为相应的0进制
l_data = ConvertHexChar(lstr); //低位转换为相应的10进制
if( (hexdata == -1) || (l_data == -1) )
{
AfxMessageBox("请按照16进制字符要求输入",MB_ICONERROR);
break;
}
else
hexdata = hexdata*16 + l_data; //安装16进制方式高位低位合并
senddata[iLength] = (char)hexdata; //int整型数转换为char字符型,并存入数组senddata[]
i++; //进入下一次循环
iLength++; //成功转换一组(2个)字符,记录长度加1
}
}
}
senddata.SetSize(iLength);
delete ppchar;
return iLength;
}
//=================16进制转字符串显示=====================
//16进制转字符串显示的函数
//传入参数Data为16进制的字符串
//函数返回为CString的结果sResult
CString DisplayHex2CString(CString Data)
{
CString sResult;
CString sTemp;
int Data_Length;
Data_Length = Data.GetLength();
if (Data_Length == 0)
return "";
char* pchar = new char[Data_Length+1]; //用了new分配内存空间,要记得释放
strncpy_s(pchar, Data_Length+1,Data,Data_Length);
for (int i = 0; i < Data_Length; i++)
{
sTemp.Format("%02X", pchar[i]);
sResult = sResult + sTemp;
}
delete pchar; //释放内存空间
return sResult;
}
- #include "stdafx.h"
- #include "string.h"
- #include
- #include
- #include
- using namespace std;
-
- char ConvertHexChar(char ch)
- {
- //将一个字符转换为相应的十六进制
- if ((ch >= '0') && (ch <= '9'))
- return ch - 48;//0x30;
- else if ((ch >= 'A') && (ch <= 'F'))
- return ch - 'A' + 10;
- else if ((ch >= 'a') && (ch <= 'f'))
- return ch - 'a' + 10;
- else return (-1);
- }
-
- //=================16进制转字符串显示=====================
- //16进制转字符串显示的函数
- //传入参数Data为16进制的字符串
- //函数返回为CString的结果sResult
- CString DisplayHex2CString(CString Data)
- {
- CString sResult;
- CString sTemp;
- int Data_Length;
- Data_Length = Data.GetLength();
- if (Data_Length == 0)
- return "";
- char* pchar = new char[Data_Length+1]; //用了new分配内存空间,要记得释放
- strncpy_s(pchar, Data_Length+1,(const char*)Data,Data_Length);
- for (int i = 0; i < Data_Length; i++)
- {
- sTemp.Format("%02X", pchar[i]);
- sResult = sResult + sTemp;
- }
- delete pchar; //释放内存空间
- return sResult;
- }
-
- //=================16进制转字符串======================
- //16进制转字符串,输入16进制的字符串,输出转换为16进制码
- //传入参数str为字符串,判断输入是否按照16进制格式输入
- int ConvertHexC2String(CString str)
- {
- //先判断输入字符串是否2个字符一组
- int str_Length,iLength;
- int hexdata, l_data;
- char hstr,lstr;
- char cTemp; str_Length = str.GetLength();
- iLength = 0;
- //senddata.SetSize(str_Length/2); //预先设置数组长度,不设置时,允许有错
- char *ppchar = new char[str_Length+1];
- char senddata[100];
-
-
- strncpy_s(ppchar, str_Length+1,str,str_Length);
- for(int i=0; i
- {
- cTemp = ppchar[i];
- if(cTemp == ' ')
- {
- //iLength--;
- i++;
- continue; //如检测到空格则跳过,继续下一次循环
- }
- else
- {
- hstr = ppchar[i]; //取出字符作为16进制高位
- i++;
- lstr = ppchar[i]; //取出下一个字符作为16进制低位
- if(lstr == ' ') //若取出的低位为空格,则不符合16进制2个一组的格式,终止循环
- {
- //AfxMessageBox("请按照16进制每2个字符一组的方式输入", MB_ICONERROR);
- printf("请按照16进制每2个字符一组的方式输入 \n");
- break;
- }
- else
- {
- hexdata = ConvertHexChar(hstr); //高位转换为相应的0进制
- l_data = ConvertHexChar(lstr); //低位转换为相应的10进制
- if( (hexdata == -1) || (l_data == -1) )
- {
- //AfxMessageBox("请按照16进制字符要求输入",MB_ICONERROR);
- printf("请按照16进制字符要求输入 \n");
- break;
- }
- else
- hexdata = hexdata*16 + l_data; //安装16进制方式高位低位合并
- senddata[iLength] = (char)hexdata; //int整型数转换为char字符型,并存入数组senddata[]
- printf("%d ", hexdata);
- i++; //进入下一次循环
- iLength++; //成功转换一组(2个)字符,记录长度加1
- }
- }
- }
-
- //printf("senddata = %s \n", senddata);
- //senddata.SetSize(iLength);
- delete ppchar;
- return iLength;
- }
-
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- int m = 0;
- char ch = '0';
- char chdata = '1';
- printf("chdata = 0x%x \n", chdata);
-
- //m = ConvertHexChar(ch);
-
- //cout << DisplayHex2CString("12345") << endl;
-
- ConvertHexC2String("1224");
-
- //printf("m = 0x%x", m);
- getchar();
- return 0;
- }
-