今天,我们抽空来弄下STM32F103RBT6通过SPI方式驱动RC522 NFC模块读写S50复旦卡~. i- J" j' |- G
一个简单的下例子,NFC的应用在生活中随处可见了。我们这里的假设应用场景是在不同杯子( b `) L& v) v) |1 J
底部粘上复旦卡,来辨别不同的杯子TYPE型号~这里仅对块地址17的第一个字节进行判断!7 @5 B: m i+ y8 S0 A2 b
复旦卡就是常见的那种门禁卡钥匙扣形状的:1 o! O! M0 B4 l
/ X: \7 p+ K7 c" l0 e
主板用自制的STM32F103RBT6的一个小板:
) ^4 M1 Z9 q+ @8 K3 T' @8 ]$ l& b& M
: y% ~6 o% n* ]% N/ J5 l/ \/ ]- d下载器用CMSIS DAP 带串口的:
2 l; o- h5 J8 c+ `
7 e6 N* a+ m) G2 [3 u: q6 {: M- T好,下面开始接线:
' @ M6 y8 A4 R) u
- e( Y0 A, H: D+ Z
接好线的图:
3 ^5 f8 x' U( G1 a
; t- e- v1 ]* V# ^STM32F103RBT6 和RC522 及S50复旦卡就不多说了,网上大把资料。/ [1 N' }3 a3 A# @; O7 H
上程序:
- E2 E* L& w) Wspi.h
' k! P9 K0 O6 m1 ?6 p4 N6 V, l- #ifndef __SPI_H1 `( u9 H1 a/ p- Q
- #define __SPI_H
: H' T& Z5 P" ~1 f - #include "sys.h"; k! O, V5 L* g9 l
- " O: i0 k4 ]$ ]2 V
. F+ R4 m+ D' N- //#define RC522_RST PCout(7)! s: W1 J& x8 e, u6 m8 @
- #define RC522_RST PCout(7) //测试后恢复PCout(7)$ l6 K Z% W- g6 o0 J
- #define RC522_CS PBout(9) X. X& }# |" y; o8 F- K
- #define SPIReadByte() SPIWriteByte(0)
; Y+ `5 x$ g& W9 j0 Z* N - // SPI总线速度设置
4 [ W4 U8 P, q/ ~+ }, S - #define SPI_SPEED_2 09 n D3 F! _2 W, {$ L* c
- #define SPI_SPEED_4 1
" `- F9 y% R7 Z' o- X+ m - #define SPI_SPEED_8 2
4 z9 D+ {* E* j: k( I% B - #define SPI_SPEED_16 3
, r' `, j" r$ @/ s! ` - #define SPI_SPEED_32 4
6 j# @! j/ q- \" D - #define SPI_SPEED_64 5- ]5 t: r2 X6 t9 c, t
- #define SPI_SPEED_128 6
7 I' |# h# o: C% j. Y - #define SPI_SPEED_256 71 B4 U6 s- ]0 k7 H
- % \& a- G; E9 X; h2 N1 n
- void SPI2_Init(void); //初始化SPI口
% E- I8 x) h6 u& P - void SPI2_SetSpeed(u8 SpeedSet); //设置SPI速度 # r3 Z+ e+ d8 p* W& T3 ~4 e
- u8 SPIWriteByte(u8 TxData);//SPI总线读写一个字节
3 z! {, }. t+ x: _1 k; y -
0 n1 j2 v& ^- K" y - #endif+ ?* m' M8 a% m+ y; M) i! F
9 m7 S3 b# I% U4 D4 i7 k1 P
复制代码 spi.c
?. P7 X1 t# J0 w B- #include "spi.h"
g. [: Q! T9 n' W- `
, |+ @! P0 O0 F. }, c5 L! o" F, ?- //这里针是对SPI2的初始化3 l R3 \+ l* X2 i5 |" }6 c
- void SPI2_Init(void)
" N( |( F0 i* f8 `5 Z - { 5 I6 ?+ F- t* k4 \+ v8 v, ~
- RCC->APB2ENR|=1<<3; //PORTB时钟使能 ; O+ y: Y& Q6 v: u1 o+ Q& M
- RCC->APB2ENR|=1<<4; //PORTC时钟使能 1 S* N# Z7 H0 x9 ^
- RCC->APB1ENR|=1<<14; //SPI2时钟使能 + B3 _8 y) @1 Y6 R% a1 W' j6 ]
- GPIOB->CRH&=0XFFFFFF0F;
0 H) T( [# c0 E - GPIOB->CRH|=0X00000030;//PB.9 推挽输出 8 `8 N4 s0 H2 _5 y: }1 ]1 U& K
- GPIOC->CRL&=0X0FFFFFFF; 2 j* |/ @# X n2 H! s
- GPIOC->CRL|=0X30000000;//PC. 7 推挽输出 ) z/ c( C7 H! e. i
- // GPIOB->CRH&=0XFFFFFFF0;
: D1 V' q6 f+ Q$ P# S - // GPIOB->CRH|=0X00000003;//PB. 8 推挽输出 此脚做测试用,测试完恢复PC7复位RFID功能
. N# D4 a% f. ]* s8 F - RC522_RST=1; //RC522 复位脚置1
7 Q. s/ o5 V m* @2 Z* v# N ] - RC522_CS=1;/ f+ z2 m2 h0 ?5 w5 X
- : c- O/ w/ `4 u) Z Z4 g
- ; U4 T7 Y* E P! R
- //这里只针对SPI口初始化
1 U+ m9 {, Q( a# D - GPIOB->CRH&=0X000FFFFF; , w: A- U# [: T6 R
- GPIOB->CRH|=0XBBB00000; //PB13/14/15复用 w, V$ g4 y* G- l3 a' Q4 o p
- GPIOB->ODR|=0X7<<13; //PB13/14/15上拉
2 P% z& F2 ~) t1 P$ Q! ] - SPI2->CR1|=0<<10; //全双工模式 * z- b. c; i& b* J7 {2 i& a
- SPI2->CR1|=1<<9; //软件nss管理
9 F% H: ^: J4 l+ d' C: P, _ - SPI2->CR1|=1<<8;
* v4 v# S2 H& `, v: p1 K8 \! H
" }4 d) R" L, t( Y; O* Q# V- SPI2->CR1|=1<<2; //SPI主机
- }( _" w# z# V1 Z - SPI2->CR1|=0<<11; //8bit数据格式 " U- O8 {; S9 p; ~/ W. l
- SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
: x5 \" I4 |) {3 ] - SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1
9 F, ~7 A/ P. i' E# d0 y - //对SPI2属于APB1的外设.时钟频率最大为36M.
, K' ]! ~6 U# w8 A/ R! o2 O - SPI2->CR1|=3<<3; //Fsck=Fpclk1/256- ]& b# ], d N# G! ~4 m8 {( x
- SPI2->CR1|=0<<7; //MSBfirst
+ r4 i* y' e) A - SPI2->CR1|=1<<6; //SPI设备使能6 a) _4 ~" I9 s6 ^
- SPI2_SetSpeed(5);
% [6 Z& x* m# c" e+ m7 x - SPIWriteByte(0xff);//启动传输
' W8 |. t+ e/ w% n - }
8 ~4 O' \# S* U% T - //SPI2速度设置函数( j8 X6 T9 B! h( y
- //SpeedSet:0~7" |( X8 b0 {8 C) `
- //SPI速度=fAPB2/2^(SpeedSet+1)
4 H& X7 j' F! ?; |: @ - //fAPB2时钟一般为90Mhz
" e) e" M9 Y+ _5 ` - void SPI2_SetSpeed(u8 SpeedSet). N; w# D5 a( \) S6 U% J
- {& e. f6 L7 M* {9 t) e2 I+ P
- SpeedSet&=0X07; //限制范围" y) \; d) D# z
- SPI2->CR1&=0XFFC7;
d: y4 R; q6 J/ l. \ - SPI2->CR1|=SpeedSet<<3; //设置SPI5速度
8 W( U- X% x& L2 p5 q3 y, q& Q - SPI2->CR1|=1<<6; //SPI设备使能
. F! i+ ^. `+ \ - } . F' a4 _2 s) R# `. B9 M+ @
- //SPI2 读写一个字节
M1 K( ` _7 L - //TxData:要写入的字节
/ F0 |+ z# A4 s+ k+ W7 C - //返回值:读取到的字节
# L+ C4 Y* W/ B. H$ v - u8 SPIWriteByte(u8 TxData)7 e+ l2 U3 f0 \9 O- W6 G
- { " q( R4 X) i* K8 Z- _
- u16 retry=0; 5 Q# M# g5 ?! v0 |( Z! s5 K
- while((SPI2->SR&1<<1)==0) //等待发送区空
' d& [% ]6 ~; k8 P" V- Y M' S* v+ s - {% q, o1 k; _+ O# E) D
- retry++;1 ?* P, A. x$ K0 X
- if(retry>=0XFFFE)return 0; //超时退出1 B. z" u& x) n. I5 W/ W
- }
# w/ [ U5 A% V- z - SPI2->DR=TxData; //发送一个byte $ Q; m s6 l# w% B
- retry=0;9 @, w7 ~. V' M: Y8 f$ k
- while((SPI2->SR&1<<0)==0) //等待接收完一个byte
7 v3 {' s, ~* S# F - {) b8 y A: x2 E9 u, V/ ?
- retry++;
) } s+ J; y5 z2 t7 J - if(retry>=0XFFFE)return 0; //超时退出+ S2 R$ e0 D# U. y0 E, E) o) p
- } Z: i3 Q/ r" {1 d- o
- return SPI2->DR; //返回收到的数据
8 ^* M L7 @. v. N& I& Q$ v - }
5 Z; d& O6 E! }6 _' B& H5 c2 L) L
6 @, H( C( q, J6 L7 Q$ i- . P7 B# |6 R, b
) d* j/ ~# G- @! n6 t+ T
复制代码 rc522.h
! r3 u- H+ b' l0 s- F" u- N. u- #ifndef _RC522_H_
4 r/ Z1 g- C. ^& X - #define _RC522_H_' C& s( u- z1 `$ M1 s! f! S. a) b
6 O' e% g# e0 E" K' \- #include <stm32f10x.h> $ d0 o$ \9 B( \3 z/ Z
- #include "sys.h"
/ s; c+ b* [* Y1 l9 x - #include "spi.h") z- h1 E4 d2 g! O4 C% ]9 Q/ Y
- 4 w/ s' @ n5 i2 `0 ]
6 o+ r3 Y2 t9 k V- extern u8 CupType;0 i; L* ~3 b* |4 o3 E4 }
. n0 E' p( U7 A9 `- g8 V. k
- _" b/ y9 ^6 ^- Q8 Z# w' h' e& O7 }5 i- /////////////////////////////////////////////////////////////////////' ? j- v) w" u8 P3 b+ g$ t3 ~
- //MF522命令字
. {" E u5 t- s7 l' W8 e0 L4 |- y f - /////////////////////////////////////////////////////////////////////# q8 E" t/ D8 V/ M. K; }' p
- #define PCD_IDLE 0x00 //取消当前命令
! E v+ Z$ s* j" w" M - #define PCD_AUTHENT 0x0E //验证密钥
# c, l' l4 j1 b; B, ?! f' H - #define PCD_RECEIVE 0x08 //接收数据
: B: X9 L ]- I f& U: H - #define PCD_TRANSMIT 0x04 //发送数据8 }* M$ }, q. v/ V
- #define PCD_TRANSCEIVE 0x0C //发送并接收数据
+ R1 U2 D* h9 k: O( p - #define PCD_RESETPHASE 0x0F //复位! m- U4 Z6 T) p U+ g9 c, F
- #define PCD_CALCCRC 0x03 //CRC计算
" ^, Q" b7 g" i
( V+ K' ]& z1 g5 {: ?4 k- /////////////////////////////////////////////////////////////////////
) o% Z8 h" D, p5 Y - //Mifare_One卡片命令字; Y0 |+ Q/ J, v, R
- /////////////////////////////////////////////////////////////////////
$ ^5 `' ~: _; h, K- | - #define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态
; g; c( |9 q! P( S - #define PICC_REQALL 0x52 //寻天线区内全部卡
7 d' V% a l% C% j0 q }0 w* I - #define PICC_ANTICOLL1 0x93 //防冲撞
& y" Y m3 ^( ~* q) T+ |& X - #define PICC_ANTICOLL2 0x95 //防冲撞
, |+ I4 S* H3 N7 X# r - #define PICC_AUTHENT1A 0x60 //验证A密钥
4 D. e- g q. `5 R# N - #define PICC_AUTHENT1B 0x61 //验证B密钥2 y3 x2 K$ D' d
- #define PICC_READ 0x30 //读块/ w1 \4 v, U- X3 {& r5 _2 }8 w6 C
- #define PICC_WRITE 0xA0 //写块. }. Z6 O. c9 q! W! b9 F1 D! f. [
- #define PICC_DECREMENT 0xC0 //扣款
4 c6 }0 B G- N! c9 e* e! F - #define PICC_INCREMENT 0xC1 //充值
6 Y4 o4 ]! d2 a# v$ x5 z - #define PICC_RESTORE 0xC2 //调块数据到缓冲区
) C ], U' B5 _+ W - #define PICC_TRANSFER 0xB0 //保存缓冲区中数据
, [5 N' C( N% _/ x1 z/ |4 o - #define PICC_HALT 0x50 //休眠
- q# Q% `1 v& \' j, j* q - / \3 w5 M2 `& i
- /////////////////////////////////////////////////////////////////////, e$ J/ ?# {1 `; `
- //MF522 FIFO长度定义' S/ b" h5 ?9 B& s! K# m4 f$ t7 T. d4 Y
- /////////////////////////////////////////////////////////////////////
) g# [, Y& R. e6 Z2 z* v) y - #define DEF_FIFO_LENGTH 64 //FIFO size=64byte
( e7 }! {% b+ v4 {+ f/ k* F. d - #define MAXRLEN 18; o$ c5 ?3 y) B6 w( R
) W& l; B0 q7 i: I2 @! `- /////////////////////////////////////////////////////////////////////& F$ H8 I& z; Y3 E1 y# P
- //MF522寄存器定义
Q+ X0 g2 w! P: U - /////////////////////////////////////////////////////////////////////
+ V# M' ~ L: q' z2 Q: p - // PAGE 06 T# N4 s6 Z# k e Z8 `
- #define RFU00 0x00 4 R! \" `: J6 X- j& S
- #define CommandReg 0x01 ! n$ B" `$ \5 M7 X% \- l/ d
- #define ComIEnReg 0x02 1 z. v9 l) r9 [# O
- #define DivlEnReg 0x03
1 x# f2 |: Y1 Y1 C7 W3 j9 W6 d' l - #define ComIrqReg 0x04
9 _/ H2 r( P- v E$ W# w) _8 M Z - #define DivIrqReg 0x05
4 C6 J5 l* ~5 r2 S$ ? - #define ErrorReg 0x06 $ a5 E. d$ {) _, U# Q1 {& M4 P6 c5 i
- #define Status1Reg 0x07
" @1 |0 u" l" O# v) o# X6 I# R - #define Status2Reg 0x08
7 r' @' w3 W% }2 |' w, _ - #define FIFODataReg 0x093 P# a. z w$ _: t2 u* ]" K
- #define FIFOLevelReg 0x0A
6 e! e( l* \8 D) i. v/ _) [$ \! m - #define WaterLevelReg 0x0B
. B! V1 _0 E7 t& j5 R - #define ControlReg 0x0C
6 m4 W2 d- }( G) I5 O ?1 X" E - #define BitFramingReg 0x0D
5 u/ B6 Q9 C& {3 b% r, t/ m - #define CollReg 0x0E
" {7 z$ m) K2 h5 l, h: @/ f; Q1 j$ e - #define RFU0F 0x0F
, F4 v4 X5 n) `0 w5 w6 h" F - // PAGE 1
+ m& ~: p8 l) g1 @ - #define RFU10 0x10
7 x" G$ x. H/ e1 `6 E9 @ - #define ModeReg 0x11
# g9 Z6 A) d8 R - #define TxModeReg 0x12
: e0 ^$ s* @( R+ ^1 m - #define RxModeReg 0x13: I# \3 G3 s$ |( ]
- #define TxControlReg 0x147 G- {+ M+ T P' }- s8 E7 J* v7 x
- #define TxAutoReg 0x15
9 i1 y- s! q. [2 | - #define TxSelReg 0x162 c% _0 Y) V" ^0 ~
- #define RxSelReg 0x17
; W/ @9 ]: d @( ~; r7 |+ W - #define RxThresholdReg 0x188 a9 A! P \8 c( j
- #define DemodReg 0x19" C! y- M8 y# |4 y* b& n
- #define RFU1A 0x1A* h* D% m; e2 O; ^. H3 S
- #define RFU1B 0x1B l- j4 C$ H/ b6 a" \3 e
- #define MifareReg 0x1C
4 b, k. Y2 h G3 O4 ~' E - #define RFU1D 0x1D
3 k" |5 a8 v8 y" B8 h C6 ~ - #define RFU1E 0x1E: n8 `9 E: N" u
- #define SerialSpeedReg 0x1F
9 \% \/ T* B; D2 A: @8 j - // PAGE 2
+ A5 o& n0 \( [" d; ]5 U6 ? - #define RFU20 0x20
: s7 L: S) L" q7 s; s( l! t - #define CRCResultRegM 0x21
. E+ w/ d: R- l5 s: J/ U' l& q - #define CRCResultRegL 0x22" U# Y& M. ~* x& Y* y$ R2 b
- #define RFU23 0x23
( f9 E& b9 b/ t) s& b- z/ p - #define ModWidthReg 0x24 U" Y, K- ~# d, ^3 S$ S
- #define RFU25 0x25! U( d! x" o( X. E" b8 U% E% o
- #define RFCfgReg 0x26
9 D' ]5 U( M, Z' v; J9 \3 @ - #define GsNReg 0x27
, r1 w. ^( g( I; y+ Q. ]" R2 @" { - #define CWGsCfgReg 0x28) q2 g& H2 I/ N/ p( c3 G
- #define ModGsCfgReg 0x29
% M, p3 E9 J' b, w0 `5 E - #define TModeReg 0x2A1 w7 t) C$ v& X! S2 T2 `; `1 A
- #define TPrescalerReg 0x2B- N) f W: l" ~" p# y' G( [
- #define TReloadRegH 0x2C
/ ^6 r3 V; A9 M4 u - #define TReloadRegL 0x2D& P) g8 y8 S, b1 h4 |
- #define TCounterValueRegH 0x2E
4 ]2 A# q0 v; r+ j' }# {: L - #define TCounterValueRegL 0x2F
. W* V* c8 r6 h r+ i - // PAGE 3
/ j$ @5 s% o1 _# G+ J - #define RFU30 0x30
" T, x9 h8 j% f - #define TestSel1Reg 0x31( i+ c) F/ [& j2 k
- #define TestSel2Reg 0x32- }! k4 S+ Q+ t
- #define TestPinEnReg 0x330 d M: i1 ]0 p4 a# W
- #define TestPinValueReg 0x34
5 F; p; t1 y. c; S% | - #define TestBusReg 0x35* a% p) j9 M. t, F# j
- #define AutoTestReg 0x36, I6 Q; B2 `) A
- #define VersionReg 0x37$ t! W5 N7 b. q) |. O/ l1 |
- #define AnalogTestReg 0x38
& d" I& E0 v. Q0 y9 t1 V! v. x0 a1 f R - #define TestDAC1Reg 0x39
$ s9 w* Z- v, e0 H - #define TestDAC2Reg 0x3A / o$ T) }" f( g* ~$ a9 U& u
- #define TestADCReg 0x3B . ]! Z$ N1 R5 O- [0 a
- #define RFU3C 0x3C . I* R: P! ?* Z7 B" Y
- #define RFU3D 0x3D 2 E% ~: v" i" R% G- ~
- #define RFU3E 0x3E " t! \6 x- e" k1 Y
- #define RFU3F 0x3F# e+ S6 {+ S4 M
+ G- t8 p1 X9 B* C: B$ F3 w- /////////////////////////////////////////////////////////////////////
: E) B" X- q( R) y* Q - //和MF522通讯时返回的错误代码" H* \4 S N' [4 S' A M* {+ e
- /////////////////////////////////////////////////////////////////////2 u- ?3 w5 k6 ]4 _) w
- #define MI_OK 0
! @ `! c8 T8 z: ?( o4 Y - #define MI_NOTAGERR 1& ? v! y+ v' H7 ~9 q% G0 u! v& d
- #define MI_ERR 28 a2 p9 O5 N0 o- V% `; X
- ! L) ^% @; l& j. f' f
- #define SHAQU1 0X01; T4 ]6 J3 O/ O6 X
- #define KUAI4 0X04
* L) c2 F9 a, C - #define KUAI7 0X07
; p" l. ~( p" {' M( j - #define REGCARD 0xa1
* f6 r# T2 R+ c - #define CONSUME 0xa2* Y Z& b& _. q# K
- #define READCARD 0xa3
0 [% [4 X8 f: B0 q" F - #define ADDMONEY 0xa45 C* K' W% q6 j8 U Y
- * T$ U1 Q' ` |9 o5 q! Q
- //
- t$ Y& I& o9 p& @2 a) n - //#define spi_cs 1;) q1 F! d Q, o# P* ~0 E# A. Q
- //sbit spi_ck=P0^6;
2 M) O a$ t+ G% Z( b/ m - //sbit spi_mosi=P0^7;
* E/ r1 q9 C* Y9 D/ ]( _$ l: W - //sbit spi_miso=P4^1;
& w! k" ^$ D7 D' _, x4 N* n - //sbit spi_rst=P2^7;! X1 |1 X, S3 G, h j6 }* D o
- #define SPIReadByte() SPIWriteByte(0)
- x# Z X" N* o1 x: j - //u8 SPIWriteByte(u8 byte);& X) P6 d+ A) s/ n
- //void SPI2_Init(void);. o4 }+ V, @$ S( `2 ?
3 h C; y! y8 X8 w* e0 A' U3 n' z- . K6 U# n4 o& `. ?% ?
- //#define MYRC522_CS PAout(4)9 q) C# b" M+ R
- //#define MYRC522_RST PAout(6)
$ ^0 P; _4 l/ L/ `0 I7 w! d) V
. |, ~9 _2 M" L+ _! c
! E; W- q1 l( u) T; s- e+ w. L8 j: j
- void InitRc522(void);
& V' F" s8 b- F6 i5 b" G - void ClearBitMask(u8 reg,u8 mask);9 b/ n6 S6 x2 ^! x# x! I9 n. {2 u) K
- void WriteRawRC(u8 Address, u8 value);/ N r2 l2 J# a' a+ @' k
- void SetBitMask(u8 reg,u8 mask);; R1 P, O* m: w2 m: q! o5 q ^
- char PcdComMF522(u8 Command,
8 w& r0 K! [ q0 g h* o - u8 *pIn , 8 e, _. W8 h& x4 m2 g4 h
- u8 InLenByte,7 `6 l+ d {, R% W
- u8 *pOut ,
7 |. C5 c. X5 J - u8 *pOutLenBit);/ [( W& V+ ?% s6 `' u. b
- void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut );9 l2 _/ A i. t' |" O$ s
- u8 ReadRawRC(u8 Address);5 b2 b; _$ y" h& v' I: @
- void PcdAntennaOn(void);1 {7 L! d9 y" G( `! d# K
- ; x7 n7 t# e; s2 K0 m
- char PcdReset(void);) ]' z7 d% k; W# @4 t! B
- char PcdRequest(unsigned char req_code,unsigned char *pTagType);
" F* x# U) X( k; u$ @1 } - void PcdAntennaOn(void);
k) r6 S' z% Q1 F8 H; T" l1 ` - void PcdAntennaOff(void);
; r* P0 z4 c- y; w3 `7 M5 G - char M500PcdConfigISOType(unsigned char type);
& _7 ~, Q* W/ e* k - char PcdAnticoll(unsigned char *pSnr);
: y/ q) e/ A* S' i/ M3 I - char PcdSelect(unsigned char *pSnr);
( E2 Y& b: u |* Z2 b, H7 { - char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);. N: D( O% H& c" d' `! ]
- char PcdWrite(unsigned char addr,unsigned char *pData);2 j, W0 L4 i$ d) l3 l( N" E$ K/ Z, [
- char PcdRead(unsigned char addr,unsigned char *pData);
3 H4 x* Y! q4 c& a# u. } - char PcdHalt(void);
7 q* s/ Z6 O4 M6 l9 G) z - void Reset_RC522(void);
* Z1 I; E9 g: B; a6 n. o - u8 RfidTest(void);
3 C& ?5 g) P/ g' A, q2 }, d0 ~ - u8 ReadCupType(void);
4 i" ~( c$ x9 c# Q+ [3 h - u8 WriteCupType1(void);
7 x& E: ?3 Z9 p2 L7 m* `7 a* V - u8 WriteCupType2(void);
. f3 B# ^* ?: e5 W3 ?# R - ) h4 G! m# [+ \, p) H8 E9 d% o
- #endif) O( W# K1 q S' P, v: U: c2 P6 n R7 p# b
复制代码 rc522.c
) q: @7 i* j4 m }- #include "sys.h"
/ G- M& l. M2 q- ] - #include "delay.h"6 F/ M# W( d; U( p+ V$ n
- #include "rc522.h"
: p2 c- f3 I7 \; f - #include <stdio.h>
7 w, }7 L' X5 H7 ]- C% n; i# W - #include <string.h>
9 i+ d2 O. S6 k2 J; O - #include <ctype.h>
% D9 j! l5 N- x4 c: j5 Q - #include <stdlib.h>5 t7 n5 d+ R2 `" y& Y, }) a. X+ B
- #include <stdarg.h>. c/ ?/ w8 V: R
- #include <math.h>
- g8 r6 v" d! y& `: |3 O I
8 M0 ]( Z2 W: o8 b! d- u8 CupType;
" l3 Q0 U" v; O* ^1 Z& h - 6 v+ v/ E% V3 o4 [0 k% H0 ]% f
- /*0扇区的第0块是不能写的,只能读,前4字节是卡片ID*/0 ]6 Z& a- N0 p5 G" y' K
- /*块3前6字节是A密钥,中间4字节是控制块,后6字节是B密钥*/, h5 i" p5 l8 `) y$ w7 A
- /*扇区0:0-3块 扇区1:4-7块 扇区2:8-11块 扇区3:12-15块*/6 C' {; a0 O l
- /*3、7、11、15块存储密钥*/9 {0 n4 V* c/ \1 E H1 H, I
- void delay_ns(u32 ns)
\. ]2 f O7 ^& P3 g4 d/ G" \ - {
; ?2 C" l; G; j0 B9 Q - u32 i;
! ~# x3 ]: e/ a9 G& |8 s% w2 J, N - for(i=0;i<ns;i++). @2 h* f* v# G7 f' z4 V4 y
- {
2 x2 n9 X" i& R! l/ X8 M3 ? - __nop();
0 |; V" C" d+ i9 V0 e* M* C - __nop();6 i: e- }, X9 I
- __nop();
6 ?+ q U9 ?2 R2 s - __nop();
# L7 \; @# C; A - __nop(); ) Y9 Y% ]( @& {' W
- }
( l I2 d1 U0 i$ R/ W - }, d; ^& n0 X8 X+ p. b( w! C
+ j! q& c' d1 Y8 C4 C
* @$ p% o/ ~! p9 Z% h, K- void InitRc522(void)
3 Y9 Z, t U2 t( D6 { - {: _7 w+ Q* \& e0 |8 F! b
- SPI2_Init();
4 r0 S) S% |; c, {% w9 n9 ] - PcdReset();
2 z( `. d0 r9 i- T2 d - PcdAntennaOff(); ; B% J$ g8 T; n3 y6 s& B# Y
- PcdAntennaOn();. z# F" `1 q9 c# |) V3 j+ O
- M500PcdConfigISOType( 'A' );: v1 R+ l4 A2 ?. b& b! ?! l
- }0 l8 }5 n- I+ o; w& h
- 7 K5 o' W, w1 N9 \
- void Reset_RC522(void)& j I6 m; E0 f2 E
- {9 U* N. X8 D6 R ~3 ~$ M) I2 p) @
- PcdReset();& a f5 A& K4 ^ K5 X, \0 u
- PcdAntennaOff();
; X9 q9 q7 n& y- @: L9 P - PcdAntennaOn();
V8 w' P W" F - }
+ \( A8 \8 U% l0 P" R - /////////////////////////////////////////////////////////////////////5 Z( C% d; n: T% l6 t8 M
- //功 能:寻卡
& ^# d( j( h4 V - //参数说明: req_code[IN]:寻卡方式
! J+ N. Q" Z: F$ _ - // 0x52 = 寻感应区内所有符合14443A标准的卡0 m, l4 [% X8 O3 D& h9 I9 U0 o% e
- // 0x26 = 寻未进入休眠状态的卡3 s+ ?' a: V3 F" N1 [
- // pTagType[OUT]:卡片类型代码9 h7 E8 l+ s5 H. g4 p
- // 0x4400 = Mifare_UltraLight/ {) [* j/ G+ \
- // 0x0400 = Mifare_One(S50)
& Z# i4 }8 i5 r `5 _3 g6 o - // 0x0200 = Mifare_One(S70); d! g0 `$ ~6 w7 f7 V: o
- // 0x0800 = Mifare_Pro(X)
" c8 }& ^9 `0 T% k" M9 v( N$ H - // 0x4403 = Mifare_DESFire
+ \- V' Q d! Y- U - //返 回: 成功返回MI_OK5 O8 ~4 I" a( B
- /////////////////////////////////////////////////////////////////////9 i, e! l. Z# T
- char PcdRequest(u8 req_code,u8 *pTagType)
* y5 u- e" l* z2 v - {
5 a/ f! d( k$ R5 e% @ - char status;
/ Q6 r6 ?, l2 F/ M% k* e0 M - u8 unLen;0 S$ R2 V% C$ [3 w, v' X8 u6 H1 _
- u8 ucComMF522Buf[MAXRLEN]; ( N, \- g1 A) _
- 1 G& @. e0 N; D* S
- ClearBitMask(Status2Reg,0x08);
2 t- [* Z) C$ h - WriteRawRC(BitFramingReg,0x07);+ ~: F# Q' w( Q: O
- SetBitMask(TxControlReg,0x03);
! B; d& C3 |- u0 X$ g- a - ' Z- m1 I" H* T
- ucComMF522Buf[0] = req_code;- e% j; B( o X1 ~
- / f0 q5 t& \+ z& r
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
. u$ J/ m3 R: ]6 w. ?# Z! \ - " ]; U. i5 R( P6 v; B
- if ((status == MI_OK) && (unLen == 0x10))
! r" S' ?! `2 O3 }: i5 W- l - {
, k* a0 g; ?+ Z- W! o1 ] - *pTagType = ucComMF522Buf[0];0 g& g9 C& n% E: I- D. g& x* n
- *(pTagType+1) = ucComMF522Buf[1];+ q! }' e/ s J/ H7 x9 x
- }
, ?, t% i% ?( I$ W - else+ U+ c0 j1 P: G/ t
- { status = MI_ERR; }
* l+ k! B3 r6 k1 X W - 9 @/ M! ~: g9 e5 V, B0 J
- return status;. X/ J. X% d5 Z, v K
- }
* j; y, p5 @0 w+ B3 S8 e - V# D4 K: s( H4 q/ e
- /////////////////////////////////////////////////////////////////////
! r9 O& H, j) t* k% |6 g9 ` - //功 能:防冲撞
+ \5 [7 T7 s1 Q# H u" z- Y+ n- s - //参数说明: pSnr[OUT]:卡片序列号,4字节# ^% d: C% |5 T: E# e; ]7 t
- //返 回: 成功返回MI_OK
9 |0 W8 [) |: F# u: l, K - ///////////////////////////////////////////////////////////////////// 1 ]& _8 K/ |2 `% K
- char PcdAnticoll(u8 *pSnr)
% E, `: L: k4 J5 I9 m! ]5 y8 {! ~ - {! d6 X6 l/ q; z4 ?# D% P! P
- char status;
( r% B7 L/ G) O4 w" J5 f# ~2 o - u8 i,snr_check=0;4 s/ B# {+ @* Q: x1 V( z0 X, q1 y
- u8 unLen;
& u& D/ n$ \" t% ^; Y - u8 ucComMF522Buf[MAXRLEN]; / H. V9 b1 X: }4 u* U8 i2 u3 F
-
1 U5 @- \2 E! O0 q1 ?0 r - : T7 w' X! J. n! E, O
- ClearBitMask(Status2Reg,0x08);0 o6 o% G1 g# z' L
- WriteRawRC(BitFramingReg,0x00);( d' w* W4 J1 X& [7 ^, [
- ClearBitMask(CollReg,0x80);2 c& [/ s6 V& A' l- ~$ N. \' E1 s
-
- h! q! J# t! { i$ V$ Y - ucComMF522Buf[0] = PICC_ANTICOLL1;* _2 |& P; \2 X1 _9 U ~7 ~
- ucComMF522Buf[1] = 0x20;
2 |8 A# n' `1 Q: K5 a, o - / U, f& s0 G( T3 t6 ]( r
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
1 n4 i. h7 g( _
0 T9 W5 z! {2 [# ~ N- if (status == MI_OK)* T' D) L, l$ `) \8 B* h
- {
" Q/ V, ^- i2 f- d0 w6 v - for (i=0; i<4; i++){ . l, h3 g1 l) D$ }
- *(pSnr+i) = ucComMF522Buf[i];
6 V' b/ A4 {2 g% g - snr_check ^= ucComMF522Buf[i];
8 a3 y1 |( {! o - }, d2 F* H8 Y* z: \5 [
- if (snr_check != ucComMF522Buf[i]){
( u4 i0 ^; U D: r' H( \ - status = MI_ERR;
% E8 D1 T$ _6 ^4 D) `# _/ C% c - }
9 P/ F/ t+ [) c) r& W( N - }" B" H& _' e) Q* @. v5 P
-
6 v8 |7 i5 U4 S. I6 r - SetBitMask(CollReg,0x80);' x$ a# k( Z$ N! W. J
- return status;
8 K1 X- o5 m1 s! I5 [4 G - }
) A9 }' e9 A) z. b1 b2 ?6 R0 S - 9 W/ P4 f4 O. Z- H3 F3 C
- /////////////////////////////////////////////////////////////////////
7 {+ y! I9 {6 F0 s& f- X - //功 能:选定卡片6 Q* q" T/ V' O
- //参数说明: pSnr[IN]:卡片序列号,4字节
. b% q5 n! f' s" _5 b8 q3 I - //返 回: 成功返回MI_OK
2 C/ D6 i; F7 K! C6 | a1 |/ l" V - ////////////////////////////////////////////////////////////////////// _( X" R& t+ c5 U! O
- char PcdSelect(u8 *pSnr)
. I8 [+ o. u* e' ^. g - {
$ G. \( L( G$ A1 ?7 O) o0 D! p - char status;) ?- P8 W; w3 u6 G- P9 q8 t, P, t: ]
- u8 i;
/ T( g$ q$ ^. u) c& a - u8 unLen;
6 J! }$ b ~0 H i7 v - u8 ucComMF522Buf[MAXRLEN]; 5 o. w7 X' p+ c: ?
- & u/ p |. Z: ?! ^
- ucComMF522Buf[0] = PICC_ANTICOLL1;( i y5 |2 }! J' ^; c
- ucComMF522Buf[1] = 0x70;
$ t( r$ j1 T* i4 ~2 N0 A9 C - ucComMF522Buf[6] = 0;
$ f3 C6 v" n- I/ A8 I* z- d - for (i=0; i<4; i++)- r$ [8 g7 ]/ U/ h/ m% s6 d t
- {
) O! i! s# w- }4 ?% Z - ucComMF522Buf[i+2] = *(pSnr+i);+ A4 V( [* [; e1 a# f! m; e
- ucComMF522Buf[6] ^= *(pSnr+i);( R V, R# {$ ^* v$ W
- }3 P2 ^. x& U& p( h2 @
- CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
6 V/ |, t2 E [$ C6 [ - n1 s7 t6 i$ l& \3 ]# {
- ClearBitMask(Status2Reg,0x08);2 m) [# D: P) B& Q6 i8 X
8 `; f6 g3 W O; \- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
& ~6 W2 b( B' V* F - * e2 G8 F3 l* ?; V) S2 j
- if ((status == MI_OK) && (unLen == 0x18))
7 u% n7 h4 G; [ - { status = MI_OK; }4 r! {: @& i2 @1 Z0 Z9 c5 R, y
- else+ S: o# O2 v* T9 {/ G/ t. R
- { status = MI_ERR; }
- m) p% Z3 b, s$ M/ Z7 Y. \9 [
* I2 z* Z* ?( F, T* j" c( [! r- return status; [/ m4 X+ a" T: f
- }
1 K: z' y. R6 r- C: y, ?0 L5 d - : I- M( i' U' x/ y, a
- /////////////////////////////////////////////////////////////////////
" K& j% o- @; E5 n! Y6 c- g9 Q - //功 能:验证卡片密码
+ z" W7 ?* T4 G* l) q9 \- c+ D - //参数说明: auth_mode[IN]: 密码验证模式) f, [! Y0 X# O; R
- // 0x60 = 验证A密钥7 y& u$ b) ^" i6 B' r
- // 0x61 = 验证B密钥 ) @' J! Y% k9 ~
- // addr[IN]:块地址
H5 Y/ Y& g1 Y* g, i - // pKey[IN]:密码
. E& X0 o1 G" }' o - // pSnr[IN]:卡片序列号,4字节% X. P. ^: y9 O" e# S7 K
- //返 回: 成功返回MI_OK5 t7 E7 O3 q4 u% p: k6 {0 \* |
- /////////////////////////////////////////////////////////////////////
" B7 k- ~$ `9 R k7 p# G! ` - char PcdAuthState(u8 auth_mode,u8 addr,u8 *pKey,u8 *pSnr) U) g% p/ @$ ]. M2 y) |+ e( L
- {
4 e1 L6 c7 Y! I - char status;( R/ B" Z4 P% ]+ Y/ Q
- u8 unLen;
% c, Z+ l! h. A) s' m9 T8 f - u8 ucComMF522Buf[MAXRLEN];
9 X/ A0 r0 a0 t) P$ d, L
! ?( x2 F8 L% b2 p4 L/ L- ucComMF522Buf[0] = auth_mode;
! v( z- H! l8 }$ a+ _3 W+ ^" g - ucComMF522Buf[1] = addr;9 T! k1 S" v5 }. D
- memcpy(&ucComMF522Buf[2], pKey, 6); / ]5 O: I. R. N, o
- memcpy(&ucComMF522Buf[8], pSnr, 4); 2 F- K! W" \. ~# v$ v# g7 ]5 `
- M' I5 [. ~3 S
- status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);9 P6 w7 ]/ H$ V9 q
- if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
0 s/ g# g; Q, C" k( x! a9 } - { status = MI_ERR; }+ C# g8 w2 T" }4 E
-
- w& d! v, `* K* o ? - return status;& Z: M. d+ {' a0 n6 G
- }% ]5 n+ _! h1 K6 u; Q
. [) w! `3 `+ h* F. R% Y) l- /////////////////////////////////////////////////////////////////////
% g( Z/ f( i9 E) h: F% ?, u - //功 能:读取M1卡一块数据8 b% [2 y7 {4 X% D1 p; l
- //参数说明: addr[IN]:块地址
$ P1 n9 s9 f! N# i# ]) t - // p [OUT]:读出的数据,16字节
' G" y e$ b; E2 L3 m) S; S5 ~ - //返 回: 成功返回MI_OK% q5 Y" c5 k b. z/ ?$ W- Z9 W' u
- /////////////////////////////////////////////////////////////////////
2 N# h6 P' F2 U Z - char PcdRead(u8 addr,u8 *p )
6 o7 |% W9 _4 X6 m7 ? L2 a - {- k2 k9 F F3 [) ?
- char status;/ ~4 M: X2 v! J0 B. k
- u8 unLen;
: ?: j! r/ Q6 o - u8 i,ucComMF522Buf[MAXRLEN]; 9 B, I4 Y9 m3 B3 r q7 g
- 9 j: a" { L- ^" w( n5 g
- ucComMF522Buf[0] = PICC_READ;
6 Q4 y: \" K$ f0 o2 T1 ]6 R - ucComMF522Buf[1] = addr;
) g) t( y; L: M% Q - CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);, L, ^0 k( u; O5 B: l
- ; H. t" I9 t7 ^: ~
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
8 S3 W. \: N" |) c9 b+ P9 Z8 F6 t/ h - if ((status == MI_OK) && (unLen == 0x90))) ?1 d5 ^( G, M3 x- ~# J3 P+ b! A8 d
- {: o0 \" o+ | \+ i; }
- for (i=0; i<16; i++)
2 d) ]$ v# z0 I8 e - { *(p +i) = ucComMF522Buf[i]; }
4 |+ S2 ~) A; ^& ^8 n - }
. c8 n2 T! q% J3 F( b6 t" s - else1 P$ v2 U* v; c h
- { status = MI_ERR; }) h7 d+ @( M! a" e
-
% j( V4 j' \& D - return status;
, _0 u3 x& U, i" p, l: V. k. h - }
* B0 G: F: d! Q+ @4 i5 v/ w6 ?* a! W - 1 M" L% Z0 D! y
- /////////////////////////////////////////////////////////////////////6 ]4 |( j# Y2 u7 h# f
- //功 能:写数据到M1卡一块
% d1 [% J4 J4 _4 J6 p5 z; h - //参数说明: addr[IN]:块地址
: k+ \/ w: ~3 ~$ u - // p [IN]:写入的数据,16字节7 l& J. J0 B( S# G' I* o3 x- l$ h
- //返 回: 成功返回MI_OK /*读01扇区数据,改密码只能写3、7、11、15扇区*/
- p$ W8 N& U$ B% \( |+ p - /////////////////////////////////////////////////////////////////////
5 A# ^- X0 a/ B( ^ - char PcdWrite(u8 addr,u8 *p )
9 t# x" N3 O$ ^9 ` - {1 R5 P* T4 o* g6 P9 P
- char status;3 L/ a* l/ q2 X0 O$ ~2 p L4 l
- u8 unLen;
: X+ M) B5 B1 h# c - u8 i,ucComMF522Buf[MAXRLEN]; [+ k6 t7 c. q% p! e9 L |& \
-
: m7 I1 u0 g6 C9 N; I. P - ucComMF522Buf[0] = PICC_WRITE;
' S) d4 Z, {) E1 a, ~+ Q% H - ucComMF522Buf[1] = addr;7 [. i. ^! t% e( O" M/ G
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
. w( z- ~1 u6 z6 M/ l8 ? - % P+ \- b/ h% y& ?
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
. J: \0 y" k" H6 { - + b& ?; ^5 M; X3 I2 D
- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
9 c- N4 R; `! I+ n! |, O( j - { status = MI_ERR; }
0 A u1 v0 a; o - & _5 P; m- U, p J% y
- if (status == MI_OK)
; k5 c& V9 `1 F" J0 X: v+ s - {8 s! \" Q& W/ e/ p8 O, T0 i: j% a
- //memcpy(ucComMF522Buf, p , 16);
! w+ N0 Y! G) l7 E4 h/ @( l - for (i=0; i<16; i++)
$ ?1 l" ^* Z0 j M: ~5 `$ _ - {
& G% |( L5 @ S( X1 H7 K/ m/ i - ucComMF522Buf[i] = *(p +i);
m9 b: D1 [8 h/ ~ - }
$ c0 Z8 b5 Y& e7 c. i - CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);6 K/ t7 t! _/ Q+ x7 Q# s8 O. y2 \
( R `# V3 _6 \( m) x. M- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
% ?5 ]( P; s" K' ` - if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
: O( M* Z$ j t, b, Z6 e - { status = MI_ERR; }
9 a, W1 F* ^* `2 ?+ U+ n - }+ W) l3 }3 G) F5 F2 h+ a
- % |' K& P" x2 N! T8 U
- return status;
, {# v e @9 S8 G# J - }6 P, M o7 t0 T3 I( O
7 Q6 }( S5 W2 F: o7 J7 F; @- /////////////////////////////////////////////////////////////////////
' p/ e; j( m+ V( \8 Z( _/ n - //功 能:命令卡片进入休眠状态8 W) p) d2 w4 \7 d
- //返 回: 成功返回MI_OK) n* O& o5 _6 u2 S9 a M: v
- /////////////////////////////////////////////////////////////////////7 d9 [; F( Z. W" X
- char PcdHalt(void)6 U5 f+ v% _ e
- {
- m+ O3 I6 _& R9 ~. c$ s5 u - uint8_t status;
2 @4 y/ b. T2 E* E - uint8_t unLen;$ d. \$ h& q! I9 S/ o
- uint8_t ucComMF522Buf[MAXRLEN];
; `9 E2 t% A, a( [- A
$ J B, }# K0 w+ u+ ~) X- ucComMF522Buf[0] = PICC_HALT;( I: l" s' H) a8 W# W8 E. \- r Y
- ucComMF522Buf[1] = 0;
9 b- {; j; E& m& ?, L, u; E8 K5 b - CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
3 {7 L( o7 A/ O1 d1 _/ ` - ; j+ j% F- C/ \+ i
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);. r% H; \2 z- Y
- 9 j! g& V6 J E$ ]/ G
- return status;
3 E- O; b* T" `0 { - }
/ v6 \. Y4 i0 d: l - 1 [5 c8 Y& ~" q) w) c
- /////////////////////////////////////////////////////////////////////
: M$ L4 X2 U3 y2 G - //用MF522计算CRC16函数9 O/ X1 B# G# k' M/ k$ b: H
- /////////////////////////////////////////////////////////////////////
$ ] ~4 K; K( B2 X( O3 F. H - void CalulateCRC(u8 *pIn ,u8 len,u8 *pOut )$ D, O }- [. D( q' S* K- m
- {. s! `8 u3 }$ }( |7 i: j+ P
- u8 i,n;' @% j, Q! w# S6 L. s; c
- ClearBitMask(DivIrqReg,0x04);) o, i' _) b1 W6 B
- WriteRawRC(CommandReg,PCD_IDLE);4 v) }! z2 N& i
- SetBitMask(FIFOLevelReg,0x80);2 n# H0 Q0 \) j& V* [
- for (i=0; i<len; i++)6 a T& `- k+ [ J
- { WriteRawRC(FIFODataReg, *(pIn +i)); }3 W. R# `, n! v# @2 K# @4 N
- WriteRawRC(CommandReg, PCD_CALCCRC);
# H/ e1 m! j, y6 [ - i = 0xFF;
- N1 T2 @' E' ]5 G, ]& a9 J+ V# Y$ V - do
: o3 C" _- p6 H1 p - {
- Y' R8 r6 z- I" j5 Q' o - n = ReadRawRC(DivIrqReg);
- z5 `& B. r8 z3 i - i--;; E9 |1 p: m' ~6 m; g4 }
- }' y( m3 T5 W( y% Q8 ?
- while ((i!=0) && !(n&0x04));
$ @1 T4 R8 m: A* R - pOut [0] = ReadRawRC(CRCResultRegL);* A: b* l* n! j8 B: Y- k1 t7 |; c
- pOut [1] = ReadRawRC(CRCResultRegM);
" w7 @7 k6 z' _- J, A - }* @% [" A' r) }& D) a
# {# M+ p6 V$ s0 `" ^- /////////////////////////////////////////////////////////////////////7 | X7 F+ W) r! s* R u
- //功 能:复位RC522% @" t; Y& j( J6 H5 {
- //返 回: 成功返回MI_OK
/ M0 Z- n6 q( k+ W( s- M - /////////////////////////////////////////////////////////////////////( R. @$ g: _4 v3 L6 i6 U2 U* G
- char PcdReset(void)! u% ^( G6 f' F3 j% e5 q+ o
- {
, A2 H. d6 i2 d4 C6 [* u - W" B' [+ P. ^+ a: W6 J$ n
- RC522_RST=1;
- L2 J% J4 q% T5 A. @ - delay_ns(1000);
: u' D1 ~5 h9 D3 }: n( \ - RC522_RST=0;
# ~7 E# I4 [6 ~% P: Q - delay_ns(1000);
8 O2 W+ V8 d8 K' B- P8 e7 _ - RC522_RST=1;% L9 f: F$ w- A( e& C
- delay_ns(1000);
, H# A4 s9 L3 F* d" l! V7 P - WriteRawRC(CommandReg,PCD_RESETPHASE);
* F! R& a o$ M1 J8 |- f" p - delay_ns(1000);
! D8 i- d( e7 y% J5 O' R0 ` A: R" m! `8 a -
2 j/ I2 z0 C8 B! } [1 O, R( q - WriteRawRC(ModeReg,0x3D); //和Mifare卡通讯,CRC初始值0x6363
" C) c4 d x7 T0 c6 l% ~ - WriteRawRC(TReloadRegL,30); & G8 E, E2 t$ @; |* F
- WriteRawRC(TReloadRegH,0); L1 I3 _! {. ?
- WriteRawRC(TModeReg,0x8D);( J0 z% W; W% c) V$ f& w2 L
- WriteRawRC(TPrescalerReg,0x3E);% `- W7 R; R6 k
-
8 ?5 c- @! T8 o+ b- l+ g& k - WriteRawRC(TxAutoReg,0x40); //6 `7 g+ J* N$ z, N- s
- //WriteRawRC(ComIEnReg,0x20);
# M; F! a* P5 x- X/ J - //WriteRawRC(DivlEnReg,0x90); " C" \: B, N: g T& y/ j
-
& T1 W' X' {2 x! a - return MI_OK;
* b4 u6 m: Z$ J$ F - }/ H0 @- ^ J; w" c
- //////////////////////////////////////////////////////////////////////
; O* d f9 t8 o) J& } - //设置RC632的工作方式
# T: k. j- P* T9 e" F3 L! S - //////////////////////////////////////////////////////////////////////' P# l: t' M0 O' z
- char M500PcdConfigISOType(u8 type)3 o( [3 P* N7 y4 T# h
- {
* t0 Q7 E$ m: D - if (type == 'A') //ISO14443_A
9 n5 P! n) U }0 E2 X - { , @. ]% _$ C- K' U \9 V, V5 a
- ClearBitMask(Status2Reg,0x08);$ y! i) K( p; N! b9 ?; O5 s2 D
- WriteRawRC(ModeReg,0x3D);//3F
. y# \: Z3 y# e7 O* s - WriteRawRC(RxSelReg,0x86);//84
w+ W/ r- A$ ^+ _& i2 q/ L - WriteRawRC(RFCfgReg,0x7F); //4F
6 ]! H4 L! P' G( K - WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) / o5 o+ n) ^) H0 ~
- WriteRawRC(TReloadRegH,0);
& C9 ^; W2 ~% y - WriteRawRC(TModeReg,0x8D);5 l9 w3 H/ T6 m5 [" h* J
- WriteRawRC(TPrescalerReg,0x3E);7 {# g2 N- j5 \7 c9 P- ^! f3 j
- delay_ns(1000);+ Z5 q4 q# B% ?' z9 u) D
- PcdAntennaOn();
% O+ u8 `6 W" C. L* O - }' h" S3 s4 ?) [, q8 V
- else{ return 1; }
4 j% l9 j, `9 S- Y - ! y% ]5 `. l2 t" B) u ?8 k% `- I: D
- return MI_OK;1 x7 ?6 l; T+ j+ ]
- }. {2 ~1 R" g. `$ ~
- /////////////////////////////////////////////////////////////////////9 s7 D: r" j3 g: P2 a7 i- K8 ]
- //功 能:读RC632寄存器
9 @+ S g7 d7 \2 H! {+ X - //参数说明:Address[IN]:寄存器地址2 ~' i& q I# ~( }( E! x# e
- //返 回:读出的值
5 L) P/ D+ m5 Z/ l1 a0 j - /////////////////////////////////////////////////////////////////////$ Q6 y- K4 c: B1 |! c/ s4 s- Z" ?
- u8 ReadRawRC(u8 Address)
' d# q. q3 ?: F( } - {
# k5 T2 i& j& P) [ - u8 ucAddr;
% O$ p# J9 a! q: Q$ C$ Q" q - u8 ucResult=0;3 D6 d4 @( s* i1 H3 ~
- RC522_CS=0;8 m5 {! X! L: K* L3 b* V, m( ? m# n
- ucAddr = ((Address<<1)&0x7E)|0x80;. i- b" K" l6 H" j$ P5 t$ L) p
- ( c* I4 J# z' I0 ` C5 a
- SPIWriteByte(ucAddr);
7 s: U: C {3 G. i' a4 R) n: q8 j - ucResult=SPIReadByte();+ p; z% U! Q1 ?: S1 @ U; x# n
- RC522_CS=1;; g# Q. b( o" Q. B k
- return ucResult;
% B" R; F$ k) }) y! R - }
! J k# s4 x4 G- t - 6 R- I9 n" k# b, m
- /////////////////////////////////////////////////////////////////////
9 S" C3 d8 C) i* j% ], t - //功 能:写RC632寄存器
4 F+ ]9 l& [& R) I - //参数说明:Address[IN]:寄存器地址
! Q7 L/ U6 F4 v$ r4 t - // value[IN]:写入的值
+ y; F8 m( X7 C - /////////////////////////////////////////////////////////////////////0 w" I$ l; G) b9 N/ q' l6 I
- void WriteRawRC(u8 Address, u8 value)& y; c6 e) s% A7 B6 x
- {
1 U: m; N: t/ a2 X! t* r - u8 ucAddr;
" W& i9 J$ E, g4 |' W+ {; J7 b: P5 H - ' v/ i3 a! y p4 Q( O3 a$ b
- RC522_CS=0;
( d4 v- ]( o* E3 g0 d - ucAddr = ((Address<<1)&0x7E);
/ G7 F% `, V v! Z- C$ }
( [9 {: F. L/ O$ u# ]$ @- m- SPIWriteByte(ucAddr);7 N( N; X; s" P2 R$ n2 H
- SPIWriteByte(value);& x3 z# X% s$ h) u" i! z
- RC522_CS=1;
! B, L' N' a' V - }( g+ w5 B6 h. ?1 G v" ~* M: V- ?
- /////////////////////////////////////////////////////////////////////
. Z8 G$ k% @+ k' x - //功 能:置RC522寄存器位
9 s' X* g" X; g7 N8 ~. I: w2 k; m - //参数说明:reg[IN]:寄存器地址
: _# Y# Z2 J+ ~, ?2 r: q - // mask[IN]:置位值* E0 L, n2 _/ p/ k8 e
- /////////////////////////////////////////////////////////////////////* ?0 `1 L* z! S9 j7 g Z
- void SetBitMask(u8 reg,u8 mask) 4 k- u+ q- S9 {1 {# N5 p1 B
- {: e3 l: Q9 F0 o! s% ?
- char tmp = 0x0;1 F- N6 I6 m# h8 a/ P
- tmp = ReadRawRC(reg);
* _# a$ [- b, i8 V - WriteRawRC(reg,tmp | mask); // set bit mask( u8 S& K6 [% C. |# ~6 ]
- }
3 r! t& o; b/ t' [# n8 j: j - + ^- h+ ~3 l9 n; a/ U5 ~( o
- /////////////////////////////////////////////////////////////////////
- t8 V. P# X% x/ S( C; D - //功 能:清RC522寄存器位
" F/ p" V2 l$ ^2 E8 A - //参数说明:reg[IN]:寄存器地址% C k3 n. @2 e, `4 n$ U
- // mask[IN]:清位值5 {- |; d# r5 T4 v; {1 y
- /////////////////////////////////////////////////////////////////////) u; W8 p. W$ n" }3 U" E" e O
- void ClearBitMask(u8 reg,u8 mask)
' s6 ^ Y" X% g9 | - {
& m( S" [/ D0 M; {) ?. {6 ? - char tmp = 0x0;
3 \+ i( _' f { - tmp = ReadRawRC(reg);. d, f* [, Q/ ?% c$ \7 U. f
- WriteRawRC(reg, tmp & ~mask); // clear bit mask
8 S* V, Q# V6 `6 x1 Q: H - }
9 ~3 `/ m) H8 v- c( a
2 O; [0 R: _) |, _6 ^+ q: U: I2 }- /////////////////////////////////////////////////////////////////////
# s8 `6 n3 G0 z7 A$ H- _ - //功 能:通过RC522和ISO14443卡通讯
7 k' K+ I; N5 Z' a9 Z - //参数说明:Command[IN]:RC522命令字$ N( M* a( B O2 h" e" N/ }( A
- // pIn [IN]:通过RC522发送到卡片的数据
5 j: X9 E- k6 j - // InLenByte[IN]:发送数据的字节长度
, s7 g( H' W& M: K. P - // pOut [OUT]:接收到的卡片返回数据, A6 f v/ p/ l! [% Y
- // *pOutLenBit[OUT]:返回数据的位长度3 n7 k) F( w; w5 Z2 v- \4 Z+ D
- /////////////////////////////////////////////////////////////////////
3 u9 ~ {+ a- Z8 W9 x$ e/ I; C* u - char PcdComMF522(u8 Command, % V e) U/ C- c
- u8 *pIn , 6 F2 v' C$ {' q/ d8 X& M9 r
- u8 InLenByte,
: H- a! H5 q, n) P: l - u8 *pOut , ; X: a! W6 L% O0 w z! M- l8 E
- u8 *pOutLenBit)% g$ X" C/ d6 X4 N% N
- {3 e4 E9 ]2 Z, `" X" d: s7 {) G
- char status = MI_ERR;
V, f V6 x& L - u8 irqEn = 0x00;; b0 K+ X! g+ b; z8 O' _0 a9 m
- u8 waitFor = 0x00;
9 U- K6 ?$ U ~$ B1 ] - u8 lastBits;4 y: N+ u1 h3 E0 Y: m
- u8 n;
* l2 Y% I: U% Z( J - long i;
* |/ p9 h3 A; z; L" W* z) M2 L4 q - switch (Command){7 }6 n( E+ j) z; O+ o* T
- case PCD_AUTHENT:
* H5 g& Z5 b; e0 O- c5 E0 |9 d* q - irqEn = 0x12;5 | F7 D6 J/ m, C/ r1 K% C
- waitFor = 0x10;' ?9 c7 l1 F1 `5 l. Q7 {
- break;. r: k \7 Y& n7 X6 d1 e: h
- case PCD_TRANSCEIVE:9 P# K5 C5 H/ p: H8 l5 r
- irqEn = 0x77; y0 V$ ^. w5 X% Q+ I1 P% Y$ c
- waitFor = 0x30;
. d6 [/ s) r1 x/ x. A" O) Y# ? - break;
, g% | [, C* E/ K3 L( ^! C0 d6 A - default:
: O$ \( [# \5 a; ` - break;; U' \, y/ l' s- F) c( h
- }. a) t% [! v4 g" V! u0 b- _
-
# j$ J8 y7 A7 G. q- v - WriteRawRC(ComIEnReg,irqEn|0x80);
, ]% t, W; r0 l* @ - ClearBitMask(ComIrqReg,0x80); //清所有中断位 H0 M4 U( n2 v+ `
- WriteRawRC(CommandReg,PCD_IDLE);, P! O) U* [0 \$ H7 D
- SetBitMask(FIFOLevelReg,0x80); //清FIFO缓存
. c$ }6 O2 w% F- N# \: {$ N% I -
& n$ n" N; P, M3 R# r* @5 j* w - for (i=0; i<InLenByte; i++){ 2 [" G6 R" w8 M+ S" d2 X
- WriteRawRC(FIFODataReg, pIn [i]);
2 S3 e, z5 m/ h& x/ I3 `8 S, T - }5 n8 v3 ^' L: G$ k% U4 L
- WriteRawRC(CommandReg, Command); $ e0 E2 ]: f. b: g7 N, D
- 2 k$ V1 ?& Y4 Q
- if (Command == PCD_TRANSCEIVE){ 1 |3 D7 V2 M: p' z
- SetBitMask(BitFramingReg,0x80);
1 |3 l% c l& }* T# F - } //开始传送6 r; r8 V# N! m0 ^3 g3 ?$ T
-
5 s& T8 o+ b+ M: `. p/ v - //i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
$ h8 O/ E4 c. j- B( k) ] - i = 100000;1 T. ]4 w9 W. e# C9 `
- do ' B0 g, a7 Y& o) x( m
- {
- U! o) c) p3 m p4 P - n = ReadRawRC(ComIrqReg);$ |5 l m4 _) b7 N' F* b
- i--;
' H7 Z$ q* q# U9 D - }while ((i!=0) && !(n&0x01) && !(n&waitFor));6 E& N& T1 o; @4 M" |
- ClearBitMask(BitFramingReg,0x80);8 [1 q+ X8 W4 `" `+ M/ F+ r
5 K, l: D5 G* d! Z: r# o- if (i!=0){ $ `# i" p" c6 `# T2 [( S
- if(!(ReadRawRC(ErrorReg)&0x1B)){
1 J5 d: F6 }% w9 A - status = MI_OK;
8 s; w( Z7 @5 z% C - if (n & irqEn & 0x01){ ( N# b" t7 w$ |' A
- status = MI_NOTAGERR;$ j3 z* ^( M: |% H* L
- }
& x+ z$ F- Z3 I6 ?: @ - if (Command == PCD_TRANSCEIVE){# z. W2 Z2 u; |) Q* J
- n = ReadRawRC(FIFOLevelReg);
) @6 E7 y+ S0 o' B% E- { - lastBits = ReadRawRC(ControlReg) & 0x07;/ L- X1 t2 G- W! w/ d
- if (lastBits){ - F7 s8 ~2 r9 s" n
- *pOutLenBit = (n-1)*8 + lastBits;
( \( X' F% v# Z; Z7 s" a - }else{
& ^; R. E# z. b7 J& w' D - *pOutLenBit = n*8; % w& G0 D% h: y0 Z+ c; L0 u
- }4 J, I3 e8 |' j0 s. [* R
- if (n == 0){ / H9 A4 ]: `3 H
- n = 1;
6 M3 |* ~: N+ n! _, L+ F - }7 m K$ h2 T6 J$ m
- if (n > MAXRLEN){
" Y6 R% f' W3 N, ] - n = MAXRLEN; : J* Z( t% j- R& I% S. t2 _8 ^
- }
& i4 B' U0 m! a, K: c4 P/ u( _3 f - for (i=0; i<n; i++){ ! V$ F* p8 H# y$ y) R* L
- pOut [i] = ReadRawRC(FIFODataReg); 7 x3 B& l; b: t- f. q4 i
- }7 J* Y' |7 L0 {6 l7 R% f2 H$ | l
- }! p# V! A% L. \& q( m7 J
- }else{
1 h; `9 h/ @) k# ~2 k+ v; ]: [ - status = MI_ERR; & J6 P; ?1 J+ o$ A6 S2 b) e6 H% H0 R
- }
5 n4 i) b" Q2 d' N6 t1 `0 ]% j. I - 0 H" ^+ h* U" R8 M6 g1 Y) ^
- }
% b u8 o: j& ^' _7 ~/ q - SetBitMask(ControlReg,0x80); // stop timer now
; b+ N: x0 m7 T3 p3 z, T! n& L* D - WriteRawRC(CommandReg,PCD_IDLE);
0 Y7 k2 c9 D. F! R, n( ~ - return status;! T8 a. q8 `' O% i. j6 u1 N5 f
- }3 M% S0 ^; r$ t
4 J0 t5 k2 v7 N' `' ^- x- /////////////////////////////////////////////////////////////////////
6 v; v$ v5 }7 w/ ^ - //开启天线 % m) d% w' e/ I8 o
- //每次启动或关闭天险发射之间应至少有1ms的间隔
; X! I) U% V1 P/ i - /////////////////////////////////////////////////////////////////////& `1 v- N+ P( r' F; N/ R
- void PcdAntennaOn(void)2 d8 r. @9 W2 K; L! D, h
- {' L3 e& U0 \+ V0 W! U
- u8 i;, w: L" O) \/ C
- i = ReadRawRC(TxControlReg);
. j H+ c3 x% @- N - if (!(i & 0x03)){& F2 j! ^. B6 u+ o
- SetBitMask(TxControlReg, 0x03);% Y/ g: ?* y9 t( k9 {* k
- }, Z4 e/ C9 x. V& B: O$ C( }% P+ |$ d$ o
- }9 Q# ~- H) p2 Q* P" S, A$ I
8 F* Y3 U2 s4 Q( M8 I7 |
, K' S+ S; Q$ L: v9 G& z# ?9 {- /////////////////////////////////////////////////////////////////////9 ?" ~: o6 E4 C7 Y) ^% ^
- //关闭天线! e3 x; z t5 C
- /////////////////////////////////////////////////////////////////////
8 y8 s# ~# ~- A3 m- g* O' d* q8 p. B - void PcdAntennaOff(void)
/ D6 S9 y+ ^8 F6 v Y8 j - {) v; f8 ~0 S- i* ]& K
- ClearBitMask(TxControlReg, 0x03);4 v3 g( c8 T8 U1 i7 A; _+ w* [
- }- F$ F4 k) \' L# |7 ~6 w( |
- extern unsigned char CT[2];//卡类型 @2 ^+ m! O5 E" h; Y. y L3 k
- extern unsigned char SN[4]; //卡号
1 H8 Z) _9 s- w" Q! ^$ M) j( Z - extern unsigned char pptr[64];% q! T, S/ |2 B, C: ?
- extern unsigned char KEY[6];: F% ]$ d, u+ ~ q: M: Q
& _4 ?* I6 }! \8 F6 L: H2 Q* i8 ~. ~- 4 k0 p( k) N5 k7 g1 m
- u8 RfidTest(void)6 U0 L/ K! _% |% g! b
- {# u3 @8 b% o) [( S T3 i
- static u8 oncnt;
5 Z( V8 d0 n; F4 j; c2 O - static u16 allcnt;
* J% P/ g& e8 b; e5 D1 a( g - static u8 res=1;% J7 a7 c2 J$ o
- u8 status;) C/ Q8 n& h# ~9 f9 J
- allcnt++; /*未明确什么含义 RF卡扫描次数?*/; [5 N. H/ T6 o
- if(PcdRequest(PICC_REQALL,CT)==0) /*扫描卡*/
Z; H6 N0 i3 m- F& k) X/ J# V- t# B - {" I$ E8 n, g9 M
- status = PcdAnticoll(SN); /*防冲撞--获取卡号*/2 [& }6 _) z- ~" x
- status = PcdSelect(SN); /*根据卡号选择卡*/
$ s& c* ^- n0 X - //1个扇区4个块 每个块16个字节 密码长度6个字节2 h* B7 P- Z7 n) n7 `
- //块地址=扇区编号×4+扇区内的块编号 17 代表4扇区 块1$ O4 `! A5 H' N: k# [7 N4 |
- //将保存在块地址17内的6个字节的密码与秘钥B进行比较! |% w* l2 `4 l
- //调用该函数需要选择密码验证是KEYA还是KEYB,# ?8 D/ s$ U, h8 N+ h$ d8 ~" ^
- //然后输入你要操作的块地址(想要读写的)()
( A' o& @" J! [# Z7 d- N; {6 p/ ]* I - //存放密码数组和存放卡片序列号的数组。(感觉仅用来计算扇区)8 t. V9 l; [4 w
- //验证成功后就可以对该块所在的扇区内所有的块进行操作了
/ m: ]" j5 o" ? - //读、写、加值、减值、转移、恢复), [' ?# b- ? O4 L* z
- //KEYA KEYB 默认密码都是0XFF
; I2 _/ k; \9 ]8 U% [ - status = PcdAuthState(PICC_AUTHENT1B,17,KEY,SN); /*解密:验证B密钥,密码所在地址 3-7-11-15-19*/
; ?& R8 X9 I1 r. u" o( x - status = PcdRead(17,pptr); /*读4扇区01块数据 返回16个字节数据*/0 J- T5 B5 x0 i1 @7 g& V$ }; y
- if(status == MI_OK) //5次以上成功
1 H1 a# h3 n5 Z: `0 i/ V - {
- [; S& P* s9 l( F$ | - oncnt++;
" D5 N& A" @' I) M8 B$ C - CupType = pptr[0];//茶杯类型在0位置' h& H& F, g$ U) z" {8 ^
- }
6 S, C) C; w" F5 B - }. {0 @( s) x% V; k$ S& \
- if(allcnt>13)//检测13次
6 s% O+ T5 m4 d1 F* N: {, w - {
& F4 S/ u7 U$ A! _' e9 a: | - if(oncnt>5)//5次以上成功
& R; ?9 u& b8 Z. e! }3 q6 ^8 x - {
! L: l: t7 ~$ B. b. c - res= 0;( n5 [; |! [ \! B" N
- }$ \; `, V3 m' ]( r
- else1 V7 f& E1 z, u7 t
- {9 U9 U J) S& I! P+ t0 O- s) Q
- res = 1;7 P3 s4 j& R9 @, a$ t+ C2 {" |7 t5 e) u
- CupType=0xff;7 L; D9 _0 W. w, @6 H) `9 n
- }
0 a) X, s$ }5 I( J3 P' h - allcnt=0;oncnt=0;7 z5 ]2 @( H4 f3 j0 ~% W/ T# w, M
- }
# z9 Y! T# I$ D - return res;
# P& r; o$ S0 {8 J3 C# Z - }
6 o+ t* c. w3 j! k) y - /////////////////////////////////////////////////////////////////////
% e7 }+ a% Y4 g- X - //功 能:读取杯子类型% |8 R7 H' b7 L7 _ b/ Q
- //
& k2 F5 d$ H, m# k* G - //返 回: 失败 返回0xff 型号一返回01 型号二返回02 空白卡返回00; G) O( H$ Y9 }$ X- B2 y" p
- ///////////////////////////////////////////////////////////////////// . Y$ A2 I, [" x# K
6 P! _) X7 l: z! |- extern u8 CheckRFTime;/ A; e2 W& }, l" i; o
- u8 AllCnt=0;% H& M, i. x+ m, K M
- 0 \4 y3 [3 `% f& d
- u8 ReadCupType(void)0 M2 q+ K; \3 X6 }# c/ R5 V
- {
4 G; T! i U1 w1 S+ O) k1 P) L4 X( d - u8 status;
r9 T5 ]1 c2 M" O, N
2 P7 K8 W4 k' u$ T- AllCnt++;/ X! z0 T1 }7 W
- /*无卡次数,也就是非MI_OK的次数*/( v% J5 N) F/ I) G! p, t; V! K
- status = PcdRequest(PICC_REQALL,CT); /*扫描卡 0 OK 2失败*/# S G7 m. m, P# X/ F2 a, r$ E- X
- if(status==MI_OK)8 ?# i! v3 S* m8 @. a# A9 u$ ? |
- printf("寻卡状态:成功\r\n");
- _+ {6 z: e* J; r - else1 {1 r/ G, d3 H/ Q. c; v
- {4 [, X+ S- c$ e* g1 W
- printf("寻卡状态:失败\r\n");
9 D: z3 {/ Y- ^ - return 0XDF;9 o2 i* b" c+ ~5 @6 `" W
- }' Z; I) K- X1 I# K9 N9 @6 e
- 4 s) r8 E- c2 I, ~4 M
- status = PcdAnticoll(SN); /*防冲撞*/
* ?! \3 J( A; R- r2 C - if(status==MI_OK) j( z4 l' F& C& @
- printf("防冲撞:成功\r\n");1 u H$ B: L8 J4 O( W) G
- else# U* h9 T3 l+ K8 q9 P U7 z4 x
- {, ^( H( r1 W! c1 ]+ E, V) R' l! z& h
- printf("防冲撞:失败\r\n");, W. g9 }- e! y7 ?5 L
- return 0XDF;: X6 i& s4 c( G( a" T
- }
- {' |# a; j. m4 G. A; j7 Q3 m -
6 J$ T9 H/ U: G1 x7 {2 K - status = PcdSelect(SN); /*选卡*/
+ o, {: K. O! p. E" @2 k+ J. { - if(status==MI_OK)" Q- S: V+ H# j' P2 a- N
- printf("选卡:成功\r\n");6 n' `5 O) k; h
- else
# i+ v/ Y6 L; _0 B$ F - {/ e9 l2 }& A k; q: Z5 @ ?; Z
- printf("选卡:失败\r\n");) a0 _+ G; j& F$ K4 E+ z; E
- return 0XDF;
4 R$ ~1 |+ t% B2 C3 L2 W - }, W# }0 c" ~) D0 t
-
6 @# M K6 Y" c - //PS:块地址17之前被强制性写入了杯子的型号(用另一个程序)) D f0 S' B6 u/ M+ R' [
- status = PcdAuthState(PICC_AUTHENT1A,17,KEY,SN);
4 P) L% [9 @& O( a' [ - if(status==MI_OK)
e5 x3 l3 D8 ?5 s( D6 x0 _# M - printf("密码校验:成功\r\n");
2 Z, j- u8 p) q3 ^5 U% H! | - else
/ v1 K, u$ e+ N! d3 z' Q7 _ - {7 V. Q5 F- B G3 z2 E
- printf("密码校验:失败\r\n");
! ]8 B" h" S; p2 w# ?( S' u - return 0XDF; 4 q& P- [$ [1 _5 H" s. ]
-
: N8 D, V0 S; j: ]- i# L2 ~# G1 @* k - }
0 N3 x" ?: ^) ^ - : N' o1 x h% Z% {/ N
- status = PcdRead(17,pptr);
0 L1 q. q0 R' J. \ - ( D9 t# b2 ?$ X, s' N* C2 ^) R
- if(status == MI_OK)7 }% b: q+ T) A; ^1 k
- {
9 Z0 K [; H& Y! G" F) Z2 I - return pptr[0];9 x& m" i' D% l! I# M* d* A! v
-
! I1 E* _) G6 I/ O I, S - }0 D' v& N& H: J. v+ k
- else
! o& q4 [& p: p0 n - {: ~' S3 _! W5 b
- return 0XEF;
, Z* i0 N2 x6 n5 u. n - }
8 C6 N" Q$ o7 E' ~ - ; y% j" S5 t5 l9 q* ~; } T
- + f) D! E$ k7 K7 F: t$ W# c5 Y
- }
8 \, O' Q( ~: w1 d% @, B - 6 M8 {2 w4 }& Q# H8 ~! @2 G8 r- l
- /*写杯子类型1*// O$ _- ]7 x1 z& w# J |; ^
- u8 WriteCupType1(void)* W+ D8 s5 w' A5 ^' R' `6 `( M
- {# W; D7 z+ o( y0 d9 w
/ A( g$ a7 W5 C! I4 h7 O" G- u8 status; + w2 \3 J" c' d9 \
- u8 CUP1KEY[16]={0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF};2 Z. K. E3 }, z$ c; f
- 7 F5 I! \4 V* K) m, u( h) X* P
- AllCnt++;
/ a$ r+ r( c5 h5 b2 k' F - /*无卡次数,也就是非MI_OK的次数*/
2 n n }6 g0 E' e) k. L; A - status = PcdRequest(PICC_REQALL,CT); /*扫描卡 0 OK 2失败*// M* D( U7 O4 R! C, q0 ~* Y
- printf("%d%s",PICC_REQALL,CT);
; A; t, Z s4 Q, ?4 [ - if(status==MI_OK)
; {: T) S3 I& F4 _5 E - printf("寻卡状态:成功\r\n");
@ R/ Q4 Z- o9 w& T - else
5 }! o& p3 U' R% A& x6 v# s1 Y6 s/ W: f - {$ i% F6 t7 @/ u. I7 O7 e8 @
- printf("寻卡状态:失败\r\n");
/ f3 C9 M6 p- R5 C - return 0XDF;
7 p7 ?; s5 l" O. U8 x& p - }
9 S1 I/ K& H* G' v -
2 `1 c# z2 }$ A6 x9 t. s l - status = PcdAnticoll(SN); /*防冲撞*/* J9 ^3 R! N5 q* X3 r
- if(status==MI_OK)
/ J0 e9 _! Y1 g& A - printf("防冲撞:成功\r\n");
. t6 t4 x0 A% @1 K - else
0 d( b6 V# u- V6 s1 F, @8 e) a. i' K - {8 v0 N7 ~9 w8 W5 ^& f# L' c
- printf("防冲撞:失败\r\n");
, O4 O: T( T: m" o1 e/ [2 G - return 0XDF;- f) a; [+ }, }( D3 R8 J4 p
- }
* N" I/ s$ c. N5 C -
* q( I( Q, B4 v0 ? - status = PcdSelect(SN); /*选卡*/4 E4 i6 I d, l9 S! `& y% M
- if(status==MI_OK)1 r y. J7 J$ U' ~
- printf("选卡:成功\r\n");9 Y9 G$ _8 f0 B( U( H& L) H
- else
; P% Z: E4 B( ?" l1 u - {
& ]3 r: n1 d8 h - printf("选卡:失败\r\n");! g* l! q! Y6 S1 H4 C3 K1 B4 S
- return 0XDF;3 |% d5 O7 R+ V9 F1 w l4 D
- }
. J/ N+ s4 j: H$ I+ G3 x -
" x) U0 M1 c: E. m$ K6 Z - //PS:块地址17之前被强制性写入了杯子的型号(用另一个程序)
6 ]2 x% N' w1 w! R - status = PcdAuthState(PICC_AUTHENT1A,17,KEY,SN);
% E. t9 A; A5 J3 M5 q8 g$ Z+ f0 }& v - if(status==MI_OK). ^# J/ F6 J( }; W- i9 p
- printf("密码校验:成功\r\n");& U1 ]4 `" d6 p; g `* b% r' z
- else4 \# R- L9 |& V$ L3 g2 f2 e
- {; u$ @. g2 b8 h* P0 t: x) x" ]
- printf("密码校验:失败\r\n");/ J3 L5 s. h& U# h) S
- return 0XDF;
/ S( f* \% j5 ^ a - ' I& x- s6 ~- I" M$ @% K
- }
# l, o! j8 X1 @6 t" x6 J' V -
3 z' b$ h$ R0 |- v$ q: R2 y+ \0 w - status = PcdWrite(17,CUP1KEY);
* c. a3 @# P; j9 g - printf("%S",CUP1KEY);
0 r5 i! D) P- p: \8 ]/ c - if(status == MI_OK)
! F7 b `7 e9 ? g6 S) @ Z - {& H" E7 t7 b& W D" m3 ^
- return MI_OK;
% o, c) c$ h8 U3 ^0 h9 f - , G1 A3 b9 x a& k2 A' @
- }
% y* \8 K# a" y* W - else* K( F0 G3 P! h6 V4 C# e4 x& g+ D
- {7 u( u- i% _4 W+ e8 ?8 X
- return 0XEF;) Q, d& c9 ]" @
- }
8 K" j2 O* T3 ]0 D/ r h - }7 @7 u! j! x r
- /*写杯子类型2*/5 }% b& G4 [/ K5 O) Q
- u8 WriteCupType2(void)
4 M. Z+ q8 w' U* E0 q& _) `3 H - {
5 o: ]' ?) z2 w& c$ w4 p& z - : t( d Q: P% i8 N& d2 u6 v
- u8 status; ( _9 V2 t- L6 x
- u8 CUP2KEY[16]={0X02,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF};4 \. l7 Q8 N0 X5 \4 g3 |5 j- T5 L4 S
- 5 O( b) ~0 r+ J6 U, }! t2 f
- AllCnt++;+ \3 s, ~; q! a- V, }
- /*无卡次数,也就是非MI_OK的次数*/
, a9 T( F0 y; G - status = PcdRequest(PICC_REQALL,CT); /*扫描卡 0 OK 2失败*/
2 h, N6 R' a" T2 g3 | - if(status==MI_OK)
9 x# }* N7 K0 j; H& j7 W - printf("寻卡状态:成功\r\n");- q% j6 C# E% S1 B
- else/ Y. y$ c5 E, z3 a1 ^: F( o
- {1 |" Y* Q' D& }% F$ _4 P' t0 R
- printf("寻卡状态:失败\r\n");. X1 | G: s ]! L- Q* u
- return 0XDF;
9 k) q4 T3 K' k% J: l - }. d8 H; ~# [* V* d
-
9 e; K3 o n+ @5 T) y1 V - status = PcdAnticoll(SN); /*防冲撞*/
; w. f* I9 I# z; a/ A - if(status==MI_OK)
' A( e/ \3 V, C- e - printf("防冲撞:成功\r\n");
& O6 t# t8 Q! A1 ^" f8 i - else& o2 S& c3 Q8 N* x7 p
- {
8 W+ \1 |* R, P7 {( `6 w& K8 h - printf("防冲撞:失败\r\n");0 C* I7 h- r# _/ `: z+ N& [( z
- return 0XDF;
; E, k7 Y/ @% Y - }
" }; \- s# f8 T0 z& s3 v# \ - ; _( {. K. V8 _, C
- status = PcdSelect(SN); /*选卡*/
9 Y9 U! m3 ~$ o - if(status==MI_OK)
/ G; F% |. R, _+ l9 x4 j3 l4 z - printf("选卡:成功\r\n");
9 h' S+ o$ R* Y; Z - else
: s7 s' r% B+ r5 O+ N% F - {
% u3 ]# W3 Z7 Q3 i; Q - printf("选卡:失败\r\n");
! P9 o) T* @7 M. L) D& y - return 0XDF;* i' H: [) z2 t- D
- }' O2 B) s# a& {1 a9 A
-
: `/ t( c% q7 ^2 H2 N/ h( U6 Y/ M( ^ - //PS:块地址17之前被强制性写入了杯子的型号(用另一个程序)
3 a8 y6 \: q/ ?3 [. f6 |2 T ^' N - status = PcdAuthState(PICC_AUTHENT1A,17,KEY,SN);
* K2 o4 g( p" M/ s+ A - if(status==MI_OK)/ R, S" J' G0 u
- printf("密码校验:成功\r\n");
g5 e z* O r3 L: P5 J - else
. f8 T- `# O9 W; M6 y" I, G5 U! { - {5 ]9 Q/ ]) j, i- t
- printf("密码校验:失败\r\n");
+ h0 c+ g, T; d6 h2 G5 g - return 0XDF; 3 z+ W' k" T- Y9 Q
- + G: ]1 L% [" @# d7 ?, L
- }) {" u) s& z, x0 Q$ ~1 U
- ) X' Z. E4 q0 R
- status = PcdWrite(17,CUP2KEY);
$ Z' s/ E. s# r2 T; }# c -
4 ]# k" P$ z$ y - if(status == MI_OK)7 k8 d |0 U d* s, U: N2 w+ |
- {
, u% g1 A& T/ k1 ? - return MI_OK;
* j6 C* V, B" t% P -
5 j% v# W# y$ c( e - }
/ p. K1 H% h4 T% y - else
5 p* p$ i. ]* C' w; p - {+ R2 f; E- i6 C {9 |( H0 `, e6 w
- return 0XEF;
: x" r8 ?, }, R/ G+ B - }8 g" Q( a" r; s$ J! C. ?9 @
- }( u3 Y+ x- v6 ?
- 9 [9 K0 f& {- T/ X% s. ]5 b A# \
- /////////////////////////////////////////////////////////////////////
. d Y7 S+ s) L$ Y) ~2 P - //功 能:扣款和充值
% C2 m! i' g( f! L# p7 l - //参数说明: dd_mode[IN]:命令字" M0 {; i8 B4 w, X( \7 l+ e
- // 0xC0 = 扣款
0 F" y) b6 {3 |- ]5 F - // 0xC1 = 充值5 p% ^* W: }3 p( j8 v
- // addr[IN]:钱包地址 b. r0 F7 A9 g. R4 c6 \7 }
- // pValue[IN]:4字节增(减)值,低位在前0 t3 ~5 y+ I* c, `5 j9 U) h, k
- //返 回: 成功返回MI_OK5 J8 l8 Y" x) L _$ ?4 _1 k
- /////////////////////////////////////////////////////////////////////
- h1 E' I8 @7 n1 l - /*char PcdValue(u8 dd_mode,u8 addr,u8 *pValue)
$ z5 H7 {7 V* a" T2 a; W! M0 T% m - {: s O$ G. o6 L o; P. P
- char status;
+ [, h ]. S9 x- _9 y; u D1 s' r - u8 unLen;, s o& A+ L! A5 G1 G$ C% C
- u8 ucComMF522Buf[MAXRLEN]; # n; q+ {5 w' w+ b
- //u8 i;
" y8 Q+ I: _. D - , g9 w5 S9 T( h
- ucComMF522Buf[0] = dd_mode;. B( a: z" p/ J" a7 D- v
- ucComMF522Buf[1] = addr;
5 H7 X# B# R8 z) _- U9 z - CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
+ E0 h6 o1 q/ b. ~* b. z7 M' g -
1 ~3 v( C3 m7 h - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
' T/ v @" y3 T4 L1 k: l. k' M
7 X" s9 B; v# `9 A1 {- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
; q8 g/ v, M8 m8 {. a1 u0 S - { status = MI_ERR; }) ^1 ?& B3 J' h; V
-
# h: ]% W$ b3 T7 g: F - if (status == MI_OK)& h% q4 s- K6 P. y' ^( s
- {
- }5 I, } O6 }" E - memcpy(ucComMF522Buf, pValue, 4);
, Z. H& a( n6 f, ?* C: o# @) J - //for (i=0; i<16; i++)9 E7 a; i* S0 D( A! ], i- X# E0 {
- //{ ucComMF522Buf[i] = *(pValue+i); }1 G% V. a5 F& c% K6 |+ w. {
- CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
2 ?0 B, n' \# Y- p s7 O O* v3 R - unLen = 0; ~2 @5 X2 J, C7 S
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
! l2 ?8 d5 i9 [6 Q - if (status != MI_ERR)5 P9 `: j1 ]3 s! R: _4 |) j8 e# p
- { status = MI_OK; }
! u& ?3 K: q4 j1 ^ - }2 ~* {! V/ n# y$ b5 p/ x, |3 Q
-
8 u/ A5 C3 E8 E, ` - if (status == MI_OK)4 H: G0 N1 `. i4 I: t
- {
) M9 ` o6 R3 V$ m8 g+ U - ucComMF522Buf[0] = PICC_TRANSFER;
9 L; [: s- Z3 w/ g1 s - ucComMF522Buf[1] = addr;9 q) ~* X; H; U- Q
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
7 k5 Q& A" R' q& {& n -
; U7 g2 b6 R8 ~8 j+ q) S! {0 z - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
% S) ?5 V8 A6 Z& ~+ ]1 a0 R - ; }; }. G4 ^5 Z- n$ x- v# X
- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))! i7 R" O H7 e% L$ T" R9 h
- { status = MI_ERR; }
0 t# R. C) `, ^ - }
9 R/ N6 M. \- o8 q- Z) j1 `7 z - return status;! w6 h6 g4 t& F& n
- }*/
0 l4 b1 E# i+ c+ }2 z! d - ( W' T/ R& c8 J# ^' M6 c
- /////////////////////////////////////////////////////////////////////- m, V5 W& w+ _( |6 J. V3 N
- //功 能:备份钱包# _* s4 Q) m( C7 k/ Z1 w
- //参数说明: sourceaddr[IN]:源地址7 {9 U2 E# u" V5 R C) V
- // goaladdr[IN]:目标地址
& L+ B% s8 N" N6 ]. @2 g4 @ - //返 回: 成功返回MI_OK
* X7 a/ t6 O: L" d4 A( V$ x- V - /////////////////////////////////////////////////////////////////////
, E% z1 @+ m+ j0 r( `6 a - /*char PcdBakValue(u8 sourceaddr, u8 goaladdr)
/ ?% l0 @5 T2 r( S' N$ v - {
" l$ O u8 M7 X( t* N- a - char status;1 r1 m& D& c* t# M3 S* ^- {1 E' D
- u8 unLen;- q* t, J6 e" m" {( M6 C
- u8 ucComMF522Buf[MAXRLEN];
1 f3 ^2 ~; p1 A" z0 [4 Q - : o" I3 o+ Q6 \- o; _
- ucComMF522Buf[0] = PICC_RESTORE;% c0 v, ?/ {$ n* I x! S$ Z8 j
- ucComMF522Buf[1] = sourceaddr;
1 ~% Z. W4 u$ a; m2 O - CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);/ q7 h: H6 B/ Z* c& N2 E4 m
-
3 u/ Q0 K% k/ j4 N& y. v - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
3 s# N g: t! @7 A - 0 {) R$ b9 t4 b# C
- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)). }) T: z0 ~3 u9 l9 r
- { status = MI_ERR; }/ O- Q: p/ n2 N+ H' w
- 8 c7 W1 G9 m% A4 [+ W: _+ @
- if (status == MI_OK)
4 T$ V: t; K& i1 K - {1 ~8 t0 Y. {' n- A" L
- ucComMF522Buf[0] = 0;! ]8 G9 ]8 S% c9 O9 `# X4 n
- ucComMF522Buf[1] = 0;$ |' a& u* w& O4 C$ I
- ucComMF522Buf[2] = 0;
. P9 x ^, P. n. { - ucComMF522Buf[3] = 0; r/ c& N; ^8 V$ ?: t% h% u _
- CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
1 a$ b# H* N4 B: j& ]' ^ - : Z1 u) b0 I# m( C) v9 m
- status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
: q- o( B* M: t! y1 p - if (status != MI_ERR)1 Z& n: B" y2 \9 [$ x# W- H
- { status = MI_OK; }4 V- B$ q. A% y& A
- }7 K8 p/ V) g l2 u) ]
- 6 y. V9 f& e4 `
- if (status != MI_OK)
8 m( q5 e: @; M, {7 x - { return MI_ERR; }
& Q6 `6 |! `0 g" Q2 |" B ~ -
& i. S6 W& i/ Y8 |& Z' Q - ucComMF522Buf[0] = PICC_TRANSFER;
0 A1 C7 O8 J8 X! {6 D7 K8 j) x- s - ucComMF522Buf[1] = goaladdr;/ U: |9 K# {: }/ _
- , R) w i" A( O2 H% G- Y
- CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);$ K+ _5 }6 j3 u$ w2 u5 T t! V
-
/ p0 ~. a+ V& ^ @& r5 }2 L - status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);& [' K* B, T* q/ H5 V* ~' j; h
- 5 m$ V+ \: K7 P- e; V
- if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
) o' W( j( |/ e+ z9 o0 Z5 d - { status = MI_ERR; }3 W, Y1 h2 N$ q. u$ G W+ W
- o2 y. K. d9 x
- return status;, V O# W0 B4 P5 o% c# N
- }*/) x* Y) w% \0 \' K% T0 [! l
复制代码 通过串口来读写RF卡(仅块地址17):+ w) A9 d* z, d+ _" |$ Z
指令:SS11PP //查询杯子RFID型号" I# c' b/ q$ O5 y8 R5 r
指令:SS22PP //强制写杯子RFID卡为型号13 V4 [ x2 O# S# L. R
指令:SS22PP //强制写杯子RFID卡为型号2
& p; s# O1 p! t+ \% Q" Z3 E2 X# f
编译下载,通过串口操作(S50卡放读写模块上):! \: E" x* w m
5 O7 [, a$ C% B3 O好了,简单的分析就到这了~大神勿喷~感谢观看~, f, p% R4 E- j: F
代码:
, R5 S2 t i8 C4 M
STM32F103RBT6_RC522_NFC_DEMO.rar
(511.74 KB, 下载次数: 4)
|