1. 程式人生 > >agooou [QQ:35327864, email: [email p

agooou [QQ:35327864, email: [email p

    我使用的是串列埠讀卡器,RFID卡是philips的Mifare-M1卡。操作讀卡器,就是操作串列埠裝置。串列埠裝置的基礎只是,請參考 https://www.ibm.com/developerworks/cn/linux/l-serials/ ,此文講得很詳細。
    在嵌入式平臺下,串列埠設定需要做得更全一些,以避免一些特殊字元問題。本文描述了一種用select進行非阻塞方式讀取的方法,方便了應用程式進行整合。
1,開啟串列埠
int open_comm (const char* device) {
    if (device == NULL) return -1;
    int fd = open (device, O_RDWR|O_NOCTTY|O_NDELAY);
    return fd;
}

2,設定串列埠
static int speed_arr[] = {B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
                          B38400, B19200, B9600, B4800, B2400, B1200, B300, };
static int name_arr[] = { 115200, 38400,  19200,  9600,  4800,  2400,  1200,  300,
                          38400,  19200,  9600, 4800, 2400, 1200,  300, };

int set_options (int fd, int speed, int databits, int stopbits, int parity) {
    struct termios options;
    int status = 0;
    if ((status = tcgetattr (fd, &options)) != 0) {
        ERROR ("fail: status=%d, %s", status, strerror (errno));
        return -1;
    }

    int bSpeed = -1;
    for (int i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
        if (speed == name_arr[i]) {
            bSpeed = speed_arr[i];
            break;
        }
    }
    if (bSpeed == -1) {
        ERROR ("wrong speed=%d", speed);
        return -1;
    }
    cfsetispeed (&options, bSpeed);
    cfsetospeed (&options, bSpeed);

    /*允許接收並且設定為本地模式*/
    options.c_cflag |= (CLOCAL|CREAD);

    /*設定資料位數*/
    options.c_cflag &= ~CSIZE;
    switch (databits)
    {
    case 7:
        options.c_cflag |= CS7;
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        ERROR ("Unsupported data size");
        return -1;
    }

    switch (parity)
    {
    case 'n':
    case 'N':
        options.c_cflag &= ~PARENB;   /* Clear parity enable */
        options.c_iflag &= ~INPCK;     /* Enable parity checking */
        break;
    case 'o':
    case 'O':
        options.c_cflag |= (PARODD | PARENB);  /* 設定為奇效驗*/
        options.c_iflag |= INPCK;             /* Disnable parity checking */
        break;
    case 'e':
    case 'E':
        options.c_cflag |= PARENB;     /* Enable parity */
        options.c_cflag &= ~PARODD;   /* 轉換為偶效驗*/
        options.c_iflag |= INPCK;       /* Disnable parity checking */
        break;
    case 'S':
    case 's':  /*as no parity*/
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        break;
    default:
        ERROR ("Unsupported parity");
        return -1;
    }

    /* 設定停止位*/
    switch (stopbits)
    {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        ERROR ("Unsupported stop bits");
        return -1;
    }

    /* Set input parity option */
    //if (parity != 'n')
    //  options.c_iflag |= INPCK;

    options.c_cc[VINTR] = 0;
    options.c_cc[VQUIT] = 0;
    options.c_cc[VERASE] = 0;
    options.c_cc[VKILL] = 0;
    options.c_cc[VEOF] = 0;
    options.c_cc[VTIME] = 1;
    options.c_cc[VMIN] = 0;
    options.c_cc[VSWTC] = 0;
    options.c_cc[VSTART] = 0;
    options.c_cc[VSTOP] = 0;
    options.c_cc[VSUSP] = 0;
    options.c_cc[VEOL] = 0;
    options.c_cc[VREPRINT] = 0;
    options.c_cc[VDISCARD] = 0;
    options.c_cc[VWERASE] = 0;
    options.c_cc[VLNEXT] = 0;
    options.c_cc[VEOL2] = 0;
    //options.c_cc[VTIME] = 150; // 15 seconds
    //options.c_cc[VMIN] = 0;

    tcflush (fd,TCIFLUSH); /* Update the options and do it NOW */
    if ((status = tcsetattr (fd,TCSANOW,&options)) != 0) {
        ERROR ("fail: status=%d, %s", status, strerror (errno));
        return -1;
    }
    return 0;
}



3,在一定超時時間內讀取資料
static int cmd_read_timeout (int fd, unsigned char* buf, int msec) {
    if (fd < 0 || buf == NULL) {
        ERROR ("fd = %d, buf=%p", fd, buf);
        return -1;
    }

    int maxfd = fd;
    fd_set fdread;

    FD_ZERO (&fdread);
    FD_SET (fd, &fdread);

    /* set a suitable timeout to play around with */
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = msec*1000;

    int nread = 0;
    int rc = select (maxfd+1, &fdread, NULL, NULL, &timeout);
    switch (rc) {
    case -1:
        ERROR ("error: %s", strerror (errno));
        /* select error */
        nread = -1;
        break;
    case 0:
        //DEBUG ("timeout!");
        nread = -1;
        break;
    default:
    {
        /* readable sockets */
        if (FD_ISSET (fd, &fdread)) {
            nread = read (fd, buf, 512);
            //DEBUG ("read(%d):%s\n", nread, buf);
            if ((buf[1] + 2) == nread) {
                // checksum
                unsigned char checksum = 0;
                for (int i = 0; i < nread; i++) {
                    checksum = checksum^buf[i];
                }
                if (checksum == 0) {
                    // get right command.
                } else {
                    nread = 0;
                }
            } else {
                // ERROR cmd lenght;
                DEBUG ("cmd length not right! got data len=%d, require=%d", nread, buf[1]+2);
                nread = 0;
            }
        } else {
            ERROR ("fd not set! maybe error!");
            nread = -1;
        }
        break;
    }
    }
    return nread;
}



4,讀取唯一的卡號和sector0上block1的資料。
//============================================
//  Command List, preamble + length + command
//============================================
static const unsigned char SelectCard[]=      {0xBA,0x02,0x01 };
static const unsigned char LoginSector0[]=    {0xBA,0x0A,0x02,0x00,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static const unsigned char LoginSector1[]=    {0xBA,0x0A,0x02,0x01,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static const unsigned char ReadBlock1[]=      {0xBA,0x03,0x03,0x01};
static const unsigned char WriteBlock1[]=     {0xBA,0x13,0x04,0x01,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
static const unsigned char ReadValue[]=       {0xBA,0x03,0x05,0x05};
static const unsigned char InitializeValue[]=   {0xBA,0x07,0x06,0x04,0x00,0x00,0x00,0x01};
static const unsigned char IncrementValue[]=  {0xBA,0x07,0x08,0x04,0x00,0x00,0x00,0x20};
static const unsigned char DecrementValue[]=  {0xBA,0x07,0x09,0x04,0x03,0x00,0x00,0x00};
static const unsigned char CopyValue[]=       {0xBA,0x04,0x0A,0x04,0x05};
static const unsigned char ReadULPage5[]=     {0xBA,0x03,0x10,0x05};
static const unsigned char WriteULPage5[]=    {0xBA,0x07,0x11,0x05,0x11,0x22,0x33,0x44};
static const unsigned char TurnOnRedLed[]=    {0xBA,0x03,0x40,0x01};
static const unsigned char TurnOffRedLed[]=   {0xBA,0x03,0x40,0x00};

static int wrap_data (unsigned char* dest, const unsigned char* src, int len) {
    if (dest == NULL || src == NULL || len == 0) return -1;
    memcpy (dest, src, len);
    unsigned char checksum = 0;
    for (int i = 0; i < len; i++) {
        checksum = checksum ^ src[i];
    }
    dest[len] = checksum;
    return 0;
}

int clear_comm (int fd) {
    tcflush(fd,TCIFLUSH);
    return 0;
}

int read_card_id_name (int fd, unsigned char* id, unsigned char* name) {
    if (id == NULL || name == NULL) return -1;
    unsigned char data_send[512] = {0};
    unsigned char data_recv[512] = {0};
    int nWrite = 0;
    int nRead = 0;

    tcflush(fd,TCIFLUSH);

    wrap_data (data_send, SelectCard, sizeof (SelectCard));
    nWrite = write (fd, data_send, sizeof (SelectCard) + 1);
    if ((nRead = cmd_read_timeout (fd, data_recv, 300)) <= 0) {
        return -1;
    }
    //DEBUG ("(%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", nRead, data_recv[0], data_recv[1], data_recv[2], data_recv[3], data_recv[4], data_recv[5], data_recv[6], data_recv[7], data_recv[8], data_recv[9]);
    if ((data_recv[2] != 0x01) || (data_recv[3] != 0)) {
        return -1;
    }

    int retcode = 0;
    unsigned char card_type = data_recv[data_recv[1]];
    switch (card_type) {
    case 1:
    case 4:
        memcpy (id, &data_recv[4], 4);
#if 1
        // verify password of sector0
        wrap_data (data_send, LoginSector0, sizeof (LoginSector0));
        nWrite = write (fd, data_send, sizeof (LoginSector0) + 1);
        if ((nRead = cmd_read_timeout (fd, data_recv, 300)) <= 0) {
            return -1;
        }
        if ((data_recv[2] != 0x02) || (data_recv[3] != 0x02)) {
            return -1;
        }

        // read data from block1
        wrap_data (data_send, ReadBlock1, sizeof (ReadBlock1));
        nWrite = write (fd, data_send, sizeof (ReadBlock1) + 1);
        if ((nRead = cmd_read_timeout (fd, data_recv, 300)) <= 0) {
            return -1;
        }
        if ((data_recv[2] != 0x03) || (data_recv[3] != 0)) {
            return -1;
        }
        memcpy (name, &data_recv[4], 16);
#endif
        retcode = 0;
        break;
    case 3:
        memcpy (id, &data_recv[4], 7);
        retcode = -1;
        break;
    case 2:
    case 5:
    case 6:
    default:
        retcode = -1;
        break;
    }
    if (retcode != 0) {
        return retcode;
    }
    // Glare Red Led to indicate working ok
    wrap_data (data_send, TurnOnRedLed, sizeof (TurnOnRedLed));
    nWrite = write (fd, data_send, sizeof (TurnOnRedLed) + 1);
    nRead = cmd_read_timeout (fd, data_recv, 300);
    usleep (200*1000);
    wrap_data (data_send, TurnOffRedLed, sizeof (TurnOffRedLed));
    nWrite = write (fd, data_send, sizeof (TurnOffRedLed) + 1);
    nRead = cmd_read_timeout (fd, data_recv, 300);

    return 0;
}

5,閃爍紅燈,提示操作成功。

int GlareLed (int fd) {
    int retcode = 0;
    unsigned char data_send[512] = {0};
    unsigned char data_recv[512] = {0};
    int nWrite = 0;
    int nRead = 0;

    // Glare Red Led to indicate working ok
    wrap_data (data_send, TurnOnRedLed, sizeof (TurnOnRedLed));
    nWrite = write (fd, data_send, sizeof (TurnOnRedLed) + 1);
    nRead = cmd_read_timeout (fd, data_recv, 300);
    DEBUG ("get %d bytes", nRead);
    usleep (200*1000);
    wrap_data (data_send, TurnOffRedLed, sizeof (TurnOffRedLed));
    nWrite = write (fd, data_send, sizeof (TurnOffRedLed) + 1);
    nRead = cmd_read_timeout (fd, data_recv, 300);
    DEBUG ("get %d bytes", nRead);
    return 0;
}


6,主函式

int main(int argc, char **argv)
{
    const char *dev ="/dev/ttyUSB0";
    if (argc > 1) dev = argv[1];

    int fd = open (dev, O_RDWR|O_NOCTTY|O_NDELAY);         //| O_NOCTTY | O_NDELAY
    if (fd < 0) {
        ERROR ("Can't Open Serial Port");
        return -1;
    }
    if (set_options (fd, B115200, 8, 1, 'N') != 0) {
        ERROR ("Set Parity Error");
        close (fd);
        return -1;
    }

    while (1) {
        unsigned char id[10];
        unsigned char name[20];
        int ret = read_card_id_name (fd, id, name);
        if (ret == 0) {
            printf ("%02x%02x%02x%02x\n ", id[0], id[1], id[2], id[3]);
        }
        //GlareLed (fd);
        //DEBUG ("");
        //string content = getdata (fd);
        //printf ("%s", content.c_str ());
        //write(fd, "AT1", 3);
        usleep (300*1000);
    }
    close(fd);
    return 0;
}

7,遇到問題
在開發過程中,發現在嵌入式環境中,接收的資料經常會莫名丟失,0x13,0x11經常會不見了,丟失的都是這兩個數,後來加上如下這段就好了。
    options.c_cc[VINTR] = 0;
    options.c_cc[VQUIT] = 0;
    options.c_cc[VERASE] = 0;
    options.c_cc[VKILL] = 0;
    options.c_cc[VEOF] = 0;
    options.c_cc[VTIME] = 1;
    options.c_cc[VMIN] = 0;
    options.c_cc[VSWTC] = 0;
    options.c_cc[VSTART] = 0;
    options.c_cc[VSTOP] = 0;
    options.c_cc[VSUSP] = 0;
    options.c_cc[VEOL] = 0;
    options.c_cc[VREPRINT] = 0;
    options.c_cc[VDISCARD] = 0;
    options.c_cc[VWERASE] = 0;
    options.c_cc[VLNEXT] = 0;
    options.c_cc[VEOL2] = 0;

8,有問題可以聯絡 [email protected]

相關推薦

agooou [QQ:35327864, email: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5c3d3b333333291c3b313d3530723f3331">[email&#160;p

    我使用的是串列埠讀卡器,RFID卡是philips的Mifare-M1卡。操作讀卡器,就是操作串列埠裝置。串列埠裝置的基礎只是,請參考 https://www.ibm.com/developerworks/cn/linux/l-serials/ ,此文講得很詳細。

agooou [QQ:35327864, email: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e382848c8c8c96a3848e828a8fcd808c8e">[email&#160;p

        windows系統中,我們在開啟別人機器共享時,必須用一個使用者登入,若我們想用一個其他的使用者登入去檢視該使用者具有許可權的目錄時,經常會出現錯誤:(系統發生 1219 錯誤。提供的憑據與已存在的憑據集衝突。)        為什麼會出現這個錯誤呢?因為你的

agooou [QQ:35327864, email: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1475737b7b7b61547379757d783a777b79">[email&#160;p

作者 QQ: 35327864,msn: [email protected],mail: [email protected]   為了能在android平臺上播放全格式的多媒體檔案,我們需要自己做一個多媒體播放器。android自帶的opencore系統

agooou [QQ:35327864, email: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2140464e4e4e5461464c40484d0f424e4c">[email&#160;p

微信接入驗證Nodejs版例子程式 介紹 本程式按照微信公眾平臺開發者文件>開始開發>接入指南,進行開發。 微信使用第三方伺服器時要求配置伺服器 登入公眾平臺後,在 基本配置->填寫伺服器配置 中修改資訊時要求填寫的URL能正確

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7c35283c">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

一朵一花似吾意,一情一海透心骨。執之雲淡飄飄零,攜友日出日日憶。漸水未曾猶解渴,破衫未己身中寒。寥寥星星月眨光,枝枝葉葉樹憾藤。遙遞一疊千紙鶴,同日明月共相思。眷戀恩情久久重,相識逢意日日深。時光悄息落塵土,往事音訊今何在?但願君心知餘意,兩情投義友誼續。 一次吃飯,認識了

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="df968b9f">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.在百度翻譯平臺中,申請賬號,申請之後,會得到APP_ID和SECURITY_KEY 2.java程式碼如下 import net.sf.json.JSONObject; import com.

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ca839e8a">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.給input輸入框一個onchange="change()" 事件 <input type="text"  onchange="change()" name="username" value="${actionBean.map.username }" class=

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="61283521">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

 select * from   (select a.title,a.openurl,to_char(b.noticetime / (1000 * 60 * 60 * 24) + TO_DATE('1

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="541d0014">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.不正確引入springboot jstl的依賴包,可能會出現如下錯誤 The absolute uri: http://java.sun.com/jsp/jstl/core cannot be r

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b3fae7f3">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

select * from oa_schedule b where b.task_id in(  select a.wf_orunid from BPM.BPM_ArchivedData a   wh

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bbf2effb">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1新建一個readfilecallback.js //非同步式回撥函式; //定義一個讀取檔案回撥函式; function readfilecallback(err,data){ if(err){ c

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4d04190d">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

 //檔案上傳需要的引數    private File upload;//上傳的檔案 upload和在jsp檔案<input type="file" name="upload">name

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ade4f9ed">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

Documents and Settings是什麼檔案? 答案: 是系統使用者設定資料夾,包括各個使用者的文件、收藏夾、上網瀏覽資訊、配置檔案等。 補:這裡面的東西不要隨便刪除,這儲存著所有使用者的文件和賬戶設定,如果刪除就會重新啟動不能登陸的情況,尤其是裡面的default user、all users、a

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b2fbe6f2">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.新建一個Student的抽象類; package com.eduask.testabstract; //定義一個Student抽象類; public abstract class Student { public abstract void stu_Id(); pu

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f1b8a5b1">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.關閉mysql # service mysqld stop 2.遮蔽許可權 # mysqld_safe --skip-grant-table 3.新開起一個終端輸入 # mysql -

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7a332e3a">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.Java程式碼如下: package com.eduask; import java.io.IOException; import java.util.Date; import javax.servlet.ServletException; import j

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="50190410">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

述職報告 尊敬的領導: 您好!我是呂金含。我於2017年3月15日成為公司的試用員工。 目前在研發四部OA專案組工作,作為一名新進員工,我在同事們的幫助下很快地適應了研發四部開發的相關工作。初來公司的

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cd84998d">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

1.自己寫得小程式驗證宣告式異常處理的實現,就以表的查詢為例子。查詢表時我故意把表的名字寫錯。 2.在專案service包中,list方法。 3.在專案action包中,對應的list方法。 4.在strut.xml中新增如下: 5.在WebRoot下新建一個erro

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bcf5e8fc">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

   String  time="1477843200000";          long timeL =Long.parseLong(time);Date currentTime = new Da

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="60293420">[email&#160;protected]a>眾匯雲聚 QQ群:437393312

springboot亂碼現象可以用以下方法來解決,本人是以防萬一,所以都設定了。 1.jsp檔案編碼方式設定為UTF-8,如果新建的jsp檔案,預設不是utf-8,在eclipse中,設定新建的jsp