xinshui 发表于 2011-2-22 19:57:00

串口读出的数据转中文字符

我参照网上的API串口代码,写了一个接收串口数据的上位机程序,但是出现了转成中文字符变成乱码或者一部分正常。
如果在线程或者接收信息处使用Sleep(),会编程乱码或者一部分正常。如果不延时,中文字符就不显示。只显示单字节字符


////////////////线程处理
DWORD WINAPI CNniView::Fun1Proc(LPVOID lpParameter)
{
HWND vhwnd = ((CDataSwitch*)lpParameter)->vhwnd; //View类窗口句柄
HANDLE hCom = ((CDataSwitch*)lpParameter)->hCom; //串口句柄

char str; //;

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("关闭串口");

}

代码基本是抄,不知道那里除了问题
页: [1]
查看完整版本: 串口读出的数据转中文字符