|
我参照网上的API串口代码,写了一个接收串口数据的上位机程序,但是出现了转成中文字符变成乱码或者一部分正常。
如果在线程或者接收信息处使用Sleep(),会编程乱码或者一部分正常。如果不延时,中文字符就不显示。只显示单字节字符
////////////////线程处理
DWORD WINAPI CNniView::Fun1Proc(LPVOID lpParameter)
{
HWND vhwnd = ((CDataSwitch*)lpParameter)->vhwnd; //View类窗口句柄
HANDLE hCom = ((CDataSwitch*)lpParameter)->hCom; //串口句柄
char str[1024]; //[1];
while(comFlag==TRUE)
{
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
COMSTAT ComStat;
DWORD dwErrorFlags;
memset(str,'\0',1024);
DWORD dwBytesRead = 1024; //读取的字节数
BOOL bReadStat;
ClearCommError(hCom,&dwErrorFlags,&ComStat); //异步使用
//min C/C++函数,返回最小值,
//本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数。
dwBytesRead=min(dwBytesRead, (DWORD)ComStat.cbInQue);
bReadStat=ReadFile(
hCom, // 串口的句柄
&str, // 读入的数据存储的地址,
// 即读入的数据将存储在以该指针的值为首地址的一片内存区
dwBytesRead, //读入的字节数
&dwBytesRead, // 指向一个DWORD数值,该数值返回读操作实际读入的字节数
&m_osRead //重叠操作时,该参数指向一个OVERLAPPED结构,
);
if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
AfxMessageBox("串口正在读操作");
WaitForSingleObject(m_osRead.hEvent,2000);
}
}
PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
::SendMessage(vhwnd,UM_DLGDATARECV,0,(LPARAM)str); // 通过消息输出
}
//AfxMessageBox("串口被关闭,线程结束");
return 0;
}
///////////////接收处理部分/////////////////
不知到什么原因,收到的数据,总能显示单字节字符,双字节不是不现实,就是乱码
void CNniView::OnDlgDataRecv(WPARAM wParam,LPARAM lParam)
{
CEdit& theEdit = GetEditCtrl();
CString rxData;
rxData.Empty();
int nTextLength;
int nLenght;
int pLenght; //
pLenght=m_showStr.GetLength(); //原字串长度
rxData.Format(_T("%s"),lParam); //转化为宽字符串
m_showStr+=rxData;
nLenght=m_showStr.GetLength(); //新字串长度
while(pLenght<nLenght) //(int i=0;i<(nLenght-pLenght-1);i++) //每次循环新增字符总数量
{
//获得文字的长度
nTextLength = theEdit.GetWindowTextLength();
//将光标放在文本最末
theEdit.SetSel(nTextLength, nTextLength);
//m_showStr.Mid(i,1);
//写入文本,在光标后
theEdit.ReplaceSel( m_showStr.Mid(pLenght,1) );
pLenght++;
//将光标放在文本最末
theEdit.SetSel(nTextLength, nTextLength);
//Sleep(5);
}
Sleep(1);
return;
}
////////////////////打开端口
void CNniView::OnOpenCom()
{
// TODO: Add your control notification handler code here
//全局串口开启标志
comFlag=TRUE;
//MessageBox("收到");
//实例化数据交换类
CDataSwitch *pDS = new CDataSwitch;
CSplitterWnd *ps = (CSplitterWnd*)GetParent(); //获得拆分窗口的父窗口
CNniView1 *pView1 = (CNniView1*)(ps->GetPane(1,0)); //View1类句柄
pDS->vhwnd=this->m_hWnd; //获得View视图窗体的句柄 ,只是个句柄
pDS->ahwnd=pView1->m_hWnd; //获得View1视图窗体的句柄 ,只是个句柄
this->m_hCom=CreateFile(
"COM5", //COM口
GENERIC_READ|GENERIC_WRITE, //允许读和写
0, //独占方式
NULL,
OPEN_EXISTING, //打开而不是创建
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式 0, //同步方式
NULL
);
//传递串口句柄进入数据交换类给线程使用
pDS->hCom=m_hCom;
if(m_hCom==(HANDLE)-1)
{
AfxMessageBox("打开COM失败!");
return;
}
SetupComm(m_hCom,1024,1024); //输入缓冲区和输出缓冲区的大小都是1024
DCB dcb;
GetCommState(m_hCom,&dcb);
dcb.BaudRate= 4800; //波特率为9600
dcb.ByteSize= 8; //每个字节有8位
dcb.StopBits= 0; //1个停止位
dcb.Parity= 0; //无奇偶校验位
dcb.fParity = 0; //设定无奇偶校验使能
dcb.fBinary = 1; //Win32API不支持非二进制方式传输,所以必须是真
SetCommState(m_hCom,&dcb);
COMMTIMEOUTS TimeOuts;
TimeOuts.ReadIntervalTimeout=MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=0;
TimeOuts.ReadTotalTimeoutConstant=0;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier=100;
TimeOuts.WriteTotalTimeoutConstant=500;
//设置超时
SetCommTimeouts(m_hCom,&TimeOuts);
PurgeComm(this->m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
//创建线程
this->m_hThread1=CreateThread(NULL,0,this->Fun1Proc,(LPVOID)pDS,0/*CREATE_SUSPENDED*/,&this->m_dwThreadId/*NULL*/);
CloseHandle(this->m_hThread1);
pView1->GetDlgItem(IDC_CHANGE_BTN)->SetWindowText("关闭串口");
}
代码基本是抄,不知道那里除了问题 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|