概述
这里所说的读卡器是指一种电脑外部输入设备,能读出卡内的序列号,并通过串口输出至电脑,一些考勤刷卡系统、网吧管理系统等等。要进行串口编程前,需得了解相关的知识,可以多百度一下。以下是数据通信系统的基本构成图:
完整的通信系统包括发送端、接收端、转换数据的接口以及传送数据的实际信道或媒体
DTE(Data Terminal Equipment):发送与接收的节点
DSE(Data Switching Equipment):中间节点,负责数据转送工作
DCE(Data Communication Equipment ):负责数据与电气信号转换的设备
DTE与DCE间的数据传输线路通常使用RS-232
DTE与DSE间的媒体则包括了双绞线、同轴电缆、光纤或无线电等
本次实验所使用的读卡器是非接触式、RS8H10D型号10位序列号输出读卡器,通信格式为RS232(9600/1200,n,8,1,),ASCII编码,也可以在计算机设备管理器看到COM口的端口信息,如下图所示:
具体的API编程知识,可以参看这里:http://www.vckbase.com/document/viewdoc/?id=1734 下面是在CodeBlocks环境下编写的C++代码,没有用到多线程,因为同步阻塞即使用多线程,也无法比较好的中途结束掉阻塞过程。
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
HANDLE cardCommFile = INVALID_HANDLE_VALUE;
string cardCommName = "\\.\COM1";
cardCommFile = CreateFile(cardCommName.c_str(), //COM名称
GENERIC_READ, //只读模式
0, //不共享端口
NULL, //安全性属性结构
OPEN_EXISTING, //打开存在的设备
0, //0表示同步
0); //必须为0
if (cardCommFile == INVALID_HANDLE_VALUE)
{
cout<<"打开串口错误"<<endl;
return -1;
}
//获取文件类型
if (GetFileType(cardCommFile) != FILE_TYPE_CHAR)
{
CloseHandle(cardCommFile);
cardCommFile = INVALID_HANDLE_VALUE;
return -1;
}
//设置I/O缓冲区大小
if (!SetupComm(cardCommFile, 1024, 1024))
{
CloseHandle(cardCommFile);
cardCommFile = INVALID_HANDLE_VALUE;
cout<<"文件句柄不是通信句柄"<<endl;
return -1;
}
//清空串口缓冲区
PurgeComm(cardCommFile, PURGE_TXABORT + PURGE_RXABORT +
PURGE_TXCLEAR + PURGE_RXCLEAR);
//获取串口设置参数
DCB dcb = {0};
GetCommState(cardCommFile, &dcb);
//设置串口参数
dcb.BaudRate = 9600; //波特率
dcb.ByteSize = 8; //每字节位数
dcb.Parity = NOPARITY; //校验位
dcb.StopBits = ONESTOPBIT; //停止位
if (!SetCommState(cardCommFile, &dcb))
{
CloseHandle(cardCommFile);
cardCommFile = INVALID_HANDLE_VALUE;
cout<<"不能够设置串口参数"<<endl;
return -1;
}
//获取超时设置
COMMTIMEOUTS timeOuts = {0};
GetCommTimeouts(cardCommFile, &timeOuts);
//设置超时参数
timeOuts.ReadIntervalTimeout = MAXWORD;
timeOuts.ReadTotalTimeoutMultiplier = 0;
timeOuts.ReadTotalTimeoutConstant = 0;
SetCommTimeouts(cardCommFile, &timeOuts);
//读取卡号信息
char strBuffer[20];
memset(strBuffer, '