打印

智能电度表读数程序 VC++6.0编写

[复制链接]
2825|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 cooldog123pp 于 2021-10-30 14:36 编辑

  此程序通过USB转485连接计算机USB口与智能电度表的RS485接口来读取电度表数据,并存储在XLS表格中。程序用VC++6.0编写,经实际测试运行稳定。
       硬件方面一台计算机,一个USB转RS485,电度表,接线简单,USB转RS485插入计算机的USB口,A-B分别接电度表的485端子。程序运行后设置好串
口参数,一般波特率设为2400,8个数据位,1个停止位,偶校验,具体参考电度表手册。点打开串口,如未出现错误提示就表示连接成功了。先点读电度表序号,再点自动读数据或点其他按扭就能读到数据。
      我这里测试的电表是深圳某公司的,其他厂家的电表也是一样可用的。




     部份源代码如下:
        // 智能电表抄系统Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "智能电表科陆抄表系统.h"
#include "智能电表科陆抄表系统Dlg.h"
#include "comdef.h"
#include <afxdb.h>
#include   <odbcinst.h>
#include <Afxdlgs.h>

#include"comdef.h"
#include "ComSetDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
        {
        public:
                CAboutDlg();
               
                // Dialog Data
                //{{AFX_DATA(CAboutDlg)
                enum { IDD = IDD_ABOUTBOX };
                //}}AFX_DATA
               
                // ClassWizard generated virtual function overrides
                //{{AFX_VIRTUAL(CAboutDlg)
        protected:
                virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
                //}}AFX_VIRTUAL
               
                // Implementation
        protected:
                //{{AFX_MSG(CAboutDlg)
                //}}AFX_MSG
                DECLARE_MESSAGE_MAP()
        };

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
        {
        //{{AFX_DATA_INIT(CAboutDlg)
        //}}AFX_DATA_INIT
        }

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
        {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CAboutDlg)
        //}}AFX_DATA_MAP
        }

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP




END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyDlg dialog

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMyDlg::IDD, pParent)
        {
        //{{AFX_DATA_INIT(CMyDlg)
        m_command = _T("");
        m_kwh = _T("");
        m_sumkwh = _T("");
        m_date = _T("");
        m_datepick = 0;
        m_operator = _T("");
        m_nume = _T("");
        m_time = COleDateTime::GetCurrentTime();
        m_curtime = _T("");
        m_curdate = _T("");
        m_recdate = _T("");
        m_rectime = _T("");
        m_meternumb = _T("");
        m_meterrecd = _T("");
        m_readsumkwh = _T("");
        m_voitage = _T("");
        m_readcommand = _T("");
        m_power = _T("");
        m_stacommand = _T("");
        m_epari = _T("");
        m_eport = _T("");
        m_estop = _T("");
        m_recdkwh = _T("");
        m_datard = _T("");
        m_payment = _T("");
        m_ebuad = 0;
        m_edata = 0;
        //}}AFX_DATA_INIT
        // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
        }

