当前位置: 代码迷 >> VC/MFC >> 请问一个用串口读取单片机消息在Edit控件中汉字显示不正常的有关问题
  详细解决方案

请问一个用串口读取单片机消息在Edit控件中汉字显示不正常的有关问题

热度:145   发布时间:2016-05-02 03:34:23.0
请教一个用串口读取单片机消息在Edit控件中汉字显示不正常的问题
最近在做一个单片机调试程序,环境是VS2008,用的MSCOMM控件,三个edit,一个发送mEditSend,一个接收只读mEditRcv,另一个显示发送的历史记录只读mEditHsty,现在问题是接收区无法正常显示单片机发回来的中文字符,但发送区和历史记录中可以正常编辑显示汉字



用串口调试助手能正常接收显示单片机发来的中文字符,说明单片机上传的内容是正确的


用16进制查看单片机上传的字符串就是这一段:
6D 6F 74 6F 72 20 74 65 73 74 20 77 69 74 68 20 4C 0A 2F 2F 2F 41 47 43 3A 20 31 37 30 0A 0A CA E4 C8 EB D6 B8 C1 EE 3A 0A 

在监视器中跟踪变量,接收到的是正确的,中文都能显示出来,




可最后显示在Edit中就是这么个鸟样了


收发操作的函数代码见下:

void CSatCtrlComDlg::OnBnClickedButton2() //发送数据 并将发送历史在对话框中显示
{

VARIANT str;

UpdateData(true);
str = COleVariant(mEditSend);

cMSCommPort.put_Output(str);
mEditHsty += str;
mEditHsty += "\r\n";

UpdateData(false);

int linecnt = cEditHsty.GetLineCount();
cEditHsty.LineScroll(linecnt-1,0);

}
BEGIN_EVENTSINK_MAP(CSatCtrlComDlg, CDialog)
ON_EVENT(CSatCtrlComDlg, IDC_MSCOMM1, 1, CSatCtrlComDlg::OnCommMscomm1, VTS_NONE)
END_EVENTSINK_MAP()

void CSatCtrlComDlg::OnCommMscomm1()  //串口有接收时显示在接收区
{

if(cMSCommPort.get_CommEvent()==2)
{
char str[1024] = {0};
long k;
VARIANT InputData = cMSCommPort.get_Input();
COleSafeArray fs;
fs = InputData;
for(k=0;k<fs.GetOneDimSize();k++)
{
fs.GetElement(&k,str+k);
}
mEditRcv += str;
UpdateData(false);

int linecnt = cEditRcv.GetLineCount();
cEditRcv.LineScroll(linecnt-1,0);
}
}


同编译器设置有关么,因为自动生成的代码老有这么一段



一直做的是单片机开发,VC各种控件特性还不太了解,还请各位高手给分析分析这是什么情况。
谢谢大家了

------解决思路----------------------
汉字可能被拆分成 2次 接受;

// "65 A3A8 CAD5 B2D8 A3"  // problem at A3
// "A9 0D0A 0D0A D2BB A1"  // problem at A9 and A1 !!!!
#define SZ  1
BYTE *CPeekCommDlg::KillHalfHZ(BYTE *pdata,UINT len)
{// 
static BYTE HalfHz=0;

BYTE firstHalf=0;
UINT HalfAt=0;
UINT total=0;
BYTE *copy=0;
BYTE *pTmp=0;
// 
// afxDump << len << "\r\n";
//
if(HalfHz != 0)
{// add last half HZ to newline
copy=new BYTE[len+1+SZ];
memset(copy,0,len+1+SZ);
copy[0]=HalfHz;
HalfHz=0;
memcpy(&copy[1],pdata,len);
total=len+1;
}
else
{// keep original
copy=new BYTE[len+SZ];
memset(copy,0,len+SZ);
memcpy(copy,pdata,len+SZ);
total=len;
}
pTmp=copy;
// check this new line
for(UINT i=0; i < total; i++)
{
if(*pTmp >= 0x80) 
{
if(firstHalf==0)
{// half hz
firstHalf = *pTmp;
HalfAt = i+1;
}
else
{// has half hz
if(i==HalfAt)
{// 1 hz
HalfAt=0;
firstHalf=0;
}
else
{// middle or end ? 0xA8 0x44
break;
}
}
}//if(*pTmp >= 0x80) 
pTmp++;
}
// 
if(HalfAt==0)
{// newline no half HZ
copy[total]=0;
}
else if (HalfAt==total)
{// newline has half HZ at end
HalfHz=firstHalf;
copy[total-1]=0;
}
// you must delete it later !
return copy;
}


使用
DWORD CPeekCommDlg::AppendText(BYTE *pdata,UINT len,COLORREF FgColor)
{
CharNewColor(FgColor);
//  make a sz
BYTE *pnew=KillHalfHZ(pdata,len);
//
LONG nStartChar;
LONG nEndChar;
m_RichEdit.GetSel(nStartChar,nEndChar);
m_RichEdit.SetSel(nEndChar,nEndChar);// go end
m_RichEdit.ReplaceSel((char*)pnew);
delete [] pnew;
//
int all=m_RichEdit.GetLineCount();
if(all > 17 ) m_RichEdit.LineScroll(all-17,0);
//
return len;
}

------解决思路----------------------
VS2008用的是Unicode编码,而单片机一般都用GB编码,因此在接收端需要进行码制转换。
------解决思路----------------------
从你那个图, 4个汉字, 占用了12字节, 说明每个汉字是三个字节,   那基本上可以确定你的单片机发过来的汉字编码是utf-8的

VS中能显示, 那是VS自己做判断处理的. 而你的VS环境编辑框默认是unicode编码.

所以要显示正常, 就只需要把你的串由UTF-8 转换成UNICODE即可
  相关解决方案