概述:
公司的控制板一般分为显示板及主控板,二者之间通过UART通讯,在2012就想搞个PC端的程序,可以做到对通讯的采集、分析及模拟功能。采集功能直接用串口小工具就行,但这样的话每次得用人脑根据通讯协议进行分析。后来又写了个CUI的,很简陋,没啥用途。
最近,一个新的显示板软件写得差不多了,我想顺带着根据通讯协议把上位机的GUI程序也写出来,软件测试会方便很多,记得以前我们为了读出传感器的值,都外挂一个AD采集模块/频率检测模块。
拟定实现的功能:
1,监视模式下,能对UART通讯实现单、双路监控,实施解析通讯数据并直观化显示
2,模拟模式下,能在PC端模拟显示板或主控板对配套控制板进行模拟测试
3,可扩展结构,可以很方便的增加新的通讯协议,即增加对以后新控制板的支持
GUI部分,我是要用wxWidgets,C++环境,看了两天,简单用用应该没太大问题,我准备GUI部分就照着C++的来,数据分析,函数实现统统用C写,自己看着明白,嘿嘿。
wxWidgets学习:
用wxWidgets的部分原因是因为codeblocks用的顺溜,codeblocks上的wxSmith还是蛮好用的,在linux和windows下都能做wxWidgets的开发。
在codeblocks(集成wxSmith)+gcc+wxWidgets开发环境搭建完成后,我就照着,一步步做,两天就把wxWidgets的基本使用方法弄清楚了,对GUI的实现也有了底。
上个小例子,这是根据《WxSmith tutorial: Accessing items in resource》这篇教程写的,
运行时效果:
各项功能运行后效果:
通讯部分:
在wxWidgets里面有现成的定时器,在打开串口时,也把定时器打开,100ms周期,在定期器处理函数内不断读取缓冲区的内容,进行解析显示。部分配置代码如下:
-
LPCTSTR lpComx;
-
HANDLE hCom;
-
void BridgeSimulationFrame::OnComCtrlClick(wxCommandEvent& event)
-
{
-
static int comStatus=0;
-
if(comStatus==0)
-
{
-
int comxID,baudrateID,parityID,stopbitsID;
-
comxID=ComPort->GetCurrentSelection();
-
baudrateID=ComBaud->GetCurrentSelection();
-
parityID=ComParity->GetCurrentSelection();
-
stopbitsID=ComStop->GetCurrentSelection();
-
-
switch(comxID)
-
{
-
case 0:
-
lpComx=_("COM1");
-
break;
-
case 1:
-
lpComx=_("COM2");
-
break;
-
case 2:
-
lpComx=_("COM3");
-
break;
-
case 3:
-
lpComx=_("COM4");
-
break;
-
case 4:
-
lpComx=_("COM5");
-
break;
-
case 5:
-
lpComx=_("COM6");
-
break;
-
case 6:
-
lpComx=_("COM7");
-
break;
-
case 7:
-
lpComx=_("COM8");
-
break;
-
case 8:
-
lpComx=_("COM9");
-
break;
-
default:
-
wxMessageBox(_("串口号异常"));
-
return;
-
break;
-
}
-
hCom=CreateFile(lpComx,
-
GENERIC_READ|GENERIC_WRITE,
-
0,
-
NULL,
-
OPEN_EXISTING,
-
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
-
NULL);
-
if (hCom == INVALID_HANDLE_VALUE)
-
{
-
wxMessageBox(_("打开串口失败!"));
-
return;
-
}
-
else
-
{
-
comStatus=1;
-
//配置串口
-
SetupComm(hCom,1024,1024); //输入缓冲区和输出缓冲区的大小都是1024
-
COMMTIMEOUTS TimeOuts;
-
//设定读超时
-
TimeOuts.ReadIntervalTimeout = 1000;
-
TimeOuts.ReadTotalTimeoutMultiplier = 0;
-
TimeOuts.ReadTotalTimeoutConstant = 0;
-
//设定写超时
-
TimeOuts.WriteTotalTimeoutMultiplier = 500;
-
TimeOuts.WriteTotalTimeoutConstant = 2000;
-
SetCommTimeouts(hCom, &TimeOuts); //设置超时
-
-
DCB dcb;
-
GetCommState(hCom, &dcb);
-
switch(baudrateID)
-
{
-
case 0:
-
dcb.BaudRate =300;
-
break;
-
case 1:
-
dcb.BaudRate =600;
-
break;
-
case 2:
-
dcb.BaudRate =1200;
-
break;
-
case 3:
-
dcb.BaudRate =2400;
-
break;
-
case 4:
-
dcb.BaudRate =4800;
-
break;
-
case 5:
-
dcb.BaudRate =9600;
-
break;
-
case 6:
-
dcb.BaudRate =14400;
-
break;
-
case 7:
-
dcb.BaudRate =19200;
-
break;
-
case 8:
-
dcb.BaudRate =38400;
-
break;
-
case 9:
-
dcb.BaudRate =56000;
-
break;
-
case 10:
-
dcb.BaudRate =115200;
-
break;
-
case 11:
-
dcb.BaudRate =128000;
-
break;
-
case 12:
-
dcb.BaudRate =256000;
-
break;
-
default:
-
wxMessageBox(_("波特率异常"));
-
break;
-
}
-
dcb.ByteSize = 8; //每个字节有8位
-
if(parityID==0)
-
{
-
dcb.Parity=NOPARITY;
-
}
-
else if(parityID==1)
-
{
-
dcb.Parity=ODDPARITY;
-
}
-
else
-
{
-
dcb.Parity=EVENPARITY;
-
}
-
if(stopbitsID==0)
-
{
-
dcb.Parity=ONESTOPBIT;
-
}
-
else
-
{
-
dcb.Parity=TWOSTOPBITS;
-
}
-
SetCommState(hCom, &dcb);
-
-
//在读写串口之前,还要用PurgeComm()函数清空缓冲区
-
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
-
-
Timer1.Start(100);
-
}
-
}
-
else
-
{
-
int ret=0;
-
ret=CloseHandle(hCom);
-
if(!ret)
-
{
-
wxMessageBox(_("关闭串口失败!"));
-
return;
-
}
-
else
-
{
-
comStatus=0;
-
Timer1.Stop();
-
}
-
return;
-
}
-
}
-
-
void BridgeSimulationFrame::OnTimer1Trigger(wxTimerEvent& event)
-
{
-
//#define FD420_MAIN_HEAD 0
-
//#define FD420_DISP_HEAD 0
-
//static unsigned char buffer[100];
-
//static unsigned char bufferPoint;
-
-
int i,j,sum;
-
int clearNum;
-
unsigned char* u8p;
-
DWORD dwBytesRead=50;//读取的字节数
-
DWORD bytecount;
-
unsigned char str[50];
-
memset(&str,'\0',50);
-
-
BOOL bReadStat;
-
-
COMSTAT ComStat;
-
DWORD dwErrorFlags;
-
-
OVERLAPPED m_osRead;
-
memset(&m_osRead,0,sizeof(OVERLAPPED));
-
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
-
-
-
-
ClearCommError(hCom,&dwErrorFlags,&ComStat);
-
if(ComStat.cbInQue<dwBytesRead)
-
dwBytesRead=ComStat.cbInQue;
-
bReadStat = ReadFile(hCom,str,dwBytesRead,&bytecount,&m_osRead);
-
-
if(!bReadStat)
-
{
-
if (GetLastError() == ERROR_IO_PENDING)
-
WaitForSingleObject(m_osRead.hEvent, 40);
-
}
-
PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
-
-
//串口数据处理及更新窗体代码省略
-
}
上面的代码是监听模式下的,模拟模式下只要根据窗体状态组成一串发送数据,然后发给下位机即可。
OVER
阅读(2445) | 评论(0) | 转发(0) |