您的位置:首页 > 其它

一个VC读写刷卡器的例子

2008-10-01 11:42 232 查看
    这个程序是2006年编写的,用来读写金诚信刷卡器,提供了IDispatch接口,可以在VB或网页中使中。

    由于这是我第一次用VC写程序,所以程序流程和注释不太详细,不过代码很简单,对希望利用VC读写串口的朋友有一定帮助。

    一、接口文件:

import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(9D6A9AC7-9C3E-46A1-859B-B1F2FCFBB320),
dual,
helpstring("ICard Interface"),
pointer_default(unique)
]
interface ICard : IDispatch
{
[id(1), helpstring("method Write")] HRESULT Write([in]long TrackIndex,[in]BSTR bstrValue,[out,retval]BOOL *pbResult);
[id(2), helpstring("method Read")] HRESULT Read([in]long TrackIndex,[out,retval]BSTR* pbstrValue);
[id(3), helpstring("method SetParameters")] HRESULT SetParameters(long lngComPort,long lngBaudRate);
[id(4), helpstring("method Reset")] HRESULT Reset();
[propget, id(5), helpstring("property ComPort")] HRESULT ComPort([out, retval] long *pVal);
[propput, id(5), helpstring("property ComPort")] HRESULT ComPort([in] long newVal);
};

[
uuid(19CB32FB-3424-48D1-AD65-572DE2BFD9EA),
version(1.0),
helpstring("MagCard 1.0 Type Library")
]
library MAGCARDLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");

[
uuid(05E20EF2-E3A8-4060-8837-8E9966354A1C),
helpstring("Card Class")
]
coclass Card
{
[default] interface ICard;
};
};


    二、头文件:

#ifndef __CARD_H_
#define __CARD_H_

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CCard
class ATL_NO_VTABLE CCard :
public CComObjectRootEx<CComSingleThreadModel>,
public IObjectSafetyImpl<CCard,INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>,
public CComCoClass<CCard, &CLSID_Card>,
public IDispatchImpl<ICard, &IID_ICard, &LIBID_MAGCARDLib>
{
public:
CCard();
~CCard();

DECLARE_REGISTRY_RESOURCEID(IDR_CARD)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CCard)
COM_INTERFACE_ENTRY(ICard)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()

// ICard
public:
STDMETHOD(get_ComPort)(/*[out, retval]*/ long *pVal);
STDMETHOD(put_ComPort)(/*[in]*/ long newVal);
STDMETHOD(Reset)();
STDMETHOD(SetParameters)(/*[in]*/long lngComPort,/*[in]*/long lngBaudRate);
STDMETHOD(Read)(/*[in]*/long TrackIndex,/*[out,retval]*/BSTR *pbstrValue);
STDMETHOD(Write)(/*[in]*/long TrackIndex,/*[in]*/BSTR bstrValue,/*[out,retval]*/BOOL *pbResult);

HANDLE hCom; //串口句柄
char m_szComName[15]; //串口名称,即COM1、COM2等。

long m_lComPort;
char m_szResetCtl[2]; //复位控制符
char m_szFormatCtl[5]; //数据格式:当第5位为31表示ISO格式,32表示IBM格式
char m_szStartPosCtl[4]; //起始位置:当第4位为36表示16,37表示20,38表示22,39表示25
char m_szDensityCtl[4]; //高密格式:第4位为48表示高密,4C表示低密
};

#endif //__CARD_H_


    三、体文件:

#include "stdafx.h"
#include "MagCard.h"
#include "Card.h"

/////////////////////////////////////////////////////////////////////////////
// CCard

CCard::CCard()
{
hCom = NULL;
m_lComPort = 0;
strcpy(m_szComName,"COM1");
SetParameters(1,9600);
}

CCard::~CCard()
{
if(hCom != NULL)
CloseHandle(hCom);
}

STDMETHODIMP CCard::Write(long TrackIndex, BSTR bstrValue, BOOL *pbResult)
{

if(hCom == NULL) return E_FAIL;

//定义写操作控制符
char m_Buff[127];
char m_StartWrite[] = {0x1B,'0',0x1B,'/0','/0','/0'}; //定义写操作头部控制符,随不同磁道而不同
char m_EndWrite[] = {0x1D,0x1B,'//',0x1B,'j','/0'}; //定义写操作尾部(即结束)控制符
switch(TrackIndex)
{
case 1:
m_StartWrite[3] = 'w';
break;
case 2:
m_StartWrite[3] = 't';
break;
default:
m_StartWrite[3] = 't';
m_StartWrite[4] = 'A';
}

//将头控制符、数据、尾控制符组装到一起
char szTemp[127];
CComBSTR bstrTemp(bstrValue);
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,bstrTemp.m_str,-1,szTemp,128,NULL,NULL);
memset(m_Buff,0,128);
strcat(m_Buff,m_StartWrite);
strcat(m_Buff,szTemp);
strcat(m_Buff,m_EndWrite);
bstrTemp.Empty();