void CMyDlg::DoDataExchange(CDataExchange* pDX)
        {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CMyDlg)
        DDX_Control(pDX, IDC_EDIT_TEMPER, m_temper);
        DDX_Control(pDX, IDC_EDIT_BATTERY, m_battery);
        DDX_Control(pDX, IDC_EDIT_SUMPOWER, m_sumpower);
        DDX_Control(pDX, IDC_EDIT_DATAREAD, m_dataread);
        DDX_Control(pDX, IDC_EDIT_HZ, m_hz);
        DDX_Control(pDX, IDC_RECDVOITAGE, m_recdvoitage);
        DDX_Control(pDX, IDC_RECDPOWER, m_recdpower);
        DDX_Control(pDX, IDC_RECDCURRENT, m_recdcurrent);
        DDX_Control(pDX, IDC_EDIT_METERNUMB, m_emeternumb);
        DDX_Control(pDX, IDC_READCOMMAND, m_ereadcommand);
        DDX_Control(pDX, IDC_POWER, m_epower);
        DDX_Control(pDX, IDC_VOITAGE, m_evoitage);
        DDX_Control(pDX, IDC_CURRENT, m_ecurrent);
        DDX_Control(pDX, IDC_STATIC_TXD, m_stxd);
        DDX_Control(pDX, IDC_STATIC_RXD, m_srxd);
        DDX_Control(pDX, IDC_STATIC_COMMAND, m_scommand);
        DDX_Control(pDX, IDC_SUMKWH, m_esumkwh);
        DDX_Control(pDX, IDC_BUTTON_READDATA, m_readdata);
        DDX_Control(pDX, IDC_EDIT_RETURNVAL, m_data);
        DDX_Control(pDX, IDC_LIST1, m_list);
        DDX_Control(pDX, IDC_BUTTON_OPENCOM, m_OpenCloseCtrl);
        DDX_Control(pDX, IDC_COMMAND, m_commd);
        DDX_Text(pDX, IDC_COMMAND, m_command);
        DDX_Text(pDX, IDC_KWH, m_kwh);
        DDX_Text(pDX, IDC_SUMKWH, m_sumkwh);
        DDX_Text(pDX, IDC_EDIT_OPERATOR, m_operator);
        DDX_Text(pDX, IDC_EDIT_NUME, m_nume);
        DDX_Text(pDX, IDC_EDIT_CURTIME, m_curtime);
        DDX_Text(pDX, IDC_EDIT_DATE, m_curdate);
        DDX_Text(pDX, IDC_EDIT_RECDATE, m_recdate);
        DDX_Text(pDX, IDC_EDIT_RECTIME, m_rectime);
        DDX_Text(pDX, IDC_EDIT_METERNUMB, m_meternumb);
        DDX_Text(pDX, IDC_EDIT_METERRECD, m_meterrecd);
        DDX_Text(pDX, IDC_VOITAGE, m_voitage);
        DDX_Text(pDX, IDC_READCOMMAND, m_readcommand);
        DDX_Text(pDX, IDC_POWER, m_power);
        DDX_Text(pDX, IDC_STATIC_COMMAND, m_stacommand);
        DDX_Text(pDX, IDC_EDIT_PARI, m_epari);
        DDX_Text(pDX, IDC_EDIT_PORT, m_eport);
        DDX_Text(pDX, IDC_EDIT_STOP, m_estop);
        DDX_Text(pDX, IDC_EDIT_RECDKWH, m_recdkwh);
        DDX_Text(pDX, IDC_EDIT_DATAREAD, m_datard);
        DDX_Text(pDX, IDC_PAYMENT, m_payment);
        DDX_Text(pDX, IDC_EDIT_BUAD, m_ebuad);
        DDX_Text(pDX, IDC_EDIT_DATA, m_edata);
        //}}AFX_DATA_MAP
        }

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
//{{AFX_MSG_MAP(CMyDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_OPENCOM, OnButtonOpencom)
ON_COMMAND(ID_MENU_COMSET, OnComset)
ON_BN_CLICKED(IDC_BUTTON_READADD, OnButtonReadadd)
ON_BN_CLICKED(IDC_BUTTON_READDATA, OnButtonReaddata)
ON_WM_TIMER()
ON_COMMAND(ID_MENU_HELP, OnMenuHelp)
ON_COMMAND(ID_MENU_CLOSE, OnMenuClose)
ON_COMMAND(ID_MENU_EXAMINE, OnMenuExamine)
ON_COMMAND(ID_MENU_OPEN, OnMenuOpen)
ON_COMMAND(ID_MENU_SAVE, OnMenuSave)
ON_COMMAND(ID_MENU_NEWS, OnMenuNews)
ON_BN_CLICKED(IDC_ADDRECORD, OnAddrecord)
ON_BN_CLICKED(IDC_BUTTON_DEL, OnButtonDel)
ON_BN_CLICKED(IDC_BUTTON_MODI, OnButtonModi)
ON_NOTIFY(NM_CLICK, IDC_LIST1, OnClickList1)
ON_WM_CTLCOLOR()
ON_BN_CLICKED(IDC_BUTTON_READVOIT, OnButtonReadvoit)
ON_BN_CLICKED(IDC_BUTTON_READCURR, OnButtonReadcurr)
ON_BN_CLICKED(IDC_BUTTON_READKWH, OnButtonReadkwh)
ON_BN_CLICKED(IDC_BUTTON_POWER, OnButtonPower)
ON_MESSAGE(WM_COMMNOTIFY, OnCommNotify)
ON_BN_CLICKED(IDC_BUTTON_DATAREAD, OnButtonDataread)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyDlg message handlers

