如何在 C++ 中同时连接 2 个 RFID 阅读器? [关闭]
Posted
技术标签:
【中文标题】如何在 C++ 中同时连接 2 个 RFID 阅读器? [关闭]【英文标题】:How to connect 2 RFID Reader simultaneously in C++? [closed] 【发布时间】:2014-08-20 10:13:19 【问题描述】:我有 2 个 RFID 阅读器。
读者 1:port=com4
和 baud=9600
读者 2:port=com9
和 baud=9600
我想同时连接 2 个 RFID 阅读器。但是,即使我在代码中实例化了两个阅读器,我也只能访问两个阅读器之一。
我执行以下操作:
MifareOne.CPP
MifareOne::MifareOne()
LoadDll();
MifareOne::~MifareOne()
CloseComm();
CloseDll();
bool IsLoadDLL = false;
bool MifareOne::LoadDll()
if (IsLoadDLL)
return true;
// TODO: Add extra initialization here
TCHAR szBuf[MAX_PATH];
GetModuleFileName(NULL, (LPTSTR)szBuf, MAX_PATH);
sprintf(szBuf, "../../../CardReader\\MasterRD.dll");
m_hInstMaster = LoadLibrary(_T(szBuf));
if (m_hInstMaster)
IsLoadDLL = true;
(FARPROC&)lib_ver = GetProcAddress(m_hInstMaster, _T("lib_ver"));
(FARPROC&)des_encrypt = GetProcAddress(m_hInstMaster, _T("des_encrypt"));
(FARPROC&)des_decrypt = GetProcAddress(m_hInstMaster, _T("des_decrypt"));
(FARPROC&)rf_init_com = GetProcAddress(m_hInstMaster, _T("rf_init_com"));
(FARPROC&)rf_init_device_number = GetProcAddress(m_hInstMaster, _T("rf_init_device_number"));
(FARPROC&)rf_get_device_number = GetProcAddress(m_hInstMaster, _T("rf_get_device_number"));
(FARPROC&)rf_get_model = GetProcAddress(m_hInstMaster, _T("rf_get_model"));
(FARPROC&)rf_get_snr = GetProcAddress(m_hInstMaster, _T("rf_get_snr"));
(FARPROC&)rf_beep = GetProcAddress(m_hInstMaster, _T("rf_beep"));
(FARPROC&)rf_init_sam = GetProcAddress(m_hInstMaster, _T("rf_init_sam"));
(FARPROC&)rf_sam_rst = GetProcAddress(m_hInstMaster, _T("rf_sam_rst"));
(FARPROC&)rf_sam_cos = GetProcAddress(m_hInstMaster, _T("rf_sam_cos"));
(FARPROC&)rf_init_type = GetProcAddress(m_hInstMaster, _T("rf_init_type"));
(FARPROC&)rf_antenna_sta = GetProcAddress(m_hInstMaster, _T("rf_antenna_sta"));
(FARPROC&)rf_request = GetProcAddress(m_hInstMaster, _T("rf_request"));
(FARPROC&)rf_anticoll = GetProcAddress(m_hInstMaster, _T("rf_anticoll"));
(FARPROC&)rf_select = GetProcAddress(m_hInstMaster, _T("rf_select"));
(FARPROC&)rf_halt = GetProcAddress(m_hInstMaster, _T("rf_halt"));
(FARPROC&)rf_download_key = GetProcAddress(m_hInstMaster, _T("rf_download_key"));
(FARPROC&)rf_M1_authentication1 = GetProcAddress(m_hInstMaster, _T("rf_M1_authentication1"));
(FARPROC&)rf_M1_authentication2 = GetProcAddress(m_hInstMaster, _T("rf_M1_authentication2"));
(FARPROC&)rf_M1_read = GetProcAddress(m_hInstMaster, _T("rf_M1_read"));
(FARPROC&)rf_M1_write = GetProcAddress(m_hInstMaster, _T("rf_M1_write"));
(FARPROC&)rf_M1_initval = GetProcAddress(m_hInstMaster, _T("rf_M1_initval"));
(FARPROC&)rf_M1_readval = GetProcAddress(m_hInstMaster, _T("rf_M1_readval"));
(FARPROC&)rf_M1_decrement = GetProcAddress(m_hInstMaster, _T("rf_M1_decrement"));
(FARPROC&)rf_M1_increment = GetProcAddress(m_hInstMaster, _T("rf_M1_increment"));
(FARPROC&)rf_M1_restore = GetProcAddress(m_hInstMaster, _T("rf_M1_restore"));
(FARPROC&)rf_M1_transfer = GetProcAddress(m_hInstMaster, _T("rf_M1_transfer"));
(FARPROC&)rf_typea_rst = GetProcAddress(m_hInstMaster, _T("rf_typea_rst"));
(FARPROC&)rf_cos_command = GetProcAddress(m_hInstMaster, _T("rf_cos_command"));
(FARPROC&)rf_atqb = GetProcAddress(m_hInstMaster, _T("rf_atqb"));
(FARPROC&)rf_attrib = GetProcAddress(m_hInstMaster, _T("rf_attrib"));
(FARPROC&)rf_typeb_cos = GetProcAddress(m_hInstMaster, _T("rf_typeb_cos"));
(FARPROC&)rf_hltb = GetProcAddress(m_hInstMaster, _T("rf_hltb"));
(FARPROC&)rf_at020_check = GetProcAddress(m_hInstMaster, _T("rf_at020_check"));
(FARPROC&)rf_at020_read = GetProcAddress(m_hInstMaster, _T("rf_at020_read"));
(FARPROC&)rf_at020_write = GetProcAddress(m_hInstMaster, _T("rf_at020_write"));
(FARPROC&)rf_at020_lock = GetProcAddress(m_hInstMaster, _T("rf_at020_lock"));
(FARPROC&)rf_at020_count = GetProcAddress(m_hInstMaster, _T("rf_at020_count"));
(FARPROC&)rf_at020_deselect = GetProcAddress(m_hInstMaster, _T("rf_at020_deselect"));
(FARPROC&)rf_light = GetProcAddress(m_hInstMaster, _T("rf_light"));
(FARPROC&)rf_ClosePort = GetProcAddress(m_hInstMaster, _T("rf_ClosePort"));
(FARPROC&)rf_GetErrorMessage = GetProcAddress(m_hInstMaster, _T("rf_GetErrorMessage"));
if (NULL == lib_ver ||
NULL == des_encrypt ||
NULL == des_decrypt ||
NULL == rf_init_com ||
NULL == rf_init_device_number ||
NULL == rf_get_device_number ||
NULL == rf_get_model ||
NULL == rf_beep ||
NULL == rf_init_sam ||
NULL == rf_sam_rst ||
NULL == rf_sam_cos ||
NULL == rf_init_type ||
NULL == rf_antenna_sta ||
NULL == rf_request ||
NULL == rf_anticoll ||
NULL == rf_select ||
NULL == rf_halt ||
NULL == rf_download_key ||
NULL == rf_M1_authentication1 ||
NULL == rf_M1_authentication2 ||
NULL == rf_M1_read ||
NULL == rf_M1_write ||
NULL == rf_M1_initval ||
NULL == rf_M1_readval ||
NULL == rf_M1_decrement ||
NULL == rf_M1_increment ||
NULL == rf_M1_restore ||
NULL == rf_M1_transfer ||
NULL == rf_typea_rst ||
NULL == rf_cos_command ||
NULL == rf_atqb ||
NULL == rf_attrib ||
NULL == rf_typeb_cos ||
NULL == rf_hltb ||
NULL == rf_at020_check ||
NULL == rf_at020_read ||
NULL == rf_at020_write ||
NULL == rf_at020_lock ||
NULL == rf_at020_count ||
NULL == rf_at020_deselect ||
NULL == rf_light ||
NULL == rf_ClosePort ||
NULL == rf_GetErrorMessage)
return false;
else
int err = GetLastError();
return false;
return true;
bool MifareOne::CloseDll()
if(m_hInstMaster)
FreeLibrary(m_hInstMaster);
lib_ver = NULL;
des_encrypt = NULL;
des_decrypt = NULL;
rf_init_com = NULL;
rf_init_device_number = NULL;
rf_get_device_number = NULL;
rf_get_model = NULL;
rf_beep = NULL;
rf_init_sam = NULL;
rf_sam_rst = NULL;
rf_sam_cos = NULL;
rf_init_type = NULL;
rf_antenna_sta = NULL;
rf_request = NULL;
rf_anticoll = NULL;
rf_select = NULL;
rf_halt = NULL;
rf_download_key = NULL;
rf_M1_authentication1 = NULL;
rf_M1_authentication2 = NULL;
rf_M1_read = NULL;
rf_M1_write = NULL;
rf_M1_initval = NULL;
rf_M1_readval = NULL;
rf_M1_decrement = NULL;
rf_M1_increment = NULL;
rf_M1_restore = NULL;
rf_M1_transfer = NULL;
rf_typea_rst = NULL;
rf_cos_command = NULL;
rf_atqb = NULL;
rf_attrib = NULL;
rf_typeb_cos = NULL;
rf_hltb = NULL;
rf_at020_check = NULL;
rf_at020_read = NULL;
rf_at020_write = NULL;
rf_at020_lock = NULL;
rf_at020_count = NULL;
rf_at020_deselect = NULL;
rf_light = NULL;
rf_ClosePort = NULL;
rf_GetErrorMessage = NULL;
m_hInstMaster = NULL;
return true;
return false;
bool MifareOne::OpenComm(int com, int baud)
//save port and baud
mCommPort = com;
mBandRate = baud;
//open port
int state = 1;
state = rf_init_com(com, baud);
if (state != LIB_SUCCESS)
rf_ClosePort();
return false;
return true; // return TRUE unless you set the focus to a control
bool IsCloseComm = false;
void MifareOne::CloseComm()
if (IsCloseComm)
return;
rf_ClosePort();
IsCloseComm = true;
int MifareOne::Write(unsigned char* strData)
WORD icdev = 0x0000;
unsigned char mode = 0x60; // key A
unsigned char secnr = '\x1';
int state;
unsigned char strKey[] = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 ;
int nSel = 1;
state = rf_M1_authentication2(icdev, mode, (secnr / 4) * 4, strKey);
if (state)
return -1;
unsigned char strEncryptData[MAX_RF_BUFFER];
state = Encrypt(strEncryptData, strData, (unsigned char*)Encrypt_Key);
if (state)
return -1;
state = rf_M1_write(icdev, secnr, strEncryptData);
if (state)
return -1;
return 1;
Main.CPP
int main(int argc, const char* argv[])
MifareOne cardReader1;
MifareOne cardReader2;
cardReader1.OpenComm(4, 9600);
cardReader2.OpenComm(9, 9600);
cardReader1.Write((unsigned char*) "testing"); // Not work
cardReader2.Request((unsigned char*) "testing"); // Work fine
【问题讨论】:
它是操作系统(可能还有设备和库)特定的。因此,请适当地标记您的问题。标准 C++11 不了解 RFID。 “同时”字面意思是同时。所以“同时连接 2 个阅读器”与“同时连接 1 个阅读器”是矛盾的 什么是“连接 RFID 阅读器”?你称之为“同时”应该发生什么? 我正在使用计算机通过 COM 端口连接 2 个 RFID 阅读器。如果我只连接一个 RFID 阅读器,那么它工作正常(读取和写入数据都可以)。如果我连接 2 个 RFID 阅读器,那么稍后连接的读卡器可以正常工作! 编程问题是什么?我们可以知道您尝试了什么,您的问题是什么?很多代码让我们不知道真正的底层问题...... 【参考方案1】:您的问题是您用于访问 RFID 设备的 DLL 一次只支持访问一个设备。您对MifareOne::OpenComm
方法进行的两次调用中的每一次调用都在同一MasterRD.dll
中调用同一rf_init_com
函数。 rf_init_com
方法不返回任何可用于区分多个连接的句柄,因此您的 MifareOne::Write
方法无法告诉 DLL 您要使用两个连接中的哪一个。
鉴于 DLL 不允许您一次打开多个设备,因此您只有两种可能的解决方法。第一个在两个不同的进程中使用 DLL,每个进程与不同的 RFID 设备进行通信。在这种情况下,DLL 将在每个进程中具有单独的内部状态,允许您使用它在每个进程中打开不同的设备。然后,您必须使用 Windows 的众多进程间通信方法之一,以允许这两个进程相互协调或与主进程协调。
第二种是直接通过串口与RFID设备通话。 Windows 允许您同时打开在同一进程中打开的多个串行设备。使用此解决方法意味着您必须自己处理与设备通信的所有低级协议细节。您正在使用的 DLL 的相同低级详细信息旨在使您与您隔离。您还可能使用异步 I/O 或多线程来避免在从两个设备读取和写入时出现死锁。
【讨论】:
【参考方案2】:我能想到三种可能性。
首先,您正在使用Request()
方法测试一个阅读器,而另一个使用Write()
方法。可能是Write()
不正确。尝试为您的读者使用Request()
,看看会发生什么。
其次是您的 COM 端口错误。打开您的设备管理器并确定您的设备在哪些端口上运行。验证您是否使用了正确的端口在插入它们之后。
第三,另一个程序(可能是您的软件的旧版本)正在使用 COM 端口。尝试重新启动计算机或以其他方式检查端口是否正在使用中。
【讨论】:
【参考方案3】:阅读器 DLL 的界面看起来好像一次只支持一个阅读器。一个明显的迹象是 API 函数不使用可以跟踪两个同时会话的句柄。
例如,
cardReader1.OpenComm(4, 9600);
导致以下 API 调用:
state = rf_init_com(4, 9600);
成功时state
为 0。因此,没有“句柄”可以用来跟踪这个特定的rf_init_com
调用。
所以如果你下次使用
cardReader2.OpenComm(9, 9600);
打开第二个读卡器的端口。这将导致以下 API 调用:
state = rf_init_com(9, 9600);
由于 DLL 不跟踪多个连接,现在可能会发生两种情况:
-
第一个连接被第二个连接丢弃,或者
第二个连接请求将被忽略,因为与第一个读取器之间的连接仍然打开。
因此,一旦您对两个MifareOne
对象都使用了OpenComm
,对这两个对象的调用将要么转到第二个(案例1)要么转到第一个(案例2)阅读器。具体来说,如果您查看由于
cardReader1.Write((unsigned char*) "testing");
和
cardReader2.Write((unsigned char*) "testing");
您会看到这两种方法都会导致相同的 API 调用:
state = rf_M1_authentication2(icdev, mode, (secnr / 4) * 4, strKey);
state = rf_M1_write(icdev, secnr, strEncryptData);
所以 DLL 不可能区分这两个阅读器。
因此,在我看来,DLL 的设计初衷不是供多个阅读器使用。
【讨论】:
以上是关于如何在 C++ 中同时连接 2 个 RFID 阅读器? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Linux 上通过 C++ 中的串行接口与 Arduino 通信?