Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51882
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 172
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-04 14:17
文章分类

全部博文(18)

文章存档

2014年(3)

2013年(15)

我的朋友

分类: 其他平台

2014-01-02 13:57:43


概述

    公司的控制板一般分为显示板及主控板,二者之间通过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》这篇教程写的,
    运行时效果:
     
    各项功能运行后效果:
     
代码:uitest.rar

通讯部分

    在wxWidgets里面有现成的定时器,在打开串口时,也把定时器打开,100ms周期,在定期器处理函数内不断读取缓冲区的内容,进行解析显示。部分配置代码如下:

点击(此处)折叠或打开

  1. LPCTSTR lpComx;
  2. HANDLE hCom;
  3. void BridgeSimulationFrame::OnComCtrlClick(wxCommandEvent& event)
  4. {
  5.     static int comStatus=0;
  6.     if(comStatus==0)
  7.     {
  8.         int comxID,baudrateID,parityID,stopbitsID;
  9.         comxID=ComPort->GetCurrentSelection();
  10.         baudrateID=ComBaud->GetCurrentSelection();
  11.         parityID=ComParity->GetCurrentSelection();
  12.         stopbitsID=ComStop->GetCurrentSelection();

  13.         switch(comxID)
  14.         {
  15.         case 0:
  16.             lpComx=_("COM1");
  17.             break;
  18.         case 1:
  19.             lpComx=_("COM2");
  20.             break;
  21.         case 2:
  22.             lpComx=_("COM3");
  23.             break;
  24.         case 3:
  25.             lpComx=_("COM4");
  26.             break;
  27.         case 4:
  28.             lpComx=_("COM5");
  29.             break;
  30.         case 5:
  31.             lpComx=_("COM6");
  32.             break;
  33.         case 6:
  34.             lpComx=_("COM7");
  35.             break;
  36.         case 7:
  37.             lpComx=_("COM8");
  38.             break;
  39.         case 8:
  40.             lpComx=_("COM9");
  41.             break;
  42.         default:
  43.             wxMessageBox(_("串口号异常"));
  44.             return;
  45.             break;
  46.         }
  47.         hCom=CreateFile(lpComx,
  48.                         GENERIC_READ|GENERIC_WRITE,
  49.                         0,
  50.                         NULL,
  51.                         OPEN_EXISTING,
  52.                         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
  53.                         NULL);
  54.         if (hCom == INVALID_HANDLE_VALUE)
  55.         {
  56.             wxMessageBox(_("打开串口失败!"));
  57.             return;
  58.         }
  59.         else
  60.         {
  61.             comStatus=1;
  62.             //配置串口
  63.             SetupComm(hCom,1024,1024); //输入缓冲区和输出缓冲区的大小都是1024
  64.             COMMTIMEOUTS TimeOuts;
  65.             //设定读超时
  66.             TimeOuts.ReadIntervalTimeout = 1000;
  67.             TimeOuts.ReadTotalTimeoutMultiplier = 0;
  68.             TimeOuts.ReadTotalTimeoutConstant = 0;
  69.             //设定写超时
  70.             TimeOuts.WriteTotalTimeoutMultiplier = 500;
  71.             TimeOuts.WriteTotalTimeoutConstant = 2000;
  72.             SetCommTimeouts(hCom, &TimeOuts); //设置超时

  73.             DCB dcb;
  74.             GetCommState(hCom, &dcb);
  75.             switch(baudrateID)
  76.             {
  77.             case 0:
  78.                 dcb.BaudRate =300;
  79.                 break;
  80.             case 1:
  81.                 dcb.BaudRate =600;
  82.                 break;
  83.             case 2:
  84.                 dcb.BaudRate =1200;
  85.                 break;
  86.             case 3:
  87.                 dcb.BaudRate =2400;
  88.                 break;
  89.             case 4:
  90.                 dcb.BaudRate =4800;
  91.                 break;
  92.             case 5:
  93.                 dcb.BaudRate =9600;
  94.                 break;
  95.             case 6:
  96.                 dcb.BaudRate =14400;
  97.                 break;
  98.             case 7:
  99.                 dcb.BaudRate =19200;
  100.                 break;
  101.             case 8:
  102.                 dcb.BaudRate =38400;
  103.                 break;
  104.             case 9:
  105.                 dcb.BaudRate =56000;
  106.                 break;
  107.             case 10:
  108.                 dcb.BaudRate =115200;
  109.                 break;
  110.             case 11:
  111.                 dcb.BaudRate =128000;
  112.                 break;
  113.             case 12:
  114.                 dcb.BaudRate =256000;
  115.                 break;
  116.             default:
  117.                 wxMessageBox(_("波特率异常"));
  118.                 break;
  119.             }
  120.             dcb.ByteSize = 8; //每个字节有8位
  121.             if(parityID==0)
  122.             {
  123.                 dcb.Parity=NOPARITY;
  124.             }
  125.             else if(parityID==1)
  126.             {
  127.                 dcb.Parity=ODDPARITY;
  128.             }
  129.             else
  130.             {
  131.                 dcb.Parity=EVENPARITY;
  132.             }
  133.             if(stopbitsID==0)
  134.             {
  135.                 dcb.Parity=ONESTOPBIT;
  136.             }
  137.             else
  138.             {
  139.                 dcb.Parity=TWOSTOPBITS;
  140.             }
  141.             SetCommState(hCom, &dcb);

  142.             //在读写串口之前,还要用PurgeComm()函数清空缓冲区
  143.             PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);

  144.             Timer1.Start(100);
  145.         }
  146.     }
  147.     else
  148.     {
  149.         int ret=0;
  150.         ret=CloseHandle(hCom);
  151.         if(!ret)
  152.         {
  153.             wxMessageBox(_("关闭串口失败!"));
  154.             return;
  155.         }
  156.         else
  157.         {
  158.             comStatus=0;
  159.             Timer1.Stop();
  160.         }
  161.         return;
  162.     }
  163. }

  164. void BridgeSimulationFrame::OnTimer1Trigger(wxTimerEvent& event)
  165. {
  166. //#define FD420_MAIN_HEAD 0
  167. //#define FD420_DISP_HEAD 0
  168. //static unsigned char buffer[100];
  169. //static unsigned char bufferPoint;

  170.     int i,j,sum;
  171.     int clearNum;
  172.     unsigned char* u8p;
  173.     DWORD dwBytesRead=50;//读取的字节数
  174.     DWORD bytecount;
  175.     unsigned char str[50];
  176.     memset(&str,'\0',50);

  177.     BOOL bReadStat;

  178.     COMSTAT ComStat;
  179.     DWORD dwErrorFlags;

  180.     OVERLAPPED m_osRead;
  181.     memset(&m_osRead,0,sizeof(OVERLAPPED));
  182.     m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);



  183.     ClearCommError(hCom,&dwErrorFlags,&ComStat);
  184.     if(ComStat.cbInQue<dwBytesRead)
  185.         dwBytesRead=ComStat.cbInQue;
  186.     bReadStat = ReadFile(hCom,str,dwBytesRead,&bytecount,&m_osRead);

  187.     if(!bReadStat)
  188.     {
  189.         if (GetLastError() == ERROR_IO_PENDING)
  190.             WaitForSingleObject(m_osRead.hEvent, 40);
  191.     }
  192.     PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

  193. //串口数据处理及更新窗体代码省略
  194. }
上面的代码是监听模式下的,模拟模式下只要根据窗体状态组成一串发送数据,然后发给下位机即可。
OVER
阅读(2445) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~