BOOL CMyDlg::OnInitDialog()
        {
        CDialog::OnInitDialog();
        
        // Add "About..." menu item to system menu.
        
        // IDM_ABOUTBOX must be in the system command range.
        ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
        ASSERT(IDM_ABOUTBOX < 0xF000);
        
        CMenu* pSysMenu = GetSystemMenu(FALSE);
        if (pSysMenu != NULL)
                {
                CString strAboutMenu;
                strAboutMenu.LoadString(IDS_ABOUTBOX);
                if (!strAboutMenu.IsEmpty())
                        {
                        pSysMenu->AppendMenu(MF_SEPARATOR);
                        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
                        }
                }
        
        // Set the icon for this dialog.  The framework does this automatically
        //  when the application's main window is not a dialog
        SetIcon(m_hIcon, TRUE);                        // Set big icon
        SetIcon(m_hIcon, FALSE);                // Set small icon
        
        // TODO: Add extra initialization here
        UpdateData(TRUE);//更新编辑框内容
        //buf={0};
        K=0;
        CDC dc;
        // CRect rect=IDR_MENU1;
        CMenu *menu;
        m_menu.LoadMenu(IDR_MENU1);
    //m_menu.LoadToolbar(IDR_MENUIMAGES);
    ////m_menu.LoadToolbar(IDR_TOOLBAR);
        // SetMenu(&m_menu);
        //SetBackgroundColor(RGB(0,255,255)); //设置背景色为白色
        m_Font.CreatePointFont(240,"宋体");//创建字体
        //m_Font.CreatePointFont(120, "Arial", NULL);
        dc.SelectObject(&m_Font);
        
        
        // dc.FillSolidRect(rect,RGB(80,89,202));//菜单被选中
        dc.SetTextColor(RGB(10,0,181));//设置文本颜色
        //dc.DrawText(*pText,rect,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
        // dc.Detach();
        
        m_menu.LoadMenu(IDR_MENU1);
    SetMenu(&m_menu);
    //修改菜单栏颜色
    m_brushback.Detach();
    m_brushback.CreateSolidBrush(RGB(215,255,255));//控件背景色
        MENUINFO mi;  //MENUINFO结构未定义
    mi.cbSize=sizeof(MENUINFO);//在StdAfx.cpp文件里的最前面部分添加这个语句:#define  WINVER 0x0501
    mi.fMask=MIM_BACKGROUND;
    mi.hbrBack=(HBRUSH)m_brushback;
    int result=SetMenuInfo((HMENU)(m_menu.m_hMenu),&mi);
    m_menu.Detach();//去掉这句可以让菜单栏变色,但是其他函数要GetMenu()所以。。
        //m_menu.SetBackgroundColor(RGB(255,0,0));//210,220,235));
        // DrawMenuBar();
        
        //m_brushback.CreateSolidBrush(RGB(255,190,255));
        //SetDialogBkColor(RGB(0,192,128),RGB(200,0,0));
        //        m_bmpback.LoadBitmap( IDB_BITMAP_BACK );  //加载背景图
        //        m_brushback.CreatePatternBrush( &m_bmpback );//用背景图填充主窗口背景
/*        m_strPort="COM3";   //预设为COM2口
    m_nBaud=2400;
    m_nDataBits=8;
    m_nParity=1;
        m_nStopBits=0;
    m_eport=m_strPort;
        m_ebuad.Format("%d",m_nBaud);
    m_edata.Format("%d",m_nDataBits);
    m_epari.Format("%d",m_nParity);
    m_estop.Format("%d",m_nStopBits);    */
CFile file;  //从ComSer.dat文件中调入串口参数
//        if(!file.Open("./ComSer.dat",CFile::modeRead))
        //{
         //         CreateUser();
                        //if(!file.Open("./ComSer.dat",CFile::modeRead))
        //        return FALSE;
//        }

ComStat Cs;
file.Open("./ComSet.dat",CFile::modeRead);
while(file.Read(&Cs,sizeof(Cs)))
{

//file.Read(&Cs,sizeof(Cs));
m_eport=Cs.sPort;
        m_strPort=Cs.sPort;
m_ebuad=Cs.nBaud;
m_nBaud=m_ebuad;
m_edata=Cs.nData;
m_nDataBits=Cs.nData;

m_nParity=Cs.nPari;
        switch(m_nParity) // 校验设置
                        {
                        case 0:
                        
                                m_epari="NOPARITY";
                                break;
                                
                        case 1:
                                m_epari="EVENPARITY";
                                break;
                                
                        case 2:
                        
               m_epari="ODDPARITY";
                                break;
                                
                        default:;
                        }

        m_nStopBits=Cs.nStop;
        switch(m_nStopBits) // 停止位
                        {
                        case 0:
                                
             m_estop="ONESTOPBIT";
                                break;
                                
                        case 1:
                        
m_estop="ONE5STOPBITS";

                                break;
                                
                        case 2:
                        
                m_estop="TWOSTOPBITS";
                                break;
                                
                        default:;
                        }




        }
    hBitmap = LoadBitmap(AfxGetInstanceHandle(),
                MAKEINTRESOURCE(IDB_BITMAP_OFF)); // IDB_BITMAP_TEST为资源图片ID
    m_srxd.SetBitmap(hBitmap);
    m_stxd.SetBitmap(hBitmap);
    m_Font1.CreatePointFont(120, "Arial", NULL);//设置(控件型)变量的字体
    m_esumkwh.SetFont(&m_Font1,true);  
    m_scommand.SetFont(&m_Font1,true);  
    m_commd.SetFont(&m_Font1,true);  
    m_ecurrent.SetFont(&m_Font1,true);  
    m_evoitage.SetFont(&m_Font1,true);
    m_epower.SetFont(&m_Font1,true);
    m_ereadcommand.SetFont(&m_Font1,true);
    m_emeternumb.SetFont(&m_Font1,true);
    m_data.SetFont(&m_Font1,true);
    //m_list.SetFont(&m_Font1,true);
        
        
    //  m_color = RGB(0,0,128);
    m_list.SetBkColor(RGB(0,0,255));
    // m_color = RGB(0,128,128);
    m_list.SetTextColor(RGB(0,128,128));//
    m_list.SubclassDlgItem(IDC_LIST1,this);
    m_list.InsertColumn(0,"序号",0,40);
    m_list.InsertColumn(1,"电表表号",0,85);
    m_list.InsertColumn(2,"抄表日期",0,100);
    m_list.InsertColumn(3,"抄表时间",0,60);
    m_list.InsertColumn(4,"电压",0,55);
    m_list.InsertColumn(5,"电流",0,55);
    m_list.InsertColumn(6,"功率",0,70);
    m_list.InsertColumn(7,"操作员",0,50);
    m_list.InsertColumn(8,"度数",0,85);
        m_list.InsertColumn(9,"交费记录",0,60);
        m_list.InsertColumn(10,"停电时间",0,70);
        m_list.InsertColumn(11,"频率",0,60);
        m_hWnd=this->GetSafeHwnd();
    // 为WM_COMMNOTIFY消息创建事件对象,手工重置,初始化为有信号的
        if((m_hPostMsgEvent=CreateEvent(NULL, TRUE, TRUE, NULL))==NULL)               
                return FALSE;
        memset(&m_osRead, 0, sizeof(OVERLAPPED));
        memset(&m_osWrite, 0, sizeof(OVERLAPPED));
        // 为异步读创建事件对象,手工重置,初始化为无信号的
        if((m_osRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
                return FALSE;
    m_stacommand="读电量命令";
    m_readcommand="68 75 76 00 00 00 10 11 04 33 33 33 33";
        m_bPortOpened=0;
        m_command="68 AA AA AA AA AA AA 68 13 00";
    Readfig=false;
        SetTimer(1,1000,NULL);
        UpdateData(false);//更新编辑框内容
        return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
        {
        if ((nID & 0xFFF0) == IDM_ABOUTBOX)
                {
                CAboutDlg dlgAbout;
                dlgAbout.DoModal();
                }
        else
                {
                CDialog::OnSysCommand(nID, lParam);
                }
        }

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMyDlg::OnPaint()
        {
        CPaintDC dc(this); // 填充背景色
        CRect rect;
        GetClientRect(&rect);        
        
        if (IsIconic())
                {
                CPaintDC dc(this); // device context for painting
               
                SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
               
                // Center icon in client rectangle
                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;
               
                // Draw the icon
                dc.DrawIcon(x, y, m_hIcon);
                }
        else
                {
                CDialog::OnPaint();
                }
        //dc.FillRect( rect, &m_brushback );  //填充背景图
        }

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMyDlg::OnQueryDragIcon()
        {
        return (HCURSOR) m_hIcon;
        }

void CMyDlg::OnButtonOpencom() //打开关闭串口
        {
        // TODO: Add your control notification handler code here
        CString temp;
    m_OpenCloseCtrl.GetWindowText(temp);  //
    UpdateData(true);
        m_bPortOpened=!m_bPortOpened;
    if(m_bPortOpened)   //如串口可连接
                {                  
                COMMTIMEOUTS TimeOuts;
                // 异步方式打开串口
                m_hCom=CreateFile(m_strPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
                if(m_hCom==INVALID_HANDLE_VALUE)   ////如串口打开错误则返回
                        {        
                        m_bPortOpened=!m_bPortOpened;
                        SetTimer(4,2000,NULL );
                        AfxMessageBox("串口不存在");                        
                        return ;      
                        }
        SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);//设置输入、输出缓冲区的大小
        SetCommMask(m_hCom,EV_RXCHAR);//设置事件驱动的类型
        PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR| PURGE_RXCLEAR );
                //清干净输入、输出缓冲区
                // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
                TimeOuts.ReadIntervalTimeout=MAXDWORD;
                TimeOuts.ReadTotalTimeoutMultiplier=50;
                TimeOuts.ReadTotalTimeoutConstant=500;
                /* 设置写超时以指定WriteComm成员函数中的GetOverlappedResult函数的等待时间*/
                TimeOuts.WriteTotalTimeoutMultiplier=50;
                TimeOuts.WriteTotalTimeoutConstant=500;
                SetCommTimeouts(m_hCom, &TimeOuts);
                DCB dcb;
                //得到串口当前配置
                if(!GetCommState(m_hCom, &dcb))
                        {                 SetTimer(4,2000,NULL );
                MessageBox("串口设置错误,请重新设置。");
                return ;
                        }
                dcb.fBinary=1;//允许二进制模式
                dcb.BaudRate=m_nBaud;//波特率为9600
                dcb.ByteSize=m_nDataBits;//数据位为8位
                dcb.Parity=m_nParity ;//无校验位
                dcb.StopBits=m_nStopBits;//停止位为1位
        switch(m_nParity) // 校验设置
                        {
                        case 0:
                                dcb.Parity=NOPARITY;
                                break;
                                
                        case 1:
                                dcb.Parity=EVENPARITY;
                                break;
                                
                        case 2:
                                dcb.Parity=ODDPARITY;
                                break;
                                。。。。。。。。
游客,如果您要查看本帖隐藏内容请回复

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1839

主题

6413

帖子

30

粉丝