|
此程序通過(guò)USB轉(zhuǎn)485連接計(jì)算機(jī)USB口與智能電度表的RS485接口來(lái)讀取電度表數(shù)據(jù),并存儲(chǔ)在XLS表格中。程序用VC++6.0編寫(xiě),經(jīng)實(shí)際測(cè)試運(yùn)行穩(wěn)定。
硬件方面一臺(tái)計(jì)算機(jī),一個(gè)USB轉(zhuǎn)RS485,電度表,接線簡(jiǎn)單,USB轉(zhuǎn)RS485插入計(jì)算機(jī)的USB口,A-B分別接電度表的485端子。程序運(yùn)行后設(shè)置好串
口參數(shù),一般波特率設(shè)為2400,8個(gè)數(shù)據(jù)位,1個(gè)停止位,偶校驗(yàn),具體參考電度表手冊(cè)。點(diǎn)打開(kāi)串口,如未出現(xiàn)錯(cuò)誤提示就表示連接成功了。先點(diǎn)讀電度表序號(hào),再點(diǎn)自動(dòng)讀數(shù)據(jù)或點(diǎn)其他按扭就能讀到數(shù)據(jù)。
我這里測(cè)試的電表是深圳某公司的,其他廠家的電表也是一樣可用的。
無(wú)標(biāo)題.png (95.73 KB, 下載次數(shù): 78)
下載附件
程序運(yùn)行界面
2021-10-18 17:05 上傳
部份源代碼如下:
// 智能電表抄系統(tǒng)Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "智能電表科陸抄表系統(tǒng).h"
#include "智能電表科陸抄表系統(tǒng)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);//更新編輯框內(nèi)容
//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)); //設(shè)置背景色為白色
m_Font.CreatePointFont(240,"宋體");//創(chuàng)建字體
//m_Font.CreatePointFont(120, "Arial", NULL);
dc.SelectObject(&m_Font);
// dc.FillSolidRect(rect,RGB(80,89,202));//菜單被選中
dc.SetTextColor(RGB(10,0,181));//設(shè)置文本顏色
//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結(jié)構(gòu)未定義
mi.cbSize=sizeof(MENUINFO);//在StdAfx.cpp文件里的最前面部分添加這個(gè)語(yǔ)句:#define WINVER 0x0501
mi.fMask=MIM_BACKGROUND;
mi.hbrBack=(HBRUSH)m_brushback;
int result=SetMenuInfo((HMENU)(m_menu.m_hMenu),&mi);
m_menu.Detach();//去掉這句可以讓菜單欄變色,但是其他函數(shù)要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"; //預(yù)設(shè)為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文件中調(diào)入串口參數(shù)
// 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) // 校驗(yàn)設(shè)置
{
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);//設(shè)置(控件型)變量的字體
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,"序號(hào)",0,40);
m_list.InsertColumn(1,"電表表號(hào)",0,85);
m_list.InsertColumn(2,"抄表日期",0,100);
m_list.InsertColumn(3,"抄表時(shí)間",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,"度數(shù)",0,85);
m_list.InsertColumn(9,"交費(fèi)記錄",0,60);
m_list.InsertColumn(10,"停電時(shí)間",0,70);
m_list.InsertColumn(11,"頻率",0,60);
m_hWnd=this->GetSafeHwnd();
// 為WM_COMMNOTIFY消息創(chuàng)建事件對(duì)象,手工重置,初始化為有信號(hào)的
if((m_hPostMsgEvent=CreateEvent(NULL, TRUE, TRUE, NULL))==NULL)
return FALSE;
memset(&m_osRead, 0, sizeof(OVERLAPPED));
memset(&m_osWrite, 0, sizeof(OVERLAPPED));
// 為異步讀創(chuàng)建事件對(duì)象,手工重置,初始化為無(wú)信號(hào)的
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);//更新編輯框內(nèi)容
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() //打開(kāi)關(guān)閉串口
{
// 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;
// 異步方式打開(kāi)串口
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) ////如串口打開(kāi)錯(cuò)誤則返回
{
m_bPortOpened=!m_bPortOpened;
SetTimer(4,2000,NULL );
AfxMessageBox("串口不存在");
return ;
}
SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);//設(shè)置輸入、輸出緩沖區(qū)的大小
SetCommMask(m_hCom,EV_RXCHAR);//設(shè)置事件驅(qū)動(dòng)的類型
PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR| PURGE_RXCLEAR );
//清干凈輸入、輸出緩沖區(qū)
// 把間隔超時(shí)設(shè)為最大,把總超時(shí)設(shè)為0將導(dǎo)致ReadFile立即返回并完成操作
TimeOuts.ReadIntervalTimeout=MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=50;
TimeOuts.ReadTotalTimeoutConstant=500;
/* 設(shè)置寫(xiě)超時(shí)以指定WriteComm成員函數(shù)中的GetOverlappedResult函數(shù)的等待時(shí)間*/
TimeOuts.WriteTotalTimeoutMultiplier=50;
TimeOuts.WriteTotalTimeoutConstant=500;
SetCommTimeouts(m_hCom, &TimeOuts);
DCB dcb;
//得到串口當(dāng)前配置
if(!GetCommState(m_hCom, &dcb))
{ SetTimer(4,2000,NULL );
MessageBox("串口設(shè)置錯(cuò)誤,請(qǐng)重新設(shè)置。");
return ;
}
dcb.fBinary=1;//允許二進(jìn)制模式
dcb.BaudRate=m_nBaud;//波特率為9600
dcb.ByteSize=m_nDataBits;//數(shù)據(jù)位為8位
dcb.Parity=m_nParity ;//無(wú)校驗(yàn)位
dcb.StopBits=m_nStopBits;//停止位為1位
switch(m_nParity) // 校驗(yàn)設(shè)置
{
case 0:
dcb.Parity=NOPARITY;
break;
case 1:
dcb.Parity=EVENPARITY;
break;
case 2:
dcb.Parity=ODDPARITY;
break;
。。。。。。。。
全部源碼可從51hei下載。
51hei.png (11.3 KB, 下載次數(shù): 64)
下載附件
2021-10-19 00:57 上傳
代碼下載:
智能電表科陸抄表系統(tǒng).7z
(12.12 MB, 下載次數(shù): 49)
2021-10-19 01:00 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|