这里所说的读卡器是指一种电脑外部输入设备,能读出卡内的序列号,并通过串口输出至电脑,一些考勤刷卡系统、网吧管理系统等等。要进行串口编程前,需得了解相关的知识,可以多百度一下。以下是数据通信系统的基本构成图:

完整的通信系统包括发送端、接收端、转换数据的接口以及传送数据的实际信道或媒体
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, '\0', sizeof(strBuffer));
    DWORD nRead = 0;
    cout<<"请刷卡..."<<endl;
    if (!ReadFile(cardCommFile, strBuffer, 14, &nRead, NULL))   //14为此读卡器每次读取的数据长度
    {
        cout<<"读取串口数据失败"<<endl;
    }
    char strCard[20];
    memset(strCard, '\0', sizeof(strCard));
    memcpy(strCard, strBuffer + 1, 10); //取出中间10卡号
    cout<<strCard<<endl;
    PurgeComm(cardCommFile, PURGE_TXABORT + PURGE_RXABORT +
              PURGE_TXCLEAR + PURGE_RXCLEAR);
    CloseHandle(cardCommFile);
    cardCommFile = INVALID_HANDLE_VALUE;
    return 0;
}
运行结果如下:

参看文章:

1.Win32串口编程 http://www.vckbase.com/document/viewdoc/?id=1734


Logo

快速构建 Web 应用程序

更多推荐