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