//发送给刷卡器
DWORD dwCount;
WriteFile(hCom,m_Buff,strlen(m_Buff),&dwCount,NULL);//将数据写入指定磁道
Sleep(500); //等待500毫秒

//等待刷卡器返回结果
memset(m_Buff,0,127);
ReadFile(hCom,m_Buff,127,&dwCount,NULL);
FlushFileBuffers(hCom);
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); //清空全部缓冲区,PURGE_TXCLEAR发送缓冲区,PURGE_RXCLEAR接收缓冲区
return S_OK;
}

STDMETHODIMP CCard::Read(long TrackIndex, BSTR *pbstrValue)
{
if(hCom == NULL) return E_FAIL;
if(TrackIndex>3 ||TrackIndex <1) return E_FAIL;

//发送读准备操作控制符
DWORD dwCount;
char m_szRead[] = {0x1B,'0','/0'};
WriteFile(hCom,m_szRead,2,&dwCount,NULL);

//发送读取磁道数控制符
char m_szTrack[]={0x1B,'0',0x1B,'/0','/0','/0'};
switch(TrackIndex)
{
case 1: //第一磁道
m_szTrack[3] = 'r';
break;
case 2: //第二磁道
m_szTrack[3] = ']';
break;
default: //默认为第三磁道
m_szTrack[3] = 'T';
m_szTrack[4] = ']';
break;
}
WriteFile(hCom,m_szTrack,5,&dwCount,NULL);
Sleep(20);

//读取指定的磁道
char m_Buff[127];
memset(m_Buff,0,128);
ReadFile(hCom,m_Buff,127,&dwCount,NULL);

//解析读取的结果
if(dwCount>0)
{
m_Buff[dwCount] = '/0';
if(TrackIndex<3)
{
memcpy(m_Buff,&m_Buff[2],dwCount-4);
m_Buff[dwCount-4] = '/0';
}
else{
memcpy(m_Buff,&m_Buff[3],dwCount-5);
m_Buff[dwCount-5] = '/0';
}
}
else
m_Buff[0] = '/0';

//将结果返回给用户
CComBSTR bstrTemp;
bstrTemp.Append(m_Buff);
*pbstrValue = bstrTemp.Copy();
bstrTemp.Empty();

return S_OK;
}

STDMETHODIMP CCard::SetParameters(long lngComPort,long lngBaudRate)
{

if(hCom != NULL)
CloseHandle(hCom);

m_lComPort = lngComPort;
wsprintf(m_szComName,"COM%d",lngComPort);

hCom=CreateFile(m_szComName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);

if(hCom==(HANDLE)-1){
hCom = NULL;
return E_FAIL;
}

//设置串口通讯参数
DCB dcb;
GetCommState(hCom,&dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.StopBits = 0;
dcb.EofChar = 26;
dcb.fRtsControl = 0;
SetCommState(hCom,&dcb); //设置通讯参数

//设置读写超时参数
COMMTIMEOUTS tagCommTimeOuts ; //定义超时结构,并填写该结构
tagCommTimeOuts.ReadIntervalTimeout = 10;
tagCommTimeOuts.ReadTotalTimeoutMultiplier = 200;
tagCommTimeOuts.ReadTotalTimeoutConstant = 500; //总的读超时时间为ReadIntervalTimeout*ReadTotalTimeoutMultiplier+ReadTotalTimeoutConstant
tagCommTimeOuts.WriteTotalTimeoutConstant = 0;
tagCommTimeOuts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(hCom,&tagCommTimeOuts ) ;//设置读写操作所允许的超时

SetupComm(hCom,512,512); //设置串口输入和输出缓冲区均为128位
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); //清空全部缓冲区,PURGE_TXCLEAR发送缓冲区,PURGE_RXCLEAR接收缓冲区

//发送刷卡器控制符
DWORD dwCount;
char vFormat[] = {0x1B,'0',0x1B,'T','1'};
WriteFile(hCom,vFormat,5,&dwCount,NULL); //数据格式:最后一位1表示ISO,2表示IBM
char vDensity[]={0x1B,'0',0x1B,'H'};
WriteFile(hCom,vDensity,4,&dwCount,NULL); //第二磁道高密度:最后一位H表示高,L表示低
char vPos[]={0x1B,'0',0x1B,'6'};
WriteFile(hCom,vPos,4,&dwCount,NULL);//起始位置:最后一位为6表示16,7表示20,8表示22,9表示25

return S_OK;
}

STDMETHODIMP CCard::Reset()
{

if(hCom==NULL)
return E_FAIL;

DWORD dwCount;
char m_szControl[]={0x1B,'a','/0'};
WriteFile(hCom,m_szControl,3,&dwCount,NULL);
Sleep(200);

return S_OK;
}

STDMETHODIMP CCard::get_ComPort(long *pVal)
{
*pVal = m_lComPort;
return S_OK;
}

STDMETHODIMP CCard::put_ComPort(long newVal)
{
if(newVal >8 || newVal <1) return E_FAIL;

m_lComPort = newVal;
wsprintf(m_szComName,"COM%d",newVal);

return S_OK;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  VC6 串口通信 COM控件