【开源中国 APP 全新上线】“动弹” 回归、集成大模型对话、畅读技术报告”
在Mscomm控件接收每100ms的串口数据时,能在文本框显示接收的数据。但teechart控件在接收数据并绘制一部分图后就停止绘制后面的曲线图了。 teechart的绘图函数是在Mscomm的oncomm响应事件中的。代码如下:
// comm1.2Dlg.cpp : 实现文件
//
#include "stdafx.h"
#include "comm1.2.h"
#include "comm1.2Dlg.h"
#include "CSeries.h"
#include "CLegend.h"
#include "CAxes.h"
#include "CAxis.h"
#include "CScroll.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// Ccomm12Dlg 对话框
Ccomm12Dlg::Ccomm12Dlg(CWnd* pParent /*=NULL*/)
: CDialog(Ccomm12Dlg::IDD, pParent)
, m_EditRxData(_T(""))
, m_EditTxData(_T(""))
, strtemp_recive_data(_T(""))
, X(0)
, Y(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void Ccomm12Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_RXDATA, m_EditRxData);
DDX_Text(pDX, IDC_EDIT_TXDATA, m_EditTxData);
DDX_Control(pDX, IDC_TAB1, m_TabCtrl);
DDX_Control(pDX, IDC_COMBO_SERIALPORT, m_ComBo_SerialPort);
DDX_Control(pDX, IDC_COMBO_BAUD, m_ComBo_Baud);
DDX_Control(pDX, IDC_COMBO_CAL, m_ComBo_Cal);
DDX_Control(pDX, IDC_COMBO_BDATA, m_ComBo_BData);
DDX_Control(pDX, IDC_COMBO_BSTOP, m_ComBo_BStop);
DDX_Control(pDX, IDC_BUTTON_POORTOPEN, m_Button_Open);
DDX_Control(pDX, IDC_BUTTON_PORTCLOSE, m_Button_Close);
DDX_Control(pDX, IDC_BUTTON_SEND, m_Button_Send);
DDX_Control(pDX, IDC_MSCOMM1, m_CtrlComm);
}
BEGIN_MESSAGE_MAP(Ccomm12Dlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON_POORTOPEN, &Ccomm12Dlg::OnBnClickedButtonPoortopen)
ON_BN_CLICKED(IDC_BUTTON_PORTCLOSE, &Ccomm12Dlg::OnBnClickedButtonPortclose)
ON_BN_CLICKED(IDC_BUTTON_SEND, &Ccomm12Dlg::OnBnClickedButtonSend)
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, &Ccomm12Dlg::OnTcnSelchangeTab1)
ON_BN_CLICKED(IDC_CHECK1, &Ccomm12Dlg::OnBnClickedCheck1)
END_MESSAGE_MAP()
// Ccomm12Dlg 消息处理程序
BOOL Ccomm12Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_ComBo_SerialPort.AddString("COM1");
m_ComBo_SerialPort.AddString("COM2");
m_ComBo_SerialPort.AddString("COM3");
m_ComBo_SerialPort.SetCurSel(0);
m_ComBo_Baud.AddString("19200");
m_ComBo_Baud.AddString("9600");
m_ComBo_Baud.AddString("115200");
m_ComBo_Baud.SetCurSel(1);
m_ComBo_Cal.AddString("无校验");
m_ComBo_Cal.AddString("奇校验");
m_ComBo_Cal.AddString("偶校验");
m_ComBo_Cal.SetCurSel(0);
m_ComBo_BData.AddString("6");
m_ComBo_BData.AddString("7");
m_ComBo_BData.AddString("8");
m_ComBo_BData.AddString("9");
m_ComBo_BData.SetCurSel(2);
m_ComBo_BStop.AddString("1位");
m_ComBo_BStop.AddString("2位");
m_ComBo_BStop.SetCurSel(0);
if(m_CtrlComm.get_PortOpen())
m_CtrlComm.put_PortOpen(FALSE);
m_CtrlComm.put_CommPort(1); //选择串口号1
m_CtrlComm.put_RThreshold(2); //收到两个字节引发OnComm事件
m_CtrlComm.put_InputMode(1); //输入模式选为二进制
m_CtrlComm.put_InBufferSize(1024); //设置输入缓冲区的大小,Bytes
m_CtrlComm.put_OutBufferSize(1024); //设置输出缓冲区的大小,Bytes
m_CtrlComm.put_Settings("19200,n,8,1"); //设置串口参数,波特率,无奇偶校验,8位数据位,1位停止位
m_CtrlComm.put_InputMode(1); //以二进制方法验取数据
// m_CtrlComm.put_RThreshold(1); //每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
m_CtrlComm.put_InputLen(0); //设置当前接收区数据长度为0
m_CtrlComm.put_PortOpen(TRUE); //打开串口
m_CtrlComm.get_Input(); //先预读缓冲区以清除残留数据
m_Button_Close.EnableWindow(FALSE);
//添加选项卡名称
TCITEM item;
item.mask = TCIF_TEXT;
item.pszText = "恒速恒力控制";
m_TabCtrl.InsertItem(0,&item);
item.pszText = "响应时间测试";
m_TabCtrl.InsertItem(1,&item);
//设置IDC_TAB1为父窗口
page1.Create(IDD_DIALOGBAR1,&m_TabCtrl);
page2.Create(IDD_DIALOGBAR2,&m_TabCtrl);
//获得IDC_TABTEST客户区大小
CRect rc;
m_TabCtrl.GetClientRect(&rc);
//调整子对话框在父窗口中的位置
rc.top += 30;
rc.bottom -= 8;
rc.left += 8;
rc.right -= 8;
//设置子对话框尺寸并移动到指定位置
page1.MoveWindow(&rc);
page2.MoveWindow(&rc);
//分别设置隐藏和显示
page1.ShowWindow(true);
page2.ShowWindow(false);
//设置默认的选项卡
m_TabCtrl.SetCurSel(0);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void Ccomm12Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR Ccomm12Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void Ccomm12Dlg::OnBnClickedButtonPoortopen()
{
// TODO: 在此添加控件通知处理程序代码
CString strSerialPortText,strBaudRateText,strCheckDigitText,strDataBitsText,strStopBitText;
int COM_NUM;
CString SerialPortMessage;
//串口数据类型转换
m_ComBo_SerialPort.GetLBText(m_ComBo_SerialPort.GetCurSel(),strSerialPortText);
m_ComBo_Baud.GetLBText(m_ComBo_Baud.GetCurSel(),strBaudRateText);
m_ComBo_Cal.GetLBText(m_ComBo_Cal.GetCurSel(),strCheckDigitText);
m_ComBo_BData.GetLBText(m_ComBo_BData.GetCurSel(),strDataBitsText);
m_ComBo_BStop.GetLBText(m_ComBo_BStop.GetCurSel(),strStopBitText);
COM_NUM = atoi(strSerialPortText.Mid(3));
if(strCheckDigitText == "奇校验")
strCheckDigitText = "o";
else if(strCheckDigitText == "偶校验")
strCheckDigitText = "e";
else if(strCheckDigitText == "无校验")
strCheckDigitText = "n";
strStopBitText = strStopBitText.Left(strStopBitText.GetLength()-2);
SerialPortMessage = strBaudRateText+","+strCheckDigitText+","+strDataBitsText+","+strStopBitText;
this->m_ComBo_SerialPort.EnableWindow(FALSE);
this->m_ComBo_Baud.EnableWindow(FALSE);
this->m_ComBo_Cal.EnableWindow(FALSE);
this->m_ComBo_BData.EnableWindow(FALSE);
this->m_ComBo_BStop.EnableWindow(FALSE);
this->m_Button_Close.EnableWindow(TRUE);
m_Button_Open.EnableWindow(FALSE);
if(m_CtrlComm.get_PortOpen())
m_CtrlComm.put_PortOpen(FALSE);
m_CtrlComm.put_CommPort(COM_NUM); //选择串口号
m_CtrlComm.put_RThreshold(2); //收到两个字节引发OnComm事件
m_CtrlComm.put_InputMode(1); //输入模式选为二进制
m_CtrlComm.put_InBufferSize(1024); //设置输入缓冲区的大小,Bytes
m_CtrlComm.put_OutBufferSize(1024); //设置输出缓冲区的大小,Bytes
m_CtrlComm.put_Settings(SerialPortMessage); //设置串口参数,波特率,奇偶校验,数据位,停止位
m_CtrlComm.put_InputMode(1); //以二进制方法验取数据
// m_CtrlComm.put_RThreshold(1); //每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
m_CtrlComm.put_InputLen(0); //设置当前接收区数据长度为0
// m_ctrlComm.put_PortOpen(TRUE); //打开串口
if(!m_CtrlComm.get_PortOpen())
m_CtrlComm.put_PortOpen(TRUE);
else
AfxMessageBox("Can not open serial port!");
m_CtrlComm.get_Input(); //先预读缓冲区以清除残留数据
UpdateData(FALSE);
}
BEGIN_EVENTSINK_MAP(Ccomm12Dlg, CDialog)
ON_EVENT(Ccomm12Dlg, IDC_MSCOMM1, 1, Ccomm12Dlg::OnCommMscomm1, VTS_NONE)
END_EVENTSINK_MAP()
void Ccomm12Dlg::OnCommMscomm1()
{
// TODO: 在此处添加消息处理程序代码
VARIANT variant_inp;
COleSafeArray safearray_inp;
long len,k;
BYTE rxdata[2048];
BYTE bt = NULL;
if(m_CtrlComm.get_CommEvent() == 2) //事件值为2表示接收缓冲区内有字符
{
//以下你可以根据自己的通信协议加入处理代码
UpdateData(TRUE);
variant_inp = m_CtrlComm.get_Input(); //读缓冲区
safearray_inp = variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len = safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k); //转换为BYTE型数组
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
bt = *(char*)(rxdata+k); //字符型
//strtemp_recive_data.Format("%X",bt); //将字符送入临时变量strtemp存放
m_EditRxData+=bt; //加入接收编辑框对应字符串
strtemp_recive_data+=bt;
}
while(!strtemp_recive_data.IsEmpty()&&AllisNum(strtemp_recive_data.Left(1)))
{
long count = 0;
int i,nStart = 0,nEnd = 0,nX_End = 0;
for(i=0;i<strtemp_recive_data.GetLength();i++)
{
if((strtemp_recive_data)[i] == ',')
{
count++;
if(count == 1)
{
nX_End = i;
}
else if(count == 3)
{
nStart = i;
}
else if(count == 4)
{
nEnd = i;
break;
}
}
}
CString strtempY = strtemp_recive_data.Mid(nStart+1,nEnd-nStart-1);
if(AllisNum(strtempY))
Y = atof(strtempY);
else
continue;
CString strtempX = strtemp_recive_data.Left(nX_End);
if(AllisNum(strtempX))
X = atof(strtempX);
else
continue;
//================================================================================
COleSafeArray XValues;
COleSafeArray YValues;
DWORD Xnum[] = {10000};
DWORD Ynum[] = {10000};
XValues.Create(VT_R8,1,Xnum);
YValues.Create(VT_R8,1,Ynum);
double tmp;
long index = 0;
for(long i=0;i<10;i++)
{
tmp = X;
XValues.PutElement(&index,&tmp);
tmp = Y;
YValues.PutElement(&index,&tmp);
index++;
}
CSeries serDemo = (CSeries)page1.m_CtrlTchart1.Series(0);
serDemo.AddXY(X,Y,strtempX,0);
CAxes chartaxis = (CAxes)page1.m_CtrlTchart1.get_Axis();
CAxis chartaxisbottem = (CAxis)chartaxis.get_Bottom();
chartaxisbottem.Scroll(1.0,TRUE);
strtemp_recive_data.Empty(); //当字符串第一个为数字时清空
}
strtemp_recive_data.Empty(); //当字符串第一个不为数字时清空
}
UpdateData(FALSE);
CEdit* pedit = (CEdit*)GetDlgItem(IDC_EDIT_RXDATA);
pedit->LineScroll(pedit->GetLineCount());
}
void Ccomm12Dlg::OnBnClickedButtonPortclose()
{
// TODO: 在此添加控件通知处理程序代码
this->m_ComBo_SerialPort.EnableWindow(TRUE);
this->m_ComBo_Baud.EnableWindow(TRUE);
this->m_ComBo_Cal.EnableWindow(TRUE);
this->m_ComBo_BData.EnableWindow(TRUE);
this->m_ComBo_BStop.EnableWindow(TRUE);
this->m_Button_Open.EnableWindow(TRUE);
if(m_CtrlComm.get_PortOpen())
m_CtrlComm.put_PortOpen(FALSE);
}
void Ccomm12Dlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
m_CtrlComm.put_Output(COleVariant(m_EditTxData));
}
void Ccomm12Dlg::OnTcnSelchangeTab1(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在此添加控件通知处理程序代码
int CurSel = m_TabCtrl.GetCurSel();
switch(CurSel)
{
case 0:
page1.ShowWindow(true);
page2.ShowWindow(false);
break;
case 1:
page1.ShowWindow(false);
page2.ShowWindow(true);
break;
}
*pResult = 0;
}
void Ccomm12Dlg::OnBnClickedCheck1()
{
// TODO: 在此添加控件通知处理程序代码
CButton* pBtn = (CButton*)GetDlgItem(IDC_CHECK1);
CByteArray hexdata;
int len;
if(pBtn->GetCheck())
{
len = String2Hex("AABB04F87878FF",hexdata);
m_CtrlComm.put_Output(COleVariant(hexdata));
}
else
{
len = String2Hex("AABB04F07070FF",hexdata);
m_CtrlComm.put_Output(COleVariant(hexdata));
}
}
// 十六进制转换函数
int Ccomm12Dlg::String2Hex(CString str, CByteArray& senddata)
{
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.GetLength();
senddata.SetSize(len/2);
for(int i=0;i<len;)
{
char lstr,hstr=str[i];
if(hstr==' ')
{
i++;
continue;
}
i++;
if(i>=len)
break;
lstr=str[i];
hexdata=ConvertHexChar(hstr);
lowhexdata=ConvertHexChar(lstr);
if((hexdata==16)||(lowhexdata==16))
break;
else
hexdata=hexdata*16+lowhexdata;
i++;
senddata[hexdatalen]=(char)hexdata;
hexdatalen++;
}
senddata.SetSize(hexdatalen);
return hexdatalen;
}
// 将一个字符转换为相应的十六进制
char Ccomm12Dlg::ConvertHexChar(char ch)
{
if((ch>='0')&&(ch<='9'))
return ch-0x30;
else if((ch>='A')&&(ch<='F'))
return ch-'A'+10;
else if((ch>='a')&&(ch<='f'))
return ch-'a'+10;
else
return ch;
}
// 判断字符串是否为数字
bool Ccomm12Dlg::AllisNum(CString str)
{
for(int i = 0;i<str.GetLength();i++)
{
int num = (int)str[i];
if(num >=48 && num<= 57)
continue;
else
return false;
}
return true;
}
运行到这里teechart就停止绘制曲线了,但文本框能正常显示继续接收的数据。这是不是与teechart的绘制效率有关?