嵌入式开发记录-day32 SPI总线下的 RFID模块rc522
1、SPI驱动总线架构:SPI核心层(x),SPI控制器驱动层(x),SPI设备驱动层(√),这里不详细说总线如何传输数据。
1、SPI核心层:代码在源码下:ls drivers/spi/*.o
2、SPI控制器驱动层:ls include/linux/spi/
3、SPI总线的四根线:
SPI_0_CLK:SPI传输数据的时钟信号;GPC1_1---->/SPI_2_CLK
SPI_0_nSS:片选使能控制端;BK_LED---->/SPI_2_nSS
SPI_0_MISO:总线传输数据线,master input slaver output,主机输入从机输出;I2C_AD6---->SPI_2_MISO
SPI_0_MOSI:总线传输数据线,主机输出从机输入;I2C_SCL6---->SPI_2_MOSI
模块需求GPIO:RST--->DC33_EN--->GPK1_0
4、RFID模块;(与mcp251x的can模块互斥)wifi不能不能使用
驱动配置: make menuconfig Device Drivers->SPI support->SPI_RC522
2、主要看SPI总线的接口
1、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的信息
2、spi2_board_info设备描述结构体,设备注册函数spi_register_board_info
3、Linux驱动的四部曲:
虚拟平台总线 | RS485(串口) | I2C | SPI(RFID) | |
设备注册 |
设备描述结构体platform_device 设备注册APIplatform_add_devices |
platform_device platform_add_devices |
i2c_board_info i2c_register_board_info |
spi_board_info spi_register_board_info |
驱动注册(probe) |
驱动描述结构体platform_driver 驱动注册APIplatform_driver_register |
platform_driver platform_driver_register |
i2c_driver i2c_add_driver |
spi_driver spi_register_driver |
传输API(数据下传,和硬件通信) | GPIO操作API、外部中断等等 | GPIO输出 |
i2c_msg i2c_transfer |
spi_transfer spi_sync |
数据上传(和文件系统上传) |
misc_register register_chrdev |
misc_register register_chrdev |
misc_register register_chrdev |
misc_register |
4、配置了SPI后,查询SPI模块
cat sys/bus/spi/devices/spi2.0/modalias 看到rc522
增加一个spi设备my_rc522(直接将RC522修改my_rc522),然后去掉rfid和can驱动(精英版不要这一步)
cat sys/bus/spi/devices/spi2.0/modalias
rfid的设备名称应该为my_rc522
#ifdef CONFIG_SPI_RC522
{
.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],
}
#endif
drivers/spi/Makefile中注释掉rc522.c文件的编译 // 取消内核中编译rc522的驱动
4.直接在probe中做复位,读,写测试
写:rc522_write→rc522_sync_write→rc522_sync→spi_async
读:rc522_read→rc522_sync_read→rc522_sync→spi_async
5、注册驱动和卸载
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/ioctl.h> 4 #include <linux/fs.h> 5 #include <linux/device.h> 6 #include <linux/err.h> 7 #include <linux/list.h> 8 #include <linux/errno.h> 9 #include <linux/mutex.h> 10 #include <linux/slab.h> 11 #include <linux/compat.h> 12 #include <linux/spi/spi.h> 13 #include <linux/spi/spidev.h> 14 #include <asm/uaccess.h> 15 #include <linux/gpio.h> 16 #include <mach/gpio.h> 17 #include <plat/gpio-cfg.h> 18 #include <linux/delay.h> 19 20 static int __devinit my_rc522_probe(struct spi_device *spi) 21 { 22 /* reset */ 23 //my_rc522_reset(); 24 printk("my_rc522_probe!\n"); // 看到输出这句话说明驱动注册成功 25 26 return 0; 27 } 28 29 static int __devexit my_rc522_remove(struct spi_device *spi) 30 { 31 printk("my_rc522_remove!\n"); 32 return 0; 33 } 34 35 static struct spi_driver my_rc522_spi_driver = { 36 .driver = { 37 .name = "my_rc522", 38 .owner = THIS_MODULE, 39 }, 40 .probe = my_rc522_probe, 41 .remove = __devexit_p(my_rc522_remove), 42 43 /* NOTE: suspend/resume methods are not necessary here. 44 * We don't do anything except pass the requests to/from 45 * the underlying controller. The refrigerator handles 46 * most issues; the controller driver handles the rest. 47 */ 48 }; 49 50 static int __init my_rc522_init(void) 51 { 52 spi_register_driver(&my_rc522_spi_driver); 53 return 0; 54 } 55 56 static void __exit my_rc522_exit(void) 57 { 58 spi_unregister_driver(&my_rc522_spi_driver); 59 } 60 61 module_exit(my_rc522_exit); 62 module_init(my_rc522_init); 63 64 MODULE_AUTHOR("topeet: rty"); 65 MODULE_LICENSE("GPL");
6、与rc522模块的数据传输,需要遵循模块所使用的SPI芯片协议,以及命令格式发送接收数据、从rc522驱动中提取spi传输的核心代码
读寄存器、写寄存器、读数据、写数据、建立连接、获取SPI芯片版本号
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/ioctl.h> 4 #include <linux/fs.h> 5 #include <linux/device.h> 6 #include <linux/err.h> 7 #include <linux/list.h> 8 #include <linux/errno.h> 9 #include <linux/mutex.h> 10 #include <linux/slab.h> 11 #include <linux/compat.h> 12 #include <linux/spi/spi.h> 13 #include <linux/spi/spidev.h> 14 #include <asm/uaccess.h> 15 #include <linux/gpio.h> 16 #include <mach/gpio.h> 17 #include <plat/gpio-cfg.h> 18 #include <linux/delay.h> 19 20 #include "spidev_test.h" // 包含外部头文件 21 #include "spidev.h" 22 23 struct spi_device *my_spi; // 接收返回来得设备 24 25 #define RC522_RESET_PIN EXYNOS4_GPK1(0) // 定义模块复位引脚 26 27 // 初始化RC522模块上电的时序 28 void my_rc522_reset() 29 { 30 //printk("************************ %s\n", __FUNCTION__); 31 if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET")) 32 pr_err("failed to request GPK1_0 for RC522 reset control\n"); 33 34 s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP); 35 gpio_set_value(RC522_RESET_PIN, 0); 36 37 mdelay(5); 38 39 gpio_set_value(RC522_RESET_PIN, 1); 40 gpio_free(RC522_RESET_PIN); 41 } 42 43 // 写一个寄存器 44 static int write_test(unsigned char *buffer, int len) 45 { 46 int status; 47 struct spi_transfer t = { 48 .tx_buf = buffer, 49 .len = len, 50 }; 51 struct spi_message m; 52 spi_message_init(&m); 53 spi_message_add_tail(&t, &m); 54 DECLARE_COMPLETION_ONSTACK(done); 55 m.complete = complete; 56 m.context = &done; 57 58 printk("spi_async send begin!\n"); 59 status = spi_async(my_spi,&m); 60 if(status == 0){ 61 wait_for_completion(&done); 62 status = m.status; 63 if (status == 0) 64 status = m.actual_length; 65 } 66 return status; 67 } 68 // 读一个寄存器 69 static int read_test(unsigned char *buffer, int len) 70 { 71 int status; 72 struct spi_transfer t = { 73 .rx_buf = buffer, 74 .len = len, 75 }; 76 struct spi_message m; 77 spi_message_init(&m); 78 spi_message_add_tail(&t, &m); 79 DECLARE_COMPLETION_ONSTACK(done); 80 m.complete = complete; 81 m.context = &done; 82 83 printk("spi_async read begin!\n"); 84 status = spi_async(my_spi,&m); 85 if(status == 0){ 86 wait_for_completion(&done); 87 status = m.status; 88 if (status == 0) 89 status = m.actual_length; 90 } 91 return status; 92 } 93 94 // 读数据 95 static unsigned char ReadRawRC(int addr) 96 { 97 int ret; 98 unsigned char ReData; 99 unsigned char Address; 100 101 Address = (unsigned char)addr << 1; 102 Address |= (1 << 7); 103 Address &= ~(1 << 0); 104 105 ret = write_test(&Address, 1); 106 if (ret < 0) 107 printk("spi:SPI Write error\n"); 108 109 udelay(100); 110 111 ret = read_test(&ReData, 1); 112 if (ret < 0) 113 printk("spi:SPI Read error\n"); 114 115 return ReData; 116 } 117 // 写数据 118 static int WriteRawRC(int addr, int data) 119 { 120 int ret; 121 unsigned char TxBuf[2]; 122 123 //bit7:MSB=0,bit6~1:addr,bit0:RFU=0 124 TxBuf[0] = ((unsigned char)addr << 1)&0x7E; 125 //TxBuf[0] &= 0x7E; 126 127 TxBuf[1] = (unsigned char)data; 128 129 ret = write_test(TxBuf, 2); 130 131 if (ret < 0) 132 printk("spi:SPI Write error\n"); 133 134 udelay(10); 135 136 return ret; 137 } 138 139 // 模块初始化 建立通信成功 140 static int rc522_init() 141 { 142 int ret; 143 char version = 0; 144 145 //reset 146 WriteRawRC(CommandReg, PCD_RESETPHASE); 147 udelay(10); 148 WriteRawRC(ModeReg, 0x3D); // 写寄存器值 149 WriteRawRC(TReloadRegL, 30); 150 WriteRawRC(TReloadRegH, 0); 151 WriteRawRC(TModeReg, 0x8D); 152 WriteRawRC(TPrescalerReg, 0x3E); 153 154 version = ReadRawRC(VersionReg); // 读取RFID模块所使用的芯片的版本 155 printk("Chip Version: 0x%x\n", version); 156 157 return 0; 158 } 159 160 static int __devinit my_rc522_probe(struct spi_device *spi) 161 { 162 163 printk("my_rc522_probe!\n"); 164 165 /* reset */ 166 my_rc522_reset(); // 初始化上电时序 167 my_spi = spi; // 将设备传出来 168 rc522_init(); // 模块初始化 确认建立通信成功 169 170 return 0; 171 } 172 173 static int __devexit my_rc522_remove(struct spi_device *spi) 174 { 175 printk("my_rc522_remove!\n"); 176 return 0; 177 } 178 179 static struct spi_driver my_rc522_spi_driver = { 180 .driver = { 181 .name = "my_rc522", 182 .owner = THIS_MODULE, 183 }, 184 .probe = my_rc522_probe, 185 .remove = __devexit_p(my_rc522_remove), 186 187 /* NOTE: suspend/resume methods are not necessary here. 188 * We don't do anything except pass the requests to/from 189 * the underlying controller. The refrigerator handles 190 * most issues; the controller driver handles the rest. 191 */ 192 }; 193 194 195 static int __init my_rc522_init(void) 196 { 197 spi_register_driver(&my_rc522_spi_driver); 198 return 0; 199 } 200 201 static void __exit my_rc522_exit(void) 202 { 203 spi_unregister_driver(&my_rc522_spi_driver); 204 } 205 206 module_exit(my_rc522_exit); 207 module_init(my_rc522_init); 208 209 210 MODULE_AUTHOR("topeet: rty"); 211 MODULE_LICENSE("GPL");
7、应用层传输数据的驱动
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/ioctl.h> 4 #include <linux/fs.h> 5 #include <linux/device.h> 6 #include <linux/err.h> 7 #include <linux/list.h> 8 #include <linux/errno.h> 9 #include <linux/mutex.h> 10 #include <linux/slab.h> 11 #include <linux/compat.h> 12 #include <linux/spi/spi.h> 13 #include <linux/spi/spidev.h> 14 #include <asm/uaccess.h> 15 #include <linux/gpio.h> 16 #include <mach/gpio.h> 17 #include <plat/gpio-cfg.h> 18 #include <linux/delay.h> 19 #include <linux/miscdevice.h> 20 21 struct spi_device *my_spi; 22 23 #define RC522_RESET_PIN EXYNOS4_GPK1(0) 24 void my_rc522_reset() 25 { 26 //printk("************************ %s\n", __FUNCTION__); 27 if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET")) 28 pr_err("failed to request GPK1_0 for RC522 reset control\n"); 29 30 s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP); 31 gpio_set_value(RC522_RESET_PIN, 0); 32 33 mdelay(5); 34 35 gpio_set_value(RC522_RESET_PIN, 1); 36 gpio_free(RC522_RESET_PIN); 37 } 38 39 //static ssize_t rc522_write(unsigned char *buffer, int len) 40 static ssize_t rc522_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) 41 { 42 int status; 43 unsigned char tx_buf[2]; 44 // 与应用层数据交互 45 status = copy_from_user(tx_buf,buf,count); 46 47 struct spi_transfer t = { 48 .tx_buf = tx_buf, 49 .len = count, 50 }; 51 struct spi_message m; 52 spi_message_init(&m); 53 spi_message_add_tail(&t, &m); 54 DECLARE_COMPLETION_ONSTACK(done); 55 m.complete = complete; 56 m.context = &done; 57 58 printk("spi_async send begin!\n"); 59 status = spi_async(my_spi,&m); 60 if(status == 0){ 61 wait_for_completion(&done); 62 status = m.status; 63 if (status == 0) 64 status = m.actual_length; 65 } 66 return status; 67 } 68 69 70 //static ssize_t rc522_read(unsigned char *buffer, int len) 71 static ssize_t rc522_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) 72 { 73 int status; 74 unsigned char *rx_buf; 75 76 struct spi_transfer t = { 77 .rx_buf = &rx_buf, 78 .len = count, 79 }; 80 struct spi_message m; 81 spi_message_init(&m); 82 spi_message_add_tail(&t, &m); 83 DECLARE_COMPLETION_ONSTACK(done); 84 m.complete = complete; 85 m.context = &done; 86 87 printk("spi_async read begin!\n"); 88 status = spi_async(my_spi,&m); 89 if(status == 0){ 90 wait_for_completion(&done); 91 status = m.status; 92 if (status == 0) 93 status = m.actual_length; 94 } 95 // 数据返回值应用 96 status = copy_to_user(buf,&rx_buf,status); 97 98 return status; 99 } 100 101 int rc522_open(struct inode *inode,struct file *filp) 102 { 103 return 0; 104 } 105 106 // 数据交互的文件系统 节点API 107 static struct file_operations rc522_ops = { 108 .owner = THIS_MODULE, 109 .open = rc522_open, 110 .read = rc522_read, 111 .write = rc522_write, 112 }; 113 114 // 使用杂项设备注册SPI模块,SPI有默认的节点 但是也可以使用杂项设备注册 115 static struct miscdevice rc522_dev = { 116 .minor = MISC_DYNAMIC_MINOR, 117 .fops = &rc522_ops, 118 .name = "rc522", 119 }; 120 121 static int __devinit my_rc522_probe(struct spi_device *spi) 122 { 123 124 printk("my_rc522_probe!\n"); 125 126 /* reset */ 127 my_rc522_reset(); 128 my_spi = spi; 129 130 misc_register(&rc522_dev); 131 132 return 0; 133 } 134 135 static int __devexit my_rc522_remove(struct spi_device *spi) 136 { 137 printk("my_rc522_remove!\n"); 138 misc_deregister(&rc522_dev); 139 return 0; 140 } 141 142 static struct spi_driver my_rc522_spi_driver = { 143 .driver = { 144 .name = "my_rc522", 145 .owner = THIS_MODULE, 146 }, 147 .probe = my_rc522_probe, 148 .remove = __devexit_p(my_rc522_remove), 149 150 /* NOTE: suspend/resume methods are not necessary here. 151 * We don't do anything except pass the requests to/from 152 * the underlying controller. The refrigerator handles 153 * most issues; the controller driver handles the rest. 154 */ 155 }; 156 157 158 static int __init my_rc522_init(void) 159 { 160 spi_register_driver(&my_rc522_spi_driver); 161 return 0; 162 } 163 164 static void __exit my_rc522_exit(void) 165 { 166 spi_unregister_driver(&my_rc522_spi_driver); 167 } 168 169 module_exit(my_rc522_exit); 170 module_init(my_rc522_init); 171 172 MODULE_AUTHOR("topeet: rty"); 173 MODULE_LICENSE("GPL");
8、应用获取模块数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 * SPI testing utility (using spidev driver) 3 * 4 * Copyright (c) 2007 MontaVista Software, Inc. 5 * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License. 10 * 11 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include 12 */ 13 14 #include <stdint.h> 15 #include <unistd.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <getopt.h> 19 #include <fcntl.h> 20 #include <sys/ioctl.h> 21 #include <linux/types.h> 22 23 #include "spidev.h" 24 #include "spidev_test.h" 25 26 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 27 28 static void pabort(const char *s) 29 { 30 perror(s); 31 32 abort(); 33 } 34 35 static const char *device = "/dev/rc522"; 36 static uint8_t mode; 37 static uint8_t bits = 8; 38 static uint32_t speed = 400 * 1000;//500000; 39 static uint16_t delay; 40 41 int g_SPI_Fd = 0; 42 43 unsigned char UID[5], Temp[4]; 44 45 /******************************************* 46 函数名称:tochar 47 功 能:处理16进制函数 48 参 数:id 49 返回值 :无 50 ********************************************/ 51 #if 0 52 void tochar(unsigned char id) 53 { 54 switch(id) 55 { 56 case 0x00:printf("00");break; 57 case 0x01:printf("01");break; 58 case 0x02:printf("02");break; 59 case 0x03:printf("03");break; 60 case 0x04:printf("04");break; 61 case 0x05:printf("05");break; 62 case 0x06:printf("06");break; 63 case 0x07:printf("07");break; 64 case 0x08:printf("08");break; 65 case 0x09:printf("09");break; 66 case 0x0a:printf("0a");break; 67 case 0x0b:printf("0b");break; 68 case 0x0c:printf("0c");break; 69 case 0x0d:printf("0d");break; 70 case 0x0e:printf("0e");break; 71 case 0x0f:printf("0f");break; 72 case 0x10:printf("10");break; 73 case 0x11:printf("11");break; 74 case 0x12:printf("12");break; 75 case 0x13:printf("13");break; 76 case 0x14:printf("14");break; 77 case 0x15:printf("15");break; 78 case 0x16:printf("16");break; 79 case 0x17:printf("17");break; 80 case 0x18:printf("18");break; 81 case 0x19:printf("19");break; 82 case 0x1a:printf("1a");break; 83 case 0x1b:printf("1b");break; 84 case 0x1c:printf("1c");break; 85 case 0x1d:printf("1d");break; 86 case 0x1e:printf("1e");break; 87 case 0x1f:printf("1f");break; 88 case 0x20:printf("20");break; 89 case 0x21:printf("21");break; 90 case 0x22:printf("22");break; 91 case 0x23:printf("23");break; 92 case 0x24:printf("24");break; 93 case 0x25:printf("25");break; 94 case 0x26:printf("26");break; 95 case 0x27:printf("27");break; 96 case 0x28:printf("28");break; 97 case 0x29:printf("29");break; 98 case 0x2a:printf("2a");break; 99 case 0x2b:printf("2b");break; 100 case 0x2c:printf("2c");break; 101 case 0x2d:printf("2d");break; 102 case 0x2e:printf("2e");break; 103 case 0x2f:printf("2f");break; 104 case 0x30:printf("30");break; 105 case 0x31:printf("31");break; 106 case 0x32:printf("32");break; 107 case 0x33:printf("33");break; 108 case 0x34:printf("34");break; 109 case 0x35:printf("35");break; 110 case 0x36:printf("36");break; 111 case 0x37:printf("37");break; 112 case 0x38:printf("38");break; 113 case 0x39:printf("39");break; 114 case 0x3a:printf("3a");break; 115 case 0x3b:printf("3b");break; 116 case 0x3c:printf("3c");break; 117 case 0x3d:printf("3d");break; 118 case 0x3e:printf("3e");break; 119 case 0x3f:printf("3f");break; 120 case 0x40:printf("40");break; 121 case 0x41:printf("41");break; 122 case 0x42:printf("42");break; 123 case 0x43:printf("43");break; 124 case 0x44:printf("44");break; 125 case 0x45:printf("45");break; 126 case 0x46:printf("46");break; 127 case 0x47:printf("47");break; 128 case 0x48:printf("48");break; 129 case 0x49:printf("49");break; 130 case 0x4a:printf("4a");break; 131 case 0x4b:printf("4b");break; 132 case 0x4c:printf("4c");break; 133 case 0x4d:printf("4d");break; 134 case 0x4e:printf("4e");break; 135 case 0x4f:printf("4f");break; 136 case 0x50:printf("50");break; 137 case 0x51:printf("51");break; 138 case 0x52:printf("52");break; 139 case 0x53:printf("53");break; 140 case 0x54:printf("54");break; 141 case 0x55:printf("55");break; 142 case 0x56:printf("56");break; 143 case 0x57:printf("57");break; 144 case 0x58:printf("58");break; 145 case 0x59:printf("59");break; 146 case 0x5a:printf("5a");break; 147 case 0x5b:printf("5b");break; 148 case 0x5c:printf("5c");break; 149 case 0x5d:printf("5d");break; 150 case 0x5e:printf("5e");break; 151 case 0x5f:printf("5f");break; 152 case 0x60:printf("60");break; 153 case 0x61:printf("61");break; 154 case 0x62:printf("62");break; 155 case 0x63:printf("63");break; 156 case 0x64:printf("64");break; 157 case 0x65:printf("65");break; 158 case 0x66:printf("66");break; 159 case 0x67:printf("67");break; 160 case 0x68:printf("68");break; 161 case 0x69:printf("69");break; 162 case 0x6a:printf("6a");break; 163 case 0x6b:printf("6b");break; 164 case 0x6c:printf("6c");break; 165 case 0x6d:printf("6d");break; 166 case 0x6e:printf("6e");break; 167 case 0x6f:printf("6f");break; 168 case 0x70:printf("70");break; 169 case 0x71:printf("71");break; 170 case 0x72:printf("72");break; 171 case 0x73:printf("73");break; 172 case 0x74:printf("74");break; 173 case 0x75:printf("75");break; 174 case 0x76:printf("76");break; 175 case 0x77:printf("77");break; 176 case 0x78:printf("78");break; 177 case 0x79:printf("79");break; 178 case 0x7a:printf("7a");break; 179 case 0x7b:printf("7b");break; 180 case 0x7c:printf("7c");break; 181 case 0x7d:printf("7d");break; 182 case 0x7e:printf("7e");break; 183 case 0x7f:printf("7f");break; 184 case 0x80:printf("80");break; 185 case 0x81:printf("81");break; 186 case 0x82:printf("82");break; 187 case 0x83:printf("83");break; 188 case 0x84:printf("84");break; 189 case 0x85:printf("85");break; 190 case 0x86:printf("86");break; 191 case 0x87:printf("87");break; 192 case 0x88:printf("88");break; 193 case 0x89:printf("89");break; 194 case 0x8a:printf("8a");break; 195 case 0x8b:printf("8b");break; 196 case 0x8c:printf("8c");break; 197 case 0x8d:printf("8d");break; 198 case 0x8e:printf("8e");break; 199 case 0x8f:printf("8f");break; 200 case 0x90:printf("90");break; 201 case 0x91:printf("91");break; 202 case 0x92:printf("92");break; 203 case 0x93:printf("93");break; 204 case 0x94:printf("94");break; 205 case 0x95:printf("95");break; 206 case 0x96:printf("96");break; 207 case 0x97:printf("97");break; 208 case 0x98:printf("98");break; 209 case 0x99:printf("99");break; 210 case 0x9a:printf("9a");break; 211 case 0x9b:printf("9b");break; 212 case 0x9c:printf("9c");break; 213 case 0x9d:printf("9d");break; 214 case 0x9e:printf("9e");break; 215 case 0x9f:printf("9f");break; 216 case 0xa0:printf("a0");break; 217 case 0xa1:printf("a1");break; 218 case 0xa2:printf("a2");break; 219 case 0xa3:printf("a3");break; 220 case 0xa4:printf("a4");break; 221 case 0xa5:printf("a5");break; 222 case 0xa6:printf("a6");break; 223 case 0xa7:printf("a7");break; 224 case 0xa8:printf("a8");break; 225 case 0xa9:printf("a9");break; 226 case 0xaa:printf("aa");break; 227 case 0xab:printf("ab");break; 228 case 0xac:printf("ac");break; 229 case 0xad:printf("ad");break; 230 case 0xae:printf("ae");break; 231 case 0xaf:printf("af");break; 232 case 0xb0:printf("b0");break; 233 case 0xb1:printf("b1");break; 234 case 0xb2:printf("b2");break; 235 case 0xb3:printf("b3");break; 236 case 0xb4:printf("b4");break; 237 case 0xb5:printf("b5");break; 238 case 0xb6:printf("b6");break; 239 case 0xb7:printf("b7");break; 240 case 0xb8:printf("b8");break; 241 case 0xb9:printf("b9");break; 242 case 0xba:printf("ba");break; 243 case 0xbb:printf("bb");break; 244 case 0xbc:printf("bc");break; 245 case 0xbd:printf("bd");break; 246 case 0xbe:printf("be");break; 247 case 0xbf:printf("bf");break; 248 case 0xc0:printf("c0");break; 249 case 0xc1:printf("c1");break; 250 case 0xc2:printf("c2");break; 251 case 0xc3:printf("c3");break; 252 case 0xc4:printf("c4");break; 253 case 0xc5:printf("c5");break; 254 case 0xc6:printf("c6");break; 255 case 0xc7:printf("c7");break; 256 case 0xc8:printf("c8");break; 257 case 0xc9:printf("c9");break; 258 case 0xca:printf("ca");break; 259 case 0xcb:printf("cb");break; 260 case 0xcc:printf("cc");break; 261 case 0xcd:printf("cd");break; 262 case 0xce:printf("ce");break; 263 case 0xcf:printf("cf");break; 264 case 0xd0:printf("d0");break; 265 case 0xd1:printf("d1");break; 266 case 0xd2:printf("d2");break; 267 case 0xd3:printf("d3");break; 268 case 0xd4:printf("d4");break; 269 case 0xd5:printf("d5");break; 270 case 0xd6:printf("d6");break; 271 case 0xd7:printf("d7");break; 272 case 0xd8:printf("d8");break; 273 case 0xd9:printf("d9");break; 274 case 0xda:printf("da");break; 275 case 0xdb:printf("db");break; 276 case 0xdc:printf("dc");break; 277 case 0xdd:printf("dd");break; 278 case 0xde:printf("de");break; 279 case 0xdf:printf("df");break; 280 case 0xe0:printf("e0");break; 281 case 0xe1:printf("e1");break; 282 case 0xe2:printf("e2");break; 283 case 0xe3:printf("e3");break; 284 case 0xe4:printf("e4");break; 285 case 0xe5:printf("e5");break; 286 case 0xe6:printf("e6");break; 287 case 0xe7:printf("e7");break; 288 case 0xe8:printf("e8");break; 289 case 0xe9:printf("e9");break; 290 case 0xea:printf("ea");break; 291 case 0xeb:printf("eb");break; 292 case 0xec:printf("ec");break; 293 case 0xed:printf("ed");break; 294 case 0xee:printf("ee");break; 295 case 0xef:printf("ef");break; 296 case 0xf0:printf("f0");break; 297 case 0xf1:printf("f1");break; 298 case 0xf2:printf("f2");break; 299 case 0xf3:printf("f3");break; 300 case 0xf4:printf("f4");break; 301 case 0xf5:printf("f5");break; 302 case 0xf6:printf("f6");break; 303 case 0xf7:printf("f7");break; 304 case 0xf8:printf("f8");break; 305 case 0xf9:printf("f9");break; 306 case 0xfa:printf("fa");break; 307 case 0xfb:printf("fb");break; 308 case 0xfc:printf("fc");break; 309 case 0xfd:printf("fd");break; 310 case 0xfe:printf("fe");break; 311 case 0xff:printf("ff");break; 312 default: 313 ; 314 } 315 } 316 #endif 317 318 int WriteRawRC(int addr, int data) 319 { 320 int ret; 321 int fd = g_SPI_Fd; 322 unsigned char TxBuf[2]; 323 324 //bit7:MSB=0,bit6~1:addr,bit0:RFU=0 325 TxBuf[0] = ((unsigned char)addr << 1)&0x7E; 326 //TxBuf[0] &= 0x7E; 327 328 TxBuf[1] = (unsigned char)data; 329 330 ret = write(fd, TxBuf, 2); 331 if (ret < 0) 332 printf("spi:SPI Write error\n"); 333 334 usleep(10); 335 336 return ret; 337 } 338 339 unsigned char ReadRawRC(int addr) 340 { 341 int ret; 342 int fd = g_SPI_Fd; 343 unsigned char ReData; 344 unsigned char Address; 345 346 Address = (unsigned char)addr << 1; 347 Address |= (1 << 7); 348 Address &= ~(1 << 0); 349 350 ret = write(fd, &Address, 1); 351 if (ret < 0) 352 printf("spi:SPI Write error\n"); 353 354 usleep(100); 355 356 ret = read(fd, &ReData, 1); 357 if (ret < 0) 358 printf("spi:SPI Read error\n"); 359 360 return ReData; 361 } 362 363 void SetBitMask(unsigned char reg,unsigned char mask) 364 { 365 char tmp = 0x0; 366 367 tmp = ReadRawRC(reg) | mask; 368 369 WriteRawRC(reg,tmp | mask); 370 } 371 372 //******************************************************************/ 373 //功 能:清RC522寄存器位 374 //参数说明:reg[IN]:寄存器地址 375 // mask[IN]:清位值 376 //******************************************************************/ 377 void ClearBitMask(unsigned char reg, unsigned char mask) 378 { 379 char tmp = 0x0; 380 381 tmp = ReadRawRC(reg)&(~mask); 382 383 WriteRawRC(reg, tmp); // clear bit mask 384 } 385 386 int rc522_init() 387 { 388 int ret; 389 char version = 0; 390 391 //reset 392 WriteRawRC(CommandReg, PCD_RESETPHASE); 393 usleep(10); 394 WriteRawRC(ModeReg, 0x3D); 395 WriteRawRC(TReloadRegL, 30); 396 WriteRawRC(TReloadRegH, 0); 397 WriteRawRC(TModeReg, 0x8D); 398 WriteRawRC(TPrescalerReg, 0x3E); 399 400 version = ReadRawRC(VersionReg); 401 printf("Chip Version: 0x%x\n", version); 402 usleep(50000); 403 404 return 0; 405 } 406 407 void PcdAntennaOn() 408 { 409 unsigned char i; 410 411 WriteRawRC(TxASKReg, 0x40); 412 usleep(20); 413 414 i = ReadRawRC(TxControlReg); 415 if(!(i&0x03)) 416 SetBitMask(TxControlReg, 0x03); 417 418 i = ReadRawRC(TxASKReg); 419 } 420 421 static void print_usage(const char *prog) 422 { 423 printf("Usage: %s [-DsbdlHOLC3]\n", prog); 424 puts(" -D --device device to use (default /dev/spidev1.1)\n" 425 " -s --speed max speed (Hz)\n" 426 " -d --delay delay (usec)\n" 427 " -b --bpw bits per word \n" 428 " -l --loop loopback\n" 429 " -H --cpha clock phase\n" 430 " -O --cpol clock polarity\n" 431 " -L --lsb least significant bit first\n" 432 " -C --cs-high chip select active high\n" 433 " -3 --3wire SI/SO signals shared\n"); 434 exit(1); 435 } 436 437 static void parse_opts(int argc, char *argv[]) 438 { 439 while (1) { 440 static const struct option lopts[] = { 441 { "device", 1, 0, 'D' }, 442 { "speed", 1, 0, 's' }, 443 { "delay", 1, 0, 'd' }, 444 { "bpw", 1, 0, 'b' }, 445 { "loop", 0, 0, 'l' }, 446 { "cpha", 0, 0, 'H' }, 447 { "cpol", 0, 0, 'O' }, 448 { "lsb", 0, 0, 'L' }, 449 { "cs-high", 0, 0, 'C' }, 450 { "3wire", 0, 0, '3' }, 451 { "no-cs", 0, 0, 'N' }, 452 { "ready", 0, 0, 'R' }, 453 { NULL, 0, 0, 0 }, 454 }; 455 int c; 456 457 c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL); 458 459 if (c == -1) 460 break; 461 462 switch (c) { 463 case 'D': 464 device = optarg; 465 break; 466 case 's': 467 speed = atoi(optarg); 468 break; 469 case 'd': 470 delay = atoi(optarg); 471 break; 472 case 'b': 473 bits = atoi(optarg); 474 break; 475 case 'l': 476 mode |= SPI_LOOP; 477 break; 478 case 'H': 479 mode |= SPI_CPHA; 480 break; 481 case 'O': 482 mode |= SPI_CPOL; 483 break; 484 case 'L': 485 mode |= SPI_LSB_FIRST; 486 break; 487 case 'C': 488 mode |= SPI_CS_HIGH; 489 break; 490 case '3': 491 mode |= SPI_3WIRE; 492 break; 493 case 'N': 494 mode |= SPI_NO_CS; 495 break; 496 case 'R': 497 mode |= SPI_READY; 498 break; 499 default: 500 print_usage(argv[0]); 501 break; 502 } 503 } 504 } 505 506 //******************************************************************/ 507 //功 能:通过RC522和ISO14443卡通讯 508 //参数说明:Command[IN]:RC522命令字 509 // pInData[IN]:通过RC522发送到卡片的数据 510 // InLenByte[IN]:发送数据的字节长度 511 // pOutData[OUT]:接收到的卡片返回数据 512 // *pOutLenBit[OUT]:返回数据的位长度 513 //******************************************************************/ 514 char PcdComMF522(unsigned char Command, unsigned char *pInData, 515 unsigned char InLenByte, unsigned char *pOutData, 516 unsigned int *pOutLenBit) 517 { 518 char status = MI_ERR; 519 unsigned char irqEn = 0x00; 520 unsigned char waitFor = 0x00; 521 unsigned char lastBits; 522 unsigned char n; 523 unsigned int i; 524 525 switch (Command) 526 { 527 case PCD_AUTHENT: 528 irqEn = 0x12; 529 waitFor = 0x10; 530 break; 531 case PCD_TRANSCEIVE: 532 irqEn = 0x77; 533 waitFor = 0x30; 534 break; 535 default: 536 break; 537 } 538 539 WriteRawRC(ComIEnReg, irqEn|0x80); 540 ClearBitMask(ComIrqReg, 0x80); 541 WriteRawRC(CommandReg, PCD_IDLE); 542 SetBitMask(FIFOLevelReg, 0x80); // 清空FIFO 543 for(i=0; i<InLenByte; i++) 544 WriteRawRC(FIFODataReg, pInData[i]); // 数据写入FIFO 545 546 WriteRawRC(CommandReg, Command); // 命令写入命令寄存器 547 548 if(Command == PCD_TRANSCEIVE) 549 SetBitMask(BitFramingReg,0x80); // 开始发送 550 551 i = 6000; //根据时钟频率调整,操作M1卡最大等待时间25ms 552 do 553 { 554 n = ReadRawRC(ComIrqReg); 555 i--; 556 } 557 while((i!=0)&&!(n&0x01)&&!(n&waitFor)); 558 559 ClearBitMask(BitFramingReg, 0x80); 560 561 if(i!=0) 562 { 563 if(!(ReadRawRC(ErrorReg) & 0x1B)) 564 { 565 status = MI_OK; 566 if (n&irqEn&0x01) 567 status = MI_NOTAGERR; 568 if(Command == PCD_TRANSCEIVE) 569 { 570 n = ReadRawRC(FIFOLevelReg); 571 572 lastBits = ReadRawRC(ControlReg) & 0x07; 573 if(lastBits) 574 *pOutLenBit = (n-1)*8 + lastBits; 575 else 576 *pOutLenBit = n*8; 577 578 if(n == 0) 579 n = 1; 580 if(n>MAXRLEN) 581 n = MAXRLEN; 582 583 for (i=0; i<n; i++) 584 pOutData[i] = ReadRawRC(FIFODataReg); 585 } 586 } 587 else 588 { 589 status = MI_ERR; 590 } 591 } 592 593 SetBitMask(ControlReg, 0x80);// stop timer now 594 WriteRawRC(CommandReg, PCD_IDLE); 595 596 return status; 597 } 598 599 char PcdRequest(unsigned char req_code, unsigned char *pTagType) 600 { 601 char status; 602 unsigned int unLen; 603 unsigned char ucComMF522Buf[MAXRLEN]; 604 605 ClearBitMask(Status2Reg, 0x08); 606 WriteRawRC(BitFramingReg, 0x07); 607 SetBitMask(TxControlReg, 0x03); 608 609 ucComMF522Buf[0] = req_code; 610 611 status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 612 1, ucComMF522Buf, &unLen); 613 614 if ((status == MI_OK) && (unLen == 0x10)) 615 { 616 *pTagType = ucComMF522Buf[0]; 617 *(pTagType+1) = ucComMF522Buf[1]; 618 } 619 else 620 { 621 status = MI_ERR; 622 } 623 624 return status; 625 } 626 627 //******************************************************************/ 628 //功 能:防冲撞 / 629 //参数说明: pSnr[OUT]:卡片序列号,4字节 / 630 //返 回: 成功返回MI_OK / 631 //******************************************************************/ 632 char PcdAnticoll(unsigned char *pSnr) 633 { 634 char status; 635 unsigned char i, snr_check = 0; 636 unsigned int unLen; 637 unsigned char ucComMF522Buf[MAXRLEN]; 638 639 ClearBitMask(Status2Reg, 0x08); 640 WriteRawRC(BitFramingReg, 0x00); 641 ClearBitMask(CollReg, 0x80); 642 643 ucComMF522Buf[0] = PICC_ANTICOLL1; 644 ucComMF522Buf[1] = 0x20; 645 646 status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 647 2, ucComMF522Buf, &unLen); 648 649 if(status == MI_OK) 650 { 651 for (i=0; i<4; i++) 652 { 653 *(pSnr+i) = ucComMF522Buf[i]; 654 snr_check ^= ucComMF522Buf[i]; 655 } 656 if (snr_check != ucComMF522Buf[i]) 657 { 658 status = MI_ERR; 659 } 660 } 661 662 SetBitMask(CollReg,0x80); 663 664 return status; 665 } 666 667 void Find_Card(void) 668 { 669 if(PcdRequest(0x52, Temp) == MI_OK) 670 { 671 if(Temp[0]==0x04 && Temp[1]==0x00) 672 printf("MFOne-S50\n"); 673 else if(Temp[0]==0x02 && Temp[1] == 0x00) 674 printf("MFOne-S70\n"); 675 else if(Temp[0]==0x44 && Temp[1]==0x00) 676 printf("MF-UltraLight\n"); 677 else if(Temp[0]==0x08 && Temp[1]==0x00) 678 printf("MF-Pro\n"); 679 else if(Temp[0]==0x44 && Temp[1]==0x03) 680 printf("MF Desire\n"); 681 else 682 printf("Unknown\n"); 683 684 printf("SUCCESS!\n"); 685 } 686 else 687 { 688 printf("No card!\n"); 689 } 690 } 691 692 void Auto_Reader(void) 693 { 694 int i = 0; 695 unsigned long num = 0; 696 697 // while(1) 698 //{ 699 if(PcdRequest(0x52,Temp) == MI_OK) 700 { 701 if(Temp[0]==0x04 && Temp[1]==0x00) 702 printf("MFOne-S50\n"); 703 else if(Temp[0]==0x02 && Temp[1]==0x00) 704 printf("MFOne-S70\n"); 705 else if(Temp[0]==0x44 && Temp[1]==0x00) 706 printf("MF-UltraLight\n"); 707 else if(Temp[0]==0x08 && Temp[1]==0x00) 708 printf("MF-Pro\n"); 709 else if(Temp[0]==0x44 && Temp[1]==0x03) 710 printf("MF Desire\n"); 711 else 712 printf("Unknown\n"); 713 714 if(PcdAnticoll(UID) == MI_OK) 715 { 716 printf("Card Id is(%d):", num++); 717 #if 1 718 for(i=0; i<4; i++) 719 printf("%x", UID[i]); 720 #else 721 tochar(UID[0]); 722 tochar(UID[1]); 723 tochar(UID[2]); 724 tochar(UID[3]); 725 #endif 726 printf("\n"); 727 728 PcdRequest(0x52,Temp);//clear 729 } 730 else 731 { 732 printf("no serial num read\n"); 733 } 734 } 735 else 736 { 737 printf("No Card!\n"); 738 } 739 740 usleep(300000); 741 // } 742 } 743 744 void HandleConfigMenu(unsigned char inputvalue) 745 { 746 #if 0 747 switch(toupper(inputvalue)) 748 { 749 case 'A': 750 Auto_Reader(); 751 break; 752 case 'F': 753 Find_Card(); 754 break; 755 default: 756 DisplayConfigMenu(); 757 } 758 #endif 759 760 //Find_Card(); 761 762 Auto_Reader(); 763 } 764 765 int main(int argc, char *argv[]) 766 { 767 unsigned char i; 768 769 int ret = 0; 770 int fd; 771 772 parse_opts(argc, argv); 773 774 fd = open(device, O_RDWR); 775 if (fd < 0) 776 pabort("can't open device"); 777 778 g_SPI_Fd = fd; 779 780 #if 0 781 /* 782 * spi mode 783 */ 784 ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); 785 if (ret == -1) 786 pabort("can't set spi mode"); 787 788 ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); 789 if (ret == -1) 790 pabort("can't get spi mode"); 791 792 /* 793 * bits per word 794 */ 795 ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); 796 if (ret == -1) 797 pabort("can't set bits per word"); 798 799 ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); 800 if (ret == -1) 801 pabort("can't get bits per word"); 802 803 /* 804 * max speed hz 805 */ 806 ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); 807 if (ret == -1) 808 pabort("can't set max speed hz"); 809 810 ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); 811 if (ret == -1) 812 pabort("can't get max speed hz"); 813 814 printf("spi mode: %d\n", mode); 815 printf("bits per word: %d\n", bits); 816 printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); 817 #endif 818 819 rc522_init(); 820 821 PcdAntennaOn(); 822 823 HandleConfigMenu(i); 824 825 close(fd); 826 827 return ret; 828 }
9、所使用的头文件(来源于讯为)
spidev_test.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 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.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*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 */