• 4412 SPI驱动


    1.Linux主机驱动和外设驱动分离思想(I2C驱动里有)

    SPI驱动总线架构:SPI核心层(x),SPI控制器驱动层(x),SPI设备驱动层(√)。前面两个设备驱动搞明白了可以去看

    2.教程中介绍:SPI函数接口(API):

    简单介绍SPI协议,硬件原理(4412datasheet)

    3.教程中介绍:SPI函数接口(API):

    简单介绍SPI协议,硬件原理(4412datasheet)

    • SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选)
    • SPI(rfid模块)的硬件基础知识(增加reset)
    • SPI CLK管脚复用:Android4.0(wifi不能用)
    • rfid的驱动配置:
      • Device Drivers
      • →SPI support
      • →SPI_RC522
    • can的驱动配置:
    • Networking support
      • →CAN bus subsystem support
      • →CAN Device Drivers
    • Platform CAN drivers with Netlink support(默认配置,不用动)
    • CAN_MCP251X

    设备注册:spi_board_info,spi_register_board_info

    驱动注册函数和结构体:spi_register_driver/spi_unregister_driver,spi_driver

    读写函数和结构体:spi_transfer和spi_message结构体,spi_async

    1.驱动“设备注册,驱动注册,probe,数据下传,数据上传”的小结

    虚拟平台:

    ①因为LED,蜂鸣器等等,因为这些驱动本身不是总线。所以都注册在虚拟平台总线上(platform_device)。

    ②然后platfrom_driver_register就是在驱动程序中使用了,注册时的platfrom_driver结构体中有name成员对应platform_device的名字。此结构当然还有probe,remove,suspend,resume等配套的功能接口。

    ③然后对LED来说,GPIO的操作基本是在probe中初始化。

    ④然后应用层如果需要调用,那么在probe里就需要注册杂项设备、字符设备等。

    I2C:

    ①I2C的设备注册和平台注册类似,都是在arc/arm/mach-exynos/mach-itop4412.c中完成的

    ②和平台设备类似,I2C使用的函数不一样罢了,而且结构体也是i2c_driver了

    ③I2C对硬件的传输,使用i2c_transfer结合i2c_msg

    ④然后应用层如果需要调用,那么需要注册杂项设备,和虚拟平台类似。

    SPI:

      基本和I2C类似不同的是操作硬件的函数,spi_transfer要配置一下,然后传输用spi_sync。SPI让应用层调用使用字符设备。

    2.设备-SPI设备注册一级设备注册之后的查询方法

    配置SPI的内核之后可以用,查询到

    [root@iTOP-4412]# cat sys/bus/spi/devices/spi2.0/modalias                              
    rc522

    SPI_board_info参数

    spi_board_info参数
        .modalias = "rc522",    //初始化设备的名称
        .platform_data = NULL,    
        .max_speed_hz = 10*1000*1000,    //初始化传输速率
        .bus_num = 2,        //控制器编号
        .chip_select = 0,    //控制器片选的编号
        .mode = SPI_MODE_0,    //spi的模式
        .controller_data = &spi2_csi[0],    //片选IO的信息

    spi2_board_info设备描述结构体,设备注册函数spi_register_board_info

    增加一个spi设备my_rc522,然后去掉rfid和can驱动

    /* add by cym 20141222 for RC522 RFID */
    #ifdef CONFIG_SPI_RC522
            {
                    .modalias = "rc522",
                    .platform_data = NULL,
                    .max_speed_hz = 10*1000*1000,
                    .bus_num = 2,
                    .chip_select = 0,
                    .mode = SPI_MODE_0,
                    .controller_data = &spi2_csi[0],
            }
    #endif
    /* end add */
    /* add by ct 2018825 */
            {
                    .modalias = "my_rc522",
                    .platform_data = NULL,
                    .max_speed_hz = 10*1000*1000,
                    .bus_num = 2,
                    .chip_select = 0,
                    .mode = SPI_MODE_0,
                    .controller_data = &spi2_csi[0],
            }
    /* end add */
    mach-itop4412.c

    cat sys/bus/spi/devices/spi2.0/modalias
    rfid的设备名称my_rc522

    3.驱动-spi驱动注册和卸载。I2C设备初始化完成-进入probe函数。(不能加载wifi驱动)

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/ioctl.h>
    #include <linux/fs.h>
    #include <linux/device.h>
    #include <linux/err.h>
    #include <linux/list.h>
    #include <linux/errno.h>
    #include <linux/mutex.h>
    #include <linux/slab.h>
    #include <linux/compat.h>
    
    #include <linux/spi/spi.h>
    #include <linux/spi/spidev.h>
    
    #include <asm/uaccess.h>
    
    #include <linux/gpio.h>
    #include <mach/gpio.h>
    #include <plat/gpio-cfg.h>
    #include <linux/delay.h>
    
    static int __devinit my_rc522_probe(struct spi_device *spi)
    {
        /* reset */
        printk(KERN_EMERG "my_rc522_probe!
    ");
    
    
        return 0;
    }
    
    static int __devexit my_rc522_remove(struct spi_device *spi)
    {
        printk(KERN_EMERG "my_rc522_remove!
    ");
        return 0;
    }
    
    static struct spi_driver my_rc522_spi_driver = {
        .driver = {
            .name = "my_rc522",
            .owner = THIS_MODULE,
        },
        .probe = my_rc522_probe,
        .remove = __devexit_p(my_rc522_remove),
    };
    
    static int __init my_rc522_init(void)
    {
        spi_register_driver(&my_rc522_spi_driver);
        return 0;
    }
    
    static void __exit my_rc522_exit(void)
    {
        spi_unregister_driver(&my_rc522_spi_driver);
    }
    
    module_init(my_rc522_init);
    module_exit(my_rc522_exit);
    
    MODULE_AUTHOR("topeet: ct");
    MODULE_LICENSE("GPL");
    my_rc522.c

    4.驱动-spi数据的传输(rfid模块,不能加载wifi驱动)

    • 1.本节实验需要RFID的硬件模块
    • 2.1平台文件中RC522的设备名称直接改为my_rc522
    • 2.2需要配置rfid对应的menuconfig
    • 2.3 drivers/spi/Makefile中注释掉rc522.c文件的编译
    • 3.从rc522驱动中提取spi传输的核心代码
    • 4.直接在probe中做复位,读,写测试
      • 写:rc522_write→rc522_sync_write→rc522_sync→spi_async
      • 读:rc522_read→rc522_sync_read→rc522_sync→spi_async

     my_rc522

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/ioctl.h>
    #include <linux/fs.h>
    #include <linux/device.h>
    #include <linux/err.h>
    #include <linux/list.h>
    #include <linux/errno.h>
    #include <linux/mutex.h>
    #include <linux/slab.h>
    #include <linux/compat.h>
    #include <linux/spi/spi.h>
    #include <linux/spi/spidev.h>
    #include <asm/uaccess.h>
    #include <linux/gpio.h>
    #include <mach/gpio.h>
    #include <plat/gpio-cfg.h>
    #include <linux/delay.h>
    
    #include "spidev_test.h"
    #include "spidev.h"
    
    struct spi_device *my_spi;
    
    #define RC522_RESET_PIN    EXYNOS4_GPK1(0)
    void my_rc522_reset()
    {
        //printk("************************ %s
    ", __FUNCTION__);
        if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET"))
                    pr_err("failed to request GPK1_0 for RC522 reset control
    ");
    
            s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP);
            gpio_set_value(RC522_RESET_PIN, 0);
    
            mdelay(5);
    
            gpio_set_value(RC522_RESET_PIN, 1);
            gpio_free(RC522_RESET_PIN);
    }
    
    
    static int write_test(unsigned char *buffer, int len)
    {
        int status;
        struct spi_transfer    t = {
            .tx_buf        = buffer,
            .len        = len,
        };
        struct spi_message    m;
        spi_message_init(&m);
        spi_message_add_tail(&t, &m);
        DECLARE_COMPLETION_ONSTACK(done);
        m.complete = complete;
        m.context = &done;
        
        printk("spi_async send begin!
    ");
        status = spi_async(my_spi,&m);
        if(status == 0){
            wait_for_completion(&done);
            status = m.status;
            if (status == 0)
                status = m.actual_length;
        }
        return status;
    }
    
    static int read_test(unsigned char *buffer, int len)
    {
        int status;
        struct spi_transfer    t = {
            .rx_buf        = buffer,
            .len        = len,
        };
        struct spi_message    m;
        spi_message_init(&m);
        spi_message_add_tail(&t, &m);
        DECLARE_COMPLETION_ONSTACK(done);
        m.complete = complete;
        m.context = &done;
        
        printk("spi_async read begin!
    ");
        status = spi_async(my_spi,&m);
        if(status == 0){
            wait_for_completion(&done);
            status = m.status;
            if (status == 0)
                status = m.actual_length;
        }
        return status;
    }
    
    static unsigned char ReadRawRC(int addr)
    {
        int ret;
        unsigned char  ReData;
        unsigned char  Address;
        
        Address  = (unsigned char)addr << 1;
        Address |= (1 << 7);
        Address &= ~(1 << 0);
        
        ret = write_test(&Address, 1);
        if (ret < 0)
            printk("spi:SPI Write error
    ");
    
        udelay(100);
    
        ret = read_test(&ReData, 1);
        if (ret < 0)
            printk("spi:SPI Read error
    ");
    
        return ReData;
    }
    
    static int WriteRawRC(int addr, int data)
    {
        int ret;
        unsigned char  TxBuf[2];
    
        //bit7:MSB=0,bit6~1:addr,bit0:RFU=0
        TxBuf[0] = ((unsigned char)addr << 1)&0x7E;
        //TxBuf[0] &= 0x7E;
    
        TxBuf[1] = (unsigned char)data;
        
        ret = write_test(TxBuf, 2);
        
        if (ret < 0)
            printk("spi:SPI Write error
    ");
    
        udelay(10);
    
        return ret;
    }
    
    
    static int rc522_init()
    {
        int ret;
        char version = 0;
    
        //reset
        WriteRawRC(CommandReg, PCD_RESETPHASE);
        udelay(10);
        WriteRawRC(ModeReg, 0x3D);
        WriteRawRC(TReloadRegL, 30);
        WriteRawRC(TReloadRegH, 0);
        WriteRawRC(TModeReg, 0x8D);
        WriteRawRC(TPrescalerReg, 0x3E);
    
        version = ReadRawRC(VersionReg);
        printk("Chip Version: 0x%x
    ", version);
    
        return 0;
    }
    
    static int __devinit my_rc522_probe(struct spi_device *spi)
    {
        
        printk("my_rc522_probe!
    ");
        
        /* reset */
        my_rc522_reset();
        my_spi = spi;
        rc522_init();
        
        return 0;
    }
    
    static int __devexit my_rc522_remove(struct spi_device *spi)
    {
        printk("my_rc522_remove!
    ");
        return 0;
    }
    
    static struct spi_driver my_rc522_spi_driver = {
        .driver = {
            .name  = "my_rc522",
            .owner = THIS_MODULE,
        },
        .probe =    my_rc522_probe,
        .remove = __devexit_p(my_rc522_remove),
    
        /* NOTE:  suspend/resume methods are not necessary here.
         * We don't do anything except pass the requests to/from
         * the underlying controller.  The refrigerator handles
         * most issues; the controller driver handles the rest.
         */
    };
    
    
    static int __init my_rc522_init(void)
    {
        spi_register_driver(&my_rc522_spi_driver);
        return 0;
    }
    
    static void __exit my_rc522_exit(void)
    {
        spi_unregister_driver(&my_rc522_spi_driver);
    }
    
    module_exit(my_rc522_exit);
    module_init(my_rc522_init);
    
    
    MODULE_AUTHOR("topeet: rty");
    MODULE_LICENSE("GPL");
    my_rc522.c

    spidev.h

    /*
     * include/linux/spi/spidev.h
     *
     * Copyright (C) 2006 SWAPP
     *    Andrea Paterniani <a.paterniani@swapp-eng.it>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
      */
    
    #ifndef SPIDEV_H
    #define SPIDEV_H
    
    #include <linux/types.h>
    
    /* User space versions of kernel symbols for SPI clocking modes,
     * matching <linux/spi/spi.h>
     */
    
    #define SPI_CPHA        0x01
    #define SPI_CPOL        0x02
    
    #define SPI_MODE_0        (0|0)
    #define SPI_MODE_1        (0|SPI_CPHA)
    #define SPI_MODE_2        (SPI_CPOL|0)
    #define SPI_MODE_3        (SPI_CPOL|SPI_CPHA)
    
    #define SPI_CS_HIGH        0x04
    #define SPI_LSB_FIRST        0x08
    #define SPI_3WIRE        0x10
    #define SPI_LOOP        0x20
    #define SPI_NO_CS        0x40
    #define SPI_READY        0x80
    
    /*---------------------------------------------------------------------------*/
    
    /* IOCTL commands */
    
    #define SPI_IOC_MAGIC            'k'
    
    /**
     * struct spi_ioc_transfer - describes a single SPI transfer
     * @tx_buf: Holds pointer to userspace buffer with transmit data, or null.
     *    If no data is provided, zeroes are shifted out.
     * @rx_buf: Holds pointer to userspace buffer for receive data, or null.
     * @len: Length of tx and rx buffers, in bytes.
     * @speed_hz: Temporary override of the device's bitrate.
     * @bits_per_word: Temporary override of the device's wordsize.
     * @delay_usecs: If nonzero, how long to delay after the last bit transfer
     *    before optionally deselecting the device before the next transfer.
     * @cs_change: True to deselect device before starting the next transfer.
     *
     * This structure is mapped directly to the kernel spi_transfer structure;
     * the fields have the same meanings, except of course that the pointers
     * are in a different address space (and may be of different sizes in some
     * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel).
     * Zero-initialize the structure, including currently unused fields, to
     * accommodate potential future updates.
     *
     * SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync().
     * Pass it an array of related transfers, they'll execute together.
     * Each transfer may be half duplex (either direction) or full duplex.
     *
     *    struct spi_ioc_transfer mesg[4];
     *    ...
     *    status = ioctl(fd, SPI_IOC_MESSAGE(4), mesg);
     *
     * So for example one transfer might send a nine bit command (right aligned
     * in a 16-bit word), the next could read a block of 8-bit data before
     * terminating that command by temporarily deselecting the chip; the next
     * could send a different nine bit command (re-selecting the chip), and the
     * last transfer might write some register values.
     */
    struct spi_ioc_transfer {
        __u64        tx_buf;
        __u64        rx_buf;
    
        __u32        len;
        __u32        speed_hz;
    
        __u16        delay_usecs;
        __u8        bits_per_word;
        __u8        cs_change;
        __u32        pad;
    
        /* If the contents of 'struct spi_ioc_transfer' ever change
         * incompatibly, then the ioctl number (currently 0) must change;
         * ioctls with constant size fields get a bit more in the way of
         * error checking than ones (like this) where that field varies.
         *
         * NOTE: struct layout is the same in 64bit and 32bit userspace.
         */
    };
    
    /* not all platforms use <asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */
    #define SPI_MSGSIZE(N) 
        ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) 
            ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
    #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
    
    
    /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
    #define SPI_IOC_RD_MODE            _IOR(SPI_IOC_MAGIC, 1, __u8)
    #define SPI_IOC_WR_MODE            _IOW(SPI_IOC_MAGIC, 1, __u8)
    
    /* Read / Write SPI bit justification */
    #define SPI_IOC_RD_LSB_FIRST        _IOR(SPI_IOC_MAGIC, 2, __u8)
    #define SPI_IOC_WR_LSB_FIRST        _IOW(SPI_IOC_MAGIC, 2, __u8)
    
    /* Read / Write SPI device word length (1..N) */
    #define SPI_IOC_RD_BITS_PER_WORD    _IOR(SPI_IOC_MAGIC, 3, __u8)
    #define SPI_IOC_WR_BITS_PER_WORD    _IOW(SPI_IOC_MAGIC, 3, __u8)
    
    /* Read / Write SPI device default max speed hz */
    #define SPI_IOC_RD_MAX_SPEED_HZ        _IOR(SPI_IOC_MAGIC, 4, __u32)
    #define SPI_IOC_WR_MAX_SPEED_HZ        _IOW(SPI_IOC_MAGIC, 4, __u32)
    
    
    
    #endif /* SPIDEV_H */
    spidev.h

    spidev_test.h

    #define MAXRLEN        18
    #define MIN_STRENGTH  228
    //******************************************************************/
    //                    RC522 FIFO���ȶ���                            /
    //******************************************************************/
    #define DEF_FIFO_LENGTH             64           //FIFO size=64byte
    
    //******************************************************************/
    //                       RC522������                                /
    //******************************************************************/
    #define PCD_IDLE                  0x00           //ȡ����ǰ����
    #define PCD_AUTHENT               0x0E           //��֤��Կ
    #define PCD_RECEIVE               0x08           //��������
    #define PCD_TRANSMIT              0x04           //��������
    #define PCD_TRANSCEIVE            0x0C           //���Ͳ���������
    #define PCD_RESETPHASE            0x0F           //��λ
    #define PCD_CALCCRC               0x03           //CRC����
    
    //******************************************************************/
    //                   Mifare_One��Ƭ������                          */
    //******************************************************************/
    #define PICC_REQIDL               0x26           //Ѱ��������δ��������״̬
    #define PICC_REQALL               0x52           //Ѱ��������ȫ����
    #define PICC_ANTICOLL1            0x93           //����ײ
    #define PICC_ANTICOLL2            0x95           //����ײ
    #define PICC_AUTHENT1A            0x60           //��֤A��Կ
    #define PICC_AUTHENT1B            0x61           //��֤B��Կ
    #define PICC_READ                 0x30           //����
    #define PICC_WRITE                0xA0           //�
    #define PICC_DECREMENT            0xC0           //�ۿ�
    #define PICC_INCREMENT            0xC1           //��ֵ
    #define PICC_RESTORE              0xC2           //�������ݵ�������
    #define PICC_TRANSFER             0xB0           //���滺����������
    #define PICC_HALT                 0x50           //����
    
    //******************************************************************/
    //                        MF522�Ĵ�������                           /
    //******************************************************************/
    // PAGE 0
    #define     RFU00                 0x00    
    #define     CommandReg            0x01    
    #define     ComIEnReg             0x02    
    #define     DivlEnReg             0x03    
    #define     ComIrqReg             0x04    
    #define     DivIrqReg             0x05
    #define     ErrorReg              0x06    
    #define     Status1Reg            0x07    
    #define     Status2Reg            0x08    
    #define     FIFODataReg           0x09
    #define     FIFOLevelReg          0x0A
    #define     WaterLevelReg         0x0B
    #define     ControlReg            0x0C
    #define     BitFramingReg         0x0D
    #define     CollReg               0x0E
    #define     RFU0F                 0x0F
    // PAGE 1     
    #define     RFU10                 0x10
    #define     ModeReg               0x11
    #define     TxModeReg             0x12
    #define     RxModeReg             0x13
    #define     TxControlReg          0x14
    #define     TxASKReg              0x15
    #define     TxSelReg              0x16
    #define     RxSelReg              0x17
    #define     RxThresholdReg        0x18
    #define     DemodReg              0x19
    #define     RFU1A                 0x1A
    #define     RFU1B                 0x1B
    #define     MifareReg             0x1C
    #define     RFU1D                 0x1D
    #define     RFU1E                 0x1E
    #define     SerialSpeedReg        0x1F
    // PAGE 2    
    #define     RFU20                 0x20  
    #define     CRCResultRegM         0x21
    #define     CRCResultRegL         0x22
    #define     RFU23                 0x23
    #define     ModWidthReg           0x24
    #define     RFU25                 0x25
    #define     RFCfgReg              0x26
    #define     GsNReg                0x27
    #define     CWGsCfgReg            0x28
    #define     ModGsCfgReg           0x29
    #define     TModeReg              0x2A
    #define     TPrescalerReg         0x2B
    #define     TReloadRegH           0x2C
    #define     TReloadRegL           0x2D
    #define     TCounterValueRegH     0x2E
    #define     TCounterValueRegL     0x2F
    // PAGE 3      
    #define     RFU30                 0x30
    #define     TestSel1Reg           0x31
    #define     TestSel2Reg           0x32
    #define     TestPinEnReg          0x33
    #define     TestPinValueReg       0x34
    #define     TestBusReg            0x35
    #define     AutoTestReg           0x36
    #define     VersionReg            0x37
    #define     AnalogTestReg         0x38
    #define     TestDAC1Reg           0x39  
    #define     TestDAC2Reg           0x3A   
    #define     TestADCReg            0x3B   
    #define     RFU3C                 0x3C   
    #define     RFU3D                 0x3D   
    #define     RFU3E                 0x3E   
    #define     RFU3F          0x3F
    
    //******************************************************************/
    //                    RC522ͨѶ���ش������                         /
    //******************************************************************/
    #define MI_ERR                      0xFE 
    //#define MI_ERR                         //(-2)
    
    
    // Mifare Error Codes 
    // Each function returns a status value, which corresponds to the 
    // mifare error codes. 
    
    #define MI_OK                          0 
    #define MI_CHK_OK                      0 
    #define MI_CRC_ZERO                    0 
    
    #define MI_CRC_NOTZERO                 1 
    
    #define MI_NOTAGERR                 0xFF 
    #define MI_CHK_FAILED               0xFF 
    #define MI_CRCERR                   0xFE 
    #define MI_CHK_COMPERR              0xFE 
    #define MI_EMPTY                    0xFD 
    #define MI_AUTHERR                  0xFC 
    #define MI_PARITYERR                0xFB 
    #define MI_CODEERR                  0xFA 
    
    #define MI_SERNRERR                 0xF8 
    #define MI_KEYERR                   0xF7 
    #define MI_NOTAUTHERR               0xF6 
    #define MI_BITCOUNTERR              0xF5 
    #define MI_BYTECOUNTERR             0xF4 
    #define MI_IDLE                     0xF3 
    #define MI_TRANSERR                 0xF2 
    #define MI_WRITEERR                 0xF1 
    #define MI_INCRERR                  0xF0 
    #define MI_DECRERR                  0xEF 
    #define MI_READERR                  0xEE 
    #define MI_OVFLERR                  0xED 
    #define MI_POLLING                  0xEC 
    #define MI_FRAMINGERR               0xEB 
    #define MI_ACCESSERR                0xEA 
    #define MI_UNKNOWN_COMMAND          0xE9 
    #define MI_COLLERR                  0xE8 
    #define MI_RESETERR                 0xE7 
    #define MI_INITERR                  0xE7 
    #define MI_INTERFACEERR             0xE7 
    #define MI_ACCESSTIMEOUT            0xE5 
    #define MI_NOBITWISEANTICOLL        0xE4 
    #define MI_QUIT                     0xE2 
    
    #define MI_RECBUF_OVERFLOW          0xCF 
    #define MI_SENDBYTENR               0xCE 
    
    #define MI_SENDBUF_OVERFLOW         0xCC 
    #define MI_BAUDRATE_NOT_SUPPORTED   0xCB 
    #define MI_SAME_BAUDRATE_REQUIRED   0xCA 
    
    #define MI_WRONG_PARAMETER_VALUE    0xC5 
    
    #define MI_BREAK                    0x9E 
    #define MI_NY_IMPLEMENTED           0x9D 
    #define MI_NO_MFRC                  0x9C 
    #define MI_MFRC_NOTAUTH             0x9B 
    #define MI_WRONG_DES_MODE           0x9A 
    #define MI_HOST_AUTH_FAILED         0x99 
    
    #define MI_WRONG_LOAD_MODE          0x97 
    #define MI_WRONG_DESKEY             0x96 
    #define MI_MKLOAD_FAILED            0x95 
    #define MI_FIFOERR                  0x94 
    #define MI_WRONG_ADDR               0x93 
    #define MI_DESKEYLOAD_FAILED        0x92 
    
    #define MI_WRONG_SEL_CNT            0x8F 
    #define MI_RC531_WRONG_READVALUE    0x8E //LI ADDED 09-4-24 
    #define MI_WRONG_TEST_MODE          0x8C 
    #define MI_TEST_FAILED              0x8B 
    #define MI_TOC_ERROR                0x8A 
    #define MI_COMM_ABORT               0x89 
    #define MI_INVALID_BASE             0x88 
    #define MI_MFRC_RESET               0x87 
    #define MI_WRONG_VALUE              0x86 
    #define MI_VALERR                   0x85
    spidev_test.h

    5.Linux-spi利用字符驱动完成应用层对spi的读和写

     驱动:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/ioctl.h>
    #include <linux/fs.h>
    #include <linux/device.h>
    #include <linux/err.h>
    #include <linux/list.h>
    #include <linux/errno.h>
    #include <linux/mutex.h>
    #include <linux/slab.h>
    #include <linux/compat.h>
    #include <linux/spi/spi.h>
    #include <linux/spi/spidev.h>
    #include <asm/uaccess.h>
    #include <linux/gpio.h>
    #include <mach/gpio.h>
    #include <plat/gpio-cfg.h>
    #include <linux/delay.h>
    #include <linux/miscdevice.h>
    
    struct spi_device *my_spi;
    
    #define RC522_RESET_PIN    EXYNOS4_GPK1(0)
    void my_rc522_reset()
    {
        //printk("************************ %s
    ", __FUNCTION__);
        if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET"))
                    pr_err("failed to request GPK1_0 for RC522 reset control
    ");
    
            s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP);
            gpio_set_value(RC522_RESET_PIN, 0);
    
            mdelay(5);
    
            gpio_set_value(RC522_RESET_PIN, 1);
            gpio_free(RC522_RESET_PIN);
    }
    
    //static ssize_t rc522_write(unsigned char *buffer, int len)
    static ssize_t rc522_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
    {
        int status;
        unsigned char tx_buf[2];
        
        status = copy_from_user(tx_buf,buf,count);
        
        struct spi_transfer    t = {
            .tx_buf        = tx_buf,
            .len        = count,
        };
        struct spi_message    m;
        spi_message_init(&m);
        spi_message_add_tail(&t, &m);
        DECLARE_COMPLETION_ONSTACK(done);
        m.complete = complete;
        m.context = &done;
        
        printk("spi_async send begin!
    ");
        status = spi_async(my_spi,&m);
        if(status == 0){
            wait_for_completion(&done);
            status = m.status;
            if (status == 0)
                status = m.actual_length;
        }
        return status;
    }
    
    
    //static ssize_t rc522_read(unsigned char *buffer, int len)
    static ssize_t rc522_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
    {
        int status;
        unsigned char *rx_buf;
        
        struct spi_transfer    t = {
            .rx_buf        = &rx_buf,
            .len        = count,
        };
        struct spi_message    m;
        spi_message_init(&m);
        spi_message_add_tail(&t, &m);
        DECLARE_COMPLETION_ONSTACK(done);
        m.complete = complete;
        m.context = &done;
        
        printk("spi_async read begin!
    ");
        status = spi_async(my_spi,&m);
        if(status == 0){
            wait_for_completion(&done);
            status = m.status;
            if (status == 0)
                status = m.actual_length;
        }
        
        status = copy_to_user(buf,&rx_buf,status);
        
        return status;
    }
    
    int rc522_open(struct inode *inode,struct file *filp)
    {
        return 0;
    }
    
    
    
    static struct file_operations rc522_ops = {
        .owner     = THIS_MODULE,
        .open     = rc522_open,
        .read    = rc522_read,
        .write     = rc522_write,
    };
    
    static struct miscdevice rc522_dev = {
        .minor    = MISC_DYNAMIC_MINOR,
        .fops    = &rc522_ops,
        .name    = "rc522",
    };
    
    static int __devinit my_rc522_probe(struct spi_device *spi)
    {
        
        printk("my_rc522_probe!
    ");
        
        /* reset */
        my_rc522_reset();
        my_spi = spi;
        
        misc_register(&rc522_dev);
        
        return 0;
    }
    
    static int __devexit my_rc522_remove(struct spi_device *spi)
    {
        printk("my_rc522_remove!
    ");
        misc_deregister(&rc522_dev);    
        return 0;
    }
    
    static struct spi_driver my_rc522_spi_driver = {
        .driver = {
            .name  = "my_rc522",
            .owner = THIS_MODULE,
        },
        .probe =    my_rc522_probe,
        .remove = __devexit_p(my_rc522_remove),
    
        /* NOTE:  suspend/resume methods are not necessary here.
         * We don't do anything except pass the requests to/from
         * the underlying controller.  The refrigerator handles
         * most issues; the controller driver handles the rest.
         */
    };
    
    
    static int __init my_rc522_init(void)
    {
        spi_register_driver(&my_rc522_spi_driver);
        return 0;
    }
    
    static void __exit my_rc522_exit(void)
    {
        spi_unregister_driver(&my_rc522_spi_driver);
    }
    
    module_exit(my_rc522_exit);
    module_init(my_rc522_init);
    
    
    MODULE_AUTHOR("topeet: rty");
    MODULE_LICENSE("GPL");
    my_rc522.c

    app:

    /*
     * SPI testing utility (using spidev driver)
     *
     * Copyright (c) 2007  MontaVista Software, Inc.
     * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License.
     *
     * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
     */
    
    #include <stdint.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <getopt.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <linux/types.h>
    
    #include "spidev.h"
    #include "spidev_test.h"
    
    #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    
    static void pabort(const char *s)
    {
        perror(s);
        
        abort();
    }
    
    static const char *device = "/dev/rc522";
    static uint8_t mode;
    static uint8_t bits = 8;
    static uint32_t speed = 400 * 1000;//500000;
    static uint16_t delay;
    
    int g_SPI_Fd = 0;
    
    unsigned char UID[5], Temp[4];
    
    /*******************************************
    �������ƣ�tochar
    ��    �ܣ�����16���ƺ���
    ��    ����id
    ����ֵ  ����
    ********************************************/
    #if 0
    void tochar(unsigned char id)
    {
        switch(id) 
        {
        case 0x00:printf("00");break;
        case 0x01:printf("01");break;
        case 0x02:printf("02");break;
        case 0x03:printf("03");break;
        case 0x04:printf("04");break;
        case 0x05:printf("05");break;
        case 0x06:printf("06");break;
        case 0x07:printf("07");break;
        case 0x08:printf("08");break;
        case 0x09:printf("09");break;
        case 0x0a:printf("0a");break;
        case 0x0b:printf("0b");break;
        case 0x0c:printf("0c");break;
        case 0x0d:printf("0d");break;
        case 0x0e:printf("0e");break;
        case 0x0f:printf("0f");break;
        case 0x10:printf("10");break;
        case 0x11:printf("11");break;
        case 0x12:printf("12");break;
        case 0x13:printf("13");break;
        case 0x14:printf("14");break;
        case 0x15:printf("15");break;
        case 0x16:printf("16");break;
        case 0x17:printf("17");break;
        case 0x18:printf("18");break;
        case 0x19:printf("19");break;
        case 0x1a:printf("1a");break;
        case 0x1b:printf("1b");break;
        case 0x1c:printf("1c");break;
        case 0x1d:printf("1d");break;
        case 0x1e:printf("1e");break;
        case 0x1f:printf("1f");break;
        case 0x20:printf("20");break;
        case 0x21:printf("21");break;
        case 0x22:printf("22");break;
        case 0x23:printf("23");break;
        case 0x24:printf("24");break;
        case 0x25:printf("25");break;
        case 0x26:printf("26");break;
        case 0x27:printf("27");break;
        case 0x28:printf("28");break;
        case 0x29:printf("29");break;
        case 0x2a:printf("2a");break;
        case 0x2b:printf("2b");break;
        case 0x2c:printf("2c");break;
        case 0x2d:printf("2d");break;
        case 0x2e:printf("2e");break;
        case 0x2f:printf("2f");break;
        case 0x30:printf("30");break;
        case 0x31:printf("31");break;
        case 0x32:printf("32");break;
        case 0x33:printf("33");break;
        case 0x34:printf("34");break;
        case 0x35:printf("35");break;
        case 0x36:printf("36");break;
        case 0x37:printf("37");break;
        case 0x38:printf("38");break;
        case 0x39:printf("39");break;
        case 0x3a:printf("3a");break;
        case 0x3b:printf("3b");break;
        case 0x3c:printf("3c");break;
        case 0x3d:printf("3d");break;
        case 0x3e:printf("3e");break;
        case 0x3f:printf("3f");break;
        case 0x40:printf("40");break;
        case 0x41:printf("41");break;
        case 0x42:printf("42");break;
        case 0x43:printf("43");break;
        case 0x44:printf("44");break;
        case 0x45:printf("45");break;
        case 0x46:printf("46");break;
        case 0x47:printf("47");break;
        case 0x48:printf("48");break;
        case 0x49:printf("49");break;
        case 0x4a:printf("4a");break;
        case 0x4b:printf("4b");break;
        case 0x4c:printf("4c");break;
        case 0x4d:printf("4d");break;
        case 0x4e:printf("4e");break;
        case 0x4f:printf("4f");break;
        case 0x50:printf("50");break;
        case 0x51:printf("51");break;
        case 0x52:printf("52");break;
        case 0x53:printf("53");break;
        case 0x54:printf("54");break;
        case 0x55:printf("55");break;
        case 0x56:printf("56");break;
        case 0x57:printf("57");break;
        case 0x58:printf("58");break;
        case 0x59:printf("59");break;
        case 0x5a:printf("5a");break;
        case 0x5b:printf("5b");break;
        case 0x5c:printf("5c");break;
        case 0x5d:printf("5d");break;
        case 0x5e:printf("5e");break;
        case 0x5f:printf("5f");break;
        case 0x60:printf("60");break;
        case 0x61:printf("61");break;
        case 0x62:printf("62");break;
        case 0x63:printf("63");break;
        case 0x64:printf("64");break;
        case 0x65:printf("65");break;
        case 0x66:printf("66");break;
        case 0x67:printf("67");break;
        case 0x68:printf("68");break;
        case 0x69:printf("69");break;
        case 0x6a:printf("6a");break;
        case 0x6b:printf("6b");break;
        case 0x6c:printf("6c");break;
        case 0x6d:printf("6d");break;
        case 0x6e:printf("6e");break;
        case 0x6f:printf("6f");break;
        case 0x70:printf("70");break;
        case 0x71:printf("71");break;
        case 0x72:printf("72");break;
        case 0x73:printf("73");break;
        case 0x74:printf("74");break;
        case 0x75:printf("75");break;
        case 0x76:printf("76");break;
        case 0x77:printf("77");break;
        case 0x78:printf("78");break;
        case 0x79:printf("79");break;
        case 0x7a:printf("7a");break;
        case 0x7b:printf("7b");break;
        case 0x7c:printf("7c");break;
        case 0x7d:printf("7d");break;
        case 0x7e:printf("7e");break;
        case 0x7f:printf("7f");break;
        case 0x80:printf("80");break;
        case 0x81:printf("81");break;
        case 0x82:printf("82");break;
        case 0x83:printf("83");break;
        case 0x84:printf("84");break;
        case 0x85:printf("85");break;
        case 0x86:printf("86");break;
        case 0x87:printf("87");break;
        case 0x88:printf("88");break;
        case 0x89:printf("89");break;
        case 0x8a:printf("8a");break;
        case 0x8b:printf("8b");break;
        case 0x8c:printf("8c");break;
        case 0x8d:printf("8d");break;
        case 0x8e:printf("8e");break;
        case 0x8f:printf("8f");break;
        case 0x90:printf("90");break;
        case 0x91:printf("91");break;
        case 0x92:printf("92");break;
        case 0x93:printf("93");break;
        case 0x94:printf("94");break;
        case 0x95:printf("95");break;
        case 0x96:printf("96");break;
        case 0x97:printf("97");break;
        case 0x98:printf("98");break;
        case 0x99:printf("99");break;
        case 0x9a:printf("9a");break;
        case 0x9b:printf("9b");break;
        case 0x9c:printf("9c");break;
        case 0x9d:printf("9d");break;
        case 0x9e:printf("9e");break;
        case 0x9f:printf("9f");break;
        case 0xa0:printf("a0");break;
        case 0xa1:printf("a1");break;
        case 0xa2:printf("a2");break;
        case 0xa3:printf("a3");break;
        case 0xa4:printf("a4");break;
        case 0xa5:printf("a5");break;
        case 0xa6:printf("a6");break;
        case 0xa7:printf("a7");break;
        case 0xa8:printf("a8");break;
        case 0xa9:printf("a9");break;
        case 0xaa:printf("aa");break;
        case 0xab:printf("ab");break;
        case 0xac:printf("ac");break;
        case 0xad:printf("ad");break;
        case 0xae:printf("ae");break;
        case 0xaf:printf("af");break;
        case 0xb0:printf("b0");break;
        case 0xb1:printf("b1");break;
        case 0xb2:printf("b2");break;
        case 0xb3:printf("b3");break;
        case 0xb4:printf("b4");break;
        case 0xb5:printf("b5");break;
        case 0xb6:printf("b6");break;
        case 0xb7:printf("b7");break;
        case 0xb8:printf("b8");break;
        case 0xb9:printf("b9");break;
        case 0xba:printf("ba");break;
        case 0xbb:printf("bb");break;
        case 0xbc:printf("bc");break;
        case 0xbd:printf("bd");break;
        case 0xbe:printf("be");break;
        case 0xbf:printf("bf");break;
        case 0xc0:printf("c0");break;
        case 0xc1:printf("c1");break;
        case 0xc2:printf("c2");break;
        case 0xc3:printf("c3");break;
        case 0xc4:printf("c4");break;
        case 0xc5:printf("c5");break;
        case 0xc6:printf("c6");break;
        case 0xc7:printf("c7");break;
        case 0xc8:printf("c8");break;
        case 0xc9:printf("c9");break;
        case 0xca:printf("ca");break;
        case 0xcb:printf("cb");break;
        case 0xcc:printf("cc");break;
        case 0xcd:printf("cd");break;
        case 0xce:printf("ce");break;
        case 0xcf:printf("cf");break;
        case 0xd0:printf("d0");break;
        case 0xd1:printf("d1");break;
        case 0xd2:printf("d2");break;
        case 0xd3:printf("d3");break;
        case 0xd4:printf("d4");break;
        case 0xd5:printf("d5");break;
        case 0xd6:printf("d6");break;
        case 0xd7:printf("d7");break;
        case 0xd8:printf("d8");break;
        case 0xd9:printf("d9");break;
        case 0xda:printf("da");break;
        case 0xdb:printf("db");break;
        case 0xdc:printf("dc");break;
        case 0xdd:printf("dd");break;
        case 0xde:printf("de");break;
        case 0xdf:printf("df");break;
        case 0xe0:printf("e0");break;
        case 0xe1:printf("e1");break;
        case 0xe2:printf("e2");break;
        case 0xe3:printf("e3");break;
        case 0xe4:printf("e4");break;
        case 0xe5:printf("e5");break;
        case 0xe6:printf("e6");break;
        case 0xe7:printf("e7");break;
        case 0xe8:printf("e8");break;
        case 0xe9:printf("e9");break;
        case 0xea:printf("ea");break;
        case 0xeb:printf("eb");break;
        case 0xec:printf("ec");break;
        case 0xed:printf("ed");break;
        case 0xee:printf("ee");break;
        case 0xef:printf("ef");break;
        case 0xf0:printf("f0");break;
        case 0xf1:printf("f1");break;
        case 0xf2:printf("f2");break;
        case 0xf3:printf("f3");break;
        case 0xf4:printf("f4");break;
        case 0xf5:printf("f5");break;
        case 0xf6:printf("f6");break;
        case 0xf7:printf("f7");break;
        case 0xf8:printf("f8");break;
        case 0xf9:printf("f9");break;
        case 0xfa:printf("fa");break;
        case 0xfb:printf("fb");break;
        case 0xfc:printf("fc");break;
        case 0xfd:printf("fd");break;
        case 0xfe:printf("fe");break;
        case 0xff:printf("ff");break;
        default:
                  ;  
        }
    }
    #endif
    
    int WriteRawRC(int addr, int data)
    {
        int ret;
        int fd = g_SPI_Fd;
        unsigned char  TxBuf[2];
    
        //bit7:MSB=0,bit6~1:addr,bit0:RFU=0
        TxBuf[0] = ((unsigned char)addr << 1)&0x7E;
        //TxBuf[0] &= 0x7E;
    
        TxBuf[1] = (unsigned char)data;
        
        ret = write(fd, TxBuf, 2);
        if (ret < 0)
            printf("spi:SPI Write error
    ");
    
        usleep(10);
    
        return ret;
    }
    
    unsigned char ReadRawRC(int addr)
    {
        int ret;
        int fd = g_SPI_Fd;
        unsigned char  ReData;
        unsigned char  Address;
        
        Address  = (unsigned char)addr << 1;
        Address |= (1 << 7);
        Address &= ~(1 << 0);
        
        ret = write(fd, &Address, 1);
        if (ret < 0)
            printf("spi:SPI Write error
    ");
    
        usleep(100);
    
        ret = read(fd, &ReData, 1);
        if (ret < 0)
            printf("spi:SPI Read error
    ");
    
        return ReData;
    }
    
    void SetBitMask(unsigned char reg,unsigned char mask)  
    {
          char tmp = 0x0;
        
          tmp = ReadRawRC(reg) | mask;
        
          WriteRawRC(reg,tmp | mask);
    }
    
    //******************************************************************/
    //��    �ܣ���RC522�Ĵ���λ
    //����˵����reg[IN]:�Ĵ�����ַ
    //          mask[IN]:��λֵ
    //******************************************************************/
    void ClearBitMask(unsigned char reg, unsigned char mask)  
    {
        char tmp = 0x0;
        
        tmp = ReadRawRC(reg)&(~mask);
        
        WriteRawRC(reg, tmp);  // clear bit mask
    }
    
    int rc522_init()
    {
        int ret;
        char version = 0;
    
        //reset
        WriteRawRC(CommandReg, PCD_RESETPHASE);
        usleep(10);
        WriteRawRC(ModeReg, 0x3D);
        WriteRawRC(TReloadRegL, 30);
        WriteRawRC(TReloadRegH, 0);
        WriteRawRC(TModeReg, 0x8D);
        WriteRawRC(TPrescalerReg, 0x3E);
    
        version = ReadRawRC(VersionReg);
        printf("Chip Version: 0x%x
    ", version);
        usleep(50000);
    
        return 0;
    }
    
    void PcdAntennaOn()
    {
        unsigned char i;
      
        WriteRawRC(TxASKReg, 0x40);
          usleep(20);
      
        i = ReadRawRC(TxControlReg);
          if(!(i&0x03))
                SetBitMask(TxControlReg, 0x03);
          
        i = ReadRawRC(TxASKReg);
    }
    
    static void print_usage(const char *prog)
    {
        printf("Usage: %s [-DsbdlHOLC3]
    ", prog);
        puts("  -D --device   device to use (default /dev/spidev1.1)
    "
             "  -s --speed    max speed (Hz)
    "
             "  -d --delay    delay (usec)
    "
             "  -b --bpw      bits per word 
    "
             "  -l --loop     loopback
    "
             "  -H --cpha     clock phase
    "
             "  -O --cpol     clock polarity
    "
             "  -L --lsb      least significant bit first
    "
             "  -C --cs-high  chip select active high
    "
             "  -3 --3wire    SI/SO signals shared
    ");
        exit(1);
    }
    
    static void parse_opts(int argc, char *argv[])
    {
        while (1) {
            static const struct option lopts[] = {
                { "device",  1, 0, 'D' },
                { "speed",   1, 0, 's' },
                { "delay",   1, 0, 'd' },
                { "bpw",     1, 0, 'b' },
                { "loop",    0, 0, 'l' },
                { "cpha",    0, 0, 'H' },
                { "cpol",    0, 0, 'O' },
                { "lsb",     0, 0, 'L' },
                { "cs-high", 0, 0, 'C' },
                { "3wire",   0, 0, '3' },
                { "no-cs",   0, 0, 'N' },
                { "ready",   0, 0, 'R' },
                { NULL, 0, 0, 0 },
            };
            int c;
    
            c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
    
            if (c == -1)
                break;
    
            switch (c) {
            case 'D':
                device = optarg;
                break;
            case 's':
                speed = atoi(optarg);
                break;
            case 'd':
                delay = atoi(optarg);
                break;
            case 'b':
                bits = atoi(optarg);
                break;
            case 'l':
                mode |= SPI_LOOP;
                break;
            case 'H':
                mode |= SPI_CPHA;
                break;
            case 'O':
                mode |= SPI_CPOL;
                break;
            case 'L':
                mode |= SPI_LSB_FIRST;
                break;
            case 'C':
                mode |= SPI_CS_HIGH;
                break;
            case '3':
                mode |= SPI_3WIRE;
                break;
            case 'N':
                mode |= SPI_NO_CS;
                break;
            case 'R':
                mode |= SPI_READY;
                break;
            default:
                print_usage(argv[0]);
                break;
            }
        }
    }
    
    //******************************************************************/
    //��    �ܣ�ͨ��RC522��ISO14443��ͨѶ
    //����˵����Command[IN]:RC522������
    //          pInData[IN]:ͨ��RC522���͵���Ƭ������
    //          InLenByte[IN]:�������ݵ��ֽڳ���
    //          pOutData[OUT]:���յ��Ŀ�Ƭ��������
    //          *pOutLenBit[OUT]:�������ݵ�λ����
    //******************************************************************/
    char PcdComMF522(unsigned char Command, unsigned char *pInData, 
                                     unsigned char InLenByte, unsigned char *pOutData, 
                                     unsigned int  *pOutLenBit)
    {
        char status = MI_ERR;
        unsigned char irqEn  = 0x00;
        unsigned char waitFor = 0x00;
        unsigned char lastBits;
        unsigned char n;
        unsigned int  i;
        
        switch (Command)
        {
            case PCD_AUTHENT:
                  irqEn   = 0x12;
                  waitFor = 0x10;
                  break;
            case PCD_TRANSCEIVE:
                  irqEn   = 0x77;
                  waitFor = 0x30;
                  break;
            default:
                  break;
        }
        
        WriteRawRC(ComIEnReg, irqEn|0x80);
        ClearBitMask(ComIrqReg, 0x80);
        WriteRawRC(CommandReg, PCD_IDLE);
        SetBitMask(FIFOLevelReg, 0x80); // ���FIFO 
        for(i=0; i<InLenByte; i++)
            WriteRawRC(FIFODataReg, pInData[i]); // �����FIFO 
            
        WriteRawRC(CommandReg, Command); // ����д������Ĵ���
    
        if(Command == PCD_TRANSCEIVE)
            SetBitMask(BitFramingReg,0x80); // ��ʼ����     
    
        i = 6000; //����ʱ��Ƶ�ʵ���������M1�����ȴ�ʱ��25ms
          do 
        {
            n = ReadRawRC(ComIrqReg);
            i--;
        }
        while((i!=0)&&!(n&0x01)&&!(n&waitFor));
        
        ClearBitMask(BitFramingReg, 0x80);
    
        if(i!=0)
        {
            if(!(ReadRawRC(ErrorReg) & 0x1B))
            {
                status = MI_OK;
                if (n&irqEn&0x01)
                    status = MI_NOTAGERR;
                if(Command == PCD_TRANSCEIVE)
                {
                    n = ReadRawRC(FIFOLevelReg);
                    
                    lastBits = ReadRawRC(ControlReg) & 0x07;
                    if(lastBits)
                        *pOutLenBit = (n-1)*8 + lastBits;
                    else
                        *pOutLenBit = n*8;
    
                    if(n == 0)
                        n = 1;
                    if(n>MAXRLEN)
                        n = MAXRLEN;
    
                    for (i=0; i<n; i++)
                        pOutData[i] = ReadRawRC(FIFODataReg); 
                }
            }
            else
            {
                status = MI_ERR;
            }
        }
    
        SetBitMask(ControlReg, 0x80);// stop timer now
        WriteRawRC(CommandReg, PCD_IDLE); 
    
        return status;
    }
    
    char PcdRequest(unsigned char req_code, unsigned char *pTagType)
    {
        char status;  
        unsigned int  unLen;
        unsigned char ucComMF522Buf[MAXRLEN]; 
    
        ClearBitMask(Status2Reg, 0x08);
        WriteRawRC(BitFramingReg, 0x07);
        SetBitMask(TxControlReg, 0x03);
     
          ucComMF522Buf[0] = req_code;
    
          status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf,
                                           1, ucComMF522Buf, &unLen);
    
          if ((status == MI_OK) && (unLen == 0x10))
          {    
                *pTagType     = ucComMF522Buf[0];
                *(pTagType+1) = ucComMF522Buf[1];
          }
          else
        {
            status = MI_ERR;
          }
    
          return status;
    }
    
    //******************************************************************/
    //��    �ܣ�����ײ                                                  /
    //����˵��: pSnr[OUT]:��Ƭ���кţ�4�ֽ�                             /
    //��    ��: �ɹ�����MI_OK                                           /
    //******************************************************************/
    char PcdAnticoll(unsigned char *pSnr)
    {
        char status;
        unsigned char i, snr_check = 0;
        unsigned int  unLen;
        unsigned char ucComMF522Buf[MAXRLEN]; 
        
        ClearBitMask(Status2Reg, 0x08);
        WriteRawRC(BitFramingReg, 0x00);
        ClearBitMask(CollReg, 0x80);
     
        ucComMF522Buf[0] = PICC_ANTICOLL1;
        ucComMF522Buf[1] = 0x20;
    
            status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf,
                                    2, ucComMF522Buf, &unLen);
    
            if(status == MI_OK)
        {
            for (i=0; i<4; i++)
            {   
                *(pSnr+i)  = ucComMF522Buf[i];
                snr_check ^= ucComMF522Buf[i];
            }
            if (snr_check != ucComMF522Buf[i])
            {
                status = MI_ERR;
            }
        }
        
        SetBitMask(CollReg,0x80);
        
        return status;
    }
    
    void Find_Card(void)
    {
        if(PcdRequest(0x52, Temp) == MI_OK)
        {
              if(Temp[0]==0x04 && Temp[1]==0x00)  
                      printf("MFOne-S50
    ");
                else if(Temp[0]==0x02 && Temp[1] == 0x00)
                      printf("MFOne-S70
    ");
                else if(Temp[0]==0x44 && Temp[1]==0x00)
                      printf("MF-UltraLight
    ");
                else if(Temp[0]==0x08 && Temp[1]==0x00)
                      printf("MF-Pro
    ");
                else if(Temp[0]==0x44 && Temp[1]==0x03)
                      printf("MF Desire
    ");
                else
                      printf("Unknown
    ");
                
                printf("SUCCESS!
    ");
        }
        else
        {
            printf("No card!
    ");
        }
    }
    
    void Auto_Reader(void)
    {
        int i = 0;
        unsigned long num = 0;
        
      //    while(1)
        //{
            if(PcdRequest(0x52,Temp) == MI_OK)
            {
                if(Temp[0]==0x04 && Temp[1]==0x00)  
                    printf("MFOne-S50
    ");
                else if(Temp[0]==0x02 && Temp[1]==0x00)
                    printf("MFOne-S70
    ");
                else if(Temp[0]==0x44 && Temp[1]==0x00)
                    printf("MF-UltraLight
    ");
                else if(Temp[0]==0x08 && Temp[1]==0x00)
                    printf("MF-Pro
    ");
                else if(Temp[0]==0x44 && Temp[1]==0x03)
                    printf("MF Desire
    ");
                else
                    printf("Unknown
    ");
                
                if(PcdAnticoll(UID) == MI_OK)
                { 
                    printf("Card Id is(%d):", num++);
    #if 1
                    for(i=0; i<4; i++)
                        printf("%x", UID[i]);
    #else            
                    tochar(UID[0]);
                    tochar(UID[1]);
                    tochar(UID[2]);
                    tochar(UID[3]);
    #endif
                    printf("
    ");
                    
                    PcdRequest(0x52,Temp);//clear
                }
                else
                {
                    printf("no serial num read
    ");
                }
            }
            else
            {
                printf("No Card!
    ");
            }
    
            usleep(300000);
    //    } 
    }
    
    void HandleConfigMenu(unsigned char inputvalue)
    {
    #if 0
        switch(toupper(inputvalue)) 
        {
        case 'A':
                  Auto_Reader();
                  break;
        case 'F':
                  Find_Card();
                  break;
        default:
                  DisplayConfigMenu();
        }
    #endif
    
        //Find_Card();
    
        Auto_Reader();
    }
    
    int main(int argc, char *argv[])
    {
        unsigned char i;
        
        int ret = 0;
        int fd;
    
        parse_opts(argc, argv);
    
        fd = open(device, O_RDWR);
        if (fd < 0)
            pabort("can't open device");
    
        g_SPI_Fd = fd;
    
    #if 0
        /*
         * spi mode
         */
        ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
        if (ret == -1)
            pabort("can't set spi mode");
    
        ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
        if (ret == -1)
            pabort("can't get spi mode");
    
        /*
         * bits per word
         */
        ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
        if (ret == -1)
            pabort("can't set bits per word");
    
        ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
        if (ret == -1)
            pabort("can't get bits per word");
    
        /*
         * max speed hz
         */
        ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
        if (ret == -1)
            pabort("can't set max speed hz");
    
        ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
        if (ret == -1)
            pabort("can't get max speed hz");
    
        printf("spi mode: %d
    ", mode);
        printf("bits per word: %d
    ", bits);
        printf("max speed: %d Hz (%d KHz)
    ", speed, speed/1000);
    #endif
    
        rc522_init();
    
        PcdAntennaOn();
    
        HandleConfigMenu(i);
    
        close(fd);
    
        return ret;
    }
    spidev_test.c
  • 相关阅读:
    aptana中删除空行
    css预处理的引入与问题
    rsyslog 服务器重启后 发现不能接受到外部日志 只能接受本地日志 关闭防火墙即可
    php访问其他网站接口
    mysql 表查询结果 总行数计算
    linux centos 恢复 还原 备份 Snapper 快照说明
    linux 服务 启动 关闭 列表
    linux yum 安装 卸载
    php7 mysql_pconnect() 缺失 解决方法
    搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门
  • 原文地址:https://www.cnblogs.com/ch122633/p/9528760.html
Copyright © 2020-2023  润新知